Skip to content

Commit 120b271

Browse files
committed
Initial import
0 parents  commit 120b271

File tree

197 files changed

+30045
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

197 files changed

+30045
-0
lines changed

.clang-format

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
BasedOnStyle: Google
3+
StatementMacros:
4+
- INITIALIZER
5+
AlignConsecutiveMacros: true
6+
AlignConsecutiveDeclarations: false
7+
AlwaysBreakBeforeMultilineStrings: false
8+
AllowShortFunctionsOnASingleLine: false
9+
KeepEmptyLinesAtTheStartOfBlocks: true
10+
ConstructorInitializerAllOnOneLineOrOnePerLine: true
11+
---
12+
Language: Cpp
13+
AllowShortFunctionsOnASingleLine: false
14+
---
15+
Language: Proto
16+
...

.gitattributes

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# -*- conf -*-
2+
*.xz binary
3+
*.com binary
4+
*.elf binary

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# -*- conf -*-
2+
*.xz
3+
/o
4+
/HTAGS
5+
/TAGS
6+
/perf.data
7+
/perf.data.old

LICENSE

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
ISC License
2+
3+
Copyright 2022 Justine Alexandra Roberts Tunney
4+
5+
Permission to use, copy, modify, and/or distribute this software for
6+
any purpose with or without fee is hereby granted, provided that the
7+
above copyright notice and this permission notice appear in all copies.
8+
9+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10+
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11+
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12+
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13+
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14+
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15+
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16+
PERFORMANCE OF THIS SOFTWARE.

Makefile

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
2+
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
3+
4+
SHELL = /bin/sh
5+
MAKEFLAGS += --no-builtin-rules
6+
7+
.SUFFIXES:
8+
.DELETE_ON_ERROR:
9+
.FEATURES: output-sync
10+
.PHONY: o clean
11+
12+
o: o/$(MODE)/blink
13+
test: o/$(MODE)/test
14+
clean:; rm -rf o
15+
tags: TAGS HTAGS
16+
17+
include build/config.mk
18+
include build/rules.mk
19+
include blink/blink.mk
20+
include test/test.mk
21+
include test/blink/test.mk
22+
include third_party/gcc/gcc.mk
23+
include third_party/qemu/qemu.mk
24+
25+
OBJS = $(foreach x,$(PKGS),$($(x)_OBJS))
26+
SRCS := $(foreach x,$(PKGS),$($(x)_SRCS))
27+
HDRS := $(foreach x,$(PKGS),$($(x)_HDRS))
28+
INCS = $(foreach x,$(PKGS),$($(x)_INCS))
29+
BINS = $(foreach x,$(PKGS),$($(x)_BINS))
30+
TESTS = $(foreach x,$(PKGS),$($(x)_TESTS))
31+
CHECKS = $(foreach x,$(PKGS),$($(x)_CHECKS))
32+
33+
o/$(MODE)/.x:
34+
mkdir -p $(@D)
35+
touch $@
36+
o/$(MODE)/srcs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(SRCS),$(dir $(x))))
37+
$(file >$@) $(foreach x,$(SRCS),$(file >>$@,$(x)))
38+
o/$(MODE)/hdrs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(HDRS) $(INCS),$(dir $(x))))
39+
$(file >$@) $(foreach x,$(HDRS) $(INCS),$(file >>$@,$(x)))
40+
41+
DEPENDS = \
42+
o/$(MODE)/depend.host \
43+
o/$(MODE)/depend.i486 \
44+
o/$(MODE)/depend.m68k \
45+
o/$(MODE)/depend.x86_64 \
46+
o/$(MODE)/depend.arm \
47+
o/$(MODE)/depend.aarch64 \
48+
o/$(MODE)/depend.riscv64 \
49+
o/$(MODE)/depend.mips \
50+
o/$(MODE)/depend.mipsel \
51+
o/$(MODE)/depend.mips64 \
52+
o/$(MODE)/depend.mips64el \
53+
o/$(MODE)/depend.s390x \
54+
o/$(MODE)/depend.microblaze \
55+
o/$(MODE)/depend.powerpc \
56+
o/$(MODE)/depend.powerpc64le
57+
58+
o/$(MODE)/depend: $(DEPENDS)
59+
cat $^ >$@
60+
o/$(MODE)/depend.host: build/bootstrap/mkdeps.com o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt
61+
build/bootstrap/mkdeps.com -o $@ -r o/$(MODE)/ @o/$(MODE)/srcs.txt @o/$(MODE)/hdrs.txt
62+
o/$(MODE)/depend.i486: build/bootstrap/mkdeps.com o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt
63+
build/bootstrap/mkdeps.com -o $@ -r o/$(MODE)/i486/ @o/$(MODE)/srcs.txt @o/$(MODE)/hdrs.txt
64+
o/$(MODE)/depend.m68k: build/bootstrap/mkdeps.com o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt
65+
build/bootstrap/mkdeps.com -o $@ -r o/$(MODE)/m68k/ @o/$(MODE)/srcs.txt @o/$(MODE)/hdrs.txt
66+
o/$(MODE)/depend.x86_64: build/bootstrap/mkdeps.com o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt
67+
build/bootstrap/mkdeps.com -o $@ -r o/$(MODE)/x86_64/ @o/$(MODE)/srcs.txt @o/$(MODE)/hdrs.txt
68+
o/$(MODE)/depend.x86_64-gcc48: build/bootstrap/mkdeps.com o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt
69+
build/bootstrap/mkdeps.com -o $@ -r o/$(MODE)/x86_64-gcc48/ @o/$(MODE)/srcs.txt @o/$(MODE)/hdrs.txt
70+
o/$(MODE)/depend.arm: build/bootstrap/mkdeps.com o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt
71+
build/bootstrap/mkdeps.com -o $@ -r o/$(MODE)/arm/ @o/$(MODE)/srcs.txt @o/$(MODE)/hdrs.txt
72+
o/$(MODE)/depend.aarch64: build/bootstrap/mkdeps.com o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt
73+
build/bootstrap/mkdeps.com -o $@ -r o/$(MODE)/aarch64/ @o/$(MODE)/srcs.txt @o/$(MODE)/hdrs.txt
74+
o/$(MODE)/depend.riscv64: build/bootstrap/mkdeps.com o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt
75+
build/bootstrap/mkdeps.com -o $@ -r o/$(MODE)/riscv64/ @o/$(MODE)/srcs.txt @o/$(MODE)/hdrs.txt
76+
o/$(MODE)/depend.mips: build/bootstrap/mkdeps.com o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt
77+
build/bootstrap/mkdeps.com -o $@ -r o/$(MODE)/mips/ @o/$(MODE)/srcs.txt @o/$(MODE)/hdrs.txt
78+
o/$(MODE)/depend.mipsel: build/bootstrap/mkdeps.com o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt
79+
build/bootstrap/mkdeps.com -o $@ -r o/$(MODE)/mipsel/ @o/$(MODE)/srcs.txt @o/$(MODE)/hdrs.txt
80+
o/$(MODE)/depend.mips64: build/bootstrap/mkdeps.com o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt
81+
build/bootstrap/mkdeps.com -o $@ -r o/$(MODE)/mips64/ @o/$(MODE)/srcs.txt @o/$(MODE)/hdrs.txt
82+
o/$(MODE)/depend.mips64el: build/bootstrap/mkdeps.com o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt
83+
build/bootstrap/mkdeps.com -o $@ -r o/$(MODE)/mips64el/ @o/$(MODE)/srcs.txt @o/$(MODE)/hdrs.txt
84+
o/$(MODE)/depend.s390x: build/bootstrap/mkdeps.com o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt
85+
build/bootstrap/mkdeps.com -o $@ -r o/$(MODE)/s390x/ @o/$(MODE)/srcs.txt @o/$(MODE)/hdrs.txt
86+
o/$(MODE)/depend.microblaze: build/bootstrap/mkdeps.com o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt
87+
build/bootstrap/mkdeps.com -o $@ -r o/$(MODE)/microblaze/ @o/$(MODE)/srcs.txt @o/$(MODE)/hdrs.txt
88+
o/$(MODE)/depend.powerpc: build/bootstrap/mkdeps.com o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt
89+
build/bootstrap/mkdeps.com -o $@ -r o/$(MODE)/powerpc/ @o/$(MODE)/srcs.txt @o/$(MODE)/hdrs.txt
90+
o/$(MODE)/depend.powerpc64le: build/bootstrap/mkdeps.com o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt
91+
build/bootstrap/mkdeps.com -o $@ -r o/$(MODE)/powerpc64le/ @o/$(MODE)/srcs.txt @o/$(MODE)/hdrs.txt
92+
93+
TAGS: o/$(MODE)/srcs.txt $(SRCS)
94+
$(RM) $@
95+
$(TAGS) $(TAGSFLAGS) -L $< -o $@
96+
97+
HTAGS: o/$(MODE)/hdrs.txt $(HDRS)
98+
$(RM) $@
99+
build/htags -L $< -o $@
100+
101+
$(SRCS):
102+
$(HDRS):
103+
$(INCS):
104+
.DEFAULT:
105+
@echo >&2
106+
@echo NOTE: deleting o/$(MODE)/depend because of an unspecified prerequisite: $@ >&2
107+
@echo >&2
108+
rm -f o/$(MODE)/depend $(DEPENDS)
109+
110+
-include o/$(MODE)/depend

README.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# blink
2+
3+
blink is an emulator for running x86-64-linux programs on different
4+
operating systems and hardware architectures. It's designed to do the
5+
same thing as the `qemu-x86_64` command, except rather than being a 10mb
6+
binary, blink only has a ~200kb footprint. For further details on the
7+
motivations for this tool, please read <https://justine.lol/ape.html>.
8+
9+
## Getting Started
10+
11+
You can compile blink on x86-64 Linux, Darwin, FreeBSD, NetBSD, OpenBSD,
12+
or Apple Silicon with Rosetta installed, using your platform toolchain.
13+
14+
```sh
15+
$ make -j8 o///blink/blink
16+
$ o///blink/blink third_party/cosmo/hello.com
17+
hello world
18+
$ o///blink/blink third_party/cosmo/tinyhello.elf
19+
hello world
20+
```
21+
22+
There's a terminal interface for debugging:
23+
24+
```
25+
$ make -j8 o///blink/tui
26+
$ o///blink/tui third_party/cosmo/tinyhello.elf
27+
```
28+
29+
On x86-64 Linux you can cross-compile blink for Linux systems with x86,
30+
arm, m68k, riscv, mips, s390x, powerpc, or microblaze cpus. This happens
31+
using vendored musl-cross-make toolchains and static qemu for testing.
32+
33+
```sh
34+
$ make -j8 test
35+
$ o/third_party/qemu/qemu-aarch64 o//aarch64/blink/blink third_party/cosmo/hello.com
36+
hello world
37+
```
38+
39+
## Technical Details
40+
41+
blink is an x86-64 interpreter written in straightforward POSIX ANSI C.
42+
Similar to Bochs, there's no JIT or code generation currently in blink.
43+
Therefore you're trading away performance for a tinier emulator that'll
44+
just work, is ISC (rather than GPL) licensed and it won't let untrusted
45+
code get too close to your hardware. Instruction decoding is done using
46+
our trimmed-down version of Intel's disassembler Xed.

blink/address.c

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
2+
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
3+
╞══════════════════════════════════════════════════════════════════════════════╡
4+
│ Copyright 2022 Justine Alexandra Roberts Tunney │
5+
│ │
6+
│ Permission to use, copy, modify, and/or distribute this software for │
7+
│ any purpose with or without fee is hereby granted, provided that the │
8+
│ above copyright notice and this permission notice appear in all copies. │
9+
│ │
10+
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
11+
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
12+
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
13+
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
14+
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
15+
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
16+
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
17+
│ PERFORMANCE OF THIS SOFTWARE. │
18+
╚─────────────────────────────────────────────────────────────────────────────*/
19+
#include "blink/address.h"
20+
#include "blink/builtin.h"
21+
#include "blink/endian.h"
22+
#include "blink/modrm.h"
23+
#include "blink/throw.h"
24+
#include "blink/x86.h"
25+
26+
uint64_t AddressOb(struct Machine *m, uint32_t rde) {
27+
return AddSegment(m, rde, m->xedd->op.disp, m->ds);
28+
}
29+
30+
uint8_t *GetSegment(struct Machine *m, uint32_t rde, int s) {
31+
switch (s & 7) {
32+
case 0:
33+
return m->es;
34+
case 1:
35+
return m->cs;
36+
case 2:
37+
return m->ss;
38+
case 3:
39+
return m->ds;
40+
case 4:
41+
return m->fs;
42+
case 5:
43+
return m->gs;
44+
case 6:
45+
case 7:
46+
OpUd(m, rde);
47+
default:
48+
__builtin_unreachable();
49+
}
50+
}
51+
52+
uint64_t DataSegment(struct Machine *m, uint32_t rde, uint64_t i) {
53+
return AddSegment(m, rde, i, m->ds);
54+
}
55+
56+
uint64_t AddressSi(struct Machine *m, uint32_t rde) {
57+
switch (Eamode(rde)) {
58+
case XED_MODE_LONG:
59+
return DataSegment(m, rde, Read64(m->si));
60+
case XED_MODE_REAL:
61+
return DataSegment(m, rde, Read16(m->si));
62+
case XED_MODE_LEGACY:
63+
return DataSegment(m, rde, Read32(m->si));
64+
default:
65+
__builtin_unreachable();
66+
}
67+
}
68+
69+
uint64_t AddressDi(struct Machine *m, uint32_t rde) {
70+
uint64_t i = Read64(m->es);
71+
switch (Eamode(rde)) {
72+
case XED_MODE_LONG:
73+
return i + Read64(m->di);
74+
case XED_MODE_REAL:
75+
return i + Read16(m->di);
76+
case XED_MODE_LEGACY:
77+
return i + Read32(m->di);
78+
default:
79+
__builtin_unreachable();
80+
}
81+
}

blink/address.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#ifndef BLINK_ADDRESS_H_
2+
#define BLINK_ADDRESS_H_
3+
#include "blink/endian.h"
4+
#include "blink/machine.h"
5+
#include "blink/modrm.h"
6+
7+
uint64_t AddressOb(struct Machine *, uint32_t);
8+
uint64_t AddressDi(struct Machine *, uint32_t);
9+
uint64_t AddressSi(struct Machine *, uint32_t);
10+
uint8_t *GetSegment(struct Machine *, uint32_t, int);
11+
uint64_t DataSegment(struct Machine *, uint32_t, uint64_t);
12+
13+
static inline uint64_t MaskAddress(uint32_t mode, uint64_t x) {
14+
if (mode != XED_MODE_LONG) {
15+
if (mode == XED_MODE_REAL) {
16+
x &= 0xffff;
17+
} else {
18+
x &= 0xffffffff;
19+
}
20+
}
21+
return x;
22+
}
23+
24+
static inline uint64_t AddSegment(struct Machine *m, uint32_t rde, uint64_t i,
25+
const uint8_t s[8]) {
26+
if (!Sego(rde)) {
27+
return i + Read64(s);
28+
} else {
29+
return i + Read64(GetSegment(m, rde, Sego(rde) - 1));
30+
}
31+
}
32+
33+
#endif /* BLINK_ADDRESS_H_ */

0 commit comments

Comments
 (0)