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:
Justine Tunney 2020-10-29 04:53:20 -07:00
parent feed0d2b0e
commit 2d80bbc802
50 changed files with 974 additions and 1062 deletions

View file

@ -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();

View file

@ -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__

View 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

View file

@ -140,6 +140,7 @@ static const char *__asan_describe_access_poison(int c) {
case kAsanUnscoped:
return "unscoped";
default:
DebugBreak();
return "poisoned";
}
}

View file

@ -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

View file

@ -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; \

View file

@ -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 */

View file

@ -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);
}

View file

@ -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? */

View file

@ -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