Add fixes performance and static web server

This commit is contained in:
Justine Tunney 2020-10-05 23:11:49 -07:00
parent b6793d42d5
commit c45e46f871
108 changed files with 2927 additions and 819 deletions

View file

@ -35,6 +35,7 @@ TOOL_BUILD_DIRECTDEPS = \
LIBC_ELF \
LIBC_FMT \
LIBC_LOG \
LIBC_LOG_ASAN \
LIBC_TINYMATH \
LIBC_MEM \
LIBC_NEXGEN32E \

View file

@ -27,6 +27,7 @@ TOOL_BUILD_EMUBIN_CHECKS = \
TOOL_BUILD_EMUBIN_DIRECTDEPS = \
LIBC_STUBS \
LIBC_NEXGEN32E \
LIBC_TINYMATH
TOOL_BUILD_EMUBIN_DEPS := \
@ -57,10 +58,10 @@ o/dbg/tool/build/emubin/lisp.real.com.dbg: \
$(APE)
-@$(APELINK)
o/tiny/tool/build/emubin/lisp.bin.dbg: \
o/$(MODE)/tool/build/emubin/lisp.bin.dbg: \
$(TOOL_BUILD_EMUBIN_DEPS) \
o/tiny/tool/build/emubin/lisp.real.o \
o/tiny/tool/build/emubin/lispstart.o \
o/$(MODE)/tool/build/emubin/lisp.real.o \
o/$(MODE)/tool/build/emubin/lispstart.o \
tool/build/emubin/lisp.lds
@$(ELFLINK) -z max-page-size=0x10

View file

@ -3,36 +3,35 @@
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.
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
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
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#define TRACE 0
#define ERRORS 1
#define LONG long
#define WORD short
#define WORDS 2048
#define WORDS 8192
/*───────────────────────────────────────────────────────────────────────────│─╗
The LISP Challenge § 8086 PC BIOS / x86_64 Linux System Integration
The LISP Challenge § Impure x86_64 Linux 8086 PC BIOS System Integration
*/
#define ATOM(x) /* a.k.a. !(x&1) */ \
({ \
char IsAtom; \
asm("test%z1\t$1,%1" : "=@ccz"(IsAtom) : "Qm"((char)x)); \
IsAtom; \
#define TYPE(x) /* a.k.a. x&1 */ \
({ \
char IsAtom; \
asm("test%z1\t$1,%1" : "=@ccnz"(IsAtom) : "Qm"((char)x)); \
IsAtom; \
})
#define OBJECT(t, v) /* a.k.a. v<<1|t */ \
@ -57,71 +56,109 @@
c; \
})
#define REAL_READ(BASE, INDEX, DISP) /* a.k.a. b[i] */ \
({ \
__typeof(*(BASE)) Reg; \
if (__builtin_constant_p(INDEX) && !(INDEX)) { \
asm("mov\t%c2(%1),%0" \
: "=Q"(Reg) \
: "bDS"(BASE), "i"((DISP) * sizeof(*(BASE)))); \
} else { \
asm("mov\t%c3(%1,%2),%0" \
: "=Q"(Reg) \
: "b"(BASE), "DS"((long)(INDEX) * sizeof(*(BASE))), \
"i"((DISP) * sizeof(*(BASE)))); \
} \
Reg; \
#define REAL_READ_(REG, BASE, INDEX, DISP) \
({ \
__typeof(*(BASE)) Reg; \
if (__builtin_constant_p(INDEX) && !(INDEX)) { \
asm("mov\t%c2(%1),%0" \
: REG(Reg) \
: "bDS"(BASE), "i"((DISP) * sizeof(*(BASE))), \
"m"(BASE[(INDEX) + (DISP)])); \
} else { \
asm("mov\t%c3(%1,%2),%0" \
: REG(Reg) \
: "b"(BASE), "DS"((long)(INDEX) * sizeof(*(BASE))), \
"i"((DISP) * sizeof(*(BASE))), "m"(BASE[(INDEX) + (DISP)])); \
} \
Reg; \
})
#define REAL_READ_ARRAY_FIELD(OBJECT, MEMBER, INDEX, DISP) /* o->m[i] */ \
/* #ifdef __REAL_MODE__ */
#define REAL_READ(BASE, INDEX, DISP) /* a.k.a. b[i] */ \
(sizeof(*(BASE)) == 1 ? REAL_READ_("=Q", BASE, INDEX, DISP) \
: REAL_READ_("=r", BASE, INDEX, DISP))
/* #else */
/* #define REAL_READ(BASE, INDEX, DISP) BASE[INDEX + DISP] */
/* #endif */
#define REAL_READ_ARRAY_FIELD_(REG, OBJECT, MEMBER, INDEX, DISP) \
({ \
__typeof(*(OBJECT->MEMBER)) Reg; \
if (!(OBJECT)) { \
asm("mov\t%c2(%1),%0" \
: "=Q"(Reg) \
: REG(Reg) \
: "bDS"((long)(INDEX) * sizeof(*(OBJECT->MEMBER))), \
"i"(__builtin_offsetof(__typeof(*(OBJECT)), MEMBER) + \
sizeof(*(OBJECT->MEMBER)) * (DISP))); \
sizeof(*(OBJECT->MEMBER)) * (DISP)), \
"m"(OBJECT->MEMBER)); \
} else { \
asm("mov\t%c3(%1,%2),%0" \
: "=Q"(Reg) \
: REG(Reg) \
: "b"(OBJECT), "DS"((long)(INDEX) * sizeof(*(OBJECT->MEMBER))), \
"i"(__builtin_offsetof(__typeof(*(OBJECT)), MEMBER) + \
sizeof(*(OBJECT->MEMBER)) * (DISP))); \
sizeof(*(OBJECT->MEMBER)) * (DISP)), \
"m"(OBJECT->MEMBER)); \
} \
Reg; \
})
#define REAL_WRITE_ARRAY_FIELD(OBJECT, MEMBER, INDEX, DISP, VALUE) \
do { \
__typeof(*(OBJECT->MEMBER)) Reg; \
if (!(OBJECT)) { \
asm volatile("mov\t%0,%c2(%1)" \
: /* manual output */ \
: "Q"((__typeof(*(OBJECT->MEMBER)))(VALUE)), \
"bDS"((long)(INDEX) * sizeof(*(OBJECT->MEMBER))), \
"i"(__builtin_offsetof(__typeof(*(OBJECT)), MEMBER) + \
sizeof(*(OBJECT->MEMBER)) * (DISP)) \
: "memory"); \
} else { \
asm volatile("mov\t%0,%c3(%1,%2)" \
: /* manual output */ \
: "Q"((__typeof(*(OBJECT->MEMBER)))(VALUE)), "b"(OBJECT), \
"DS"((long)(INDEX) * sizeof(*(OBJECT->MEMBER))), \
"i"(__builtin_offsetof(__typeof(*(OBJECT)), MEMBER) + \
sizeof(*(OBJECT->MEMBER)) * (DISP)) \
: "memory"); \
} \
/* #ifdef __REAL_MODE__ */
#define REAL_READ_ARRAY_FIELD(OBJECT, MEMBER, INDEX, DISP) /* o->m[i] */ \
(sizeof(*(OBJECT->MEMBER)) == 1 \
? REAL_READ_ARRAY_FIELD_("=Q", OBJECT, MEMBER, INDEX, DISP) \
: REAL_READ_ARRAY_FIELD_("=r", OBJECT, MEMBER, INDEX, DISP))
/* #else */
/* #define REAL_READ_ARRAY_FIELD(o, m, i, d) o->m[i + d] */
/* #endif */
#define REAL_WRITE_ARRAY_FIELD_(REG, OBJECT, MEMBER, INDEX, DISP, VALUE) \
do { \
if (!(OBJECT)) { \
asm("mov\t%1,%c3(%2)" \
: "=m"(OBJECT->MEMBER) \
: REG((__typeof(*(OBJECT->MEMBER)))(VALUE)), \
"bDS"((long)(INDEX) * sizeof(*(OBJECT->MEMBER))), \
"i"(__builtin_offsetof(__typeof(*(OBJECT)), MEMBER) + \
sizeof(*(OBJECT->MEMBER)) * (DISP))); \
} else { \
asm("mov\t%1,%c4(%2,%3)" \
: "=m"(OBJECT->MEMBER) \
: REG((__typeof(*(OBJECT->MEMBER)))(VALUE)), "b"(OBJECT), \
"DS"((long)(INDEX) * sizeof(*(OBJECT->MEMBER))), \
"i"(__builtin_offsetof(__typeof(*(OBJECT)), MEMBER) + \
sizeof(*(OBJECT->MEMBER)) * (DISP))); \
} \
} while (0)
static void *SetMemory(void *di, int al, unsigned long cx) {
/* #ifdef __REAL_MODE__ */
#define REAL_WRITE_ARRAY_FIELD(OBJECT, MEMBER, INDEX, DISP, VALUE) \
do { \
__typeof(*(OBJECT->MEMBER)) Reg; \
switch (sizeof(*(OBJECT->MEMBER))) { \
case 1: \
REAL_WRITE_ARRAY_FIELD_("Q", OBJECT, MEMBER, INDEX, DISP, VALUE); \
break; \
default: \
REAL_WRITE_ARRAY_FIELD_("ri", OBJECT, MEMBER, INDEX, DISP, VALUE); \
break; \
} \
} while (0)
/* #else */
/* #define REAL_WRITE_ARRAY_FIELD(o, m, i, d, v) o->m[i + d] = v */
/* #endif */
long jb[8];
int setjmp(void *) __attribute__((__returns_twice__));
int longjmp(void *, int) __attribute__((__noreturn__));
static inline void *SetMemory(void *di, int al, unsigned long cx) {
asm("rep stosb"
: "=D"(di), "=c"(cx), "=m"(*(char(*)[cx])di)
: "0"(di), "1"(cx), "a"(al));
return di;
}
static void *CopyMemory(void *di, void *si, unsigned long cx) {
static inline void *CopyMemory(void *di, void *si, unsigned long cx) {
asm("rep movsb"
: "=D"(di), "=S"(si), "=c"(cx), "=m"(*(char(*)[cx])di)
: "0"(di), "1"(si), "2"(cx));
@ -147,14 +184,13 @@ static void RawMode(void) {
#endif
}
__attribute__((__noinline__)) static int PrintChar(LONG c) {
__attribute__((__noinline__)) static void PrintChar(LONG c) {
#ifdef __REAL_MODE__
asm volatile("mov\t$0x0E,%%ah\n\t"
"int\t$0x10"
: /* no outputs */
: "a"(c), "b"(7)
: "memory");
return 0;
#else
static short buf;
int rc;
@ -163,7 +199,6 @@ __attribute__((__noinline__)) static int PrintChar(LONG c) {
: "=a"(rc)
: "0"(1), "D"(1), "S"(&buf), "d"(1)
: "rcx", "r11", "memory");
return rc;
#endif
}
@ -177,6 +212,7 @@ static void PrintString(char *s) {
}
static int XlatChar(LONG c) {
if (c == 0x7F) return '\b';
if (c >= 'a') {
asm volatile("" ::: "memory");
if (c <= 'z') c -= 'a' - 'A';
@ -185,19 +221,16 @@ static int XlatChar(LONG c) {
}
static int EchoChar(LONG c) {
if (c == '\b' || c == 0x7F) {
PrintString("\b \b");
return '\b';
} else {
if (c != '\b') {
PrintChar(c);
if (c == '\r') {
PrintChar('\n');
}
return c;
}
return c;
}
static noinline int ReadChar(void) {
__attribute__((__noinline__)) static noinline int ReadChar(void) {
int c;
#ifdef __REAL_MODE__
asm volatile("int\t$0x16" : "=a"(c) : "0"(0) : "memory");
@ -213,13 +246,13 @@ static noinline int ReadChar(void) {
}
/*───────────────────────────────────────────────────────────────────────────│─╗
The LISP Challenge § LISP Machine
The LISP Challenge § Pure Original LISP Machine
*/
#define TYPE_ATOM 0
#define TYPE_CONS 1
#define ATOM 0
#define CONS 1
#define ATOM_NIL 0
#define NIL 0
#define ATOM_T 8
#define ATOM_QUOTE 12
#define ATOM_ATOM 24
@ -234,7 +267,7 @@ static noinline int ReadChar(void) {
#define ATOM_DEFUN 110
#define Quote(x) List(ATOM_QUOTE, x)
#define List(x, y) Cons(x, Cons(y, ATOM_NIL))
#define List(x, y) Cons(x, Cons(y, NIL))
#define Caar(x) Car(Car(x)) // ((A B C D) (E F G) H I) → A
#define Cdar(x) Cdr(Car(x)) // ((A B C D) (E F G) H I) → (B C D)
#define Cadar(x) Cadr(Car(x)) // ((A B C D) (E F G) H I) → B
@ -242,22 +275,40 @@ static noinline int ReadChar(void) {
#define Cadr(x) Car(Cdr(x)) // ((A B C D) (E F G) H I) → (E F G)
#define Caddr(x) Cadr(Cdr(x)) // ((A B C D) (E F G) H I) → H
#define BOOL(x) ((x) ? ATOM_T : ATOM_NIL)
#define BOOL(x) ((x) ? ATOM_T : NIL)
#define VALUE(x) ((x) >> 1)
#define PTR(i) ((i) << 1 | CONS)
#define ARRAYLEN(A) \
((sizeof(A) / sizeof(*(A))) / ((unsigned)!(sizeof(A) % sizeof(*(A)))))
struct Lisp {
WORD memory[WORDS];
WORD mem[WORDS];
unsigned char syntax[256];
unsigned char look;
char token[16];
WORD look;
WORD globals;
int index;
WORD index;
char token[128];
char str[WORDS];
};
const char kSymbols[] aligned(1) = "\
_Static_assert(sizeof(struct Lisp) <= 0x7c00 - 0x600,
"LISP Machine too large for real mode");
_Alignas(char) const char kSymbols[] = "\
NIL\0T\0QUOTE\0ATOM\0EQ\0COND\0CAR\0CDR\0CONS\0LABEL\0LAMBDA\0SET\0DEFUN\0";
_Alignas(WORD) const WORD kGlobals[] = {
[0] = PTR(2), // ((T . T) (NIL . NIL))
[1] = PTR(4), //
[2] = ATOM_T, // (T . T)
[3] = ATOM_T, //
[4] = PTR(6), // ((NIL . NIL))
[5] = NIL, //
[6] = NIL, // (NIL . NIL)
[7] = NIL, //
};
#ifdef __REAL_MODE__
static struct Lisp *const q;
#else
@ -281,28 +332,39 @@ static void SetupSyntax(void) {
q->syntax['\''] = '\'';
}
forceinline WORD Car(LONG x) {
return REAL_READ_ARRAY_FIELD(q, memory, VALUE(x), 0);
static inline WORD Car(LONG x) {
return REAL_READ_ARRAY_FIELD(q, mem, VALUE(x), 0);
}
forceinline WORD Cdr(LONG x) {
return REAL_READ_ARRAY_FIELD(q, memory, VALUE(x), 1);
static inline WORD Cdr(LONG x) {
return REAL_READ_ARRAY_FIELD(q, mem, VALUE(x), 1);
}
static WORD Cons(WORD car, WORD cdr) {
int i, c;
#if TRACE
PrintString("CONS->");
Print(car);
PrintString(" ");
Print(cdr);
#endif
int i, cell;
i = q->index;
REAL_WRITE_ARRAY_FIELD(q, memory, i, 0, car);
REAL_WRITE_ARRAY_FIELD(q, memory, i, 1, cdr);
q->index += 2;
c = OBJECT(TYPE_CONS, i);
return c;
REAL_WRITE_ARRAY_FIELD(q, mem, i, 0, car);
REAL_WRITE_ARRAY_FIELD(q, mem, i, 1, cdr);
q->index = i + 2;
cell = OBJECT(CONS, i);
#if TRACE
PrintString("CONS<-");
Print(cell);
#endif
return cell;
}
static void SetupBuiltins(void) {
CopyMemory(q->str, kSymbols, sizeof(kSymbols));
q->globals =
Cons(Cons(ATOM_NIL, ATOM_NIL), Cons(Cons(ATOM_T, ATOM_T), ATOM_NIL));
CopyMemory(q->mem, kGlobals, sizeof(kGlobals));
q->index = ARRAYLEN(kGlobals);
q->globals = PTR(0);
}
static char *StpCpy(char *d, char *s) {
@ -314,7 +376,7 @@ static char *StpCpy(char *d, char *s) {
return d;
}
static WORD Intern(char *s) {
WORD Intern(char *s) {
int j, cx;
char c, *z, *t;
z = q->str;
@ -325,7 +387,7 @@ static WORD Intern(char *s) {
break;
}
if (!c) {
return OBJECT(TYPE_ATOM, z - q->str - j - 1);
return OBJECT(ATOM, z - q->str - j - 1);
}
c = LODS(z);
}
@ -334,11 +396,11 @@ static WORD Intern(char *s) {
}
--z;
StpCpy(z, s);
return OBJECT(TYPE_ATOM, SUB((long)z, q->str));
return OBJECT(ATOM, SUB((long)z, q->str));
}
forceinline unsigned char XlatSyntax(unsigned char b) {
return REAL_READ_ARRAY_FIELD(q, syntax, b, 0); /* a.k.a. q->syntax[b] */
return REAL_READ_ARRAY_FIELD(q, syntax, b, 0);
}
static void GetToken(void) {
@ -357,7 +419,8 @@ static void GetToken(void) {
if (b != '\b') {
STOS(t, b);
} else if (t > q->token) {
--t;
PrintString("\b \b");
if (t > q->token) --t;
}
b = ReadChar();
}
@ -387,7 +450,7 @@ static WORD GetList(void) {
case '\'':
return AddList(GetQuote());
case ')':
return ATOM_NIL;
return NIL;
case '.':
return ConsumeObject();
}
@ -422,7 +485,7 @@ static void PrintList(LONG x) {
PrintChar('(');
PrintObject(Car(x));
while ((x = Cdr(x))) {
if (!ATOM(x)) {
if (TYPE(x) == CONS) {
PrintChar(' ');
PrintObject(Car(x));
} else {
@ -434,7 +497,7 @@ static void PrintList(LONG x) {
}
static void PrintObject(LONG x) {
if (ATOM(x)) {
if (TYPE(x) == ATOM) {
PrintAtom(x);
} else {
PrintList(x);
@ -447,8 +510,7 @@ static void Print(LONG i) {
}
__attribute__((__noreturn__)) static void Reset(void) {
asm volatile("jmp\tRepl");
__builtin_unreachable();
longjmp(jb, 1);
}
__attribute__((__noreturn__)) static void OnUndefined(LONG x) {
@ -472,7 +534,7 @@ __attribute__((__noreturn__)) static void OnArity(void) {
*/
static WORD Atom(LONG x) {
return BOOL(ATOM(x));
return BOOL(TYPE(x) == ATOM);
}
static WORD Null(LONG x) {
@ -480,24 +542,32 @@ static WORD Null(LONG x) {
}
static WORD Eq(LONG x, LONG y) {
return BOOL(x == y); /* undefiled if !ATOM(x)||!ATOM(y) */
return BOOL(x == y); /* undefined if !Atom(x)||!Atom(y) */
}
static WORD Assoc(LONG x, LONG y) {
for (;;) {
if (!y) OnUndefined(x);
if (Eq(Caar(y), x)) break;
y = Cdr(y);
}
return Cdar(y);
if (Null(y)) OnUndefined(x);
if (Eq(Caar(y), x)) return Cdar(y);
return Assoc(x, Cdr(y));
}
static WORD Append(LONG x, LONG y) {
if (x) {
return Cons(Car(x), Append(Cdr(x), y));
#if TRACE
PrintString("APPEND->");
Print(x);
PrintString(" ");
Print(y);
#endif
if (!Null(x)) {
x = Cons(Car(x), Append(Cdr(x), y));
} else {
return y;
x = y;
}
#if TRACE
PrintString("APPEND<-");
Print(x);
#endif
return x;
}
/**
@ -506,26 +576,41 @@ static WORD Append(LONG x, LONG y) {
* @note recoded to make lists in dot notation
* @note it's zip() basically
*/
static WORD Pair(LONG x, LONG y) {
if (!x && !y) {
return ATOM_NIL;
} else if (!ATOM(x) && !ATOM(y)) {
return Cons(Cons(Car(x), Car(y)), Pair(Cdr(x), Cdr(y)));
static WORD Pair_(LONG x, LONG y) {
if (Null(x) && Null(y)) {
return NIL;
} else if (TYPE(x) == CONS && TYPE(y) == CONS) {
return Cons(Cons(Car(x), Car(y)), Pair_(Cdr(x), Cdr(y)));
} else {
OnArity();
}
}
static WORD Pair(LONG x, LONG y) {
#if TRACE
PrintString("PAIR->");
Print(x);
PrintString(" ");
Print(y);
#endif
x = Pair_(x, y);
#if TRACE
PrintString("PAIR<-");
Print(x);
#endif
return x;
}
static WORD Appq(long m) {
if (m) {
return Cons(List(ATOM_QUOTE, Car(m)), Appq(Cdr(m)));
} else {
return ATOM_NIL;
return NIL;
}
}
static WORD Apply(long f, long a) {
return Eval(Cons(f, Appq(a)), ATOM_NIL);
return Eval(Cons(f, Appq(a)), NIL);
}
static WORD Evcon(LONG c, LONG a) {
@ -536,14 +621,29 @@ static WORD Evcon(LONG c, LONG a) {
}
}
static WORD Evlis(LONG m, LONG a) {
static WORD Evlis_(LONG m, LONG a) {
if (m) {
return Cons(Eval(Car(m), a), Evlis(Cdr(m), a));
return Cons(Eval(Car(m), a), Evlis_(Cdr(m), a));
} else {
return ATOM_NIL;
return NIL;
}
}
static WORD Evlis(LONG m, LONG a) {
#if TRACE
PrintString("EVLIS->");
Print(m);
PrintString(" ");
Print(a);
#endif
m = Evlis_(m, a);
#if TRACE
PrintString("EVLIS<-");
Print(m);
#endif
return m;
}
static WORD Set(LONG e) {
WORD name, value;
name = Car(e);
@ -563,9 +663,9 @@ static WORD Defun(LONG e) {
}
static WORD Evaluate(LONG e, LONG a) {
if (ATOM(e)) {
if (Atom(e)) {
return Assoc(e, a);
} else if (ATOM(Car(e))) {
} else if (Atom(Car(e))) {
switch (Car(e)) {
case ATOM_QUOTE:
return Cadr(e);
@ -601,6 +701,8 @@ static WORD Eval(LONG e, LONG a) {
#if TRACE
PrintString("->");
Print(e);
PrintString(" ");
Print(a);
#endif
e = Evaluate(e, a);
#if TRACE
@ -615,6 +717,7 @@ static WORD Eval(LONG e, LONG a) {
*/
void Repl(void) {
setjmp(jb);
for (;;) {
PrintString("* ");
Print(Eval(Read(), q->globals));
@ -622,7 +725,7 @@ void Repl(void) {
}
int main(int argc, char *argv[]) {
RawMode();
/* RawMode(); */
SetupSyntax();
SetupBuiltins();
PrintString("THE LISP CHALLENGE V1\r\n"

View file

@ -29,6 +29,7 @@ SECTIONS {
. = 0x1fe;
SHORT(0xaa55);
*(.text .text.*)
_etext = .;
. = ALIGN(512);
}
@ -43,10 +44,11 @@ SECTIONS {
}
}
syntax = 0x600+2048*2;
look = 0x600+2048*2+256;
token = 0x600+2048*2+256+1;
globals = 0x600+2048*2+256+1+16;
index = 0x600+2048*2+256+1+16+2;
str = 0x600+2048*2+256+1+16+2+4;
v_sectors = SIZEOF(.text) / 512;
boot = 0x7c00;
q.syntax = 8192*2;
q.look = 8192*2+256;
q.globals = 8192*2+256+2;
q.index = 8192*2+256+2+2;
q.token = 8192*2+256+2+2+2;
q.str = 8192*2+256+2+2+2+128;
v_sectors = SIZEOF(.text) / 512;

View file

@ -21,8 +21,8 @@
.code16
.section .start,"ax",@progbits
_start: jmp 1f
1: ljmp $0x600>>4,$2f
2: push %cs
1: ljmp $0x600>>4,$_begin
_begin: push %cs
pop %ds
push %cs
pop %es
@ -50,3 +50,45 @@ _start: jmp 1f
.globl _start
.globl v_sectors
.globl main
setjmp: mov %sp,%ax
stosw # sp
xchg %ax,%si
movsw %ss:(%si),(%di) # ip
mov %bp,%ax
stosw # bp
ret
.type setjmp,@function
.size setjmp,.-setjmp
.globl setjmp
longjmp:
mov (%di),%sp
mov 2(%di),%dx
mov 4(%di),%bp
pop %ax
mov %si,%ax
jmp *%dx
.type longjmp,@function
.size longjmp,.-longjmp
.globl longjmp
.globl q.syntax
.type q.syntax,@function
.globl q.look
.type q.look,@function
.globl q.globals
.type q.globals,@function
.globl q.index
.type q.index,@function
.globl q.token
.type q.token,@function
.globl q.str
.type q.str,@function
.globl boot
.type boot,@function
.globl bss
.type bss,@function
.globl rodata
.type rodata,@function

View file

@ -56,6 +56,7 @@
#include "libc/sysv/consts/sig.h"
#include "libc/sysv/consts/termios.h"
#include "libc/sysv/errfuns.h"
#include "libc/time/time.h"
#include "libc/unicode/unicode.h"
#include "libc/x/x.h"
#include "third_party/dtoa/dtoa.h"
@ -91,8 +92,7 @@ DESCRIPTION\n\
\n\
FLAGS\n\
\n\
-h\n\
-? help\n\
-h help\n\
-v verbosity\n\
-r real mode\n\
-s statistics\n\
@ -137,8 +137,9 @@ COMPLETENESS\n\
#define QUIT 0x200
#define EXIT 0x400
#define CTRL(C) ((C) ^ 0100)
#define ALT(C) (('\e' << 010) | (C))
#define CTRL(C) ((C) ^ 0100)
#define ALT(C) (('\e' << 010) | (C))
#define SEX(x, b) ((x) | ((x) & (1ull << (b)) ? -(1ull << (b)) : 0))
struct Panels {
union {
@ -215,16 +216,6 @@ static struct Breakpoints breakpoints;
static void SetupDraw(void);
static void Redraw(void);
static uint64_t SignExtend(uint64_t x, uint8_t b) {
uint64_t s;
s = 1;
b -= 1;
b &= 63;
s <<= b;
if (x & s) x |= ~(s - 1);
return x;
}
static char *FormatDouble(char *b, double x) {
return g_fmt(b, x);
}
@ -234,16 +225,15 @@ static void SetCarry(bool cf) {
}
static bool IsCall(void) {
return m->xedd->op.map == XED_ILD_MAP0 &&
(m->xedd->op.opcode == 0xE8 ||
(m->xedd->op.opcode == 0xFF && m->xedd->op.reg == 2));
return (m->xedd->op.dispatch == 0x0E8 ||
(m->xedd->op.dispatch == 0x0FF && m->xedd->op.reg == 2));
}
static bool IsLongBranch(void) {
return m->xedd && m->xedd->op.map == XED_ILD_MAP0 &&
(m->xedd->op.opcode == 0xEA || m->xedd->op.opcode == 0x9A ||
(m->xedd->op.opcode == 0xFF && m->xedd->op.reg == 3) ||
(m->xedd->op.opcode == 0xFF && m->xedd->op.reg == 5));
return m->mode != XED_MODE_LONG &&
(m->xedd->op.dispatch == 0x0EA || m->xedd->op.dispatch == 0x09A ||
(m->xedd->op.opcode == 0x0FF && m->xedd->op.reg == 3) ||
(m->xedd->op.opcode == 0x0FF && m->xedd->op.reg == 5));
}
static bool IsDebugBreak(void) {
@ -370,13 +360,16 @@ static void GetTtySize(void) {
static void TuiRejuvinate(void) {
GetTtySize();
ttyhidecursor(STDOUT_FILENO);
ttyraw(0);
ttyraw(kTtySigs);
xsigaction(SIGBUS, OnBusted, SA_NODEFER, 0, NULL);
}
static void OnCtrlC(void) {
LOGF("OnCtrlC");
action |= INT;
if (tuimode) {
action |= INT;
} else {
HaltMachine(m, kMachineExit);
}
}
static void OnQ(void) {
@ -404,7 +397,7 @@ static void OnCont(void) {
static void TuiCleanup(void) {
sigaction(SIGWINCH, oldsig + 0, NULL);
sigaction(SIGCONT, oldsig + 2, NULL);
ttyraw((enum TtyRawFlags)(-1u));
ttyraw(-1);
ttyshowcursor(STDOUT_FILENO);
CHECK_NE(-1, close(ttyfd));
tuimode = false;
@ -447,6 +440,7 @@ void TuiSetup(void) {
CHECK_NE(-1, (ttyfd = open("/dev/tty", O_RDWR)));
xsigaction(SIGWINCH, OnWinch, 0, 0, oldsig + 0);
xsigaction(SIGCONT, OnCont, SA_RESTART, 0, oldsig + 2);
xsigaction(SIGINT, OnCtrlC, 0 /* SA_NODEFER */, 0, oldsig + 3);
memcpy(&m[1], &m[0], sizeof(m[0]));
TuiRejuvinate();
}
@ -660,12 +654,19 @@ static void SetupDraw(void) {
pan.display.right - pan.display.left);
}
static long Disassemble(void) {
long lines, current;
lines = pan.disassembly.bottom - pan.disassembly.top * 2;
CHECK_NE(-1, Dis(dis, m, GetIp(), m->ip, lines));
current = DisFind(dis, GetIp());
CHECK_NE(-1, current);
return current;
}
static long GetDisIndex(void) {
long i;
if ((i = DisFind(dis, GetIp())) == -1 || IsLongBranch()) {
Dis(dis, m, GetIp(), m->ip,
pan.disassembly.bottom - pan.disassembly.top * 2);
CHECK_NE(-1, (i = DisFind(dis, GetIp())));
if ((i = DisFind(dis, GetIp())) == -1) {
i = Disassemble();
}
while (i + 1 < dis->ops.i && !dis->ops.p[i].size) ++i;
return i;
@ -864,7 +865,7 @@ static void DrawXmm(struct Panel *p, long i, long r) {
if (0 && ssewidth == 1 && (040 <= ival && ival < 0200 - 1)) {
sprintf(buf, "%`'c", ival);
} else {
int64toarray_radix10(SignExtend(ival, ssewidth * 8), buf);
int64toarray_radix10(SEX(ival, ssewidth * 8), buf);
}
} else {
uint64toarray_fixed16(ival, buf, ssewidth * 8);
@ -977,7 +978,7 @@ static void DrawBreakpoints(struct Panel *p) {
name = sym != -1 ? dis->syms.stab + dis->syms.p[sym].name : "UNKNOWN";
s = buf;
s += sprintf(s, "%p ", addr);
CHECK_LT(Demangle(s, name), buf + ARRAYLEN(buf));
CHECK_LT(Demangle(s, name, DIS_MAX_SYMBOL_LENGTH), buf + ARRAYLEN(buf));
AppendPanel(p, line, buf);
if (sym != -1 && addr != dis->syms.p[sym].addr) {
snprintf(buf, sizeof(buf), "+%#lx", addr - dis->syms.p[sym].addr);
@ -1015,7 +1016,7 @@ static void DrawTrace(struct Panel *p) {
name = sym != -1 ? dis->syms.stab + dis->syms.p[sym].name : "UNKNOWN";
s = line;
s += sprintf(s, "%p %p ", Read64(m->ss) + bp, rp);
s = Demangle(s, name);
s = Demangle(s, name, DIS_MAX_SYMBOL_LENGTH);
AppendPanel(p, i, line);
if (sym != -1 && rp != dis->syms.p[sym].addr) {
snprintf(line, sizeof(line), "+%#lx", rp - dis->syms.p[sym].addr);
@ -1417,7 +1418,6 @@ static void OnVidyaServiceTeletypeOutput(void) {
char buf[12];
n = FormatCga(m->bx[0], buf);
n += tpencode(buf + n, 6, VidyaServiceXlatTeletype(m->ax[0]), false);
LOGF("teletype output %`'.*s", n, buf);
MachinePtyWrite(pty, buf, n);
}
@ -1520,6 +1520,7 @@ static void OnInt15h(void) {
}
static bool OnHalt(int interrupt) {
LOGF("OnHalt(%d)", interrupt);
ReactiveDraw();
switch (interrupt) {
case 1:
@ -1577,15 +1578,24 @@ static void OnPageDown(void) {
static void OnUpArrow(void) {
if (action & CONTINUE) {
speed = MIN(0x40000000, MAX(1, speed) << 1);
if (speed >= -1) {
speed = MIN(0x40000000, MAX(1, speed) << 1); // 1..40mips skip
} else {
speed >>= 1;
}
} else {
--opstart;
}
LOGF("speed %d", speed);
}
static void OnDownArrow(void) {
if (action & CONTINUE) {
speed >>= 1;
if (speed > 0) {
speed >>= 1;
} else {
speed = MAX(-(5 * 1000), MIN(-10, speed) << 1); // 10ms..5s delay
}
} else {
++opstart;
}
@ -1897,6 +1907,9 @@ static void Tui(void) {
action &= ~WINCHED;
}
interactive = ++tick > speed;
if (interactive && speed < 0) {
dsleep(.001L * -speed);
}
if (!(action & CONTINUE) || interactive) {
tick = 0;
GetDisIndex();
@ -1907,7 +1920,8 @@ static void Tui(void) {
LOGF("TUI FAILURE");
PrintMessageBox(ttyfd, systemfailure, tyn, txn);
ReadKeyboard();
} else if (!IsExecuting() || (interactive && HasPendingKeyboard())) {
} else if (!IsExecuting() || ((interactive || !(action & CONTINUE)) &&
!(action & INT) && HasPendingKeyboard())) {
ReadKeyboard();
}
if (action & INT) {
@ -1961,6 +1975,9 @@ static void Tui(void) {
}
if (!IsDebugBreak()) {
ExecuteInstruction(m);
if (IsLongBranch()) {
Disassemble();
}
} else {
m->ip += m->xedd->length;
action &= ~NEXT;
@ -1997,7 +2014,7 @@ static void Tui(void) {
static void GetOpts(int argc, char *argv[]) {
int opt;
stpcpy(stpcpy(stpcpy(logpath, kTmpPath), basename(argv[0])), ".log");
while ((opt = getopt(argc, argv, "?hvtrRsb:HL:")) != -1) {
while ((opt = getopt(argc, argv, "hvtrRsb:HL:")) != -1) {
switch (opt) {
case 't':
tuimode = true;
@ -2007,6 +2024,7 @@ static void GetOpts(int argc, char *argv[]) {
break;
case 'r':
m->mode = XED_MACHINE_MODE_REAL;
g_disisprog_disable = true;
break;
case 's':
printstats = true;
@ -2024,7 +2042,6 @@ static void GetOpts(int argc, char *argv[]) {
strcpy(logpath, optarg);
break;
case 'h':
case '?':
PrintUsage(EXIT_SUCCESS, stdout);
default:
PrintUsage(EX_USAGE, stderr);

View file

@ -64,13 +64,12 @@ ssize_t WriteBuffer(struct Buffer *b, int fd) {
p = b->p;
n = b->i;
do {
TryAgain:
if ((rc = write(fd, p, n)) != -1) {
wrote = rc;
p += wrote;
n -= wrote;
} else if (errno == EINTR) {
goto TryAgain;
break;
} else {
return -1;
}

View file

@ -17,10 +17,14 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/assert.h"
#include "libc/bits/safemacros.h"
#include "libc/calls/calls.h"
#include "libc/calls/hefty/spawn.h"
#include "libc/calls/struct/iovec.h"
#include "libc/macros.h"
#include "libc/runtime/runtime.h"
#include "libc/sock/sock.h"
#include "libc/str/str.h"
#include "tool/build/lib/demangle.h"
@ -37,12 +41,14 @@ void CloseCxxFilt(void) {
void SpawnCxxFilt(void) {
int pid;
const char *cxxfilt;
char path[PATH_MAX];
if (commandv("c++filt", path)) {
cxxfilt = firstnonnull(getenv("CXXFILT"), "c++filt");
if (commandv(cxxfilt, path)) {
g_cxxfilt.fds[0] = -1;
g_cxxfilt.fds[1] = -1;
g_cxxfilt.fds[2] = 2;
if ((pid = spawnve(0, g_cxxfilt.fds, path, (char *const[]){"c++filt", NULL},
if ((pid = spawnve(0, g_cxxfilt.fds, path, (char *const[]){cxxfilt, NULL},
environ)) != -1) {
atexit(CloseCxxFilt);
}
@ -52,30 +58,50 @@ void SpawnCxxFilt(void) {
g_cxxfilt.pid = pid;
}
char *DemangleCxxFilt(char *p, const char *symbol) {
int n;
char buf[512];
bool iscomplicated;
char *CopySymbol(char *p, size_t pn, const char *s, size_t sn) {
size_t extra;
bool showdots, iscomplicated;
assert(pn >= 1 + 3 + 1 + 1);
iscomplicated = memchr(s, ' ', sn) || memchr(s, '(', sn);
extra = 1;
if (iscomplicated) extra += 2;
if (sn + extra > pn) {
sn = pn - extra - 3;
showdots = true;
} else {
showdots = false;
}
if (iscomplicated) *p++ = '"';
p = mempcpy(p, s, sn);
if (showdots) p = stpcpy(p, "...");
if (iscomplicated) *p++ = '"';
*p = '\0';
return p;
}
char *DemangleCxxFilt(char *p, size_t pn, const char *s, size_t sn) {
ssize_t rc;
size_t got;
struct iovec iov[2];
static char buf[PAGESIZE];
if (!g_cxxfilt.pid) SpawnCxxFilt();
if (g_cxxfilt.pid == -1) return NULL;
if ((n = strlen(symbol)) >= ARRAYLEN(buf)) return NULL;
memcpy(buf, symbol, n);
buf[n] = '\n';
write(g_cxxfilt.fds[0], buf, n + 1);
n = read(g_cxxfilt.fds[1], buf, ARRAYLEN(buf));
if (n > 1 && buf[n - 1] == '\n') {
if (buf[n - 2] == '\r') --n;
--n;
iscomplicated = memchr(buf, ' ', n) || memchr(buf, '(', n);
if (iscomplicated) *p++ = '"';
p = mempcpy(p, buf, n);
if (iscomplicated) *p++ = '"';
*p = '\0';
return p;
} else {
CloseCxxFilt();
return NULL;
buf[0] = '\n';
iov[0].iov_base = s;
iov[0].iov_len = sn;
iov[1].iov_base = buf;
iov[1].iov_len = 1;
writev(g_cxxfilt.fds[0], iov, ARRAYLEN(iov));
if ((rc = read(g_cxxfilt.fds[1], buf, sizeof(buf))) != -1) {
got = rc;
if (got >= 2 && buf[got - 1] == '\n') {
if (buf[got - 2] == '\r') --got;
--got;
return CopySymbol(p, pn, buf, got);
}
}
CloseCxxFilt();
return NULL;
}
/**
@ -85,10 +111,12 @@ char *DemangleCxxFilt(char *p, const char *symbol) {
* x86_64 disassembler. That's just for the GNU encoding scheme. So
* what we'll do, is just offload this work to the c++filt program.
*/
char *Demangle(char *p, const char *symbol) {
char *Demangle(char *p, const char *symbol, size_t n) {
char *r;
size_t sn;
sn = strlen(symbol);
if (startswith(symbol, "_Z")) {
if ((r = DemangleCxxFilt(p, symbol))) return r;
if ((r = DemangleCxxFilt(p, n, symbol, sn))) return r;
}
return stpcpy(p, symbol);
return CopySymbol(p, n, symbol, sn);
}

View file

@ -3,7 +3,7 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
char *Demangle(char *, const char *);
char *Demangle(char *, const char *, size_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -150,7 +150,7 @@ static char *DisLineData(struct Dis *d, char *p, const uint8_t *b, size_t n) {
static char *DisLabel(struct Dis *d, char *p, const char *name) {
p = DisColumn(DisAddr(d, p), p, ADDRLEN);
p = HighStart(p, g_high.label);
p = Demangle(p, name);
p = Demangle(p, name, DIS_MAX_SYMBOL_LENGTH);
p = HighEnd(p);
*p++ = ':';
*p = '\0';

View file

@ -6,6 +6,8 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
#define DIS_MAX_SYMBOL_LENGTH 32
struct Dis {
struct DisOps {
size_t i, n;
@ -50,6 +52,8 @@ struct Dis {
char buf[512];
};
extern bool g_disisprog_disable;
long Dis(struct Dis *, struct Machine *, uint64_t, uint64_t, int);
long DisFind(struct Dis *, int64_t);
void DisFree(struct Dis *);

View file

@ -143,21 +143,30 @@ static char *DisInt(char *p, int64_t x) {
return p;
}
static char *DisSym(struct Dis *d, char *p, int64_t addr, int64_t ip) {
long sym;
static char *DisSymImpl(struct Dis *d, char *p, int64_t x, long sym) {
int64_t addend;
const char *name;
if ((sym = DisFindSym(d, ip)) != -1 && d->syms.p[sym].name) {
addend = ip - d->syms.p[sym].addr;
name = d->syms.stab + d->syms.p[sym].name;
p = Demangle(p, name);
if (addend) {
*p++ = '+';
p = DisInt(p, addend);
}
return p;
addend = x - d->syms.p[sym].addr;
name = d->syms.stab + d->syms.p[sym].name;
p = Demangle(p, name, DIS_MAX_SYMBOL_LENGTH);
if (addend) {
*p++ = '+';
p = DisInt(p, addend);
}
return p;
}
static char *DisSym(struct Dis *d, char *p, int64_t x1, int64_t x2,
bool isrelative) {
long sym;
if ((sym = DisFindSym(d, x2)) != -1 && d->syms.p[sym].name &&
(d->syms.p[sym].isabs ^ isrelative)) {
return DisSymImpl(d, p, x2, sym);
} else if ((sym = DisFindSym(d, x1)) != -1 && d->syms.p[sym].name &&
(d->syms.p[sym].isabs ^ isrelative)) {
return DisSymImpl(d, p, x1, sym);
} else {
return DisInt(p, addr);
return DisInt(p, x1);
}
}
@ -165,7 +174,7 @@ static char *DisSymLiteral(struct Dis *d, uint32_t rde, char *p, uint64_t addr,
uint64_t ip) {
*p++ = '$';
p = HighStart(p, g_high.literal);
p = DisSym(d, p, addr, ip);
p = DisSym(d, p, addr, addr, false);
p = HighEnd(p);
return p;
}
@ -196,27 +205,36 @@ static bool IsRealModrmAbsolute(uint32_t rde) {
return Eamode(rde) == XED_MODE_REAL && ModrmRm(rde) == 6 && !ModrmMod(rde);
}
static char *DisM(struct Dis *d, uint32_t rde, char *p) {
static char *DisDisp(struct Dis *d, uint32_t rde, char *p) {
bool rela;
int64_t disp;
const char *base, *index, *scale;
p = DisSego(d, rde, p);
base = index = scale = NULL;
if (ModrmMod(rde) == 0b01 || ModrmMod(rde) == 0b10 || IsRipRelative(rde) ||
IsRealModrmAbsolute(rde) ||
(ModrmMod(rde) == 0b00 && ModrmRm(rde) == 0b100 &&
SibBase(d->xedd) == 0b101)) {
(Eamode(rde) != XED_MODE_REAL && ModrmMod(rde) == 0b00 &&
ModrmRm(rde) == 0b100 && SibBase(d->xedd) == 0b101)) {
disp = d->xedd->op.disp;
if (IsRipRelative(rde)) {
if (Mode(rde) == XED_MODE_LONG) {
disp = RipRelative(d, disp);
rela = true;
} else {
disp = Unrelative(rde, disp);
rela = false;
}
} else if (IsRealModrmAbsolute(rde)) {
disp = Unrelative(rde, disp);
rela = false;
} else {
rela = true;
}
p = DisSym(d, p, disp, disp);
p = DisSym(d, p, disp, disp, rela);
}
return p;
}
static char *DisBis(struct Dis *d, uint32_t rde, char *p) {
const char *base, *index, *scale;
base = index = scale = NULL;
if (Eamode(rde) != XED_MODE_REAL) {
if (!SibExists(rde)) {
DCHECK(!d->xedd->op.has_sib);
@ -290,6 +308,13 @@ static char *DisM(struct Dis *d, uint32_t rde, char *p) {
return p;
}
static char *DisM(struct Dis *d, uint32_t rde, char *p) {
p = DisSego(d, rde, p);
p = DisDisp(d, rde, p);
p = DisBis(d, rde, p);
return p;
}
static char *DisRegMem(struct Dis *d, uint32_t rde, char *p,
char *f(struct Dis *, uint32_t, char *)) {
if (IsModrmRegister(rde)) {
@ -452,11 +477,11 @@ static char *DisJb(struct Dis *d, uint32_t rde, char *p) {
static char *DisJvds(struct Dis *d, uint32_t rde, char *p) {
return DisSym(d, p, RipRelative(d, d->xedd->op.disp),
RipRelative(d, d->xedd->op.disp) - Read64(d->m->cs));
RipRelative(d, d->xedd->op.disp) - Read64(d->m->cs), true);
}
static char *DisAbs(struct Dis *d, uint32_t rde, char *p) {
return DisSym(d, p, d->xedd->op.disp, d->xedd->op.disp);
return DisSym(d, p, d->xedd->op.disp, d->xedd->op.disp, false);
}
static char *DisSw(struct Dis *d, uint32_t rde, char *p) {
@ -477,12 +502,12 @@ static char *DisY(struct Dis *d, uint32_t rde, char *p) {
}
static char *DisX(struct Dis *d, uint32_t rde, char *p) {
DisSego(d, rde, p);
p = DisSego(d, rde, p);
return DisSpecialAddr(d, rde, p, 6); // ds:si
}
static char *DisBBb(struct Dis *d, uint32_t rde, char *p) {
DisSego(d, rde, p);
p = DisSego(d, rde, p);
return DisSpecialAddr(d, rde, p, 3); // ds:bx
}

View file

@ -22,9 +22,13 @@
#include "libc/elf/elf.h"
#include "libc/elf/struct/sym.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/macros.h"
#include "libc/str/str.h"
#include "tool/build/lib/dis.h"
bool g_disisprog_disable;
static int DisSymCompare(const struct DisSym *a, const struct DisSym *b) {
if (a->addr != b->addr) {
if (a->addr < b->addr) return -1;
@ -72,6 +76,8 @@ static void DisLoadElfSyms(struct Dis *d, struct Elf *elf) {
if (!st[i].st_name) continue;
if (!(0 <= st[i].st_name && st[i].st_name < stablen)) continue;
if (ELF64_ST_TYPE(st[i].st_info) == STT_SECTION) continue;
if (ELF64_ST_TYPE(st[i].st_info) == STT_FILE) continue;
if (startswith(d->syms.stab + st[i].st_name, "v_")) continue;
isabs = st[i].st_shndx == SHN_ABS;
isweak = ELF64_ST_BIND(st[i].st_info) == STB_WEAK;
islocal = ELF64_ST_BIND(st[i].st_info) == STB_LOCAL;
@ -85,6 +91,7 @@ static void DisLoadElfSyms(struct Dis *d, struct Elf *elf) {
t.addr = st[i].st_value;
t.rank = -islocal + -isweak + -isabs + isprotected + isobject + isfunc;
t.iscode = DisIsText(d, st[i].st_value) ? !isobject : isfunc;
t.isabs = isabs;
APPEND(&d->syms.p, &d->syms.i, &d->syms.n, &t);
}
}
@ -93,6 +100,7 @@ static void DisLoadElfSyms(struct Dis *d, struct Elf *elf) {
bool DisIsProg(struct Dis *d, int64_t addr) {
long i;
if (g_disisprog_disable) return true;
for (i = 0; i < d->loads.i; ++i) {
if (addr >= d->loads.p[i].addr &&
addr < d->loads.p[i].addr + d->loads.p[i].size) {

View file

@ -20,6 +20,7 @@
#include "libc/log/check.h"
#include "libc/nexgen32e/tinystrcmp.h"
#include "libc/str/str.h"
#include "third_party/zlib/zlib.h"
#include "tool/build/lib/dis.h"
#include "tool/build/lib/high.h"
#include "tool/build/lib/modrm.h"
@ -163,7 +164,7 @@ static char *DisName(struct Dis *d, char *bp, const char *name,
} else if (wantsuffix || (ambiguous && !startswith(name, "f") &&
!startswith(name, "set"))) {
if (Osz(rde)) {
if (Mode(rde) != XED_MODE_REAL) {
if (ambiguous || Mode(rde) != XED_MODE_REAL) {
*p++ = 'w';
}
} else if (Rexw(rde)) {
@ -187,8 +188,8 @@ static char *DisName(struct Dis *d, char *bp, const char *name,
*/
char *DisInst(struct Dis *d, char *p, const char *spec) {
long i, n;
char sbuf[300];
char args[4][300];
char sbuf[64];
char args[4][256];
char *s, *name, *state;
bool hasarg, hasmodrm, hasregister, hasmemory;
CHECK_EQ(0, (int)d->xedd->op.error);

View file

@ -48,7 +48,7 @@ COSMOPOLITAN_C_START_
#define SibHasIndex(x) (SibIndex(x) != 4 || Rexx(x))
#define SibHasBase(x, r) (SibBase(x) != 5 || ModrmMod(r))
#define SibIsAbsolute(x, r) (!SibHasBase(x, r) && !SibHasIndex(x))
#define IsRipRelative(x) (ModrmRm(x) == 5 && !ModrmMod(x))
#define IsRipRelative(x) (Eamode(x) && ModrmRm(x) == 5 && !ModrmMod(x))
struct AddrSeg {
int64_t addr;

View file

@ -474,11 +474,8 @@ ssize_t MachinePtyWrite(struct MachinePty *pty, const void *data, size_t n) {
break;
case kMachinePtyUtf8:
if (ThomPikeCont(p[i])) {
pty->u8 <<= 6;
pty->u8 |= p[i] & 0b00111111;
if (--pty->n8) {
break;
}
pty->u8 = ThomPikeMerge(pty->u8, p[i]);
if (--pty->n8) break;
}
SetMachinePtyCell(pty, pty->u8);
pty->state = kMachinePtyAscii;

View file

@ -130,7 +130,7 @@ void GetDosLocalTime(int64_t utcunixts, uint16_t *out_time,
struct tm tm;
CHECK_NOTNULL(localtime_r(&utcunixts, &tm));
*out_time = DOS_TIME(tm.tm_hour, tm.tm_min, tm.tm_sec);
*out_date = DOS_DATE(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
*out_date = DOS_DATE(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday + 1);
}
static unsigned char *EmitZipLfileHdr(unsigned char *op, const void *name,