mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-02-07 06:53:33 +00:00
Incorporate more small improvements
This commit is contained in:
parent
1d4eb08fa1
commit
f83eb440f7
20 changed files with 121 additions and 256 deletions
2
Makefile
2
Makefile
|
@ -269,7 +269,7 @@ CHECKS = $(foreach x,$(PKGS),$($(x)_CHECKS))
|
||||||
|
|
||||||
bins: $(BINS)
|
bins: $(BINS)
|
||||||
check: $(CHECKS)
|
check: $(CHECKS)
|
||||||
test: $(TESTS) aarch64
|
test: $(TESTS)
|
||||||
depend: o/$(MODE)/depend
|
depend: o/$(MODE)/depend
|
||||||
tags: TAGS HTAGS
|
tags: TAGS HTAGS
|
||||||
|
|
||||||
|
|
|
@ -176,7 +176,7 @@ void *Worker(void *id) {
|
||||||
// inherited by the accepted sockets, but using them also has the
|
// inherited by the accepted sockets, but using them also has the
|
||||||
// side-effect that the listening socket fails with EAGAIN, every
|
// side-effect that the listening socket fails with EAGAIN, every
|
||||||
// several seconds. we can use that to our advantage to check for
|
// several seconds. we can use that to our advantage to check for
|
||||||
// the ctrl-c shutdowne event; otherwise, we retry the accept call
|
// the ctrl-c shutdowne event; otherwise we retry the accept call
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -91,6 +91,6 @@ int close(int fd) {
|
||||||
__releasefd(fd);
|
__releasefd(fd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
STRACE("%s(%d) → %d% m", "close", fd, rc);
|
STRACE("close(%d) → %d% m", fd, rc);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,14 +34,6 @@ forceinline bool __isfdkind(int fd, int kind) {
|
||||||
return 0 <= fd && fd < g_fds.n && g_fds.p[fd].kind == kind;
|
return 0 <= fd && fd < g_fds.n && g_fds.p[fd].kind == kind;
|
||||||
}
|
}
|
||||||
|
|
||||||
forceinline size_t _clampio(size_t size) {
|
|
||||||
if (!IsTrustworthy()) {
|
|
||||||
return MIN(size, 0x7ffff000);
|
|
||||||
} else {
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int sys_close_nt(struct Fd *, int) _Hide;
|
int sys_close_nt(struct Fd *, int) _Hide;
|
||||||
int _check_interrupts(bool, struct Fd *) _Hide;
|
int _check_interrupts(bool, struct Fd *) _Hide;
|
||||||
int sys_openat_metal(int, const char *, int, unsigned);
|
int sys_openat_metal(int, const char *, int, unsigned);
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
|
||||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
|
||||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
|
||||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
|
||||||
│ │
|
|
||||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
|
||||||
│ any purpose with or without fee is hereby granted, provided that the │
|
|
||||||
│ above copyright notice and this permission notice appear in all copies. │
|
|
||||||
│ │
|
|
||||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
|
||||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
|
||||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
|
||||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
|
||||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
|
||||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
|
||||||
#include "libc/nt/struct/overlapped.h"
|
|
||||||
#include "libc/str/str.h"
|
|
||||||
|
|
||||||
textwindows struct NtOverlapped *_offset2overlap(int64_t handle,
|
|
||||||
int64_t opt_offset,
|
|
||||||
struct NtOverlapped *mem) {
|
|
||||||
if (opt_offset == -1) return NULL;
|
|
||||||
bzero(mem, sizeof(struct NtOverlapped));
|
|
||||||
mem->Pointer = (void *)(uintptr_t)opt_offset;
|
|
||||||
return mem;
|
|
||||||
}
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "libc/calls/syscall_support-nt.internal.h"
|
#include "libc/calls/syscall_support-nt.internal.h"
|
||||||
#include "libc/calls/wincrash.internal.h"
|
#include "libc/calls/wincrash.internal.h"
|
||||||
#include "libc/intrin/strace.internal.h"
|
#include "libc/intrin/strace.internal.h"
|
||||||
|
#include "libc/macros.internal.h"
|
||||||
#include "libc/nt/enum/filetype.h"
|
#include "libc/nt/enum/filetype.h"
|
||||||
#include "libc/nt/errors.h"
|
#include "libc/nt/errors.h"
|
||||||
#include "libc/nt/files.h"
|
#include "libc/nt/files.h"
|
||||||
|
@ -37,13 +38,10 @@
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
|
||||||
static textwindows ssize_t sys_read_nt_impl(struct Fd *fd, void *data,
|
static textwindows ssize_t sys_read_nt_impl(struct Fd *fd, void *data,
|
||||||
size_t size, ssize_t offset) {
|
size_t size, int64_t offset) {
|
||||||
bool32 ok;
|
|
||||||
int64_t p;
|
|
||||||
uint32_t got, avail;
|
|
||||||
struct NtOverlapped overlap;
|
|
||||||
|
|
||||||
// our terrible polling mechanism
|
// try to poll rather than block
|
||||||
|
uint32_t avail;
|
||||||
if (GetFileType(fd->handle) == kNtFileTypePipe) {
|
if (GetFileType(fd->handle) == kNtFileTypePipe) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (!PeekNamedPipe(fd->handle, 0, 0, 0, &avail, 0)) break;
|
if (!PeekNamedPipe(fd->handle, 0, 0, 0, &avail, 0)) break;
|
||||||
|
@ -63,19 +61,28 @@ static textwindows ssize_t sys_read_nt_impl(struct Fd *fd, void *data,
|
||||||
POLLTRACE("sys_read_nt ready to read");
|
POLLTRACE("sys_read_nt ready to read");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offset != -1) {
|
// perform the read i/o operation
|
||||||
// windows changes the file pointer even if overlapped is passed
|
bool32 ok;
|
||||||
_npassert(SetFilePointerEx(fd->handle, 0, &p, SEEK_CUR));
|
uint32_t got;
|
||||||
|
size = MIN(size, 0x7ffff000);
|
||||||
|
if (offset == -1) {
|
||||||
|
// perform simple blocking read
|
||||||
|
ok = ReadFile(fd->handle, data, size, &got, 0);
|
||||||
|
} else {
|
||||||
|
// perform pread()-style read at particular file offset
|
||||||
|
int64_t position;
|
||||||
|
// save file pointer which windows clobbers, even for overlapped i/o
|
||||||
|
if (!SetFilePointerEx(fd->handle, 0, &position, SEEK_CUR)) {
|
||||||
|
return __winerr(); // fd probably isn't seekable?
|
||||||
|
}
|
||||||
|
struct NtOverlapped overlap = {0};
|
||||||
|
overlap.Pointer = (void *)(uintptr_t)offset;
|
||||||
|
ok = ReadFile(fd->handle, data, size, 0, &overlap);
|
||||||
|
if (!ok && GetLastError() == kNtErrorIoPending) ok = true;
|
||||||
|
if (ok) ok = GetOverlappedResult(fd->handle, &overlap, &got, true);
|
||||||
|
// restore file pointer which windows clobbers, even on error
|
||||||
|
_unassert(SetFilePointerEx(fd->handle, position, 0, SEEK_SET));
|
||||||
}
|
}
|
||||||
|
|
||||||
ok = ReadFile(fd->handle, data, _clampio(size), &got,
|
|
||||||
_offset2overlap(fd->handle, offset, &overlap));
|
|
||||||
|
|
||||||
if (offset != -1) {
|
|
||||||
// windows clobbers file pointer even on error
|
|
||||||
_npassert(SetFilePointerEx(fd->handle, p, 0, SEEK_SET));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ok) {
|
if (ok) {
|
||||||
return got;
|
return got;
|
||||||
}
|
}
|
||||||
|
@ -93,7 +100,7 @@ static textwindows ssize_t sys_read_nt_impl(struct Fd *fd, void *data,
|
||||||
}
|
}
|
||||||
|
|
||||||
textwindows ssize_t sys_read_nt(struct Fd *fd, const struct iovec *iov,
|
textwindows ssize_t sys_read_nt(struct Fd *fd, const struct iovec *iov,
|
||||||
size_t iovlen, ssize_t opt_offset) {
|
size_t iovlen, int64_t opt_offset) {
|
||||||
ssize_t rc;
|
ssize_t rc;
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
size_t i, total;
|
size_t i, total;
|
||||||
|
|
|
@ -13,7 +13,7 @@ int64_t sys_vmsplice(int, const struct iovec *, int64_t, uint32_t) _Hide;
|
||||||
int64_t sys_writev(int32_t, const struct iovec *, int32_t) _Hide;
|
int64_t sys_writev(int32_t, const struct iovec *, int32_t) _Hide;
|
||||||
size_t __iovec_size(const struct iovec *, size_t) _Hide;
|
size_t __iovec_size(const struct iovec *, size_t) _Hide;
|
||||||
ssize_t WritevUninterruptible(int, struct iovec *, int);
|
ssize_t WritevUninterruptible(int, struct iovec *, int);
|
||||||
ssize_t sys_read_nt(struct Fd *, const struct iovec *, size_t, ssize_t) _Hide;
|
ssize_t sys_read_nt(struct Fd *, const struct iovec *, size_t, int64_t) _Hide;
|
||||||
ssize_t sys_readv_metal(struct Fd *, const struct iovec *, int) _Hide;
|
ssize_t sys_readv_metal(struct Fd *, const struct iovec *, int) _Hide;
|
||||||
ssize_t sys_readv_nt(struct Fd *, const struct iovec *, int) _Hide;
|
ssize_t sys_readv_nt(struct Fd *, const struct iovec *, int) _Hide;
|
||||||
ssize_t sys_readv_serial(struct Fd *, const struct iovec *, int) _Hide;
|
ssize_t sys_readv_serial(struct Fd *, const struct iovec *, int) _Hide;
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
#ifndef COSMOPOLITAN_LIBC_CALLS_WINCRASH_INTERNAL_H_
|
#ifndef COSMOPOLITAN_LIBC_CALLS_WINCRASH_INTERNAL_H_
|
||||||
#define COSMOPOLITAN_LIBC_CALLS_WINCRASH_INTERNAL_H_
|
#define COSMOPOLITAN_LIBC_CALLS_WINCRASH_INTERNAL_H_
|
||||||
#include "libc/nt/struct/ntexceptionpointers.h"
|
#include "libc/nt/struct/ntexceptionpointers.h"
|
||||||
#include "libc/nt/struct/overlapped.h"
|
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
COSMOPOLITAN_C_START_
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
unsigned __wincrash_nt(struct NtExceptionPointers *);
|
unsigned __wincrash_nt(struct NtExceptionPointers *);
|
||||||
struct NtOverlapped *_offset2overlap(int64_t, int64_t,
|
|
||||||
struct NtOverlapped *) _Hide;
|
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
COSMOPOLITAN_C_END_
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
|
|
@ -16,20 +16,20 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/assert.h"
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/calls/internal.h"
|
#include "libc/calls/internal.h"
|
||||||
#include "libc/calls/sig.internal.h"
|
#include "libc/calls/sig.internal.h"
|
||||||
#include "libc/calls/struct/iovec.h"
|
|
||||||
#include "libc/calls/struct/iovec.internal.h"
|
#include "libc/calls/struct/iovec.internal.h"
|
||||||
#include "libc/calls/syscall_support-nt.internal.h"
|
#include "libc/calls/syscall_support-nt.internal.h"
|
||||||
#include "libc/calls/wincrash.internal.h"
|
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
#include "libc/intrin/strace.internal.h"
|
#include "libc/intrin/strace.internal.h"
|
||||||
#include "libc/intrin/weaken.h"
|
#include "libc/intrin/weaken.h"
|
||||||
|
#include "libc/macros.internal.h"
|
||||||
#include "libc/nt/errors.h"
|
#include "libc/nt/errors.h"
|
||||||
#include "libc/nt/files.h"
|
#include "libc/nt/files.h"
|
||||||
#include "libc/nt/runtime.h"
|
#include "libc/nt/runtime.h"
|
||||||
#include "libc/runtime/internal.h"
|
#include "libc/nt/struct/overlapped.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
#include "libc/sysv/consts/sicode.h"
|
#include "libc/sysv/consts/sicode.h"
|
||||||
#include "libc/sysv/consts/sig.h"
|
#include "libc/sysv/consts/sig.h"
|
||||||
|
@ -37,26 +37,31 @@
|
||||||
|
|
||||||
static textwindows ssize_t sys_write_nt_impl(int fd, void *data, size_t size,
|
static textwindows ssize_t sys_write_nt_impl(int fd, void *data, size_t size,
|
||||||
ssize_t offset) {
|
ssize_t offset) {
|
||||||
|
|
||||||
|
// perform the write i/o operation
|
||||||
bool32 ok;
|
bool32 ok;
|
||||||
int64_t h, p;
|
uint32_t sent;
|
||||||
uint32_t err, sent;
|
int64_t handle;
|
||||||
struct NtOverlapped overlap;
|
handle = g_fds.p[fd].handle;
|
||||||
|
size = MIN(size, 0x7ffff000);
|
||||||
h = g_fds.p[fd].handle;
|
if (offset == -1) {
|
||||||
|
// perform simple blocking write
|
||||||
if (offset != -1) {
|
ok = WriteFile(handle, data, size, &sent, 0);
|
||||||
// windows changes the file pointer even if overlapped is passed
|
} else {
|
||||||
SetFilePointerEx(h, 0, &p, SEEK_CUR);
|
// perform pwrite()-style write at particular file offset
|
||||||
|
int64_t position;
|
||||||
|
// save file pointer which windows clobbers, even for overlapped i/o
|
||||||
|
if (!SetFilePointerEx(handle, 0, &position, SEEK_CUR)) {
|
||||||
|
return __winerr(); // fd probably isn't seekable?
|
||||||
|
}
|
||||||
|
struct NtOverlapped overlap = {0};
|
||||||
|
overlap.Pointer = (void *)(uintptr_t)offset;
|
||||||
|
ok = WriteFile(handle, data, size, 0, &overlap);
|
||||||
|
if (!ok && GetLastError() == kNtErrorIoPending) ok = true;
|
||||||
|
if (ok) ok = GetOverlappedResult(handle, &overlap, &sent, true);
|
||||||
|
// restore file pointer which windows clobbers, even on error
|
||||||
|
_unassert(SetFilePointerEx(handle, position, 0, SEEK_SET));
|
||||||
}
|
}
|
||||||
|
|
||||||
ok = WriteFile(h, data, _clampio(size), &sent,
|
|
||||||
_offset2overlap(h, offset, &overlap));
|
|
||||||
|
|
||||||
if (offset != -1) {
|
|
||||||
// windows clobbers file pointer even on error
|
|
||||||
SetFilePointerEx(h, p, 0, SEEK_SET);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ok) {
|
if (ok) {
|
||||||
return sent;
|
return sent;
|
||||||
}
|
}
|
||||||
|
@ -86,8 +91,6 @@ textwindows ssize_t sys_write_nt(int fd, const struct iovec *iov, size_t iovlen,
|
||||||
ssize_t opt_offset) {
|
ssize_t opt_offset) {
|
||||||
ssize_t rc;
|
ssize_t rc;
|
||||||
size_t i, total;
|
size_t i, total;
|
||||||
uint32_t size, wrote;
|
|
||||||
struct NtOverlapped overlap;
|
|
||||||
if (opt_offset < -1) return einval();
|
if (opt_offset < -1) return einval();
|
||||||
while (iovlen && !iov[0].iov_len) iov++, iovlen--;
|
while (iovlen && !iov[0].iov_len) iov++, iovlen--;
|
||||||
if (iovlen) {
|
if (iovlen) {
|
||||||
|
|
104
libc/errno.h
104
libc/errno.h
|
@ -4,25 +4,35 @@
|
||||||
COSMOPOLITAN_C_START_
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @fileoverview System error codes.
|
* @fileoverview System Five error codes.
|
||||||
* @see libc/sysv/consts.sh for numbers
|
*
|
||||||
|
* This file defines the `errno` global variable. When system calls
|
||||||
|
* (e.g. read(), write(), etc.) fail they return -1 to indicate the
|
||||||
|
* failure, and that is *the only* error return value. System calls
|
||||||
|
* also update `errno` too whenever -1 is returned (otherwise errno
|
||||||
|
* isn't changed) to be a non-zero value holding one of the numbers
|
||||||
|
* below, in order to indicate why the system call failed.
|
||||||
|
*
|
||||||
|
* There is only one exception to the above rule; some system calls
|
||||||
|
* are documented with the `@returnserrno` tag, which means they'll
|
||||||
|
* return the error number rather than stuffing it in a global. You
|
||||||
|
* can usually spot these system calls easily since most of them'll
|
||||||
|
* have names like `posix_foo()` or `pthread_bar()`.
|
||||||
|
*
|
||||||
|
* @see libc/sysv/consts.sh for assigned numbers
|
||||||
|
* @see libc/sysv/dos2errno.sh for multimapped numbers
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if defined(__GNUC__) && defined(__x86_64__) && defined(__MNO_RED_ZONE__) && \
|
#if defined(__GNUC__) && defined(__aarch64__) && !defined(__STRICT_ANSI__) && \
|
||||||
!defined(__STRICT_ANSI__) && !defined(__cplusplus)
|
!defined(__cplusplus)
|
||||||
#define errno \
|
/* this header is included by 700+ files; therefore we */
|
||||||
(*({ \
|
/* hand-roll &__get_tls()->tib_errno to avoid #include */
|
||||||
errno_t *_ep; \
|
/* cosmopolitan uses x28 as the tls register b/c apple */
|
||||||
asm("call\t__errno_location" : "=a"(_ep) : /* no inputs */ : "cc"); \
|
#define errno \
|
||||||
_ep; \
|
(*({ \
|
||||||
}))
|
errno_t *__ep; \
|
||||||
#elif defined(__GNUC__) && defined(__aarch64__) && \
|
asm("sub\t%0,x28,#1092" : "=r"(__ep)); \
|
||||||
!defined(__STRICT_ANSI__) && !defined(__cplusplus)
|
__ep; \
|
||||||
#define errno \
|
|
||||||
(*({ \
|
|
||||||
errno_t *_ep; \
|
|
||||||
asm("sub\t%0,x28,#1092" : "=r"(_ep)); \
|
|
||||||
_ep; \
|
|
||||||
}))
|
}))
|
||||||
#else
|
#else
|
||||||
#define errno (*__errno_location())
|
#define errno (*__errno_location())
|
||||||
|
@ -493,7 +503,7 @@ extern const errno_t ENOMEDIUM;
|
||||||
extern const errno_t EMEDIUMTYPE;
|
extern const errno_t EMEDIUMTYPE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inappropriate file type or format. (BSD only)
|
* Inappropriate file type or format.
|
||||||
*/
|
*/
|
||||||
extern const errno_t EFTYPE;
|
extern const errno_t EFTYPE;
|
||||||
|
|
||||||
|
@ -513,7 +523,6 @@ extern const errno_t EPROGUNAVAIL;
|
||||||
extern const errno_t EPWROFF;
|
extern const errno_t EPWROFF;
|
||||||
extern const errno_t ERPCMISMATCH;
|
extern const errno_t ERPCMISMATCH;
|
||||||
extern const errno_t ESHLIBVERS;
|
extern const errno_t ESHLIBVERS;
|
||||||
|
|
||||||
extern const errno_t EADV;
|
extern const errno_t EADV;
|
||||||
extern const errno_t EBADE;
|
extern const errno_t EBADE;
|
||||||
extern const errno_t EBADFD;
|
extern const errno_t EBADFD;
|
||||||
|
@ -558,35 +567,20 @@ extern const errno_t EXFULL;
|
||||||
#define EACCES EACCES
|
#define EACCES EACCES
|
||||||
#define EADDRINUSE EADDRINUSE
|
#define EADDRINUSE EADDRINUSE
|
||||||
#define EADDRNOTAVAIL EADDRNOTAVAIL
|
#define EADDRNOTAVAIL EADDRNOTAVAIL
|
||||||
#define EADV EADV
|
|
||||||
#define EAFNOSUPPORT EAFNOSUPPORT
|
#define EAFNOSUPPORT EAFNOSUPPORT
|
||||||
#define EAGAIN EAGAIN
|
#define EAGAIN EAGAIN
|
||||||
#define EALREADY EALREADY
|
#define EALREADY EALREADY
|
||||||
#define EAUTH EAUTH
|
|
||||||
#define EBADARCH EBADARCH
|
|
||||||
#define EBADE EBADE
|
|
||||||
#define EBADEXEC EBADEXEC
|
|
||||||
#define EBADF EBADF
|
#define EBADF EBADF
|
||||||
#define EBADFD EBADFD
|
|
||||||
#define EBADMACHO EBADMACHO
|
|
||||||
#define EBADMSG EBADMSG
|
#define EBADMSG EBADMSG
|
||||||
#define EBADR EBADR
|
|
||||||
#define EBADRPC EBADRPC
|
|
||||||
#define EBADRQC EBADRQC
|
|
||||||
#define EBADSLT EBADSLT
|
|
||||||
#define EBUSY EBUSY
|
#define EBUSY EBUSY
|
||||||
#define ECANCELED ECANCELED
|
#define ECANCELED ECANCELED
|
||||||
#define ECHILD ECHILD
|
#define ECHILD ECHILD
|
||||||
#define ECHRNG ECHRNG
|
|
||||||
#define ECOMM ECOMM
|
|
||||||
#define ECONNABORTED ECONNABORTED
|
#define ECONNABORTED ECONNABORTED
|
||||||
#define ECONNREFUSED ECONNREFUSED
|
#define ECONNREFUSED ECONNREFUSED
|
||||||
#define ECONNRESET ECONNRESET
|
#define ECONNRESET ECONNRESET
|
||||||
#define EDEADLK EDEADLK
|
#define EDEADLK EDEADLK
|
||||||
#define EDESTADDRREQ EDESTADDRREQ
|
#define EDESTADDRREQ EDESTADDRREQ
|
||||||
#define EDEVERR EDEVERR
|
|
||||||
#define EDOM EDOM
|
#define EDOM EDOM
|
||||||
#define EDOTDOT EDOTDOT
|
|
||||||
#define EDQUOT EDQUOT
|
#define EDQUOT EDQUOT
|
||||||
#define EEXIST EEXIST
|
#define EEXIST EEXIST
|
||||||
#define EFAULT EFAULT
|
#define EFAULT EFAULT
|
||||||
|
@ -594,7 +588,6 @@ extern const errno_t EXFULL;
|
||||||
#define EFTYPE EFTYPE
|
#define EFTYPE EFTYPE
|
||||||
#define EHOSTDOWN EHOSTDOWN
|
#define EHOSTDOWN EHOSTDOWN
|
||||||
#define EHOSTUNREACH EHOSTUNREACH
|
#define EHOSTUNREACH EHOSTUNREACH
|
||||||
#define EHWPOISON EHWPOISON
|
|
||||||
#define EIDRM EIDRM
|
#define EIDRM EIDRM
|
||||||
#define EILSEQ EILSEQ
|
#define EILSEQ EILSEQ
|
||||||
#define EINPROGRESS EINPROGRESS
|
#define EINPROGRESS EINPROGRESS
|
||||||
|
@ -603,20 +596,6 @@ extern const errno_t EXFULL;
|
||||||
#define EIO EIO
|
#define EIO EIO
|
||||||
#define EISCONN EISCONN
|
#define EISCONN EISCONN
|
||||||
#define EISDIR EISDIR
|
#define EISDIR EISDIR
|
||||||
#define EISNAM EISNAM
|
|
||||||
#define EKEYEXPIRED EKEYEXPIRED
|
|
||||||
#define EKEYREJECTED EKEYREJECTED
|
|
||||||
#define EKEYREVOKED EKEYREVOKED
|
|
||||||
#define EL2HLT EL2HLT
|
|
||||||
#define EL2NSYNC EL2NSYNC
|
|
||||||
#define EL3HLT EL3HLT
|
|
||||||
#define EL3RST EL3RST
|
|
||||||
#define ELIBACC ELIBACC
|
|
||||||
#define ELIBBAD ELIBBAD
|
|
||||||
#define ELIBEXEC ELIBEXEC
|
|
||||||
#define ELIBMAX ELIBMAX
|
|
||||||
#define ELIBSCN ELIBSCN
|
|
||||||
#define ELNRNG ELNRNG
|
|
||||||
#define ELOOP ELOOP
|
#define ELOOP ELOOP
|
||||||
#define EMEDIUMTYPE EMEDIUMTYPE
|
#define EMEDIUMTYPE EMEDIUMTYPE
|
||||||
#define EMFILE EMFILE
|
#define EMFILE EMFILE
|
||||||
|
@ -624,29 +603,21 @@ extern const errno_t EXFULL;
|
||||||
#define EMSGSIZE EMSGSIZE
|
#define EMSGSIZE EMSGSIZE
|
||||||
#define EMULTIHOP EMULTIHOP
|
#define EMULTIHOP EMULTIHOP
|
||||||
#define ENAMETOOLONG ENAMETOOLONG
|
#define ENAMETOOLONG ENAMETOOLONG
|
||||||
#define ENAVAIL ENAVAIL
|
|
||||||
#define ENEEDAUTH ENEEDAUTH
|
|
||||||
#define ENETDOWN ENETDOWN
|
#define ENETDOWN ENETDOWN
|
||||||
#define ENETRESET ENETRESET
|
#define ENETRESET ENETRESET
|
||||||
#define ENETUNREACH ENETUNREACH
|
#define ENETUNREACH ENETUNREACH
|
||||||
#define ENFILE ENFILE
|
#define ENFILE ENFILE
|
||||||
#define ENOANO ENOANO
|
|
||||||
#define ENOATTR ENOATTR
|
|
||||||
#define ENOBUFS ENOBUFS
|
#define ENOBUFS ENOBUFS
|
||||||
#define ENOCSI ENOCSI
|
|
||||||
#define ENODATA ENODATA
|
#define ENODATA ENODATA
|
||||||
#define ENODEV ENODEV
|
#define ENODEV ENODEV
|
||||||
#define ENOENT ENOENT
|
#define ENOENT ENOENT
|
||||||
#define ENOEXEC ENOEXEC
|
#define ENOEXEC ENOEXEC
|
||||||
#define ENOKEY ENOKEY
|
|
||||||
#define ENOLCK ENOLCK
|
#define ENOLCK ENOLCK
|
||||||
#define ENOLINK ENOLINK
|
#define ENOLINK ENOLINK
|
||||||
#define ENOMEDIUM ENOMEDIUM
|
#define ENOMEDIUM ENOMEDIUM
|
||||||
#define ENOMEM ENOMEM
|
#define ENOMEM ENOMEM
|
||||||
#define ENOMSG ENOMSG
|
#define ENOMSG ENOMSG
|
||||||
#define ENONET ENONET
|
#define ENONET ENONET
|
||||||
#define ENOPKG ENOPKG
|
|
||||||
#define ENOPOLICY ENOPOLICY
|
|
||||||
#define ENOPROTOOPT ENOPROTOOPT
|
#define ENOPROTOOPT ENOPROTOOPT
|
||||||
#define ENOSPC ENOSPC
|
#define ENOSPC ENOSPC
|
||||||
#define ENOSR ENOSR
|
#define ENOSR ENOSR
|
||||||
|
@ -656,12 +627,10 @@ extern const errno_t EXFULL;
|
||||||
#define ENOTCONN ENOTCONN
|
#define ENOTCONN ENOTCONN
|
||||||
#define ENOTDIR ENOTDIR
|
#define ENOTDIR ENOTDIR
|
||||||
#define ENOTEMPTY ENOTEMPTY
|
#define ENOTEMPTY ENOTEMPTY
|
||||||
#define ENOTNAM ENOTNAM
|
|
||||||
#define ENOTRECOVERABLE ENOTRECOVERABLE
|
#define ENOTRECOVERABLE ENOTRECOVERABLE
|
||||||
#define ENOTSOCK ENOTSOCK
|
#define ENOTSOCK ENOTSOCK
|
||||||
#define ENOTSUP ENOTSUP
|
#define ENOTSUP ENOTSUP
|
||||||
#define ENOTTY ENOTTY
|
#define ENOTTY ENOTTY
|
||||||
#define ENOTUNIQ ENOTUNIQ
|
|
||||||
#define ENXIO ENXIO
|
#define ENXIO ENXIO
|
||||||
#define EOPNOTSUPP EOPNOTSUPP
|
#define EOPNOTSUPP EOPNOTSUPP
|
||||||
#define EOVERFLOW EOVERFLOW
|
#define EOVERFLOW EOVERFLOW
|
||||||
|
@ -669,43 +638,28 @@ extern const errno_t EXFULL;
|
||||||
#define EPERM EPERM
|
#define EPERM EPERM
|
||||||
#define EPFNOSUPPORT EPFNOSUPPORT
|
#define EPFNOSUPPORT EPFNOSUPPORT
|
||||||
#define EPIPE EPIPE
|
#define EPIPE EPIPE
|
||||||
#define EPROCLIM EPROCLIM
|
|
||||||
#define EPROCUNAVAIL EPROCUNAVAIL
|
|
||||||
#define EPROGMISMATCH EPROGMISMATCH
|
|
||||||
#define EPROGUNAVAIL EPROGUNAVAIL
|
|
||||||
#define EPROTO EPROTO
|
#define EPROTO EPROTO
|
||||||
#define EPROTONOSUPPORT EPROTONOSUPPORT
|
#define EPROTONOSUPPORT EPROTONOSUPPORT
|
||||||
#define EPROTOTYPE EPROTOTYPE
|
#define EPROTOTYPE EPROTOTYPE
|
||||||
#define EPWROFF EPWROFF
|
|
||||||
#define ERANGE ERANGE
|
#define ERANGE ERANGE
|
||||||
#define EREMCHG EREMCHG
|
|
||||||
#define EREMOTE EREMOTE
|
#define EREMOTE EREMOTE
|
||||||
#define EREMOTEIO EREMOTEIO
|
|
||||||
#define ERESTART ERESTART
|
#define ERESTART ERESTART
|
||||||
#define ERFKILL ERFKILL
|
|
||||||
#define EROFS EROFS
|
#define EROFS EROFS
|
||||||
#define ERPCMISMATCH ERPCMISMATCH
|
|
||||||
#define ESHLIBVERS ESHLIBVERS
|
|
||||||
#define ESHUTDOWN ESHUTDOWN
|
#define ESHUTDOWN ESHUTDOWN
|
||||||
#define ESOCKTNOSUPPORT ESOCKTNOSUPPORT
|
#define ESOCKTNOSUPPORT ESOCKTNOSUPPORT
|
||||||
#define ESPIPE ESPIPE
|
#define ESPIPE ESPIPE
|
||||||
#define ESRCH ESRCH
|
#define ESRCH ESRCH
|
||||||
#define ESRMNT ESRMNT
|
|
||||||
#define ESTALE ESTALE
|
#define ESTALE ESTALE
|
||||||
#define ESTRPIPE ESTRPIPE
|
|
||||||
#define ETIME ETIME
|
#define ETIME ETIME
|
||||||
#define ETIMEDOUT ETIMEDOUT
|
#define ETIMEDOUT ETIMEDOUT
|
||||||
#define ETOOMANYREFS ETOOMANYREFS
|
#define ETOOMANYREFS ETOOMANYREFS
|
||||||
#define ETXTBSY ETXTBSY
|
#define ETXTBSY ETXTBSY
|
||||||
#define EUCLEAN EUCLEAN
|
|
||||||
#define EUNATCH EUNATCH
|
|
||||||
#define EUSERS EUSERS
|
#define EUSERS EUSERS
|
||||||
#define EWOULDBLOCK EAGAIN
|
#define EWOULDBLOCK EAGAIN
|
||||||
#define EXDEV EXDEV
|
#define EXDEV EXDEV
|
||||||
#define EXFULL EXFULL
|
|
||||||
|
|
||||||
extern errno_t __errno;
|
extern errno_t __errno;
|
||||||
errno_t *__errno_location(void);
|
errno_t *__errno_location(void) dontthrow pureconst;
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
COSMOPOLITAN_C_END_
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
|
|
@ -3298,6 +3298,7 @@ imp 'WSCWriteNameSpaceOrder32' WSCWriteNameSpaceOrder32 ws2_32 162
|
||||||
imp 'WSCWriteProviderOrder' WSCWriteProviderOrder ws2_32 163
|
imp 'WSCWriteProviderOrder' WSCWriteProviderOrder ws2_32 163
|
||||||
imp 'WSCWriteProviderOrder32' WSCWriteProviderOrder32 ws2_32 164
|
imp 'WSCWriteProviderOrder32' WSCWriteProviderOrder32 ws2_32 164
|
||||||
imp 'WSCWriteProviderOrderEx' WSCWriteProviderOrderEx ws2_32 165
|
imp 'WSCWriteProviderOrderEx' WSCWriteProviderOrderEx ws2_32 165
|
||||||
|
imp '__sys_socket_nt' socket ws2_32 0 3
|
||||||
imp '__sys_accept_nt' accept ws2_32 1 3 # we're using WSAAccept()
|
imp '__sys_accept_nt' accept ws2_32 1 3 # we're using WSAAccept()
|
||||||
imp '__sys_bind_nt' bind ws2_32 2 3
|
imp '__sys_bind_nt' bind ws2_32 2 3
|
||||||
imp '__sys_closesocket_nt' closesocket ws2_32 3 1
|
imp '__sys_closesocket_nt' closesocket ws2_32 3 1
|
||||||
|
|
|
@ -51,6 +51,7 @@
|
||||||
#include "libc/runtime/internal.h"
|
#include "libc/runtime/internal.h"
|
||||||
#include "libc/runtime/memtrack.internal.h"
|
#include "libc/runtime/memtrack.internal.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
|
#include "libc/runtime/symbols.internal.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
#include "libc/sysv/consts/map.h"
|
#include "libc/sysv/consts/map.h"
|
||||||
#include "libc/sysv/consts/o.h"
|
#include "libc/sysv/consts/o.h"
|
||||||
|
@ -349,14 +350,20 @@ textwindows int sys_fork_nt(uint32_t dwCreationFlags) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rc = 0;
|
rc = 0;
|
||||||
|
// re-apply code morphing for thread-local storage
|
||||||
if (tib && _weaken(__set_tls) && _weaken(__morph_tls)) {
|
if (tib && _weaken(__set_tls) && _weaken(__morph_tls)) {
|
||||||
_weaken(__set_tls)(tib);
|
_weaken(__set_tls)(tib);
|
||||||
_weaken(__morph_tls)();
|
_weaken(__morph_tls)();
|
||||||
__tls_enabled_set(true);
|
__tls_enabled_set(true);
|
||||||
}
|
}
|
||||||
|
// re-apply code morphing for synchronization nops
|
||||||
if (threaded && !__threaded && _weaken(__enable_threads)) {
|
if (threaded && !__threaded && _weaken(__enable_threads)) {
|
||||||
_weaken(__enable_threads)();
|
_weaken(__enable_threads)();
|
||||||
}
|
}
|
||||||
|
// re-apply code morphing for function tracing
|
||||||
|
if (ftrace_stackdigs) {
|
||||||
|
_weaken(__hook)(_weaken(ftrace_hook), _weaken(GetSymbolTable)());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (untrackpid != -1) {
|
if (untrackpid != -1) {
|
||||||
__releasefd(untrackpid);
|
__releasefd(untrackpid);
|
||||||
|
|
|
@ -119,4 +119,4 @@ ftrace_hook:
|
||||||
1: ret
|
1: ret
|
||||||
|
|
||||||
#endif /* __x86_64__ */
|
#endif /* __x86_64__ */
|
||||||
.endfn ftrace_hook,globl
|
.endfn ftrace_hook,globl,hidden
|
||||||
|
|
|
@ -23,8 +23,6 @@
|
||||||
#include "libc/runtime/stack.h"
|
#include "libc/runtime/stack.h"
|
||||||
#include "libc/runtime/symbols.internal.h"
|
#include "libc/runtime/symbols.internal.h"
|
||||||
|
|
||||||
void ftrace_hook(void);
|
|
||||||
|
|
||||||
textstartup int ftrace_install(void) {
|
textstartup int ftrace_install(void) {
|
||||||
if (GetSymbolTable()) {
|
if (GetSymbolTable()) {
|
||||||
ftrace_stackdigs = LengthInt64Thousands(GetStackSize());
|
ftrace_stackdigs = LengthInt64Thousands(GetStackSize());
|
||||||
|
|
|
@ -33,6 +33,7 @@ extern unsigned char _tls_content[] __attribute__((__weak__));
|
||||||
|
|
||||||
void _init(void) _Hide;
|
void _init(void) _Hide;
|
||||||
int ftrace_init(void) _Hide;
|
int ftrace_init(void) _Hide;
|
||||||
|
void ftrace_hook(void) _Hide;
|
||||||
void __morph_tls(void) _Hide;
|
void __morph_tls(void) _Hide;
|
||||||
void __enable_tls(void) _Hide;
|
void __enable_tls(void) _Hide;
|
||||||
void __enable_threads(void) _Hide;
|
void __enable_threads(void) _Hide;
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#define ShouldUseMsabiAttribute() 1
|
#define ShouldUseMsabiAttribute() 1
|
||||||
#include "ape/sections.internal.h"
|
#include "ape/sections.internal.h"
|
||||||
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/calls/internal.h"
|
#include "libc/calls/internal.h"
|
||||||
#include "libc/calls/struct/sigset.h"
|
#include "libc/calls/struct/sigset.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
|
@ -36,24 +37,7 @@
|
||||||
|
|
||||||
__msabi extern typeof(VirtualProtect) *const __imp_VirtualProtect;
|
__msabi extern typeof(VirtualProtect) *const __imp_VirtualProtect;
|
||||||
|
|
||||||
#ifdef __aarch64__
|
__funline void __morph_mprotect(void *addr, size_t size, int prot, int ntprot) {
|
||||||
static privileged void __aarch64_sigprocmask(int how, const sigset_t *set,
|
|
||||||
sigset_t *oldset) {
|
|
||||||
register int r0 asm("x0") = how;
|
|
||||||
register long r1 asm("x1") = (long)set;
|
|
||||||
register long r2 asm("x2") = (long)oldset;
|
|
||||||
register long r3 asm("x3") = 8;
|
|
||||||
register long r8 asm("x8") = __NR_sigprocmask;
|
|
||||||
register long r16 asm("x16") = __NR_sigprocmask;
|
|
||||||
asm volatile("svc\t0"
|
|
||||||
: "+r"(r0)
|
|
||||||
: "r"(r1), "r"(r2), "r"(r3), "r"(r8), "r"(r16)
|
|
||||||
: "memory");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static privileged void __morph_mprotect(void *addr, size_t size, int prot,
|
|
||||||
int ntprot) {
|
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
bool cf;
|
bool cf;
|
||||||
int ax, dx;
|
int ax, dx;
|
||||||
|
@ -69,8 +53,11 @@ static privileged void __morph_mprotect(void *addr, size_t size, int prot,
|
||||||
if (ax == -EPERM) {
|
if (ax == -EPERM) {
|
||||||
kprintf("error: need pledge(prot_exec) permission to code morph\n");
|
kprintf("error: need pledge(prot_exec) permission to code morph\n");
|
||||||
}
|
}
|
||||||
|
if (ax < 0) {
|
||||||
|
kprintf("error: __morph_mprotect(%p, %#zx, %d) failed: errno=%d\n", addr,
|
||||||
|
size, prot, -ax);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
if (ax) notpossible;
|
|
||||||
} else {
|
} else {
|
||||||
__imp_VirtualProtect(addr, size, ntprot, &op);
|
__imp_VirtualProtect(addr, size, ntprot, &op);
|
||||||
}
|
}
|
||||||
|
@ -97,27 +84,6 @@ privileged void __morph_begin(sigset_t *save) {
|
||||||
bool cf;
|
bool cf;
|
||||||
intptr_t dx;
|
intptr_t dx;
|
||||||
sigset_t ss = {{-1, -1}};
|
sigset_t ss = {{-1, -1}};
|
||||||
#ifdef __x86_64__
|
|
||||||
if (IsOpenbsd()) {
|
|
||||||
asm volatile(CFLAG_ASM("syscall")
|
|
||||||
: CFLAG_CONSTRAINT(cf), "=a"(ax), "=d"(dx)
|
|
||||||
: "1"(__NR_sigprocmask), "D"(SIG_BLOCK), "S"(-1u)
|
|
||||||
: "rcx", "r8", "r9", "r10", "r11", "memory");
|
|
||||||
save->__bits[0] = ax & 0xffffffff;
|
|
||||||
if (cf) notpossible;
|
|
||||||
} else if (!IsWindows() && !IsMetal()) {
|
|
||||||
asm volatile("mov\t$8,%%r10d\n\t"
|
|
||||||
"syscall"
|
|
||||||
: "=a"(ax), "=d"(dx)
|
|
||||||
: "0"(__NR_sigprocmask), "D"(SIG_BLOCK), "S"(&ss), "1"(save)
|
|
||||||
: "rcx", "r8", "r9", "r10", "r11", "memory", "cc");
|
|
||||||
if (ax) notpossible;
|
|
||||||
}
|
|
||||||
#elif defined(__aarch64__)
|
|
||||||
__aarch64_sigprocmask(SIG_BLOCK, &ss, save);
|
|
||||||
#else
|
|
||||||
#error "unsupported architecture"
|
|
||||||
#endif
|
|
||||||
__morph_mprotect(__executable_start, __privileged_start - __executable_start,
|
__morph_mprotect(__executable_start, __privileged_start - __executable_start,
|
||||||
PROT_READ | PROT_WRITE, kNtPageWritecopy);
|
PROT_READ | PROT_WRITE, kNtPageWritecopy);
|
||||||
}
|
}
|
||||||
|
@ -131,24 +97,4 @@ privileged void __morph_end(sigset_t *save) {
|
||||||
bool cf;
|
bool cf;
|
||||||
__morph_mprotect(__executable_start, __privileged_start - __executable_start,
|
__morph_mprotect(__executable_start, __privileged_start - __executable_start,
|
||||||
PROT_READ | PROT_EXEC, kNtPageExecuteRead);
|
PROT_READ | PROT_EXEC, kNtPageExecuteRead);
|
||||||
#ifdef __x86_64__
|
|
||||||
if (IsOpenbsd()) {
|
|
||||||
asm volatile(CFLAG_ASM("syscall")
|
|
||||||
: CFLAG_CONSTRAINT(cf), "=a"(ax), "=d"(dx)
|
|
||||||
: "1"(__NR_sigprocmask), "D"(SIG_SETMASK), "S"(save->__bits[0])
|
|
||||||
: "rcx", "r8", "r9", "r10", "r11", "memory");
|
|
||||||
if (cf) notpossible;
|
|
||||||
} else if (!IsWindows() && !IsMetal()) {
|
|
||||||
asm volatile("mov\t$8,%%r10d\n\t"
|
|
||||||
"syscall"
|
|
||||||
: "=a"(ax), "=d"(dx)
|
|
||||||
: "0"(__NR_sigprocmask), "D"(SIG_SETMASK), "S"(save), "1"(0L)
|
|
||||||
: "rcx", "r8", "r9", "r10", "r11", "memory", "cc");
|
|
||||||
if (ax) notpossible;
|
|
||||||
}
|
|
||||||
#elif defined(__aarch64__)
|
|
||||||
__aarch64_sigprocmask(SIG_SETMASK, save, 0);
|
|
||||||
#else
|
|
||||||
#error "unsupported architecture"
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,8 +100,14 @@ static struct SymbolTable *OpenSymbolTableImpl(const char *filename) {
|
||||||
for (j = i = 0; i < m; ++i) {
|
for (j = i = 0; i < m; ++i) {
|
||||||
sym = symtab + (stp[i] & 0x7fffffff);
|
sym = symtab + (stp[i] & 0x7fffffff);
|
||||||
x = stp[i] >> 32;
|
x = stp[i] >> 32;
|
||||||
if (j && x == t->symbols[j - 1].x) --j;
|
if (j && x == t->symbols[j - 1].x) {
|
||||||
if (j && t->symbols[j - 1].y >= x) t->symbols[j - 1].y = x - 1;
|
// when two symbols have an identical address value, favor the
|
||||||
|
// symbol that was defined earlier in the elf data structures.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (j && t->symbols[j - 1].y >= x) {
|
||||||
|
t->symbols[j - 1].y = x - 1;
|
||||||
|
}
|
||||||
t->names[j] = sym->st_name;
|
t->names[j] = sym->st_name;
|
||||||
t->symbols[j].x = x;
|
t->symbols[j].x = x;
|
||||||
if (sym->st_size) {
|
if (sym->st_size) {
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
|
#include "libc/thread/tls.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Global variable for last error.
|
* Global variable for last error.
|
||||||
|
@ -31,3 +32,14 @@
|
||||||
* @see __errno_location() stable abi
|
* @see __errno_location() stable abi
|
||||||
*/
|
*/
|
||||||
errno_t __errno;
|
errno_t __errno;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns address of `errno` variable.
|
||||||
|
*/
|
||||||
|
errno_t *__errno_location(void) {
|
||||||
|
if (__tls_enabled) {
|
||||||
|
return &__get_tls()->tib_errno;
|
||||||
|
} else {
|
||||||
|
return &__errno;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
|
||||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
|
||||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
|
||||||
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
|
||||||
│ │
|
|
||||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
|
||||||
│ any purpose with or without fee is hereby granted, provided that the │
|
|
||||||
│ above copyright notice and this permission notice appear in all copies. │
|
|
||||||
│ │
|
|
||||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
|
||||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
|
||||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
|
||||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
|
||||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
|
||||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
|
||||||
#include "libc/thread/tls2.h"
|
|
||||||
|
|
||||||
extern errno_t __errno;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns address of errno variable.
|
|
||||||
*/
|
|
||||||
nocallersavedregisters errno_t *(__errno_location)(void) {
|
|
||||||
if (!__tls_enabled) return &__errno;
|
|
||||||
return &__get_tls_privileged()->tib_errno;
|
|
||||||
}
|
|
|
@ -40,7 +40,6 @@ LIBC_SYSV_A_FILES := \
|
||||||
libc/sysv/restorert.S \
|
libc/sysv/restorert.S \
|
||||||
libc/sysv/syscall.S \
|
libc/sysv/syscall.S \
|
||||||
libc/sysv/systemfive.S \
|
libc/sysv/systemfive.S \
|
||||||
libc/sysv/errno_location.greg.c \
|
|
||||||
libc/sysv/sysret.c \
|
libc/sysv/sysret.c \
|
||||||
libc/sysv/errno.c \
|
libc/sysv/errno.c \
|
||||||
libc/sysv/errfun.S \
|
libc/sysv/errfun.S \
|
||||||
|
|
Loading…
Reference in a new issue