mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-22 21:32:31 +00:00
Get binaries closer to running without an o/s
blinkenlights now does a pretty good job emulating what happens when binaries boot from BIOS into long mode. So it's been much easier to debug the bare metal process and wrinkle out many issues.
This commit is contained in:
parent
feed0d2b0e
commit
2d80bbc802
50 changed files with 974 additions and 1062 deletions
|
@ -84,7 +84,7 @@ int spawnve$sysv(unsigned flags, int stdiofds[3], const char *program,
|
|||
}
|
||||
|
||||
if (pid != -1) {
|
||||
if ((pid = fork$sysv()) == 0) {
|
||||
if ((pid = vfork()) == 0) {
|
||||
if (flags & SPAWN_DETACH) {
|
||||
if (setsid() == -1) abort();
|
||||
if ((rc = fork$sysv()) == -1) abort();
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/macros.h"
|
||||
.source __FILE__
|
||||
|
||||
|
|
|
@ -40,7 +40,8 @@ _start: test %rdi,%rdi
|
|||
lea 24(%rsp,%rbx,8),%rdx # envp
|
||||
.frame0
|
||||
/ bofram 9f
|
||||
.weak idata.iat,idata.iatend
|
||||
.weak idata.iat
|
||||
.weak idata.iatend
|
||||
ezlea missingno,ax # make win32 imps noop
|
||||
ezlea idata.iat,di
|
||||
ezlea idata.iatend,cx
|
||||
|
|
|
@ -140,6 +140,7 @@ static const char *__asan_describe_access_poison(int c) {
|
|||
case kAsanUnscoped:
|
||||
return "unscoped";
|
||||
default:
|
||||
DebugBreak();
|
||||
return "poisoned";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -186,11 +186,6 @@
|
|||
.endif
|
||||
.endm
|
||||
|
||||
/ Custom emulator instruction for bottom stack frame.
|
||||
.macro bofram endfunc:req
|
||||
.byte 0x0f,0x1f,0x45,\endfunc-. # nopl disp8(%rbp)
|
||||
.endm
|
||||
|
||||
/ Overrides LOOP instruction.
|
||||
/ With its mop-Fusion Mexican equivalent.
|
||||
/ Thus avoiding 3x legacy pipeline slowdown.
|
||||
|
@ -330,3 +325,8 @@ _init_\name:
|
|||
call *\symbol(%rip)
|
||||
add $32,%rsp
|
||||
.endm
|
||||
|
||||
/ Custom emulator instruction for bottom stack frame.
|
||||
.macro bofram endfunc:req
|
||||
.byte 0x0f,0x1f,0105,\endfunc-. # nopl disp8(%rbp)
|
||||
.endm
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_NEXGEN32E_RDTSCP_H_
|
||||
#define COSMOPOLITAN_LIBC_NEXGEN32E_RDTSCP_H_
|
||||
#include "libc/bits/bits.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
|
@ -32,17 +33,26 @@ COSMOPOLITAN_C_START_
|
|||
*/
|
||||
#define rdpid() \
|
||||
({ \
|
||||
bool Ok; \
|
||||
long Msr; \
|
||||
Ok = false; \
|
||||
if (X86_HAVE(RDPID)) { \
|
||||
asm volatile("rdpid\t%0" : "=r"(Msr) : /* no inputs */ : "memory"); \
|
||||
Ok = true; \
|
||||
} else if (IsLinux()) { \
|
||||
asm volatile("lsl\t%1,%0" : "=r"(Msr) : "r"(0x7b) : "memory"); \
|
||||
} else if (X86_HAVE(RDTSCP)) { \
|
||||
asm volatile(ZFLAG_ASM("lsl\t%2,%1") \
|
||||
: ZFLAG_CONSTRAINT(Ok), "=r"(Msr) \
|
||||
: "r"(0x7b) \
|
||||
: "memory"); \
|
||||
} \
|
||||
if (!Ok && X86_HAVE(RDTSCP)) { \
|
||||
asm volatile("rdtscp" \
|
||||
: "=c"(Msr) \
|
||||
: /* no inputs */ \
|
||||
: "eax", "edx", "memory"); \
|
||||
} else { \
|
||||
Ok = true; \
|
||||
} \
|
||||
if (!Ok) { \
|
||||
Msr = -1; \
|
||||
} \
|
||||
Msr; \
|
||||
|
|
|
@ -1,38 +1,3 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╠──────────────────────────────────────────────────────────────────────────────╣
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀█░█▀█░▀█▀░█░█░█▀█░█░░░█░░░█░█░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀█░█░▄░░█░░█░█░█▀█░█░░░█░░░▀█▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░▀░▀░▀▀▀░░▀░░▀▀▀░▀░▀░▀▀▀░▀▀▀░░▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀█░█▀█░█▀█░▀█▀░█▀█░█▀█░█░░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀▀░█ █░██▀░░█░░█▀█░█▀█░█░░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░▀░░░▀▀▀░▀░▀░░▀░░▀░▀░▀▀▀░▀▀▀░▀▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀▀░█░█░█▀▀░█▀█░█░█░▀█▀░█▀█░█▀█░█░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░▄▄░░░▐█░░│
|
||||
│░░░░░░░█▀▀░▄▀▄░█▀▀░█░▄░█░█░░█░░█▀█░█▀█░█░░█▀▀░░░░░░░░░░░░▄▄▄░░░▄██▄░░█▀░░░█░▄░│
|
||||
│░░░░░░░▀▀▀░▀░▀░▀▀▀░▀▀▀░▀▀▀░░▀░░▀░▀░▀▀▀░▀▀░▀▀▀░░░░░░░░░░▄██▀█▌░██▄▄░░▐█▀▄░▐█▀░░│
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▐█▀▀▌░░░▄▀▌░▌░█░▌░░▌░▌░░│
|
||||
╠──────────────────────────────────────────────────────▌▀▄─▐──▀▄─▐▄─▐▄▐▄─▐▄─▐▄─│
|
||||
│ αcτµαlly pδrταblε εxεcµταblε § telecommunications │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#ifndef COSMOPOLITAN_LIBC_NEXGEN32E_UART_H_
|
||||
#define COSMOPOLITAN_LIBC_NEXGEN32E_UART_H_
|
||||
|
||||
|
@ -53,22 +18,23 @@
|
|||
* @see www.lammertbies.nl/comm/info/serial-uart.html
|
||||
*/
|
||||
|
||||
#define COM1 0x0 /* offset in pc bios data area with port number (0x400) */
|
||||
#define COM2 0x2
|
||||
#define COM3 0x4
|
||||
#define COM4 0x6
|
||||
#define IRQ3 0x0b /* com2 interrupt number (irq3) */
|
||||
#define IRQ4 0x0c /* com1 interrupt number (irq4) */
|
||||
#define UART_DLAB (1 << 7) /* serial line conf mode bit */
|
||||
#define UART_DLL 0 /* divisor latch register */
|
||||
#define UART_DLM 1 /* divisor latch register */
|
||||
#define UART_IIR 2 /* interrupt identification register */
|
||||
#define UART_LCR 3 /* line control register */
|
||||
#define UART_LSR 5 /* line status register */
|
||||
#define UART_TTYDA (1 << 0) /* data available (rx ready) */
|
||||
#define UART_TTYOE (1 << 1) /* overrun error */
|
||||
#define UART_TTYPE (1 << 2) /* parity error */
|
||||
#define UART_TTYFE (1 << 3) /* framing error */
|
||||
#define COM1 0x0 /* offset in pc bios data area with port number (0x400) */
|
||||
#define COM2 0x2
|
||||
#define COM3 0x4
|
||||
#define COM4 0x6
|
||||
#define IRQ3 0x0b /* com2 interrupt number (irq3) */
|
||||
#define IRQ4 0x0c /* com1 interrupt number (irq4) */
|
||||
#define UART_DLAB (1 << 7) /* serial line conf mode bit */
|
||||
#define UART_DLL 0 /* divisor latch register */
|
||||
#define UART_DLM 1 /* divisor latch register */
|
||||
#define UART_IIR 2 /* interrupt identification register */
|
||||
#define UART_LCR 3 /* line control register */
|
||||
#define UART_MCR 4 /* modem control register */
|
||||
#define UART_LSR 5 /* line status register */
|
||||
#define UART_TTYDA (1 << 0) /* data available (rx ready) */
|
||||
#define UART_TTYOE (1 << 1) /* overrun error */
|
||||
#define UART_TTYPE (1 << 2) /* parity error */
|
||||
#define UART_TTYFE (1 << 3) /* framing error */
|
||||
#define UART_TTYBSR (1 << 4) /* break signal received */
|
||||
#define UART_TTYTXR (1 << 5) /* serial thr empty (tx ready) */
|
||||
#define UART_TTYIDL (1 << 6) /* serial thr empty and line idle */
|
||||
|
|
|
@ -23,12 +23,12 @@
|
|||
#include "libc/stdio/stdio.h"
|
||||
|
||||
static void fin(FILE *f) {
|
||||
f->buf[f->end] = inb(f->fd);
|
||||
f->buf[f->end] = inb(0x3F8);
|
||||
f->end = (f->end + 1) & (f->size - 1);
|
||||
}
|
||||
|
||||
static void fout(FILE *f) {
|
||||
outb(f->fd, f->buf[f->beg]);
|
||||
outb(0x3F8, f->buf[f->beg]);
|
||||
f->beg = (f->beg + 1) & (f->size - 1);
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,7 @@ static int serialstdio(FILE *f, unsigned char status, void action(FILE *)) {
|
|||
int block = 1;
|
||||
unsigned tally = 0;
|
||||
while (f->end != f->beg) {
|
||||
if (!(inb(f->fd + UART_LSR) & status)) {
|
||||
if (!(inb(0x3F8 + UART_LSR) & status)) {
|
||||
if (!block) break;
|
||||
asm("pause");
|
||||
} else {
|
||||
|
@ -50,6 +50,7 @@ static int serialstdio(FILE *f, unsigned char status, void action(FILE *)) {
|
|||
int fsreadbuf(FILE *f) {
|
||||
return serialstdio(f, UART_TTYDA, fin);
|
||||
}
|
||||
|
||||
int fswritebuf(FILE *f) {
|
||||
return serialstdio(f, UART_TTYTXR, fout);
|
||||
}
|
||||
|
|
|
@ -19,54 +19,52 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/hefty/ntspawn.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/nt/accounting.h"
|
||||
#include "libc/nt/enum/startf.h"
|
||||
#include "libc/nt/enum/status.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/process.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/startupinfo.h"
|
||||
#include "libc/nt/struct/processinformation.h"
|
||||
#include "libc/nt/synchronization.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
#define SHELL_BIN "/bin/sh"
|
||||
#define SHELL_ARG "-c"
|
||||
#define CMD_C "CMD /C "
|
||||
|
||||
static int system$sysv(const char *cmdline) {
|
||||
int rc, n, wstatus;
|
||||
struct mem {
|
||||
char shell[sizeof(SHELL_BIN)];
|
||||
char arg[sizeof(SHELL_ARG)];
|
||||
char *args[4];
|
||||
char cmdline[];
|
||||
} * mem;
|
||||
if (cmdline != NULL) {
|
||||
int pid = fork$sysv();
|
||||
if (pid == 0) {
|
||||
struct mem {
|
||||
char shell[sizeof(SHELL_BIN)];
|
||||
char arg[sizeof(SHELL_ARG)];
|
||||
char *args[4];
|
||||
char cmdline[];
|
||||
} *mem = malloc(sizeof(struct mem) + (strlen(cmdline) + 1));
|
||||
if (!mem) return enomem();
|
||||
strcpy(mem->shell, SHELL_BIN);
|
||||
strcpy(mem->arg, SHELL_ARG);
|
||||
mem->args[0] = mem->shell;
|
||||
mem->args[1] = mem->arg;
|
||||
mem->args[2] = mem->cmdline;
|
||||
mem->args[3] = NULL;
|
||||
strcpy(mem->cmdline, cmdline);
|
||||
execve$sysv(mem->shell, mem->args, environ);
|
||||
abort();
|
||||
mem = malloc(sizeof(struct mem) + (strlen(cmdline) + 1));
|
||||
if (!mem) return enomem();
|
||||
strcpy(mem->shell, SHELL_BIN);
|
||||
strcpy(mem->arg, SHELL_ARG);
|
||||
mem->args[0] = mem->shell;
|
||||
mem->args[1] = mem->arg;
|
||||
mem->args[2] = mem->cmdline;
|
||||
mem->args[3] = NULL;
|
||||
strcpy(mem->cmdline, cmdline);
|
||||
if ((rc = vfork()) != -1) {
|
||||
if (rc == 0) {
|
||||
execve$sysv(mem->shell, mem->args, environ);
|
||||
abort();
|
||||
}
|
||||
if ((rc = wait4$sysv(rc, &wstatus, 0, NULL)) != -1) {
|
||||
rc = wstatus;
|
||||
}
|
||||
}
|
||||
int rc;
|
||||
int wstatus;
|
||||
if ((rc = wait4$sysv(pid, &wstatus, 0, NULL)) != -1) rc = wstatus;
|
||||
free(mem);
|
||||
return rc;
|
||||
} else {
|
||||
return fileexists(SHELL_BIN);
|
||||
|
@ -74,27 +72,32 @@ static int system$sysv(const char *cmdline) {
|
|||
}
|
||||
|
||||
static textwindows noinline int system$nt(const char *cmdline) {
|
||||
char *mem;
|
||||
int rc, status;
|
||||
uint32_t dwExitCode;
|
||||
struct NtStartupInfo startinfo;
|
||||
struct NtProcessInformation *info;
|
||||
uint16_t *cmdline16, *quotedcmdline16;
|
||||
unsigned len, dosquotemultiplier, cmdline16bytes, quotedcmdline16bytes;
|
||||
if (cmdline != NULL) {
|
||||
int rc = -1;
|
||||
unsigned dosquotemultiplier = 2;
|
||||
unsigned len = strlen(cmdline);
|
||||
unsigned cmdline16bytes = (len + 1) * sizeof(uint16_t);
|
||||
unsigned quotedcmdline16bytes =
|
||||
rc = -1;
|
||||
dosquotemultiplier = 2;
|
||||
len = strlen(cmdline);
|
||||
cmdline16bytes = (len + 1) * sizeof(uint16_t);
|
||||
quotedcmdline16bytes =
|
||||
strlen(CMD_C) * sizeof(uint16_t) + cmdline16bytes * dosquotemultiplier;
|
||||
void *mem = malloc(sizeof(struct NtProcessInformation) + cmdline16bytes +
|
||||
quotedcmdline16bytes);
|
||||
if (mem == NULL) return enomem();
|
||||
struct NtProcessInformation *info = mem;
|
||||
uint16_t *cmdline16 =
|
||||
(uint16_t *)((char *)mem + sizeof(struct NtProcessInformation));
|
||||
uint16_t *quotedcmdline16 =
|
||||
(uint16_t *)((char *)mem + sizeof(struct NtProcessInformation) +
|
||||
cmdline16bytes);
|
||||
if (!(mem = malloc(sizeof(struct NtProcessInformation) + cmdline16bytes +
|
||||
quotedcmdline16bytes))) {
|
||||
return enomem();
|
||||
}
|
||||
info = (struct NtProcessInformation *)mem;
|
||||
cmdline16 = (uint16_t *)(mem + sizeof(struct NtProcessInformation));
|
||||
quotedcmdline16 = (uint16_t *)(mem + sizeof(struct NtProcessInformation) +
|
||||
cmdline16bytes);
|
||||
strcpyzbw(cmdline16, cmdline);
|
||||
strcpyzbw(quotedcmdline16, CMD_C);
|
||||
if (escapedos(quotedcmdline16 + strlen(CMD_C), len * dosquotemultiplier,
|
||||
cmdline16, len)) {
|
||||
struct NtStartupInfo startinfo;
|
||||
memset(&startinfo, 0, sizeof(startinfo));
|
||||
startinfo.cb = sizeof(struct NtStartupInfo);
|
||||
startinfo.dwFlags = kNtStartfUsestdhandles;
|
||||
|
@ -112,8 +115,7 @@ static textwindows noinline int system$nt(const char *cmdline) {
|
|||
/* lpCurrentDirectory */ NULL,
|
||||
/* lpStartupInfo */ &startinfo,
|
||||
/* lpProcessInformation */ info)) {
|
||||
uint32_t dwExitCode = kNtStillActive;
|
||||
int status;
|
||||
dwExitCode = kNtStillActive;
|
||||
do {
|
||||
WaitForSingleObject(info->hProcess, 0xffffffff);
|
||||
} while ((status = GetExitCodeProcess(info->hProcess, &dwExitCode)) &&
|
||||
|
@ -130,7 +132,7 @@ static textwindows noinline int system$nt(const char *cmdline) {
|
|||
} else {
|
||||
rc = einval();
|
||||
}
|
||||
free(mem), mem = NULL;
|
||||
free(mem);
|
||||
return rc;
|
||||
} else {
|
||||
/* how could cmd.exe not exist? */
|
||||
|
|
|
@ -166,6 +166,8 @@ systemfive.xnu:
|
|||
.init.start 300,_init_systemfive
|
||||
push %rbx
|
||||
push %rsi
|
||||
testb $METAL,(%rdi) # @see ape/ape.S
|
||||
jnz systemfive.init.metal
|
||||
testb $XNU,(%rdi) # @see libc/crt/crt.S
|
||||
jnz systemfive.init.xnu
|
||||
testb $FREEBSD,(%rdi) # @see libc/crt/crt.S
|
||||
|
@ -181,6 +183,11 @@ systemfive.init.linux:
|
|||
push $LINUX
|
||||
ezlea syscon.linux,si
|
||||
jmp systemfive.init.os
|
||||
systemfive.init.metal:
|
||||
pushb systemfive.linux-.Lanchorpoint
|
||||
push $METAL
|
||||
ezlea syscon.linux,si
|
||||
jmp systemfive.init.os
|
||||
systemfive.init.windows:
|
||||
pushb systemfive.enosys-.Lanchorpoint
|
||||
push $WINDOWS
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue