mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-14 06:59:10 +00:00
Add x86_64-linux-gnu emulator
I wanted a tiny scriptable meltdown proof way to run userspace programs and visualize how program execution impacts memory. It helps to explain how things like Actually Portable Executable works. It can show you how the GCC generated code is going about manipulating matrices and more. I didn't feel fully comfortable with Qemu and Bochs because I'm not smart enough to understand them. I wanted something like gVisor but with much stronger levels of assurances. I wanted a single binary that'll run, on all major operating systems with an embedded GPL barrier ZIP filesystem that is tiny enough to transpile to JavaScript and run in browsers too. https://justine.storage.googleapis.com/emulator625.mp4
This commit is contained in:
parent
467504308a
commit
f4f4caab0e
1052 changed files with 65667 additions and 7825 deletions
47
ape/ape.S
47
ape/ape.S
|
@ -44,6 +44,7 @@
|
|||
#include "libc/nexgen32e/uart.h"
|
||||
#include "libc/nexgen32e/vidya.h"
|
||||
#include "libc/nt/pedef.h"
|
||||
#include "libc/nexgen32e/vidya.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
|
||||
.source "NOTICE"
|
||||
|
@ -136,43 +137,24 @@ ape.mz: .ascii "MZ" # Mark 'Zibo' Joseph Zbikowski
|
|||
.short 0 # MZ: OEM information
|
||||
.org 0x40-4 # MZ: bytes reserved for you
|
||||
.long RVA(ape.pe) # PE: the new technology
|
||||
.endobj ape.mz,globl,hidden
|
||||
.endfn ape.mz,globl,hidden
|
||||
|
||||
/ Disk Operating System Stub
|
||||
/ @noreturn
|
||||
.org 0x40 # mz/elf header length
|
||||
stub: mov $0x40,%dl # *literally* dos
|
||||
jmp 1f # good bios skips here
|
||||
1: jmp pc
|
||||
1: jmp pc # thus avoiding heroics
|
||||
nop # system five bootpoint
|
||||
.org 0x48,0x90 # ⌂ELF → JNLE 47
|
||||
jmp 3f
|
||||
2: push %rdx # don't move or shell script breaks
|
||||
xor %edx,%edx # Z in MZ ate BIOS drive letter :(
|
||||
3: .byte 0xbd,0,0 # mov $0x????0000,%[e]bp
|
||||
jmp pc
|
||||
jmp ape.hop # already in userspace
|
||||
.org 0x48,0x90 # note ⌂ELF means JG 47
|
||||
jmp 3f # MZ also means pop r10
|
||||
2: sub $8,%rsp # a.k.a. dec %ax sub %sp
|
||||
xor %edx,%edx # MZ ate BIOS drive code
|
||||
3: .byte 0xbd,0,0 # a.k.a. mov imm,%bp
|
||||
jmp pc # real mode, is real
|
||||
jmp _start # surprise it's unix
|
||||
.endfn stub
|
||||
|
||||
/ Mitigate incidental quotation marks.
|
||||
.real
|
||||
ape.hop:pop %rdx
|
||||
push %r10 # MZ → pop %r10 w/ NexGen32e
|
||||
.weak __imp_GetStartupInfoW
|
||||
ezlea __imp_GetStartupInfoW,ax
|
||||
test %rax,%rax
|
||||
jz 0f
|
||||
.weak KernelBase.GetStartupInfo
|
||||
test %rax,%rax
|
||||
/ TODO(jart)
|
||||
/ cmpq $RVA(KernelBase.GetStartupInfo),(%rax)
|
||||
jz 0f
|
||||
jmp WinMain
|
||||
0: .weak _start
|
||||
jmp _start
|
||||
.endfn ape.hop
|
||||
.previous
|
||||
|
||||
/*─────────────────────────────────────────────────────────────────────────────╗
|
||||
│ αcτµαlly pδrταblε εxεcµταblε § ibm personal computer │
|
||||
╚──────────────────────────────────────────────────────────────────────────────┘
|
||||
|
@ -835,9 +817,9 @@ ape.pe: .ascin "PE",4
|
|||
.short v_ntsubsystem # Subsystem: 0=Neutral,2=GUI,3=Console
|
||||
.short .LDLLEXE # DllCharacteristics
|
||||
.quad 0x0000000000100000 # StackReserve
|
||||
.quad 0x0000000000030000 # StackCommit (64kb [goog] + arg + env)
|
||||
.quad 0x0000000000100000 # StackCommit
|
||||
.quad 0x0000000000080000 # HeapReserve
|
||||
.quad 0x0000000000001000 # HeapCommit (we make our own heap)
|
||||
.quad 0x0000000000001000 # HeapCommit
|
||||
.long 0x00000000 # LoaderFlags
|
||||
.long 16 # NumberOfDirectoryEntries
|
||||
.long 0,0 # ExportsDirectory
|
||||
|
@ -1933,5 +1915,10 @@ __data_start:
|
|||
.type __piro_start,@object
|
||||
.hidden __piro_start
|
||||
|
||||
.type __ubsan_data_start,@object
|
||||
.type __ubsan_data_end,@object
|
||||
.type __ubsan_types_start,@object
|
||||
.type __ubsan_types_end,@object
|
||||
|
||||
.end
|
||||
|
60
ape/ape.lds
60
ape/ape.lds
|
@ -435,36 +435,36 @@ SECTIONS {
|
|||
/*END: linux addressability guarantee */
|
||||
/*END: xnu addressability guarantee */
|
||||
|
||||
.stab 0 : { *(.stab) }
|
||||
.stabstr 0 : { *(.stabstr) }
|
||||
.stab.excl 0 : { *(.stab.excl) }
|
||||
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||
.stab.index 0 : { *(.stab.index) }
|
||||
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||
.comment 0 : { *(.comment) }
|
||||
.debug 0 : { *(.debug) }
|
||||
.line 0 : { *(.line) }
|
||||
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||
.debug_aranges 0 : { *(.debug_aranges) }
|
||||
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
|
||||
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||
.debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end ) }
|
||||
.debug_frame 0 : { *(.debug_frame) }
|
||||
.debug_str 0 : { *(.debug_str) }
|
||||
.debug_loc 0 : { *(.debug_loc) }
|
||||
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||
.debug_weaknames 0 : { *(.debug_weaknames) }
|
||||
.debug_funcnames 0 : { *(.debug_funcnames) }
|
||||
.debug_typenames 0 : { *(.debug_typenames) }
|
||||
.debug_varnames 0 : { *(.debug_varnames) }
|
||||
.debug_pubtypes 0 : { *(.debug_pubtypes) }
|
||||
.debug_ranges 0 : { *(.debug_ranges) }
|
||||
.debug_macro 0 : { *(.debug_macro) }
|
||||
.debug_addr 0 : { *(.debug_addr) }
|
||||
.gnu.attributes 0 : { KEEP(*(.gnu.attributes)) }
|
||||
.GCC.command.line 0 : { *(.GCC.command.line) }
|
||||
.stab 0 : { *(.stab) }
|
||||
.stabstr 0 : { *(.stabstr) }
|
||||
.stab.excl 0 : { *(.stab.excl) }
|
||||
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||
.stab.index 0 : { *(.stab.index) }
|
||||
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||
.comment 0 : { *(.comment) }
|
||||
.debug 0 : { *(.debug) }
|
||||
.line 0 : { *(.line) }
|
||||
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||
.debug_aranges 0 : { *(.debug_aranges) }
|
||||
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
|
||||
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||
.debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end ) }
|
||||
.debug_frame 0 : { *(.debug_frame) }
|
||||
.debug_str 0 : { *(.debug_str) }
|
||||
.debug_loc 0 : { *(.debug_loc) }
|
||||
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||
.debug_weaknames 0 : { *(.debug_weaknames) }
|
||||
.debug_funcnames 0 : { *(.debug_funcnames) }
|
||||
.debug_typenames 0 : { *(.debug_typenames) }
|
||||
.debug_varnames 0 : { *(.debug_varnames) }
|
||||
.debug_pubtypes 0 : { *(.debug_pubtypes) }
|
||||
.debug_ranges 0 : { *(.debug_ranges) }
|
||||
.debug_macro 0 : { *(.debug_macro) }
|
||||
.debug_addr 0 : { *(.debug_addr) }
|
||||
.gnu.attributes 0 : { KEEP(*(.gnu.attributes)) }
|
||||
.GCC.command.line 0 : { *(.GCC.command.line) }
|
||||
|
||||
/DISCARD/ : {
|
||||
*(.discard)
|
||||
|
|
18
ape/ape.mk
18
ape/ape.mk
|
@ -21,8 +21,7 @@ APE = $(APE_DEPS) \
|
|||
|
||||
APELINK = \
|
||||
ACTION=LINK.ape \
|
||||
$(MKDIR) \
|
||||
$(dir $@) && \
|
||||
$(MKDIR) $(@D) && \
|
||||
$(LINK) \
|
||||
$(LINKARGS) \
|
||||
$(OUTPUT_OPTION) && \
|
||||
|
@ -32,18 +31,6 @@ APELINK = \
|
|||
$(ZFLAGS) \
|
||||
-f $@.map
|
||||
|
||||
APECOPY = \
|
||||
ACTION=OBJCOPY.ape \
|
||||
TARGET=$@ \
|
||||
build/do \
|
||||
$(OBJCOPY) \
|
||||
-SO binary \
|
||||
$< \
|
||||
$@
|
||||
|
||||
DEFAULT_COPTS += -mno-red-zone
|
||||
DEFAULT_LDFLAGS += -z max-page-size=0x1000
|
||||
|
||||
APE_FILES := $(wildcard ape/*.*)
|
||||
APE_HDRS = $(filter %.h,$(APE_FILES))
|
||||
APE_SRCS = $(filter %.S,$(APE_FILES))
|
||||
|
@ -51,9 +38,6 @@ APE_OBJS = $(APE_SRCS:%.S=o/$(MODE)/%.o)
|
|||
APE_DEPS = $(APE_LIB)
|
||||
APE_CHECKS = $(APE_HDRS:%=o/%.ok)
|
||||
|
||||
o/%.com: o/%.com.dbg
|
||||
@$(APECOPY)
|
||||
|
||||
o/ape/idata.inc: \
|
||||
ape/idata.h \
|
||||
ape/relocations.h
|
||||
|
|
32
ape/idata.h
32
ape/idata.h
|
@ -32,39 +32,35 @@
|
|||
/ @see libc/nt/master.sh
|
||||
/ @see ape/ape.lds
|
||||
/ @see winimp
|
||||
.macro .imp dll:req fn:req actual hint
|
||||
.macro .imp dll:req fn:req actual:req hint
|
||||
.dll \dll
|
||||
.section .piro.data.sort.iat.2.\dll\().2.\fn,"aw",@progbits
|
||||
.section .piro.data.sort.iat.2.\dll\().2.\actual,"aw",@progbits
|
||||
.type \fn,@object
|
||||
.align __SIZEOF_POINTER__
|
||||
\fn: .quad RVA((.L\dll\().\fn))
|
||||
\fn: .quad RVA((\dll\().\actual))
|
||||
.size \fn,.-\fn
|
||||
.globl \fn
|
||||
.hidden \fn
|
||||
.previous
|
||||
.section .idata.ro.ilt.\dll\().2.\fn,"a",@progbits
|
||||
.Lidata.ilt.\dll\().\fn:
|
||||
.quad RVA((.L\dll\().\fn))
|
||||
.type .Lidata.ilt..L\dll\().\fn,@object
|
||||
.size .Lidata.ilt..L\dll\().\fn,.-.Lidata.ilt.\dll\().\fn
|
||||
.section .idata.ro.ilt.\dll\().2.\actual,"a",@progbits
|
||||
.Lidata.ilt.\dll\().\actual:
|
||||
.quad RVA((\dll\().\actual))
|
||||
.type .Lidata.ilt.\dll\().\actual,@object
|
||||
.size .Lidata.ilt.\dll\().\actual,.-.Lidata.ilt.\dll\().\actual
|
||||
.previous
|
||||
.section .idata.ro.hnt.\dll\().2.\fn,"a",@progbits
|
||||
.L\dll\().\fn:
|
||||
.section .idata.ro.hnt.\dll\().2.\actual,"a",@progbits
|
||||
\dll\().\actual:
|
||||
.ifnb \hint # hint i.e. guess function ordinal
|
||||
.short \hint
|
||||
.else
|
||||
.short 0
|
||||
.endif
|
||||
.ifnb \actual # name
|
||||
.asciz "\actual"
|
||||
.else
|
||||
.asciz "\fn"
|
||||
.endif
|
||||
.align 2 # documented requirement
|
||||
/ .globl .L\dll\().\fn
|
||||
/ .hidden .L\dll\().\fn
|
||||
.type .L\dll\().\fn,@object
|
||||
.size .L\dll\().\fn,.-.L\dll\().\fn
|
||||
.globl \dll\().\actual
|
||||
.hidden \dll\().\actual
|
||||
.type \dll\().\actual,@object
|
||||
.size \dll\().\actual,.-\dll\().\actual
|
||||
.previous
|
||||
.endm
|
||||
|
||||
|
|
|
@ -52,11 +52,13 @@
|
|||
SF: Stack Fault ────────────────┐││││││
|
||||
ES: Exception Summary Status ──┐│││││││
|
||||
C0-3: Condition Codes ──┬────┐ ││││││││
|
||||
Top of Stack Pointer ─────┐ │ ││││││││
|
||||
TOP of Stack Pointer ─────┐ │ ││││││││
|
||||
B: FPU Busy ───────────┐│ │ │ ││││││││
|
||||
││┌┴┐┌┼┐││││││││
|
||||
│↓│ │↓↓↓││││││││*/
|
||||
#define FPU_IE 0b0000000000100000000000001
|
||||
#define FPU_ZE 0b0000000000100000000000100
|
||||
#define FPU_SF 0b0000000000000000001000000
|
||||
#define FPU_C0 0b0000000000000000100000000
|
||||
#define FPU_C1 0b0000000000000001000000000
|
||||
#define FPU_C2 0b0000000000000010000000000
|
||||
|
@ -151,6 +153,7 @@
|
|||
#define PAGE_V /* */ 0b000000001
|
||||
#define PAGE_RW /* */ 0b000000010
|
||||
#define PAGE_U /* */ 0b000000100
|
||||
#define PAGE_4KB /* */ 0b010000000
|
||||
#define PAGE_2MB /* */ 0b110000000
|
||||
#define PAGE_1GB /* */ 0b110000000
|
||||
#define PAGE_TA 0b11111111111111111111111111111111111111000000000000
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue