mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-26 04:20:30 +00:00
Make improvements
- Introduce portable sched_getcpu() api - Support GCC's __target_clones__ feature - Make fma() go faster on x86 in default mode - Remove some asan checks from core libraries - WinMain() now ensures $HOME and $USER are defined
This commit is contained in:
parent
d5225a693b
commit
2ab9e9f7fd
192 changed files with 2809 additions and 932 deletions
|
@ -226,65 +226,6 @@ const char *const kSafeEnv[] = {
|
|||
"SYSTEMROOT", // needed by socket()
|
||||
};
|
||||
|
||||
const char *const kGccOnlyFlags[] = {
|
||||
"--nocompress-debug-sections",
|
||||
"--noexecstack",
|
||||
"-Wa,--nocompress-debug-sections",
|
||||
"-Wa,--noexecstack",
|
||||
"-Wa,-msse2avx",
|
||||
"-Wno-unused-but-set-variable",
|
||||
"-Wunsafe-loop-optimizations",
|
||||
"-fbranch-target-load-optimize",
|
||||
"-fcx-limited-range",
|
||||
"-fdelete-dead-exceptions",
|
||||
"-femit-struct-debug-baseonly",
|
||||
"-ffp-int-builtin-inexact",
|
||||
"-finline-functions-called-once",
|
||||
"-fipa-pta",
|
||||
"-fivopts",
|
||||
"-flimit-function-alignment",
|
||||
"-fmerge-constants",
|
||||
"-fmodulo-sched",
|
||||
"-fmodulo-sched-allow-regmoves",
|
||||
"-fno-align-jumps",
|
||||
"-fno-align-labels",
|
||||
"-fno-align-loops",
|
||||
"-fno-cx-limited-range",
|
||||
"-fno-fp-int-builtin-inexact",
|
||||
"-fno-gnu-unique",
|
||||
"-fno-gnu-unique",
|
||||
"-fno-inline-functions-called-once",
|
||||
"-fno-instrument-functions",
|
||||
"-fno-schedule-insns2",
|
||||
"-fno-whole-program",
|
||||
"-fopt-info-vec",
|
||||
"-fopt-info-vec-missed",
|
||||
"-freg-struct-return",
|
||||
"-freschedule-modulo-scheduled-loops",
|
||||
"-frounding-math",
|
||||
"-fsched2-use-superblocks",
|
||||
"-fschedule-insns",
|
||||
"-fschedule-insns2",
|
||||
"-fshrink-wrap",
|
||||
"-fshrink-wrap-separate",
|
||||
"-fsignaling-nans",
|
||||
"-fstack-clash-protection",
|
||||
"-ftracer",
|
||||
"-ftrapv",
|
||||
"-ftree-loop-im",
|
||||
"-ftree-loop-vectorize",
|
||||
"-funsafe-loop-optimizations",
|
||||
"-fversion-loops-for-strides",
|
||||
"-fwhole-program",
|
||||
"-gdescribe-dies",
|
||||
"-gstabs",
|
||||
"-mcall-ms2sysv-xlogues",
|
||||
"-mdispatch-scheduler",
|
||||
"-mfpmath=sse+387",
|
||||
"-mmitigate-rop",
|
||||
"-mno-fentry",
|
||||
};
|
||||
|
||||
void OnAlrm(int sig) {
|
||||
++gotalrm;
|
||||
}
|
||||
|
@ -400,21 +341,38 @@ bool IsSafeEnv(const char *s) {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool IsGccOnlyFlag(const char *s) {
|
||||
int m, l, r, x;
|
||||
l = 0;
|
||||
r = ARRAYLEN(kGccOnlyFlags) - 1;
|
||||
while (l <= r) {
|
||||
m = (l & r) + ((l ^ r) >> 1); // floor((a+b)/2)
|
||||
x = strcmp(s, kGccOnlyFlags[m]);
|
||||
if (x < 0) {
|
||||
r = m - 1;
|
||||
} else if (x > 0) {
|
||||
l = m + 1;
|
||||
} else {
|
||||
return true;
|
||||
char *Slurp(const char *path) {
|
||||
int fd;
|
||||
char *res = 0;
|
||||
if ((fd = open(path, O_RDONLY)) != -1) {
|
||||
ssize_t size;
|
||||
if ((size = lseek(fd, 0, SEEK_END)) != -1) {
|
||||
char *buf;
|
||||
if ((buf = calloc(1, size + 1))) {
|
||||
if (pread(fd, buf, size, 0) == size) {
|
||||
res = buf;
|
||||
} else {
|
||||
free(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
bool HasFlag(const char *flags, const char *s) {
|
||||
char buf[256];
|
||||
size_t n = strlen(s);
|
||||
if (!flags) return false;
|
||||
if (n + 2 > sizeof(buf)) return false;
|
||||
memcpy(buf, s, n);
|
||||
buf[n] = '\n';
|
||||
buf[n + 1] = 0;
|
||||
return !!strstr(flags, buf);
|
||||
}
|
||||
|
||||
bool IsGccOnlyFlag(const char *s) {
|
||||
if (s[0] == '-') {
|
||||
if (s[1] == 'f') {
|
||||
if (startswith(s, "-ffixed-")) return true;
|
||||
|
@ -428,8 +386,25 @@ bool IsGccOnlyFlag(const char *s) {
|
|||
if (startswith(s, "-mstringop-strategy=")) return true;
|
||||
if (startswith(s, "-mpreferred-stack-boundary=")) return true;
|
||||
if (startswith(s, "-Wframe-larger-than=")) return true;
|
||||
if (startswith(s, "-Walloca-larger-than=")) return true;
|
||||
}
|
||||
return false;
|
||||
static bool once;
|
||||
static char *gcc_only_flags;
|
||||
if (!once) {
|
||||
gcc_only_flags = Slurp("build/bootstrap/gcc-only-flags.txt");
|
||||
once = true;
|
||||
}
|
||||
return HasFlag(gcc_only_flags, s);
|
||||
}
|
||||
|
||||
bool IsClangOnlyFlag(const char *s) {
|
||||
static bool once;
|
||||
static char *clang_only_flags;
|
||||
if (!once) {
|
||||
clang_only_flags = Slurp("build/bootstrap/clang-only-flags.txt");
|
||||
once = true;
|
||||
}
|
||||
return HasFlag(clang_only_flags, s);
|
||||
}
|
||||
|
||||
bool FileExistsAndIsNewerThan(const char *filepath, const char *thanpath) {
|
||||
|
@ -926,12 +901,12 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
|
||||
s = basename(strdup(cmd));
|
||||
if (strstr(s, "gcc") || strstr(s, "g++")) {
|
||||
iscc = true;
|
||||
isgcc = true;
|
||||
} else if (strstr(s, "clang") || strstr(s, "clang++")) {
|
||||
if (strstr(s, "clang") || strstr(s, "clang++")) {
|
||||
iscc = true;
|
||||
isclang = true;
|
||||
} else if (strstr(s, "gcc") || strstr(s, "g++")) {
|
||||
iscc = true;
|
||||
isgcc = true;
|
||||
} else if (strstr(s, "ld.bfd")) {
|
||||
isbfd = true;
|
||||
} else if (strstr(s, "ar.com")) {
|
||||
|
@ -990,6 +965,9 @@ int main(int argc, char *argv[]) {
|
|||
AddArg(argv[i]);
|
||||
continue;
|
||||
}
|
||||
if (isgcc && IsClangOnlyFlag(argv[i])) {
|
||||
continue;
|
||||
}
|
||||
if (isclang && IsGccOnlyFlag(argv[i])) {
|
||||
continue;
|
||||
}
|
||||
|
@ -1188,7 +1166,9 @@ int main(int argc, char *argv[]) {
|
|||
!strcmp(argv[i], "-O3"))) {
|
||||
/* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97623 */
|
||||
AddArg(argv[i]);
|
||||
AddArg("-fno-code-hoisting");
|
||||
if (!isclang) {
|
||||
AddArg("-fno-code-hoisting");
|
||||
}
|
||||
} else {
|
||||
AddArg(argv[i]);
|
||||
}
|
||||
|
|
64
tool/build/findape.c
Normal file
64
tool/build/findape.c
Normal file
|
@ -0,0 +1,64 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2023 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/runtime/runtime.h"
|
||||
#include "libc/serialize.h"
|
||||
#include "libc/stdio/ftw.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
|
||||
// finds ape executables
|
||||
// usage: findelf PATH...
|
||||
|
||||
static int OnFile(const char *fpath, const struct stat *st, int typeflag,
|
||||
struct FTW *ftwbuf) {
|
||||
if (typeflag == FTW_F) {
|
||||
char buf[8] = {0};
|
||||
int fd = open(fpath, O_RDONLY);
|
||||
if (fd != -1) {
|
||||
pread(fd, buf, sizeof(buf), 0);
|
||||
close(fd);
|
||||
if (READ64LE(buf) == READ64LE("MZqFpD='") ||
|
||||
READ64LE(buf) == READ64LE("jartsr='") ||
|
||||
READ64LE(buf) == READ64LE("APEDBG='")) {
|
||||
tinyprint(1, fpath, "\n", NULL);
|
||||
}
|
||||
} else {
|
||||
perror(fpath);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void HandleArg(const char *path) {
|
||||
if (nftw(path, OnFile, 128, FTW_PHYS | FTW_DEPTH)) {
|
||||
perror(path);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc <= 1) {
|
||||
HandleArg(".");
|
||||
} else {
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
HandleArg(argv[i]);
|
||||
}
|
||||
}
|
||||
}
|
65
tool/build/findelf.c
Normal file
65
tool/build/findelf.c
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2023 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/elf/def.h"
|
||||
#include "libc/elf/struct/ehdr.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/serialize.h"
|
||||
#include "libc/stdio/ftw.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
|
||||
// finds elf executables
|
||||
// usage: findelf PATH...
|
||||
|
||||
static int OnFile(const char *fpath, const struct stat *st, int typeflag,
|
||||
struct FTW *ftwbuf) {
|
||||
if (typeflag == FTW_F && (st->st_mode & 0111)) {
|
||||
Elf64_Ehdr ehdr = {0};
|
||||
int fd = open(fpath, O_RDONLY);
|
||||
if (fd != -1) {
|
||||
pread(fd, &ehdr, sizeof(ehdr), 0);
|
||||
close(fd);
|
||||
if (READ32LE(ehdr.e_ident) == READ32LE(ELFMAG) && ehdr.e_type != ET_REL) {
|
||||
tinyprint(1, fpath, "\n", NULL);
|
||||
}
|
||||
} else {
|
||||
perror(fpath);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void HandleArg(const char *path) {
|
||||
if (nftw(path, OnFile, 128, FTW_PHYS | FTW_DEPTH)) {
|
||||
perror(path);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc <= 1) {
|
||||
HandleArg(".");
|
||||
} else {
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
HandleArg(argv[i]);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -22,6 +22,9 @@
|
|||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
|
||||
// finds portable executables (and actually portable executable)
|
||||
// usage: findelf PATH...
|
||||
|
||||
static int OnFile(const char *fpath, const struct stat *st, int typeflag,
|
||||
struct FTW *ftwbuf) {
|
||||
if (typeflag == FTW_F) {
|
||||
|
|
|
@ -29,13 +29,16 @@
|
|||
#include "libc/errno.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/fmt/magnumstrs.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/mem/gc.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/serialize.h"
|
||||
#include "libc/stdalign.internal.h"
|
||||
#include "libc/stdckdint.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/msync.h"
|
||||
|
@ -48,8 +51,10 @@
|
|||
* @fileoverview GCC Codegen Fixer-Upper.
|
||||
*/
|
||||
|
||||
#define COSMO_TLS_REG 28
|
||||
#define MRS_TPIDR_EL0 0xd53bd040u
|
||||
#define COSMO_TLS_REG 28
|
||||
#define MRS_TPIDR_EL0 0xd53bd040u
|
||||
#define IFUNC_SECTION ".init.202.ifunc"
|
||||
|
||||
#define MOV_REG(DST, SRC) (0xaa0003e0u | (SRC) << 16 | (DST))
|
||||
|
||||
static int mode;
|
||||
|
@ -365,6 +370,203 @@ static void RelinkZipFiles(void) {
|
|||
eocd = foot;
|
||||
}
|
||||
|
||||
// when __attribute__((__target_clones__(...))) is used, the compiler
|
||||
// will generate multiple implementations of a function for different
|
||||
// microarchitectures as well as a resolver function that tells which
|
||||
// function is appropriate to call. however the compiler doesn't make
|
||||
// code for the actual function. it also doesn't record where resolve
|
||||
// functions are located in the binary so we've reverse eng'd it here
|
||||
static void GenerateIfuncInit(void) {
|
||||
char *name, *s;
|
||||
long code_i = 0;
|
||||
long relas_i = 0;
|
||||
static char code[16384];
|
||||
static Elf64_Rela relas[1024];
|
||||
Elf64_Shdr *symtab_shdr = GetElfSymbolTable(elf, esize, SHT_SYMTAB, 0);
|
||||
if (!symtab_shdr) Die("symbol table section header not found");
|
||||
Elf64_Word symtab_shdr_index =
|
||||
((char *)symtab_shdr - ((char *)elf + elf->e_shoff)) / elf->e_shentsize;
|
||||
for (Elf64_Xword i = 0; i < symcount; ++i) {
|
||||
if (syms[i].st_shndx == SHN_UNDEF) continue;
|
||||
if (syms[i].st_shndx >= SHN_LORESERVE) continue;
|
||||
if (ELF64_ST_TYPE(syms[i].st_info) != STT_GNU_IFUNC) continue;
|
||||
if (!(name = GetElfString(elf, esize, symstrs, syms[i].st_name)))
|
||||
Die("could not get symbol name of ifunc");
|
||||
static char resolver_name[65536];
|
||||
strlcpy(resolver_name, name, sizeof(resolver_name));
|
||||
if (strlcat(resolver_name, ".resolver", sizeof(resolver_name)) >=
|
||||
sizeof(resolver_name))
|
||||
Die("ifunc name too long");
|
||||
Elf64_Xword function_sym_index = i;
|
||||
Elf64_Xword resolver_sym_index = -1;
|
||||
for (Elf64_Xword i = 0; i < symcount; ++i) {
|
||||
if (syms[i].st_shndx == SHN_UNDEF) continue;
|
||||
if (syms[i].st_shndx >= SHN_LORESERVE) continue;
|
||||
if (ELF64_ST_TYPE(syms[i].st_info) != STT_FUNC) continue;
|
||||
if (!(s = GetElfString(elf, esize, symstrs, syms[i].st_name))) continue;
|
||||
if (strcmp(s, resolver_name)) continue;
|
||||
resolver_sym_index = i;
|
||||
break;
|
||||
}
|
||||
if (resolver_sym_index == -1)
|
||||
// this can happen if a function with __target_clones() also has a
|
||||
// __weak_reference() defined, in which case GCC shall only create
|
||||
// one resolver function for the two of them so we can ignore this
|
||||
// HOWEVER the GOT will still have an entry for each two functions
|
||||
continue;
|
||||
|
||||
// call the resolver (using cosmo's special .init abi)
|
||||
static const char chunk1[] = {
|
||||
0x57, // push %rdi
|
||||
0x56, // push %rsi
|
||||
0xe8, 0x00, 0x00, 0x00, 0x00, // call f.resolver
|
||||
};
|
||||
if (code_i + sizeof(chunk1) > sizeof(code) || relas_i + 1 > ARRAYLEN(relas))
|
||||
Die("too many ifuncs");
|
||||
memcpy(code + code_i, chunk1, sizeof(chunk1));
|
||||
relas[relas_i].r_info = ELF64_R_INFO(resolver_sym_index, R_X86_64_PLT32);
|
||||
relas[relas_i].r_offset = code_i + 1 + 1 + 1;
|
||||
relas[relas_i].r_addend = -4;
|
||||
code_i += sizeof(chunk1);
|
||||
relas_i += 1;
|
||||
|
||||
// move the resolved function address into the GOT slot. it's very
|
||||
// important that this happen, because the linker by default makes
|
||||
// self-referencing PLT functions whose execution falls through oh
|
||||
// no. we need to repeat this process for any aliases this defines
|
||||
static const char chunk2[] = {
|
||||
0x48, 0x89, 0x05, 0x00, 0x00, 0x00, 0x00, // mov %rax,f@gotpcrel(%rip)
|
||||
};
|
||||
for (Elf64_Xword i = 0; i < symcount; ++i) {
|
||||
if (i == function_sym_index ||
|
||||
(ELF64_ST_TYPE(syms[i].st_info) == STT_GNU_IFUNC &&
|
||||
syms[i].st_shndx == syms[function_sym_index].st_shndx &&
|
||||
syms[i].st_value == syms[function_sym_index].st_value)) {
|
||||
if (code_i + sizeof(chunk2) > sizeof(code) ||
|
||||
relas_i + 1 > ARRAYLEN(relas))
|
||||
Die("too many ifuncs");
|
||||
memcpy(code + code_i, chunk2, sizeof(chunk2));
|
||||
relas[relas_i].r_info = ELF64_R_INFO(i, R_X86_64_GOTPCREL);
|
||||
relas[relas_i].r_offset = code_i + 3;
|
||||
relas[relas_i].r_addend = -4;
|
||||
code_i += sizeof(chunk2);
|
||||
relas_i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
static const char chunk3[] = {
|
||||
0x5e, // pop %rsi
|
||||
0x5f, // pop %rdi
|
||||
};
|
||||
if (code_i + sizeof(chunk3) > sizeof(code)) Die("too many ifuncs");
|
||||
memcpy(code + code_i, chunk3, sizeof(chunk3));
|
||||
code_i += sizeof(chunk3);
|
||||
}
|
||||
if (!code_i) return;
|
||||
|
||||
// prepare to mutate elf
|
||||
// remap file so it has more space
|
||||
if (elf->e_shnum + 2 > 65535) Die("too many sections");
|
||||
size_t reserve_size = esize + 32 * 1024 * 1024;
|
||||
if (ftruncate(fildes, reserve_size)) SysExit("ifunc ftruncate #1");
|
||||
elf = mmap((char *)elf, reserve_size, PROT_READ | PROT_WRITE,
|
||||
MAP_FIXED | MAP_SHARED, fildes, 0);
|
||||
if (elf == MAP_FAILED) SysExit("ifunc mmap");
|
||||
|
||||
// duplicate section name strings table to end of file
|
||||
Elf64_Shdr *shdrstr_shdr = (Elf64_Shdr *)((char *)elf + elf->e_shoff +
|
||||
elf->e_shstrndx * elf->e_shentsize);
|
||||
memcpy((char *)elf + esize, (char *)elf + shdrstr_shdr->sh_offset,
|
||||
shdrstr_shdr->sh_size);
|
||||
shdrstr_shdr->sh_offset = esize;
|
||||
esize += shdrstr_shdr->sh_size;
|
||||
|
||||
// append strings for the two sections we're creating
|
||||
const char *code_section_name = IFUNC_SECTION;
|
||||
Elf64_Word code_section_name_offset = shdrstr_shdr->sh_size;
|
||||
memcpy((char *)elf + esize, code_section_name, strlen(code_section_name) + 1);
|
||||
shdrstr_shdr->sh_size += strlen(code_section_name) + 1;
|
||||
esize += strlen(code_section_name) + 1;
|
||||
const char *rela_section_name = ".rela" IFUNC_SECTION;
|
||||
Elf64_Word rela_section_name_offset = shdrstr_shdr->sh_size;
|
||||
memcpy((char *)elf + esize, rela_section_name, strlen(rela_section_name) + 1);
|
||||
shdrstr_shdr->sh_size += strlen(rela_section_name) + 1;
|
||||
esize += strlen(rela_section_name) + 1;
|
||||
unassert(esize == shdrstr_shdr->sh_offset + shdrstr_shdr->sh_size);
|
||||
++esize;
|
||||
|
||||
// duplicate section headers to end of file
|
||||
esize = (esize + alignof(Elf64_Shdr) - 1) & -alignof(Elf64_Shdr);
|
||||
memcpy((char *)elf + esize, (char *)elf + elf->e_shoff,
|
||||
elf->e_shnum * elf->e_shentsize);
|
||||
elf->e_shoff = esize;
|
||||
esize += elf->e_shnum * elf->e_shentsize;
|
||||
unassert(esize == elf->e_shoff + elf->e_shnum * elf->e_shentsize);
|
||||
|
||||
// append code section header
|
||||
Elf64_Shdr *code_shdr = (Elf64_Shdr *)((char *)elf + esize);
|
||||
Elf64_Word code_shdr_index = elf->e_shnum++;
|
||||
esize += elf->e_shentsize;
|
||||
code_shdr->sh_name = code_section_name_offset;
|
||||
code_shdr->sh_type = SHT_PROGBITS;
|
||||
code_shdr->sh_flags = SHF_ALLOC | SHF_EXECINSTR;
|
||||
code_shdr->sh_addr = 0;
|
||||
code_shdr->sh_link = 0;
|
||||
code_shdr->sh_info = 0;
|
||||
code_shdr->sh_entsize = 1;
|
||||
code_shdr->sh_addralign = 1;
|
||||
code_shdr->sh_size = code_i;
|
||||
|
||||
// append code's rela section header
|
||||
Elf64_Shdr *rela_shdr = (Elf64_Shdr *)((char *)elf + esize);
|
||||
esize += elf->e_shentsize;
|
||||
rela_shdr->sh_name = rela_section_name_offset;
|
||||
rela_shdr->sh_type = SHT_RELA;
|
||||
rela_shdr->sh_flags = SHF_INFO_LINK;
|
||||
rela_shdr->sh_addr = 0;
|
||||
rela_shdr->sh_info = code_shdr_index;
|
||||
rela_shdr->sh_link = symtab_shdr_index;
|
||||
rela_shdr->sh_entsize = sizeof(Elf64_Rela);
|
||||
rela_shdr->sh_addralign = alignof(Elf64_Rela);
|
||||
rela_shdr->sh_size = relas_i * sizeof(Elf64_Rela);
|
||||
elf->e_shnum++;
|
||||
|
||||
// append relas
|
||||
esize = (esize + 63) & -64;
|
||||
rela_shdr->sh_offset = esize;
|
||||
memcpy((char *)elf + esize, relas, relas_i * sizeof(Elf64_Rela));
|
||||
esize += relas_i * sizeof(Elf64_Rela);
|
||||
unassert(esize == rela_shdr->sh_offset + rela_shdr->sh_size);
|
||||
|
||||
// append code
|
||||
esize = (esize + 63) & -64;
|
||||
code_shdr->sh_offset = esize;
|
||||
memcpy((char *)elf + esize, code, code_i);
|
||||
esize += code_i;
|
||||
unassert(esize == code_shdr->sh_offset + code_shdr->sh_size);
|
||||
|
||||
if (ftruncate(fildes, esize)) SysExit("ifunc ftruncate #1");
|
||||
}
|
||||
|
||||
// when __attribute__((__target_clones__(...))) is used, static binaries
|
||||
// become poisoned with rela IFUNC relocations, which the linker refuses
|
||||
// to remove. even if we objcopy the ape executable as binary the linker
|
||||
// preserves its precious ifunc code and puts them before the executable
|
||||
// header. the good news is that the linker actually does link correctly
|
||||
// which means we can delete the broken rela sections in the elf binary.
|
||||
static void PurgeIfuncSections(void) {
|
||||
Elf64_Shdr *shdrs = (Elf64_Shdr *)((char *)elf + elf->e_shoff);
|
||||
for (Elf64_Word i = 0; i < elf->e_shnum; ++i) {
|
||||
char *name;
|
||||
if (shdrs[i].sh_type == SHT_RELA ||
|
||||
((name = GetElfSectionName(elf, esize, shdrs + i)) &&
|
||||
!strcmp(name, ".init.202.ifunc"))) {
|
||||
shdrs[i].sh_type = SHT_NULL;
|
||||
shdrs[i].sh_flags &= ~SHF_ALLOC;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void FixupObject(void) {
|
||||
if ((fildes = open(epath, mode)) == -1) {
|
||||
SysExit("open");
|
||||
|
@ -373,8 +575,8 @@ static void FixupObject(void) {
|
|||
SysExit("lseek");
|
||||
}
|
||||
if (esize) {
|
||||
if ((elf = mmap(0, esize, PROT_READ | PROT_WRITE, MAP_SHARED, fildes, 0)) ==
|
||||
MAP_FAILED) {
|
||||
if ((elf = mmap((void *)0x003210000000, esize, PROT_READ | PROT_WRITE,
|
||||
MAP_FIXED | MAP_SHARED, fildes, 0)) == MAP_FAILED) {
|
||||
SysExit("mmap");
|
||||
}
|
||||
if (!IsElf64Binary(elf, esize)) {
|
||||
|
@ -393,6 +595,7 @@ static void FixupObject(void) {
|
|||
if (mode == O_RDWR) {
|
||||
if (elf->e_machine == EM_NEXGEN32E) {
|
||||
OptimizePatchableFunctionEntries();
|
||||
GenerateIfuncInit();
|
||||
} else if (elf->e_machine == EM_AARCH64) {
|
||||
RewriteTlsCode();
|
||||
if (elf->e_type != ET_REL) {
|
||||
|
@ -400,6 +603,7 @@ static void FixupObject(void) {
|
|||
}
|
||||
}
|
||||
if (elf->e_type != ET_REL) {
|
||||
PurgeIfuncSections();
|
||||
RelinkZipFiles();
|
||||
}
|
||||
if (msync(elf, esize, MS_ASYNC | MS_INVALIDATE)) {
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/fmt/libgen.h"
|
||||
#include "libc/fmt/magnumstrs.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
|
@ -45,48 +46,48 @@
|
|||
"copyright 2023 justine tunney\n" \
|
||||
"https://github.com/jart/cosmopolitan\n"
|
||||
|
||||
#define MANUAL \
|
||||
" -r o// -o OUTPUT INPUT...\n" \
|
||||
"\n" \
|
||||
"DESCRIPTION\n" \
|
||||
"\n" \
|
||||
" Generates header file dependencies for your makefile\n" \
|
||||
"\n" \
|
||||
" This tool computes the transitive closure of included paths\n" \
|
||||
" for every source file in your repository. This program does\n" \
|
||||
" it orders of a magnitude faster than `gcc -M` on each file.\n" \
|
||||
"\n" \
|
||||
" Includes look like this:\n" \
|
||||
"\n" \
|
||||
" - #include <stdio.h>\n" \
|
||||
" - #include \"samedir.h\"\n" \
|
||||
" - #include \"root/of/repository/foo.h\"\n" \
|
||||
" - .include \"asm/x86_64/foo.s\"\n" \
|
||||
"\n" \
|
||||
" Your generated make code looks like this:\n" \
|
||||
"\n" \
|
||||
" o//package/foo.o: \\\n" \
|
||||
" package/foo.c \\\n" \
|
||||
" package/foo.h \\\n" \
|
||||
" package/bar.h \\\n" \
|
||||
" libc/isystem/stdio.h\n" \
|
||||
" o//package/bar.o: \\\n" \
|
||||
" package/bar.c \\\n" \
|
||||
" package/bar.h\n" \
|
||||
"\n" \
|
||||
"FLAGS\n" \
|
||||
"\n" \
|
||||
" -h show usage\n" \
|
||||
" -o OUTPUT set output path\n" \
|
||||
" -g ROOT set generated path [default: o/]\n" \
|
||||
" -r ROOT set build output path, e.g. o/$(MODE)/\n" \
|
||||
" -S PATH isystem include path [default: libc/isystem/]\n" \
|
||||
" -s hermetically sealed mode [repeatable]\n" \
|
||||
"\n" \
|
||||
"ARGUMENTS\n" \
|
||||
"\n" \
|
||||
" OUTPUT shall be makefile code\n" \
|
||||
" INPUT should be source or @args.txt\n" \
|
||||
#define MANUAL \
|
||||
" -r o// -o OUTPUT INPUT...\n" \
|
||||
"\n" \
|
||||
"DESCRIPTION\n" \
|
||||
"\n" \
|
||||
" Generates header file dependencies for your makefile\n" \
|
||||
"\n" \
|
||||
" This tool computes the transitive closure of included paths\n" \
|
||||
" for every source file in your repository. This program does\n" \
|
||||
" it orders of a magnitude faster than `gcc -M` on each file.\n" \
|
||||
"\n" \
|
||||
" Includes look like this:\n" \
|
||||
"\n" \
|
||||
" - #include <stdio.h>\n" \
|
||||
" - #include \"samedir.h\"\n" \
|
||||
" - #include \"root/of/repository/foo.h\"\n" \
|
||||
" - .include \"asm/x86_64/foo.s\"\n" \
|
||||
"\n" \
|
||||
" Your generated make code looks like this:\n" \
|
||||
"\n" \
|
||||
" o//package/foo.o: \\\n" \
|
||||
" package/foo.c \\\n" \
|
||||
" package/foo.h \\\n" \
|
||||
" package/bar.h \\\n" \
|
||||
" libc/isystem/stdio.h\n" \
|
||||
" o//package/bar.o: \\\n" \
|
||||
" package/bar.c \\\n" \
|
||||
" package/bar.h\n" \
|
||||
"\n" \
|
||||
"FLAGS\n" \
|
||||
"\n" \
|
||||
" -h show usage\n" \
|
||||
" -o OUTPUT set output path\n" \
|
||||
" -g ROOT set generated path [default: o/]\n" \
|
||||
" -r ROOT set build output path, e.g. o/$(MODE)/\n" \
|
||||
" -S PATH isystem include path [repeatable; default: libc/isystem/]\n" \
|
||||
" -s hermetically sealed mode [repeatable]\n" \
|
||||
"\n" \
|
||||
"ARGUMENTS\n" \
|
||||
"\n" \
|
||||
" OUTPUT shall be makefile code\n" \
|
||||
" INPUT should be source or @args.txt\n" \
|
||||
"\n"
|
||||
|
||||
#define Read32(s) (s[3] << 24 | s[2] << 16 | s[1] << 8 | s[0])
|
||||
|
@ -118,6 +119,11 @@ struct Edges {
|
|||
struct Edge *p;
|
||||
};
|
||||
|
||||
struct Paths {
|
||||
long n;
|
||||
const char *p[64];
|
||||
};
|
||||
|
||||
static const uint32_t kSourceExts[] = {
|
||||
EXT("s"), // assembly
|
||||
EXT("S"), // assembly with c preprocessor
|
||||
|
@ -135,7 +141,7 @@ static const char *prog;
|
|||
static struct Edges edges;
|
||||
static struct Sauce *sauces;
|
||||
static struct Sources sources;
|
||||
static const char *systempath;
|
||||
static struct Paths systempaths;
|
||||
static const char *buildroot;
|
||||
static const char *genroot;
|
||||
static const char *outpath;
|
||||
|
@ -329,7 +335,7 @@ static const char *FindIncludePath(const char *map, size_t mapsize,
|
|||
// scan backwards for hash character
|
||||
for (;;) {
|
||||
if (q == map) {
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
if (IsBlank(q[-1])) {
|
||||
--q;
|
||||
|
@ -342,7 +348,7 @@ static const char *FindIncludePath(const char *map, size_t mapsize,
|
|||
--q;
|
||||
break;
|
||||
} else {
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -359,7 +365,7 @@ static const char *FindIncludePath(const char *map, size_t mapsize,
|
|||
if (q[-1] == '\n') {
|
||||
break;
|
||||
} else {
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -378,7 +384,7 @@ static const char *FindIncludePath(const char *map, size_t mapsize,
|
|||
++q;
|
||||
break;
|
||||
} else {
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -395,7 +401,7 @@ static void LoadRelationships(int argc, char *argv[]) {
|
|||
struct GetArgs ga;
|
||||
int srcid, dependency;
|
||||
static char srcdirbuf[PATH_MAX];
|
||||
const char *p, *pe, *src, *path, *pathend, *srcdir;
|
||||
const char *p, *pe, *src, *path, *pathend, *srcdir, *final;
|
||||
getargs_init(&ga, argv + optind);
|
||||
while ((src = getargs_next(&ga))) {
|
||||
CreateSourceId(src);
|
||||
|
@ -433,51 +439,71 @@ static void LoadRelationships(int argc, char *argv[]) {
|
|||
DieSys(src);
|
||||
}
|
||||
for (p = map, pe = map + size; p < pe; ++p) {
|
||||
char *bp;
|
||||
char right;
|
||||
char buf[PATH_MAX];
|
||||
if (!(p = memmem(p, pe - p, "include ", 8))) break;
|
||||
if (!(path = FindIncludePath(map, size, p, is_assembly))) continue;
|
||||
bp = buf;
|
||||
// copy the specified include path
|
||||
char right;
|
||||
if (path[-1] == '<') {
|
||||
if (!systempath) continue;
|
||||
bp = stpcpy(bp, systempath);
|
||||
if (!systempaths.n) continue;
|
||||
right = '>';
|
||||
} else {
|
||||
right = '"';
|
||||
}
|
||||
if ((pathend = memchr(path, right, pe - path))) {
|
||||
const char *final;
|
||||
char juf[PATH_MAX];
|
||||
if ((bp - buf) + (pathend - path) >= PATH_MAX) {
|
||||
tinyprint(2, src, ": include path too long\n", NULL);
|
||||
exit(1);
|
||||
}
|
||||
*(bp = mempcpy(bp, path, pathend - path)) = 0;
|
||||
// let foo/bar.c say `#include "foo/hdr.h"`
|
||||
dependency = GetSourceId((final = buf));
|
||||
// let foo/bar.c say `#include "hdr.h"`
|
||||
if (dependency == -1 && right == '"' && !strchr(buf, '/')) {
|
||||
if (!(final = __join_paths(juf, PATH_MAX, srcdir, buf))) {
|
||||
DiePathTooLong(buf);
|
||||
if (!(pathend = memchr(path, right, pe - path))) continue;
|
||||
if (pathend - path >= PATH_MAX) {
|
||||
tinyprint(2, src, ": uses really long include path\n", NULL);
|
||||
exit(1);
|
||||
}
|
||||
char juf[PATH_MAX];
|
||||
char incpath[PATH_MAX];
|
||||
*(char *)mempcpy(incpath, path, pathend - path) = 0;
|
||||
if (right == '>') {
|
||||
// handle angle bracket includes
|
||||
dependency = -1;
|
||||
for (long i = 0; i < systempaths.n; ++i) {
|
||||
if (!(final =
|
||||
__join_paths(juf, PATH_MAX, systempaths.p[i], incpath))) {
|
||||
DiePathTooLong(incpath);
|
||||
}
|
||||
if ((dependency = GetSourceId(final)) != -1) {
|
||||
break;
|
||||
}
|
||||
dependency = GetSourceId(final);
|
||||
}
|
||||
if (dependency == -1) {
|
||||
if (startswith(buf, genroot)) {
|
||||
dependency = CreateSourceId(src);
|
||||
} else if (!hermetic) {
|
||||
continue;
|
||||
} else if (hermetic == 1 && right == '>') {
|
||||
if (dependency != -1) {
|
||||
AppendEdge(&edges, dependency, srcid);
|
||||
p = pathend + 1;
|
||||
} else {
|
||||
if (hermetic == 1) {
|
||||
// chances are the `#include <foo>` is in some #ifdef
|
||||
// that'll never actually be executed; thus we ignore
|
||||
// since landlock make unveil() shall catch it anyway
|
||||
continue;
|
||||
}
|
||||
tinyprint(2, incpath,
|
||||
": system header not specified by the HDRS/SRCS/INCS "
|
||||
"make variables defined by the hermetic mono repo\n",
|
||||
NULL);
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
// handle double quote includes
|
||||
// let foo/bar.c say `#include "foo/hdr.h"`
|
||||
dependency = GetSourceId((final = incpath));
|
||||
// let foo/bar.c say `#include "hdr.h"`
|
||||
if (dependency == -1 && !strchr(final, '/')) {
|
||||
if (!(final = __join_paths(juf, PATH_MAX, srcdir, final))) {
|
||||
DiePathTooLong(incpath);
|
||||
}
|
||||
dependency = GetSourceId(final);
|
||||
}
|
||||
if (dependency == -1) {
|
||||
if (startswith(final, genroot)) {
|
||||
dependency = CreateSourceId(src);
|
||||
} else {
|
||||
tinyprint(
|
||||
2, final,
|
||||
": path not specified by HDRS/SRCS/INCS make variables\n",
|
||||
NULL);
|
||||
tinyprint(2, incpath,
|
||||
": path not specified by HDRS/SRCS/INCS make variables "
|
||||
"(it was included by ",
|
||||
src, ")\n", NULL);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
@ -498,6 +524,13 @@ static wontreturn void ShowUsage(int rc, int fd) {
|
|||
exit(rc);
|
||||
}
|
||||
|
||||
static void AddPath(struct Paths *paths, const char *path) {
|
||||
if (paths->n == ARRAYLEN(paths->p)) {
|
||||
Die("too many path arguments");
|
||||
}
|
||||
paths->p[paths->n++] = path;
|
||||
}
|
||||
|
||||
static void GetOpts(int argc, char *argv[]) {
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "hnsgS:o:r:")) != -1) {
|
||||
|
@ -506,10 +539,7 @@ static void GetOpts(int argc, char *argv[]) {
|
|||
++hermetic;
|
||||
break;
|
||||
case 'S':
|
||||
if (systempath) {
|
||||
Die("multiple system paths not supported yet");
|
||||
}
|
||||
systempath = optarg;
|
||||
AddPath(&systempaths, optarg);
|
||||
break;
|
||||
case 'o':
|
||||
if (outpath) {
|
||||
|
@ -555,29 +585,33 @@ static void GetOpts(int argc, char *argv[]) {
|
|||
if (!startswith(buildroot, genroot)) {
|
||||
Die("build output path must start with generated output path");
|
||||
}
|
||||
if (!systempath && hermetic) {
|
||||
systempath = "libc/isystem/";
|
||||
if (!systempaths.n && hermetic) {
|
||||
AddPath(&systempaths, "third_party/libcxx/include/");
|
||||
AddPath(&systempaths, "libc/isystem/");
|
||||
}
|
||||
if (systempath && !hermetic) {
|
||||
if (systempaths.n && !hermetic) {
|
||||
Die("system path can only be specified in hermetic mode");
|
||||
}
|
||||
if (systempath) {
|
||||
long j = 0;
|
||||
for (long i = 0; i < systempaths.n; ++i) {
|
||||
size_t n;
|
||||
struct stat st;
|
||||
if (stat(systempath, &st)) {
|
||||
DieSys(systempath);
|
||||
const char *path = systempaths.p[i];
|
||||
if (!stat(path, &st)) {
|
||||
systempaths.p[j++] = path;
|
||||
if (!S_ISDIR(st.st_mode)) {
|
||||
errno = ENOTDIR;
|
||||
DieSys(path);
|
||||
}
|
||||
}
|
||||
if (!S_ISDIR(st.st_mode)) {
|
||||
errno = ENOTDIR;
|
||||
DieSys(systempath);
|
||||
if ((n = strlen(path)) >= PATH_MAX) {
|
||||
DiePathTooLong(path);
|
||||
}
|
||||
if ((n = strlen(systempath)) >= PATH_MAX) {
|
||||
DiePathTooLong(systempath);
|
||||
}
|
||||
if (!n || systempath[n - 1] != '/') {
|
||||
if (!n || path[n - 1] != '/') {
|
||||
Die("system path must end with slash");
|
||||
}
|
||||
}
|
||||
systempaths.n = j;
|
||||
}
|
||||
|
||||
static const char *StripExt(char pathbuf[hasatleast PATH_MAX], const char *s) {
|
||||
|
|
|
@ -201,7 +201,7 @@ static void ValidateMachoSection(const char *inpath, //
|
|||
Die(inpath, "don't bother with mach-o sections");
|
||||
}
|
||||
namelen = strnlen(loadseg->name, sizeof(loadseg->name));
|
||||
if (!loadseg->name) {
|
||||
if (!loadseg->name[0]) {
|
||||
Die(inpath, "mach-o load segment missing name");
|
||||
}
|
||||
if (filesize || (loadseg->vaddr && loadseg->memsz)) {
|
||||
|
|
|
@ -433,7 +433,8 @@ static void LoadSymbols(struct Package *pkg, uint32_t object) {
|
|||
symbol.type = ELF64_ST_TYPE(obj->syms[i].st_info);
|
||||
if (symbol.bind_ != STB_LOCAL &&
|
||||
(symbol.type == STT_OBJECT || symbol.type == STT_FUNC ||
|
||||
symbol.type == STT_COMMON || symbol.type == STT_NOTYPE)) {
|
||||
symbol.type == STT_COMMON || symbol.type == STT_NOTYPE ||
|
||||
symbol.type == STT_GNU_IFUNC)) {
|
||||
if (!(name = GetElfString(obj->elf, obj->size, obj->strs,
|
||||
obj->syms[i].st_name))) {
|
||||
Die("error", "elf overflow");
|
||||
|
|
|
@ -151,17 +151,11 @@ void Connect(void) {
|
|||
struct timespec deadline;
|
||||
if ((rc = getaddrinfo(g_hostname, gc(xasprintf("%hu", g_runitdport)),
|
||||
&kResolvHints, &ai)) != 0) {
|
||||
FATALF("%s:%hu: EAI_%s %m", g_hostname, g_runitdport, gai_strerror(rc));
|
||||
FATALF("%s:%hu: DNS lookup failed: %s", g_hostname, g_runitdport,
|
||||
gai_strerror(rc));
|
||||
__builtin_unreachable();
|
||||
}
|
||||
ip4 = (const char *)&((struct sockaddr_in *)ai->ai_addr)->sin_addr;
|
||||
if (ispublicip(ai->ai_family,
|
||||
&((struct sockaddr_in *)ai->ai_addr)->sin_addr)) {
|
||||
FATALF("%s points to %hhu.%hhu.%hhu.%hhu"
|
||||
" which isn't part of a local/private/testing subnet",
|
||||
g_hostname, ip4[0], ip4[1], ip4[2], ip4[3]);
|
||||
__builtin_unreachable();
|
||||
}
|
||||
DEBUGF("connecting to %d.%d.%d.%d port %d", ip4[0], ip4[1], ip4[2], ip4[3],
|
||||
ntohs(((struct sockaddr_in *)ai->ai_addr)->sin_port));
|
||||
CHECK_NE(-1,
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include "libc/errno.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/fmt/libgen.h"
|
||||
#include "libc/serialize.h"
|
||||
#include "libc/intrin/safemacros.internal.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/log/log.h"
|
||||
|
@ -34,6 +33,7 @@
|
|||
#include "libc/mem/gc.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/serialize.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/auxv.h"
|
||||
|
|
|
@ -125,7 +125,7 @@ Keywords={
|
|||
"mayalias",
|
||||
"dontinstrument",
|
||||
"interruptfn",
|
||||
"nocallback",
|
||||
"dontcallback",
|
||||
"textstartup",
|
||||
"warnifused",
|
||||
"attributeallocsize",
|
||||
|
|
|
@ -67,7 +67,8 @@
|
|||
"progbits"
|
||||
"nobits"
|
||||
"init_array"
|
||||
"fini_array")])
|
||||
"fini_array"
|
||||
"gnu_indirect_function")])
|
||||
"\\>"])
|
||||
"GNU Assembler section, relocation, macro param qualifiers.")
|
||||
|
||||
|
|
|
@ -91,7 +91,7 @@
|
|||
"mayalias"
|
||||
"dontinstrument"
|
||||
"interruptfn"
|
||||
"nocallback"
|
||||
"dontcallback"
|
||||
"textstartup"
|
||||
"warnifused"
|
||||
"attributeallocsize"
|
||||
|
@ -206,6 +206,9 @@
|
|||
"__section__"
|
||||
"__sentinel__"
|
||||
"__simd__"
|
||||
"__vex"
|
||||
"__avx2"
|
||||
"__target_clones"
|
||||
"__target_clones__"
|
||||
"__unused__"
|
||||
"__used__"
|
||||
|
|
|
@ -71,7 +71,8 @@
|
|||
"__SUPPORT_SNAN__"
|
||||
"__GCC_IEC_559_COMPLEX"
|
||||
"__NO_MATH_ERRNO__"
|
||||
"__gnu__"))
|
||||
"__gnu__"
|
||||
"_OPENMP"))
|
||||
|
||||
(cosmo
|
||||
'("__LINKER__"))
|
||||
|
|
|
@ -215,7 +215,7 @@
|
|||
(runs (format "o/$m/%s.com%s V=5 TESTARGS=-b" name runsuffix))
|
||||
(buns (format "o/$m/test/%s_test.com%s V=5 TESTARGS=-b" name runsuffix)))
|
||||
(cond ((not (member ext '("c" "cc" "cpp" "s" "S" "rl" "f")))
|
||||
(format "m=%s; make -j12 MODE=$m o/$m/%s"
|
||||
(format "m=%s; make -j32 MODE=$m o/$m/%s"
|
||||
mode
|
||||
(directory-file-name
|
||||
(or (file-name-directory
|
||||
|
@ -226,7 +226,7 @@
|
|||
(cosmo-join
|
||||
" && "
|
||||
`("m=%s; f=o/$m/%s.com"
|
||||
,(concat "make -j12 $f MODE=$m")
|
||||
,(concat "make -j32 $f MODE=$m")
|
||||
"scp $f $f.dbg win10:; ssh win10 ./%s.com"))
|
||||
mode name (file-name-nondirectory name)))
|
||||
((eq kind 'run-xnu)
|
||||
|
@ -234,19 +234,19 @@
|
|||
(cosmo-join
|
||||
" && "
|
||||
`("m=%s; f=o/$m/%s.com"
|
||||
,(concat "make -j12 $f MODE=$m")
|
||||
,(concat "make -j32 $f MODE=$m")
|
||||
"scp $f $f.dbg xnu:"
|
||||
"ssh xnu ./%s.com"))
|
||||
mode name (file-name-nondirectory name)))
|
||||
((and (equal suffix "")
|
||||
(cosmo-contains "_test." (buffer-file-name)))
|
||||
(format "m=%s; make -j12 MODE=$m %s"
|
||||
(format "m=%s; make -j32 MODE=$m %s"
|
||||
mode runs))
|
||||
((and (equal suffix "")
|
||||
(file-exists-p (format "%s" buddy)))
|
||||
(format (cosmo-join
|
||||
" && "
|
||||
'("m=%s; n=%s; make -j12 o/$m/$n%s.o MODE=$m"
|
||||
'("m=%s; n=%s; make -j32 o/$m/$n%s.o MODE=$m"
|
||||
;; "bloat o/$m/%s.o | head"
|
||||
;; "nm -C --size o/$m/%s.o | sort -r"
|
||||
"echo"
|
||||
|
@ -258,11 +258,11 @@
|
|||
(cosmo-join
|
||||
" && "
|
||||
`("m=%s; f=o/$m/%s.com"
|
||||
,(concat "make -j12 $f MODE=$m")
|
||||
,(concat "make -j32 $f MODE=$m")
|
||||
"build/run ./$f"))
|
||||
mode name))
|
||||
((eq kind 'test)
|
||||
(format `"m=%s; f=o/$m/%s.com.ok && make -j12 $f MODE=$m" mode name))
|
||||
(format `"m=%s; f=o/$m/%s.com.ok && make -j32 $f MODE=$m" mode name))
|
||||
((and (file-regular-p this)
|
||||
(file-executable-p this))
|
||||
(format "build/run ./%s" file))
|
||||
|
@ -271,7 +271,7 @@
|
|||
(cosmo-join
|
||||
" && "
|
||||
`("m=%s; f=o/$m/%s%s.o"
|
||||
,(concat "make -j12 $f MODE=$m")
|
||||
,(concat "make -j32 $f MODE=$m")
|
||||
;; "nm -C --size $f | sort -r"
|
||||
"echo"
|
||||
"size -A $f | grep '^[.T]' | grep -v 'debug\\|command.line\\|stack' | sort -rnk2"
|
||||
|
@ -481,7 +481,7 @@
|
|||
(error "don't know how to show assembly for non c/c++ source file"))
|
||||
(let* ((default-directory root)
|
||||
(compile-command
|
||||
(format "make %s -j12 MODE=%s %s %s"
|
||||
(format "make %s -j32 MODE=%s %s %s"
|
||||
(or extra-make-flags "") mode asm-gcc asm-clang)))
|
||||
(save-buffer)
|
||||
(set-visited-file-modtime (current-time))
|
||||
|
@ -641,11 +641,11 @@
|
|||
(compile (format "sh -c %s" file)))
|
||||
((eq major-mode 'lua-mode)
|
||||
(let* ((mode (cosmo--make-mode arg)))
|
||||
(compile (format "make -j16 MODE=%s o/%s/tool/net/redbean.com && build/run o/%s/tool/net/redbean.com -i %s" mode mode mode file))))
|
||||
(compile (format "make -j32 MODE=%s o/%s/tool/net/redbean.com && build/run o/%s/tool/net/redbean.com -i %s" mode mode mode file))))
|
||||
((and (eq major-mode 'python-mode)
|
||||
(cosmo-startswith "third_party/python/Lib/test/" file))
|
||||
(let ((mode (cosmo--make-mode arg)))
|
||||
(compile (format "make -j12 MODE=%s PYHARNESSARGS=-vv PYTESTARGS=-v o/%s/%s.py.runs"
|
||||
(compile (format "make -j32 MODE=%s PYHARNESSARGS=-vv PYTESTARGS=-v o/%s/%s.py.runs"
|
||||
mode mode (file-name-sans-extension file)))))
|
||||
((eq major-mode 'python-mode)
|
||||
(compile (format "python.com %s" file)))
|
||||
|
@ -692,8 +692,10 @@
|
|||
(define-key lua-mode-map (kbd "C-c C-r") 'cosmo-run)
|
||||
(define-key python-mode-map (kbd "C-c C-r") 'cosmo-run)
|
||||
(define-key c-mode-map (kbd "C-c C-s") 'cosmo-run-test)
|
||||
(define-key c++-mode-map (kbd "C-c C-s") 'cosmo-run-test)
|
||||
(define-key c-mode-map (kbd "C-c C-_") 'cosmo-run-win7)
|
||||
(define-key c-mode-map (kbd "C-c C-_") 'cosmo-run-win10))
|
||||
(define-key c-mode-map (kbd "C-c C-_") 'cosmo-run-win10)
|
||||
(define-key c++-mode-map (kbd "C-c C-_") 'cosmo-run-win10))
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
@ -939,7 +941,7 @@
|
|||
"T[0-9][0-9]:[0-9][0-9]:[0-9][0-9]" ;; time
|
||||
"[+.][0-9][0-9][0-9][0-9][0-9][0-9]" ;; micros
|
||||
":\\([^:]+\\)" ;; file
|
||||
":\\([0-9]+\\)")) ;; line
|
||||
":\\([0-9]+\\)")) ;; line
|
||||
1 2))
|
||||
|
||||
(eval-after-load 'compile
|
||||
|
@ -948,6 +950,20 @@
|
|||
(cons 'cosmo cosmo-compilation-regexps))
|
||||
(add-to-list 'compilation-error-regexp-alist 'cosmo)))
|
||||
|
||||
(defvar cosmo-gcc123-compilation-regexps
|
||||
(list (cosmo-join
|
||||
""
|
||||
'("inlined from '[^']*' at "
|
||||
"\\([^:]+\\)" ;; file
|
||||
":\\([0-9]+\\)")) ;; line
|
||||
1 2))
|
||||
|
||||
(eval-after-load 'compile
|
||||
'(progn
|
||||
(add-to-list 'compilation-error-regexp-alist-alist
|
||||
(cons 'cosmo cosmo-gcc123-compilation-regexps))
|
||||
(add-to-list 'compilation-error-regexp-alist 'cosmo)))
|
||||
|
||||
(provide 'cosmo-stuff)
|
||||
|
||||
;;; cosmo-stuff.el ends here
|
||||
|
|
|
@ -340,7 +340,7 @@ cosmo_kws = frozenset([
|
|||
"mallocesque",
|
||||
"mayalias",
|
||||
"memcpyesque",
|
||||
"nocallback",
|
||||
"dontcallback",
|
||||
"nodebuginfo",
|
||||
"__wur",
|
||||
"dontinline",
|
||||
|
@ -399,7 +399,7 @@ cosmo_kws = frozenset([
|
|||
"mallocesque",
|
||||
"mayalias",
|
||||
"memcpyesque",
|
||||
"nocallback",
|
||||
"dontcallback",
|
||||
"nodebuginfo",
|
||||
"__wur",
|
||||
"dontinline",
|
||||
|
|
|
@ -188,7 +188,7 @@ dontasan void PrintTeb(void) {
|
|||
}
|
||||
|
||||
void PrintPeb(void) {
|
||||
struct NtPeb *peb = NtGetPeb();
|
||||
__seg_gs struct NtPeb *peb = NtGetPeb();
|
||||
printf("\n\
|
||||
╔──────────────────────────────────────────────────────────────────────────────╗\n\
|
||||
│ new technology § peb │\n\
|
||||
|
@ -327,8 +327,6 @@ void PrintPeb(void) {
|
|||
"pShimData", peb->pShimData);
|
||||
printf("0x%04x: %-40s = 0x%lx\n", offsetof(struct NtPeb, AppCompatInfo),
|
||||
"AppCompatInfo", peb->AppCompatInfo);
|
||||
printf("0x%04x: %-40s = \"%s\"\n", offsetof(struct NtPeb, CSDVersion),
|
||||
"CSDVersion", GetString(&peb->CSDVersion));
|
||||
printf("0x%04x: %-40s = 0x%lx\n",
|
||||
offsetof(struct NtPeb, ActivationContextData), "ActivationContextData",
|
||||
peb->ActivationContextData);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue