Make improvements

- Implement openpty()
- Add `--assimilate` flag to APE bootloader
- Restore Linux vDSO clock_gettime() support
- Use `$(APE_NO_MODIFY_SELF)` on more programs
This commit is contained in:
Justine Tunney 2022-05-24 10:19:39 -07:00
parent cef50f2a6b
commit d44ff6ce1f
33 changed files with 600 additions and 251 deletions

View file

@ -0,0 +1,30 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 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/macros.internal.h"
.initbss 201,_init___clock_gettime
__clock_gettime:
.quad 0
.endobj __clock_gettime,globl,hidden
.previous
.init.start 201,_init___clock_gettime
ezlea __clock_gettime_init,ax
stosq
.init.end 201,_init___clock_gettime

View file

@ -0,0 +1,19 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_ASAN_INTERNAL_H_
#define COSMOPOLITAN_LIBC_CALLS_ASAN_INTERNAL_H_
#include "libc/bits/asmflag.h"
#include "libc/calls/struct/timespec.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
forceinline bool __asan_is_valid_timespec(const struct timespec *ts) {
bool zf;
asm(ZFLAG_ASM("cmpw\t$0,0x7fff8000(%1)")
: ZFLAG_CONSTRAINT(zf)
: "r"((intptr_t)ts >> 3)
: "memory");
return zf;
}
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_CALLS_ASAN_INTERNAL_H_ */

View file

@ -27,6 +27,7 @@ textwindows int sys_clock_gettime_nt(int clockid, struct timespec *ts) {
struct timespec res;
struct NtFileTime ft;
static struct timespec mono;
if (!ts) return efault();
if (clockid == CLOCK_REALTIME) {
GetSystemTimeAsFileTime(&ft);
*ts = FileTimeToTimeSpec(ft);

View file

@ -0,0 +1,35 @@
/*-*- 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/calls/calls.h"
#include "libc/calls/internal.h"
int sys_clock_gettime_xnu(int clockid, struct timespec *ts) {
axdx_t ad;
ad = sys_gettimeofday((struct timeval *)ts, NULL, NULL);
if (ad.ax != -1) {
if (ad.ax) {
ts->tv_sec = ad.ax;
ts->tv_nsec = ad.dx;
}
ts->tv_nsec *= 1000;
return 0;
} else {
return -1;
}
}

View file

@ -17,6 +17,10 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/bits/asmflag.h"
#include "libc/bits/bits.h"
#include "libc/calls/asan.internal.h"
#include "libc/calls/clock_gettime.h"
#include "libc/calls/internal.h"
#include "libc/calls/state.internal.h"
#include "libc/calls/strace.internal.h"
@ -26,11 +30,10 @@
#include "libc/fmt/conv.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/mem/alloca.h"
#include "libc/nt/synchronization.h"
#include "libc/sysv/errfuns.h"
static typeof(sys_clock_gettime) *__clock_gettime = sys_clock_gettime;
/**
* Returns nanosecond time.
*
@ -38,6 +41,13 @@ static typeof(sys_clock_gettime) *__clock_gettime = sys_clock_gettime;
* time. Among the more popular is CLOCK_MONOTONIC. This function has a
* zero syscall implementation of that on modern x86.
*
* nowl l: 45𝑐 15𝑛𝑠
* rdtsc l: 13𝑐 4𝑛𝑠
* gettimeofday l: 44𝑐 14𝑛𝑠
* clock_gettime l: 40𝑐 13𝑛𝑠
* __clock_gettime l: 35𝑐 11𝑛𝑠
* sys_clock_gettime l: 220𝑐 71𝑛𝑠
*
* @param clockid can be CLOCK_REALTIME, CLOCK_MONOTONIC, etc.
* @param ts is where the result is stored
* @return 0 on success, or -1 w/ errno
@ -46,54 +56,49 @@ static typeof(sys_clock_gettime) *__clock_gettime = sys_clock_gettime;
* @asyncsignalsafe
*/
noinstrument int clock_gettime(int clockid, struct timespec *ts) {
int rc, e;
axdx_t ad;
char buf[45];
if (!ts) {
int rc;
char *buf;
if (IsAsan() && !__asan_is_valid_timespec(ts)) {
rc = efault();
} else if (IsAsan() && !__asan_is_valid(ts, sizeof(*ts))) {
rc = efault();
} else if (clockid == -1) {
rc = einval();
} else if (!IsWindows()) {
e = errno;
if ((rc = __clock_gettime(clockid, ts))) {
errno = e;
ad = sys_gettimeofday((struct timeval *)ts, NULL, NULL);
assert(ad.ax != -1);
if (SupportsXnu() && ad.ax) {
ts->tv_sec = ad.ax;
ts->tv_nsec = ad.dx;
}
ts->tv_nsec *= 1000;
rc = 0;
}
} else {
rc = sys_clock_gettime_nt(clockid, ts);
rc = __clock_gettime(clockid, ts);
}
#if SYSDEBUG
if (!__time_critical) {
buf = alloca(45);
STRACE("clock_gettime(%d, [%s]) → %d% m", clockid,
DescribeTimespec(buf, sizeof(buf), rc, ts), rc);
DescribeTimespec(buf, 45, rc, ts), rc);
}
#endif
return rc;
}
/**
* Returns fast system clock_gettime() if it exists.
* Returns pointer to fastest clock_gettime().
*/
void *__get_clock_gettime(void) {
void *vdso;
static bool once;
static void *result;
if (!once) {
if ((vdso = __vdsofunc("__vdso_clock_gettime"))) {
__clock_gettime = result = vdso;
}
once = true;
clock_gettime_f *__get_clock_gettime(bool *opt_out_isfast) {
bool isfast;
clock_gettime_f *res;
if (IsLinux() && (res = __vdsosym("LINUX_2.6", "__vdso_clock_gettime"))) {
isfast = true;
} else if (IsXnu()) {
isfast = false;
res = sys_clock_gettime_xnu;
} else if (IsWindows()) {
isfast = true;
res = sys_clock_gettime_nt;
} else {
isfast = false;
res = sys_clock_gettime;
}
return result;
if (opt_out_isfast) {
*opt_out_isfast = isfast;
}
return res;
}
const void *const __clock_gettime_ctor[] initarray = {
__get_clock_gettime,
};
hidden int __clock_gettime_init(int clockid, struct timespec *ts) {
clock_gettime_f *gettime;
__clock_gettime = gettime = __get_clock_gettime(0);
return gettime(clockid, ts);
}

View file

@ -0,0 +1,15 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_CLOCK_GETTIME_H_
#define COSMOPOLITAN_LIBC_CALLS_CLOCK_GETTIME_H_
#include "libc/calls/struct/timespec.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
typedef int clock_gettime_f(int, struct timespec *);
extern clock_gettime_f *__clock_gettime;
hidden clock_gettime_f __clock_gettime_init;
hidden clock_gettime_f *__get_clock_gettime(bool *);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_CALLS_CLOCK_GETTIME_H_ */

View file

@ -59,7 +59,7 @@ int gettimeofday(struct timeval *tv, struct timezone *tz) {
static textstartup void __gettimeofday_init(void) {
void *vdso;
if ((vdso = __vdsofunc("__vdso_gettimeofday"))) {
if ((vdso = __vdsosym("LINUX_2.6", "__vdso_gettimeofday"))) {
__gettimeofday = vdso;
}
}

View file

@ -118,6 +118,7 @@ i32 __sys_sigprocmask(i32, const sigset *, sigset *, u64) hidden;
i32 __sys_utimensat(i32, const char *, const struct timespec *, i32) hidden;
i32 __sys_wait4(i32, i32 *, i32, struct rusage *) hidden;
i32 sys_clock_gettime(i32, struct timespec *) hidden;
i32 sys_clock_gettime_xnu(i32, struct timespec *) hidden;
i32 sys_fstat(i32, struct stat *) hidden;
i32 sys_fstatat(i32, const char *, struct stat *, i32) hidden;
i32 sys_futimes(i32, const struct timeval *) hidden;

View file

@ -83,7 +83,7 @@ noasan textreal uint64_t *__get_virtual(struct mman *mm, uint64_t *t,
/**
* Sorts, rounds, and filters BIOS memory map.
*/
static noasan texthead void __normalize_e820(struct mman *mm) {
static noasan textreal void __normalize_e820(struct mman *mm) {
uint64_t a, b;
uint64_t x, y;
unsigned i, j, n;
@ -113,7 +113,7 @@ static noasan texthead void __normalize_e820(struct mman *mm) {
/**
* Identity maps all usable physical memory to its negative address.
*/
static noasan texthead void __invert_memory(struct mman *mm, uint64_t *pml4t) {
static noasan textreal void __invert_memory(struct mman *mm, uint64_t *pml4t) {
uint64_t i, j, *m, p, pe;
for (i = 0; i < mm->e820n; ++i) {
for (p = mm->e820[i].addr, pe = mm->e820[i].addr + mm->e820[i].size;
@ -126,7 +126,7 @@ static noasan texthead void __invert_memory(struct mman *mm, uint64_t *pml4t) {
}
}
noasan texthead void __setup_mman(struct mman *mm, uint64_t *pml4t) {
noasan textreal void __setup_mman(struct mman *mm, uint64_t *pml4t) {
__normalize_e820(mm);
__invert_memory(mm, pml4t);
}

View file

@ -16,6 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/asan.internal.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/state.internal.h"
@ -31,7 +32,8 @@
noinstrument int nanosleep(const struct timespec *req, struct timespec *rem) {
int rc;
char buf[2][45];
if (!req) {
if (!req || (IsAsan() && (!__asan_is_valid_timespec(req) ||
(rem && !__asan_is_valid_timespec(rem))))) {
rc = efault();
} else if (req->tv_sec < 0 ||
!(0 <= req->tv_nsec && req->tv_nsec <= 999999999)) {

View file

@ -20,6 +20,7 @@
#include "libc/bits/initializer.internal.h"
#include "libc/bits/safemacros.internal.h"
#include "libc/calls/calls.h"
#include "libc/calls/clock_gettime.h"
#include "libc/calls/internal.h"
#include "libc/calls/state.internal.h"
#include "libc/calls/strace.internal.h"
@ -32,10 +33,11 @@
#include "libc/sysv/consts/clock.h"
#include "libc/time/time.h"
static clock_gettime_f *__gettime;
static struct Now {
uint64_t k0;
long double r0, cpn;
typeof(sys_clock_gettime) *clock_gettime;
} g_now;
static long double GetTimeSample(void) {
@ -90,7 +92,7 @@ static long double nowl_art(void) {
static long double nowl_vdso(void) {
long double secs;
struct timespec tv;
g_now.clock_gettime(CLOCK_REALTIME, &tv);
__gettime(CLOCK_REALTIME, &tv);
secs = tv.tv_nsec;
secs *= 1 / 1e9L;
secs += tv.tv_sec;
@ -98,9 +100,10 @@ static long double nowl_vdso(void) {
}
long double nowl_setup(void) {
bool isfast;
uint64_t ticks;
if (0 && (g_now.clock_gettime = __get_clock_gettime())) {
// TODO(jart): Re-enable this.
__gettime = __get_clock_gettime(&isfast);
if (isfast) {
nowl = nowl_vdso;
} else if (X86_HAVE(INVTSC)) {
RefreshTime();

View file

@ -17,33 +17,44 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/calls/ioctl.h"
#include "libc/calls/termios.h"
#include "libc/fmt/itoa.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/pty.h"
#include "libc/sysv/consts/termios.h"
#include "libc/sysv/errfuns.h"
/**
* Opens new pseudo teletypewriter.
*
* @param ilduce receives controlling tty rw fd on success
* @param aworker receives subordinate tty rw fd on success
* @param termp may be passed to tune a century of legacy behaviors
* @param winp may be passed to set terminal display dimensions
* @param mfd receives controlling tty rw fd on success
* @param sfd receives subordinate tty rw fd on success
* @param tio may be passed to tune a century of legacy behaviors
* @param wsz may be passed to set terminal display dimensions
* @params flags is usually O_RDWR|O_NOCTTY
* @return file descriptor, or -1 w/ errno
* @return 0 on success, or -1 w/ errno
*/
int openpty(int *ilduce, int *aworker, char *name, const struct termios *termp,
const struct winsize *winp) {
return enosys();
/* TODO(jart) */
/* int fd, flags; */
/* flags = O_RDWR | O_NOCTTY; */
/* if ((fd = posix_openpt(flags)) != -1) { */
/* if (ioctl(m, TIOCSPTLCK, &n) || ioctl(m, TIOCGPTN, &n)) { */
/* } else { */
/* close(fd); */
/* } */
/* } else { */
/* return -1; */
/* } */
int openpty(int *mfd, int *sfd, char *name, const struct termios *tio,
const struct winsize *wsz) {
int m, s, n;
char buf[20];
if ((m = open("/dev/ptmx", O_RDWR | O_NOCTTY)) != -1) {
n = 0;
if (!ioctl(m, TIOCSPTLCK, &n) || !ioctl(m, TIOCGPTN, &n)) {
if (!name) name = buf;
name[0] = '/', name[1] = 'd', name[2] = 'e', name[3] = 'v';
name[4] = '/', name[5] = 'p', name[6] = 't', name[7] = 's';
name[8] = '/', FormatInt32(name + 9, n);
if ((s = open(name, O_RDWR | O_NOCTTY)) != -1) {
if (tio) ioctl(s, TCSETS, tio);
if (wsz) ioctl(s, TIOCSWINSZ, wsz);
*mfd = m;
*sfd = s;
return 0;
}
}
close(m);
}
return -1;
}

View file

@ -12,8 +12,7 @@ int __notziposat(int, const char *);
int gethostname_bsd(char *, size_t) hidden;
int gethostname_linux(char *, size_t) hidden;
int gethostname_nt(char *, size_t, int) hidden;
void *__get_clock_gettime(void) hidden;
void *__vdsofunc(const char *) hidden;
void *__vdsosym(const char *, const char *) hidden;
void __onfork(void) hidden;
void __restore_rt() hidden;
void __restore_rt_netbsd(void) hidden;

View file

@ -17,6 +17,7 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/bits/weaken.h"
#include "libc/calls/asan.internal.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
@ -39,7 +40,8 @@ int utimensat(int dirfd, const char *path, const struct timespec ts[2],
int rc;
char buf[12];
if (IsAsan() && (!__asan_is_valid(path, 1) ||
(ts && !__asan_is_valid(ts, sizeof(struct timespec) * 2)))) {
(ts && (!__asan_is_valid_timespec(ts + 0) ||
!__asan_is_valid_timespec(ts + 1))))) {
rc = efault();
} else if (weaken(__zipos_notat) && (rc = __zipos_notat(dirfd, path)) == -1) {
STRACE("zipos mkdirat not supported yet");

View file

@ -18,76 +18,136 @@
*/
#include "libc/bits/bits.h"
#include "libc/calls/calls.h"
#include "libc/calls/strace.internal.h"
#include "libc/elf/scalar.h"
#include "libc/elf/struct/ehdr.h"
#include "libc/elf/struct/phdr.h"
#include "libc/elf/struct/shdr.h"
#include "libc/elf/struct/sym.h"
#include "libc/log/libfatal.internal.h"
#include "libc/elf/struct/verdaux.h"
#include "libc/elf/struct/verdef.h"
#include "libc/intrin/kprintf.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/consts/auxv.h"
#define LAZY_RHEL7_RELOCATION 0xfffff
#define GetStr(tab, rva) ((char *)(tab) + (rva))
#define GetSection(e, s) ((void *)((intptr_t)(e) + (size_t)(s)->sh_offset))
#define GetShstrtab(e) GetSection(e, GetShdr(e, (e)->e_shstrndx))
#define GetSectionName(e, s) GetStr(GetShstrtab(e), (s)->sh_name)
#define GetPhdr(e, i) \
((Elf64_Phdr *)((intptr_t)(e) + (e)->e_phoff + \
(size_t)(e)->e_phentsize * (i)))
#define GetShdr(e, i) \
((Elf64_Shdr *)((intptr_t)(e) + (e)->e_shoff + \
(size_t)(e)->e_shentsize * (i)))
static char *GetDynamicStringTable(Elf64_Ehdr *e, size_t *n) {
char *name;
Elf64_Half i;
Elf64_Shdr *shdr;
for (i = 0; i < e->e_shnum; ++i) {
shdr = GetShdr(e, i);
name = GetSectionName(e, GetShdr(e, i));
if (shdr->sh_type == SHT_STRTAB) {
name = GetSectionName(e, GetShdr(e, i));
if (name && READ64LE(name) == READ64LE(".dynstr")) {
if (n) *n = shdr->sh_size;
return GetSection(e, shdr);
}
}
}
return 0;
static inline int CompareStrings(const char *l, const char *r) {
size_t i = 0;
while (l[i] == r[i] && r[i]) ++i;
return (l[i] & 255) - (r[i] & 255);
}
static Elf64_Sym *GetDynamicSymbolTable(Elf64_Ehdr *e, Elf64_Xword *n) {
Elf64_Half i;
Elf64_Shdr *shdr;
for (i = e->e_shnum; i > 0; --i) {
shdr = GetShdr(e, i - 1);
if (shdr->sh_type == SHT_DYNSYM) {
if (shdr->sh_entsize != sizeof(Elf64_Sym)) continue;
if (n) *n = shdr->sh_size / shdr->sh_entsize;
return GetSection(e, shdr);
static inline int CheckDsoSymbolVersion(Elf64_Verdef *vd, int sym,
const char *name, char *strtab) {
Elf64_Verdaux *aux;
for (;; vd = (Elf64_Verdef *)((char *)vd + vd->vd_next)) {
if (!(vd->vd_flags & VER_FLG_BASE) &&
(vd->vd_ndx & 0x7fff) == (sym & 0x7fff)) {
aux = (Elf64_Verdaux *)((char *)vd + vd->vd_aux);
return !CompareStrings(name, strtab + aux->vda_name);
}
if (!vd->vd_next) {
return 0;
}
}
return 0;
}
/**
* Returns Linux Kernel Virtual Dynamic Shared Object function address.
* Returns address of vDSO function.
*/
void *__vdsofunc(const char *name) {
size_t m;
char *names;
void *__vdsosym(const char *version, const char *name) {
void *p;
size_t i;
Elf64_Ehdr *ehdr;
Elf64_Xword i, n;
Elf64_Sym *symtab, *sym;
if ((ehdr = (Elf64_Ehdr *)getauxval(AT_SYSINFO_EHDR)) &&
(names = GetDynamicStringTable(ehdr, &m)) &&
(symtab = GetDynamicSymbolTable(ehdr, &n))) {
for (i = 0; i < n; ++i) {
if (!__strcmp(names + symtab[i].st_name, name)) {
return (char *)ehdr + (symtab[i].st_value & LAZY_RHEL7_RELOCATION);
}
Elf64_Phdr *phdr;
char *strtab = 0;
size_t *dyn, base;
unsigned long *ap;
Elf64_Sym *symtab = 0;
uint16_t *versym = 0;
Elf_Symndx *hashtab = 0;
Elf64_Verdef *verdef = 0;
for (ehdr = 0, ap = __auxv; ap[0]; ap += 2) {
if (ap[0] == AT_SYSINFO_EHDR) {
ehdr = (void *)ap[1];
break;
}
}
if (!ehdr || READ32LE(ehdr->e_ident) != READ32LE("\177ELF")) {
KERNTRACE("__vdsosym() → AT_SYSINFO_EHDR ELF not found");
return 0;
}
phdr = (void *)((char *)ehdr + ehdr->e_phoff);
for (base = -1, dyn = 0, i = 0; i < ehdr->e_phnum;
i++, phdr = (void *)((char *)phdr + ehdr->e_phentsize)) {
switch (phdr->p_type) {
case PT_LOAD:
// modern linux uses the base address zero, but elders
// e.g. rhel7 uses the base address 0xffffffffff700000
base = (size_t)ehdr + phdr->p_offset - phdr->p_vaddr;
break;
case PT_DYNAMIC:
dyn = (void *)((char *)ehdr + phdr->p_offset);
break;
default:
break;
}
}
if (!dyn || base == -1) {
KERNTRACE("__vdsosym() → missing program headers");
return 0;
}
for (i = 0; dyn[i]; i += 2) {
p = (void *)(base + dyn[i + 1]);
switch (dyn[i]) {
case DT_STRTAB:
strtab = p;
break;
case DT_SYMTAB:
symtab = p;
break;
case DT_HASH:
hashtab = p;
break;
case DT_VERSYM:
versym = p;
break;
case DT_VERDEF:
verdef = p;
break;
}
}
if (!strtab || !symtab || !hashtab) {
KERNTRACE("__vdsosym() → tables not found");
return 0;
}
if (!verdef) {
versym = 0;
}
for (i = 0; i < hashtab[1]; i++) {
if (ELF64_ST_TYPE(symtab[i].st_info) != STT_FUNC &&
ELF64_ST_TYPE(symtab[i].st_info) != STT_OBJECT &&
ELF64_ST_TYPE(symtab[i].st_info) != STT_NOTYPE) {
continue;
}
if (ELF64_ST_BIND(symtab[i].st_info) != STB_GLOBAL) {
continue;
}
if (!symtab[i].st_shndx) {
continue;
}
if (CompareStrings(name, strtab + symtab[i].st_name)) {
continue;
}
if (versym && !CheckDsoSymbolVersion(verdef, versym[i], version, strtab)) {
continue;
}
return (void *)(base + symtab[i].st_value);
}
KERNTRACE("__vdsosym() → symbol not found");
return 0;
}

View file

@ -17,12 +17,16 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/elf/elf.h"
#include "libc/intrin/kprintf.h"
#include "libc/runtime/runtime.h"
void CheckElfAddress(const Elf64_Ehdr *elf, size_t mapsize, intptr_t addr,
size_t addrsize) {
#if !(TRUSTWORTHY + ELF_TRUSTWORTHY + 0) || ELF_UNTRUSTWORTHY + 0
if (addr < (intptr_t)elf || addr + addrsize > (intptr_t)elf + mapsize) {
/* kprintf("%p-%p falls outside interval %p-%p", // */
/* addr, addr + addrsize, // */
/* elf, (char *)elf + mapsize); // */
abort();
}
#endif

View file

@ -2,15 +2,16 @@
#define COSMOPOLITAN_LIBC_ELF_SCALAR_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
#define Elf64_Half uint16_t
#define Elf64_Word uint32_t
#define Elf64_Sword int32_t
#define Elf64_Xword uint64_t
#define Elf64_Sxword int64_t
#define Elf64_Addr uint64_t
#define Elf64_Off uint64_t
#define Elf64_Addr uint64_t
#define Elf64_Half uint16_t
#define Elf64_Off uint64_t
#define Elf64_Section uint16_t
#define Elf64_Versym Elf64_Half
#define Elf64_Sword int32_t
#define Elf64_Sxword int64_t
#define Elf64_Versym Elf64_Half
#define Elf64_Word uint32_t
#define Elf64_Xword uint64_t
#define Elf_Symndx uint32_t
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_ELF_SCALAR_H_ */

View file

@ -1323,7 +1323,6 @@ syscon termios TIOCSETD 0x5423 0x8004741b 0x8004741b 0x8004741b 0x800474
syscon termios TIOCSIG 0x40045436 0x2000745f 0x2004745f 0x8004745f 0x8004745f 0 # boop
syscon termios TIOCSPGRP 0x5410 0x80047476 0x80047476 0x80047476 0x80047476 0 # boop
syscon termios TIOCSTI 0x5412 0x80017472 0x80017472 0 0 0 # boop
syscon termios TIOCGPTN 0x80045430 0 0x4004740f 0 0 0 # boop
syscon termios TIOCGSID 0x5429 0x40047463 0x40047463 0x40047463 0x40047463 0 # boop
syscon termios TABLDISC 0 0x3 0 0x3 0x3 0 # boop
syscon termios SLIPDISC 0 0x4 0x4 0x4 0x4 0 # boop
@ -1508,6 +1507,8 @@ syscon termios CSTOP 19 19 19 19 19 0 # unix consensus
# Pseudoteletypewriter Control
#
# group name GNU/Systemd XNU's Not UNIX! FreeBSD OpenBSD NetBSD The New Technology Commentary
syscon pty TIOCGPTN 0x80045430 0 0x4004740f 0 0 0 # boop
syscon pty TIOCSPTLCK 0x40045431 0 0 0 0 0 # boop
syscon pty TIOCPKT 0x5420 0x80047470 0x80047470 0x80047470 0x80047470 -1 # boop
syscon pty TIOCPKT_DATA 0 0 0 0 0 0 # consensus
syscon pty TIOCPKT_FLUSHREAD 1 1 1 1 1 1 # unix consensus
@ -1517,7 +1518,6 @@ syscon pty TIOCPKT_START 8 8 8 8 8 8 # unix consensus
syscon pty TIOCPKT_NOSTOP 16 16 16 16 16 16 # unix consensus
syscon pty TIOCPKT_DOSTOP 32 32 32 32 32 32 # unix consensus
syscon pty TIOCPKT_IOCTL 64 64 64 64 64 64 # unix consensus
syscon pty TIOCSPTLCK 0x40045431 0 0 0 0 -1 # boop
syscon pty PTMGET 0 0 0 0x40287401 0x40287401 -1 # for /dev/ptm
# Modem Control

View file

@ -154,11 +154,14 @@ intptr_t erfkill(void) relegated;
intptr_t ehwpoison(void) relegated;
#if defined(__MNO_RED_ZONE__) && defined(__GNUC__) && !defined(__STRICT_ANSI__)
#define __ERRFUN(FUNC) \
({ \
intptr_t NegOne; \
asm("call\t" FUNC : "=a"(NegOne), "=m"(errno)); \
NegOne; \
#define __ERRFUN(FUNC) \
({ \
intptr_t NegOne; \
asm volatile("call\t" FUNC \
: "=a"(NegOne) \
: /* no outputs */ \
: "rcx", "memory"); \
NegOne; \
})
#define einval() __ERRFUN("einval")
#define eperm() __ERRFUN("eperm")