mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-02-07 15:03:34 +00:00
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
360 lines
9.5 KiB
EmacsLisp
360 lines
9.5 KiB
EmacsLisp
;; ╔──────────────────────────────────────────────────────────────────╗
|
||
;; │ To the extent possible under law, Justine Tunney has waived │
|
||
;; │ all copyright and related or neighboring rights to this file, │
|
||
;; │ as it is written in the following disclaimers: │
|
||
;; │ • http://unlicense.org/ │
|
||
;; │ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||
;; ╚──────────────────────────────────────────────────────────────────╝
|
||
;; Reconfigures GNU Emacs syntax highlighting for GNU Assembler syntax.
|
||
|
||
(require 'asm-mode)
|
||
(require 'cosmo-cpp-constants)
|
||
|
||
(defun cosmo-regexpify (x)
|
||
(let ((join (lambda (sep lis)
|
||
(mapconcat 'identity lis sep))))
|
||
(cond ((vectorp x)
|
||
(funcall join "" (mapcar 'cosmo-regexpify x)))
|
||
((listp x)
|
||
(concat "\\(?:"
|
||
(funcall join "\\|" (mapcar 'cosmo-regexpify x))
|
||
"\\)"))
|
||
('t x))))
|
||
|
||
(defun cosmo-fontify (faces regexp limit predicate)
|
||
"Set FACES on REGEXP matches until LIMIT that satisfy PREDICATE."
|
||
(while (re-search-forward regexp limit t)
|
||
(let (i (face (save-excursion
|
||
(backward-char)
|
||
(face-at-point)))
|
||
(syntax (syntax-ppss)))
|
||
(when (funcall predicate face syntax)
|
||
(dolist (i faces)
|
||
(put-text-property (match-beginning (car i))
|
||
(match-end (car i))
|
||
'face
|
||
(cdr i)))))))
|
||
|
||
(defconst asm-mode-gas-qualifiers-regexp
|
||
(cosmo-regexpify
|
||
[("comdat"
|
||
":req"
|
||
":vararg"
|
||
["@" (;; calculates offset relative to tls block end
|
||
;; load: mov %fs:boop@tpoff,%eax
|
||
;; addr: mov %fs:0,%rax
|
||
;; lea x1@tpoff(%rax),%rax
|
||
;; addr: mov %fs:0,%rax
|
||
;; add $x1@tpoff,%rax
|
||
"tpoff"
|
||
;; allocates TLS_index structure
|
||
;; lea x@tlsgd(,%rbx,1),%rdi
|
||
;; call __tls_get_addr@plt
|
||
"tlsgd"
|
||
"tlsld"
|
||
"dtpmod"
|
||
"dtpoff"
|
||
"gottpoff"
|
||
"function"
|
||
"object"
|
||
"got"
|
||
"size"
|
||
"gotoff"
|
||
"plt"
|
||
"pltoff"
|
||
"gotpcrel"
|
||
"progbits"
|
||
"nobits"
|
||
"init_array"
|
||
"fini_array")])
|
||
"\\>"])
|
||
"GNU Assembler section, relocation, macro param qualifiers.")
|
||
|
||
(defconst asm-mode-doctag-regexp
|
||
(cosmo-regexpify
|
||
'(["<"
|
||
("p" "br"
|
||
"b" "/b"
|
||
"i" "/i"
|
||
"pre" "/pre"
|
||
"h3" "h4" "/h3" "/h4"
|
||
"ul" "ol" "li" "/ol" "/ul"
|
||
"dl" "dt" "dd" "/dl"
|
||
"table" "tr" "td" "th" "td" "/table")
|
||
">"]
|
||
["@"
|
||
("param"
|
||
"return"
|
||
"define"
|
||
"see"
|
||
"throws"
|
||
"returnstwice"
|
||
"fileoverview"
|
||
"nullable"
|
||
"noreturn"
|
||
"domain"
|
||
"clob"
|
||
"since"
|
||
"forcealignargpointer"
|
||
"mode"
|
||
"speed"
|
||
"cost"
|
||
"todo"
|
||
"assume"
|
||
"define"
|
||
"domain"
|
||
"code"
|
||
"note"
|
||
"protip"
|
||
"nxbitsafe"
|
||
"preinitsafe"
|
||
"asyncsignalsafe"
|
||
"notasyncsignalsafe"
|
||
"isa"
|
||
"sideffect")
|
||
"\\>"]))
|
||
"Assembly docstring highlighting in Google Java Style.")
|
||
|
||
(defconst asm-mode-x86-prefix-ops-regexp
|
||
(cosmo-regexpify
|
||
[(["[lL][oO][cC][kK]\\>[ \t]*"
|
||
("[mM][oO][vV][sS]"
|
||
"[aA][dD][dDcC]"
|
||
"[sS][uUbB][bB]"
|
||
"[oO][rR]"
|
||
"[aA][nN][dD]"
|
||
"[xX][oO][rR]"
|
||
"[nN][oO][tT]"
|
||
"[nN][eE][gG]"
|
||
"[iI][nN][cC]"
|
||
"[dD][eE][cC]"
|
||
"[bB][tT][sSrRcC]?"
|
||
"[xX][aA][dD][dD]"
|
||
"[xX][cC][hH][gG]"
|
||
["[cC][mM][pP][xX][cC][hH][gG]" ("8[bB]" "16[bB]") "?"])]
|
||
["[rR][eE][pP]" ("[eEzZ]" "[nN][eEzZ]") "?\\>[ \t]*"
|
||
("[mM][oO][vV][sS]"
|
||
"[sS][tT][oO][sS]"
|
||
"[sS][cC][aA][sS]"
|
||
"[cC][mM][pP][sS]"
|
||
"[nN][oO][pP]"
|
||
"[rR][eE][tT]"
|
||
"[iI][nN][sS]"
|
||
"[oO][uU][tT][sS]")])
|
||
"[bBwWlLqQ]?\\>"])
|
||
"Legal high-level 80x86 prefix instruction combinations.")
|
||
|
||
(defconst cosmo-asm-font-lock-keywords
|
||
(append
|
||
`(;; AT&T Fortran-Style Assembler Comment
|
||
;;
|
||
;; - Valid
|
||
;;
|
||
;; * /heyho
|
||
;; * //heyho
|
||
;;
|
||
;; - Ignored
|
||
;;
|
||
;; * /heyho
|
||
;; * code code //heyho
|
||
;;
|
||
("^/.*$" . font-lock-comment-face)
|
||
|
||
;; Immediate Argument
|
||
;;
|
||
;; - Valid
|
||
;;
|
||
;; * mov $2,%eax
|
||
;; * mov $~2+0x2ul,%eax
|
||
;; * mov $'c,%eax
|
||
;; * mov $'\n,%eax
|
||
;;
|
||
("[ \t,]\\$\\(\\(?:'\\(?:'\\|\\s\"\\|\\s\\.\\|.\\)\\|\\(?:0x[[:xdigit:]]+\\|0b[01]+\\|[1-9][0-9]*\\|0[0-7]*\\)\\(?:[fb]\\|u?l?l?\\)\\|[-*/&^|()%<>~+]\\|[_.[:alpha:]][-_.[:alnum:]]*\\)+\\)"
|
||
1 font-lock-constant-face)
|
||
|
||
(cosmo-asm-doctag-keywords)
|
||
|
||
;; Static Branch Prediction
|
||
;;
|
||
;; - Valid
|
||
;;
|
||
;; * jnz,pt 1f
|
||
;; * jnz,pn 1b
|
||
;;
|
||
;; - Traditionally Implied
|
||
;;
|
||
;; * jnz,pn 1f
|
||
;; * jnz,pt 1b
|
||
;;
|
||
(",p[tn]" . font-lock-keyword-face)
|
||
|
||
("\\\\\\(?:@\\|()\\)" . font-lock-function-name-face)
|
||
("\\\\\\(\\sw\\|_\\|\\.\\)+\\>" . font-lock-variable-name-face)
|
||
(,asm-mode-x86-prefix-ops-regexp . font-lock-keyword-face)
|
||
(,(concat "^\\(\\(?:\\sw\\|\\s_\\|\\.\\)+\\):[ \t]*"
|
||
"\\(\\(?:\\sw\\|\\.\\)+\\)?")
|
||
(1 font-lock-function-name-face)
|
||
(2 font-lock-keyword-face nil t))
|
||
("^\\((\\sw+)\\)?\\s +\\(\\(\\.?\\sw\\|\\s_\\)+\\(\\.\\sw+\\)*\\)"
|
||
2 font-lock-keyword-face)
|
||
("^\\(\\.\\(\\sw\\|\\s_\\|\\.\\)+\\)\\>[^:]?"
|
||
1 font-lock-keyword-face)
|
||
("^.*?\\*/\\(\\.\\(\\sw\\|\\s_\\|\\.\\)+\\)\\>[^:]?"
|
||
1 font-lock-keyword-face)
|
||
|
||
;; it's complicated
|
||
(,asm-mode-gas-qualifiers-regexp . font-lock-type-face))
|
||
|
||
cpp-font-lock-keywords
|
||
|
||
`(;; GNU-Style Assembler Comment (Ltd. 80x86 &c.)
|
||
;;
|
||
;; - Valid
|
||
;;
|
||
;; * #heyho
|
||
;; * # heyho
|
||
;; * .org . #heyho
|
||
;; * .org . ####euhhcue
|
||
;; * .org .# ###euhhcue
|
||
;;
|
||
;; - Ignored
|
||
;;
|
||
;; * #if 0
|
||
;; * #endif
|
||
;; * .ascii "#heyho"
|
||
;;
|
||
("\\(#.*\\)$" 1 font-lock-comment-face)
|
||
|
||
("'\\(\\\\?.\\)\\>" 1 font-lock-constant-face)
|
||
|
||
;; Register Value
|
||
;;
|
||
;; - Valid
|
||
;;
|
||
;; * %al
|
||
;; * %eax
|
||
;;
|
||
;; - Ignored
|
||
;;
|
||
;; * %%al
|
||
;;
|
||
("%\\sw+" . font-lock-variable-name-face)
|
||
|
||
;; Hexadecimal Literal
|
||
;;
|
||
;; - Valid
|
||
;;
|
||
;; * 0x0123456789abcdef
|
||
;; * 0XDEADBEEFu
|
||
;; * -0xdeadbeefULL
|
||
;;
|
||
;; - Ignored
|
||
;;
|
||
;; * 0x0123456789abcdefg
|
||
;;
|
||
("\\b\\(0[xX]\\)[[:xdigit:]]+\\([ulUL]*\\)\\b"
|
||
(1 font-lock-constant-face)
|
||
(2 font-lock-constant-face))
|
||
|
||
;; Binary Literal
|
||
;;
|
||
;; - Valid
|
||
;;
|
||
;; * 0b0101101101
|
||
;; * 0B0101101101u
|
||
;; * -0b0101101101ULL
|
||
;;
|
||
;; - Ignored
|
||
;;
|
||
;; * 0b012
|
||
;;
|
||
("\\b\\(0[bB]\\)[01]+\\([ulUL]*\\)\\b"
|
||
(1 font-lock-constant-face)
|
||
(2 font-lock-constant-face))
|
||
|
||
;; Octal Literal
|
||
;;
|
||
;; - Valid
|
||
;;
|
||
;; * 01234567
|
||
;; * 01234567l
|
||
;; * -01234567ULL
|
||
;;
|
||
;; - Ignored
|
||
;;
|
||
;; * 012345678
|
||
;;
|
||
("\\b\\(0\\)[0-7]+\\([ulUL]*\\)\\b"
|
||
(1 font-lock-constant-face)
|
||
(2 font-lock-constant-face))
|
||
|
||
;; Bultin Constants
|
||
;;
|
||
;; - Valid
|
||
;;
|
||
;; * 123456789
|
||
;; * 123456789l
|
||
;; * -01234567ULL
|
||
;;
|
||
;; - Ignored
|
||
;;
|
||
;; * 123456789a
|
||
;; * 123456789aul
|
||
;;
|
||
("\\b[1-9][0-9]+\\([ulUL]*\\)\\b"
|
||
1 font-lock-constant-face)
|
||
|
||
;; AT&T Fortran-Style Assembler Comment
|
||
;;
|
||
;; - Valid
|
||
;;
|
||
;; * /heyho
|
||
;; * //heyho
|
||
;;
|
||
;; - Ignored
|
||
;;
|
||
;; * /heyho
|
||
;; * code code //heyho
|
||
;;
|
||
("^/.*$" . font-lock-comment-face)
|
||
|
||
;; AT&T-Style Directional Label
|
||
;;
|
||
;; - Valid
|
||
;;
|
||
;; * 1f
|
||
;; * 99b
|
||
;;
|
||
("\\b\\([0-9]+\\)[fb]\\b" 1 font-lock-function-name-face)))
|
||
"Additional expressions to highlight in Assembler mode.")
|
||
|
||
(defun cosmo-asm-doctag-keywords (limit)
|
||
(cosmo-fontify '((0 . font-lock-constant-face))
|
||
asm-mode-doctag-regexp
|
||
limit
|
||
(lambda (face syntax)
|
||
(or (memq face '(font-lock-comment-face))
|
||
(and syntax
|
||
(nth 4 syntax))))))
|
||
|
||
(defun cosmo-asm-supplemental-hook ()
|
||
"GNU Assembly in Bell Laboratories Style."
|
||
(setq asm-comment-char ?¯) ;; Was ESR using TASM?
|
||
(font-lock-add-keywords 'asm-mode
|
||
'((cosmo-asm-doctag-keywords))
|
||
'append)
|
||
(set (make-local-variable 'require-final-newline) nil)
|
||
(set (make-local-variable 'indent-tabs-mode) t)
|
||
(set (make-local-variable 'tab-width) 8))
|
||
|
||
(progn
|
||
(add-hook 'asm-mode-hook 'cosmo-asm-supplemental-hook)
|
||
(setq asm-font-lock-keywords cosmo-asm-font-lock-keywords))
|
||
|
||
;; Make -*-unix-assembly-*- mode line work correctly.
|
||
;; TODO(jart): Would be nice to use GitHub's name instead of changing asm-mode.
|
||
(defun unix-assembly-mode ()
|
||
(interactive)
|
||
(asm-mode))
|
||
|
||
(provide 'cosmo-asm-mode)
|