Add minor improvements and cleanup

This commit is contained in:
Justine Tunney 2020-10-27 03:39:46 -07:00
parent 9e3e985ae5
commit feed0d2b0e
163 changed files with 2286 additions and 2245 deletions

View file

@ -34,7 +34,10 @@
#include "libc/errno.h"
#include "libc/fmt/bing.h"
#include "libc/fmt/fmt.h"
#include "libc/intrin/pcmpeqb.h"
#include "libc/intrin/pmovmskb.h"
#include "libc/log/check.h"
#include "libc/log/color.h"
#include "libc/log/log.h"
#include "libc/macros.h"
#include "libc/math.h"
@ -143,21 +146,19 @@ FEATURES\n\
#define kXmmHex 1
#define kXmmChar 2
#define CTRL(C) ((C) ^ 0100)
#define kMouseLeftDown 0
#define kMouseMiddleDown 1
#define kMouseRightDown 2
#define kMouseLeftUp 4
#define kMouseMiddleUp 5
#define kMouseRightUp 6
#define kMouseLeftDrag 32
#define kMouseMiddleDrag 33
#define kMouseRightDrag 34
#define kMouseWheelUp 64
#define kMouseWheelDown 65
enum Mouse {
kMouseLeftDown = 0,
kMouseMiddleDown = 1,
kMouseRightDown = 2,
kMouseLeftUp = 4,
kMouseMiddleUp = 5,
kMouseRightUp = 6,
kMouseLeftDrag = 32,
kMouseMiddleDrag = 33,
kMouseRightDrag = 34,
kMouseWheelUp = 64,
kMouseWheelDown = 65,
};
#define CTRL(C) ((C) ^ 0100)
struct MachineState {
uint64_t ip;
@ -171,6 +172,7 @@ struct MachineState {
uint8_t xmm[16][16];
struct MachineFpu fpu;
struct MachineSse sse;
struct MachineMemstat memstat;
};
struct Panels {
@ -196,8 +198,9 @@ struct Panels {
struct Panel writedata;
struct Panel stackhr;
struct Panel stack;
struct Panel status;
};
struct Panel p[20];
struct Panel p[21];
};
};
@ -230,6 +233,7 @@ static int readzoom;
static int writezoom;
static int stackzoom;
static long ips;
static long rombase;
static long codesize;
static int64_t opstart;
@ -240,20 +244,23 @@ static int64_t writestart;
static int64_t stackstart;
static int64_t framesstart;
static int64_t breakpointsstart;
static uint64_t last_opcount;
static char *codepath;
static void *onbusted;
static char *statusmessage;
static struct Machine *m;
static struct MachinePty *pty;
static struct Pty *pty;
static struct Panels pan;
static struct MachineState laststate;
static struct Breakpoints breakpoints;
static struct MachineMemstat lastmemstat;
static struct Elf elf[1];
static struct Dis dis[1];
static uint8_t xmmtype[16];
static uint8_t xmmsize[16];
long double last_seconds;
static long double statusexpires;
static struct termios oldterm;
static char logpath[PATH_MAX];
@ -386,6 +393,18 @@ static int64_t GetSp(void) {
}
}
static int64_t ReadWord(uint8_t *p) {
switch (GetPointerWidth()) {
default:
case 8:
return Read64(p);
case 4:
return Read32(p);
case 2:
return Read16(p);
}
}
static void UpdateXmmTypes(int regtype, int rmtype) {
xmmtype[RexrReg(m->xedd->op.rde)] = regtype;
if (IsModrmRegister(m->xedd->op.rde)) {
@ -519,6 +538,18 @@ static void UpdateXmmType(void) {
UpdateXmmSizes(1, 2);
UpdateXmmTypes(kXmmIntegral, kXmmIntegral);
break;
case 0x128: // MOVAPS Vps Wps
if (IsModrmRegister(m->xedd->op.rde)) {
xmmtype[RexrReg(m->xedd->op.rde)] = xmmtype[RexbRm(m->xedd->op.rde)];
xmmsize[RexrReg(m->xedd->op.rde)] = xmmsize[RexbRm(m->xedd->op.rde)];
}
break;
case 0x129: // MOVAPS Wps Vps
if (IsModrmRegister(m->xedd->op.rde)) {
xmmtype[RexbRm(m->xedd->op.rde)] = xmmtype[RexrReg(m->xedd->op.rde)];
xmmsize[RexbRm(m->xedd->op.rde)] = xmmsize[RexrReg(m->xedd->op.rde)];
}
break;
case 0x16F: // MOVDQA Vdq Wdq
if (Osz(m->xedd->op.rde) && IsModrmRegister(m->xedd->op.rde)) {
xmmtype[RexrReg(m->xedd->op.rde)] = xmmtype[RexbRm(m->xedd->op.rde)];
@ -671,7 +702,6 @@ static void OnSigAlarm(void) {
static void OnSigCont(void) {
TuiRejuvinate();
SetupDraw();
Redraw();
}
@ -771,12 +801,12 @@ void TuiSetup(void) {
LoadSyms();
ResolveBreakpoints();
ioctl(ttyout, TCGETS, &oldterm);
xsigaction(SIGALRM, OnSigAlarm, 0, 0, 0);
xsigaction(SIGINT, OnSigInt, 0, 0, oldsig + 3);
atexit(TtyRestore2);
once = true;
report = true;
}
setitimer(ITIMER_REAL, &((struct itimerval){0}), NULL);
xsigaction(SIGCONT, OnSigCont, SA_RESTART | SA_NODEFER, 0, oldsig + 2);
CopyMachineState(&laststate);
TuiRejuvinate();
@ -798,6 +828,9 @@ static void ExecSetup(void) {
}
once = true;
}
setitimer(ITIMER_REAL,
&((struct itimerval){{0, 1. / 60 * 1e6}, {0, 1. / 60 * 1e6}}),
NULL);
}
static void AppendPanel(struct Panel *p, long line, const char *s) {
@ -807,12 +840,14 @@ static void AppendPanel(struct Panel *p, long line, const char *s) {
}
static bool IsXmmNonZero(long start, long end) {
long i, j;
long i;
uint8_t v1[16], vz[16];
for (i = start; i < end; ++i) {
for (j = 0; j < 16; ++j) {
if (m->xmm[i][j]) {
return true;
}
memset(vz, 0, 16);
memcpy(v1, m->xmm[i], 16);
pcmpeqb(v1, v1, vz);
if (pmovmskb(v1) != 0xffff) {
return true;
}
}
return false;
@ -840,16 +875,8 @@ static int PickNumberOfXmmRegistersToShow(void) {
}
}
static void SetupDraw(void) {
int i, j, n, a, b, cpuy, ssey, dx[2], c2y[3], c3y[5];
for (i = 0; i < ARRAYLEN(pan.p); ++i) {
n = pan.p[i].bottom - pan.p[i].top;
for (j = 0; j < n; ++j) {
free(pan.p[i].lines[j].p);
}
free(pan.p[i].lines);
}
void SetupDraw(void) {
int i, j, n, a, b, yn, cpuy, ssey, dx[2], c2y[3], c3y[5];
cpuy = 9;
if (IsSegNonZero()) cpuy += 2;
@ -861,20 +888,21 @@ static void SetupDraw(void) {
dx[1] = txn >= a + b ? txn - a : txn;
dx[0] = txn >= a + b + b ? txn - a - b : dx[1];
a = 1 / 8. * tyn;
b = 3 / 8. * tyn;
yn = tyn - 1;
a = 1 / 8. * yn;
b = 3 / 8. * yn;
c2y[0] = a * .7;
c2y[1] = a * 2;
c2y[2] = a * 2 + b;
if (tyn - c2y[2] > 26) {
c2y[1] -= tyn - c2y[2] - 26;
c2y[2] = tyn - 26;
if (yn - c2y[2] > 26) {
c2y[1] -= yn - c2y[2] - 26;
c2y[2] = yn - 26;
}
if (tyn - c2y[2] < 26) {
c2y[2] = tyn - 26;
if (yn - c2y[2] < 26) {
c2y[2] = yn - 26;
}
a = (tyn - (cpuy + ssey) - 3) / 4;
a = (yn - (cpuy + ssey) - 3) / 4;
c3y[0] = cpuy;
c3y[1] = cpuy + ssey;
c3y[2] = cpuy + ssey + 1 + 1 + a * 1;
@ -885,8 +913,8 @@ static void SetupDraw(void) {
pan.disassembly.top = 0;
pan.disassembly.left = 0;
pan.disassembly.bottom = tyn;
pan.disassembly.right = dx[0];
pan.disassembly.bottom = yn;
pan.disassembly.right = dx[0] - 1;
/* COLUMN #2: BREAKPOINTS, MEMORY MAPS, BACKTRACE, DISPLAY */
@ -927,7 +955,7 @@ static void SetupDraw(void) {
pan.display.top = c2y[2] + 1;
pan.display.left = dx[0];
pan.display.bottom = tyn;
pan.display.bottom = yn;
pan.display.right = dx[1] - 1;
/* COLUMN #3: REGISTERS, VECTORS, CODE, MEMORY READS, MEMORY WRITES, STACK */
@ -984,18 +1012,38 @@ static void SetupDraw(void) {
pan.stack.top = c3y[4] + 1;
pan.stack.left = dx[1];
pan.stack.bottom = tyn;
pan.stack.bottom = yn;
pan.stack.right = txn;
pan.status.top = yn;
pan.status.left = 0;
pan.status.bottom = yn + 1;
pan.status.right = txn;
for (i = 0; i < ARRAYLEN(pan.p); ++i) {
if (pan.p[i].top > pan.p[i].bottom) pan.p[i].top = pan.p[i].bottom = 0;
if (pan.p[i].left > pan.p[i].right) pan.p[i].left = pan.p[i].right = 0;
pan.p[i].lines =
xcalloc(pan.p[i].bottom - pan.p[i].top, sizeof(struct Buffer));
if (pan.p[i].left > pan.p[i].right) {
pan.p[i].left = pan.p[i].right = 0;
}
if (pan.p[i].top > pan.p[i].bottom) {
pan.p[i].top = pan.p[i].bottom = 0;
}
n = pan.p[i].bottom - pan.p[i].top;
if (n == pan.p[i].n) {
for (j = 0; j < n; ++j) {
pan.p[i].lines[j].i = 0;
}
} else {
for (j = 0; j < pan.p[i].n; ++j) {
free(pan.p[i].lines[j].p);
}
free(pan.p[i].lines);
pan.p[i].lines = xcalloc(n, sizeof(struct Buffer));
pan.p[i].n = n;
}
}
MachinePtyResize(pty, pan.display.bottom - pan.display.top,
pan.display.right - pan.display.left);
PtyResize(pty, pan.display.bottom - pan.display.top,
pan.display.right - pan.display.left);
}
static long Disassemble(void) {
@ -1043,30 +1091,30 @@ static void DrawHr(struct Panel *p, const char *s) {
void DrawTerminal(struct Panel *p) {
long i, y, yn;
if (pty->conf & kMachinePtyBell) {
if (pty->conf & kPtyBell) {
if (!alarmed) {
alarmed = true;
setitimer(ITIMER_REAL, &((struct itimerval){{0, 0}, {0, 800000}}), NULL);
}
AppendStr(&pan.displayhr.lines[0], "\e[1m");
}
AppendStr(
&pan.displayhr.lines[0],
gc(xasprintf("──────────TELETYPEWRITER──%s──%s──%s──%s",
(pty->conf & kMachinePtyLed1) ? "\e[1;31m◎\e[0m" : "",
(pty->conf & kMachinePtyLed2) ? "\e[1;32m◎\e[0m" : "",
(pty->conf & kMachinePtyLed3) ? "\e[1;33m◎\e[0m" : "",
(pty->conf & kMachinePtyLed4) ? "\e[1;34m◎\e[0m" : "")));
AppendStr(&pan.displayhr.lines[0],
gc(xasprintf("──────────TELETYPEWRITER──%s──%s──%s──%s",
(pty->conf & kPtyLed1) ? "\e[1;31m◎\e[0m" : "",
(pty->conf & kPtyLed2) ? "\e[1;32m◎\e[0m" : "",
(pty->conf & kPtyLed3) ? "\e[1;33m◎\e[0m" : "",
(pty->conf & kPtyLed4) ? "\e[1;34m◎\e[0m" : "")));
for (i = 36; i < pan.displayhr.right - pan.displayhr.left; ++i) {
AppendWide(&pan.displayhr.lines[0], u'');
}
for (yn = MIN(pty->yn, p->bottom - p->top), y = 0; y < yn; ++y) {
MachinePtyAppendLine(pty, p->lines + y, y);
PtyAppendLine(pty, p->lines + y, y);
AppendStr(p->lines + y, "\e[0m");
}
}
void DrawDisplay(struct Panel *p) {
if (p->top == p->bottom) return;
switch (vidya) {
case 7:
DrawHr(&pan.displayhr, "MONOCHROME DISPLAY ADAPTER");
@ -1140,6 +1188,7 @@ static void DrawSt(struct Panel *p, long i, long r) {
static void DrawCpu(struct Panel *p) {
char buf[48];
if (p->top == p->bottom) return;
DrawRegister(p, 0, 7), DrawRegister(p, 0, 0), DrawSt(p, 0, 0);
DrawRegister(p, 1, 6), DrawRegister(p, 1, 3), DrawSt(p, 1, 1);
DrawRegister(p, 2, 2), DrawRegister(p, 2, 5), DrawSt(p, 2, 2);
@ -1239,6 +1288,7 @@ static void DrawXmm(struct Panel *p, long i, long r) {
static void DrawSse(struct Panel *p) {
long i;
if (p->top == p->bottom) return;
for (i = 0; i < MIN(16, MAX(0, p->bottom - p->top)); ++i) {
DrawXmm(p, i, i);
}
@ -1314,6 +1364,7 @@ static void DrawMemory(struct Panel *p, int zoom, long startline, long histart,
char buf[16];
bool high, changed;
long i, j, k, c, width;
if (p->top == p->bottom) return;
high = false;
width = DUMPWIDTH * (1 << zoom);
for (i = 0; i < p->bottom - p->top; ++i) {
@ -1342,6 +1393,7 @@ static void DrawMemory(struct Panel *p, int zoom, long startline, long histart,
static void DrawMaps(struct Panel *p) {
int i;
char *text, *p1, *p2;
if (p->top == p->bottom) return;
p1 = text = FormatPml4t(m);
for (i = 0; p1; ++i, p1 = p2) {
if ((p2 = strchr(p1, '\n'))) *p2++ = '\0';
@ -1357,6 +1409,7 @@ static void DrawBreakpoints(struct Panel *p) {
const char *name;
char *s, buf[256];
long i, line, sym;
if (p->top == p->bottom) return;
for (line = 0, i = breakpoints.i; i--;) {
if (breakpoints.p[i].disable) continue;
if (line >= breakpointsstart) {
@ -1396,6 +1449,7 @@ static void DrawFrames(struct Panel *p) {
const char *name;
char *s, line[256];
int64_t sp, bp, rp;
if (p->top == p->bottom) return;
rp = m->ip;
bp = Read64(m->bp);
sp = Read64(m->sp);
@ -1427,8 +1481,8 @@ static void DrawFrames(struct Panel *p) {
break;
}
sp = bp;
bp = Read64(r + 0);
rp = Read64(r + 8);
bp = ReadWord(r + 0);
rp = ReadWord(r + 8);
}
}
@ -1466,8 +1520,60 @@ static bool IsExecuting(void) {
return (action & (CONTINUE | STEP | NEXT | FINISH)) && !(action & FAILURE);
}
static int AppendStat(struct Buffer *b, const char *name, int64_t value,
bool changed) {
int width;
AppendChar(b, ' ');
if (changed) AppendStr(b, "\e[31m");
width = AppendFmt(b, "%,8ld %s", value, name);
if (changed) AppendStr(b, "\e[39m");
return 1 + width;
}
void DrawStatus(struct Panel *p) {
int yn, xn, rw;
struct Buffer s;
struct MachineMemstat *a, *b;
yn = p->top - p->bottom;
xn = p->right - p->left;
if (!yn || !xn) return;
rw = 0;
a = &m->memstat;
b = &lastmemstat;
memset(&s, 0, sizeof(s));
if (ips > 0) rw += AppendStat(&s, "ips", ips, false);
rw += AppendStat(&s, "kb", m->real.n / 1024, false);
rw += AppendStat(&s, "reserve", a->reserved, a->reserved != b->reserved);
rw += AppendStat(&s, "commit", a->committed, a->committed != b->committed);
rw += AppendStat(&s, "freed", a->freed, a->freed != b->freed);
rw += AppendStat(&s, "tables", a->pagetables, a->pagetables != b->pagetables);
rw += AppendStat(&s, "fds", m->fds.i, false);
AppendFmt(&p->lines[0], "\e[7m%-*s%s\e[0m", xn - rw,
statusmessage && nowl() < statusexpires ? statusmessage
: "das blinkenlights",
s.p);
free(s.p);
memcpy(b, a, sizeof(*a));
}
static void PreventBufferbloat(void) {
long double now, rate;
static long double last;
now = nowl();
rate = 1. / 60;
if (now - last < rate) {
dsleep(rate - (now - last));
}
last = now;
}
static void Redraw(void) {
int i, j;
ScrollOp(&pan.disassembly, GetDisIndex());
if (last_opcount) {
ips = unsignedsubtract(opcount, last_opcount) / (nowl() - last_seconds);
}
SetupDraw();
for (i = 0; i < ARRAYLEN(pan.p); ++i) {
for (j = 0; j < pan.p[i].bottom - pan.p[i].top; ++j) {
pan.p[i].lines[j].i = 0;
@ -1478,7 +1584,7 @@ static void Redraw(void) {
DrawCpu(&pan.registers);
DrawSse(&pan.sse);
DrawHr(&pan.breakpointshr, "BREAKPOINTS");
DrawHr(&pan.mapshr, "MAPS");
DrawHr(&pan.mapshr, "PML4T");
DrawHr(&pan.frameshr, m->bofram[0] ? "PROTECTED FRAMES" : "FRAMES");
DrawHr(&pan.ssehr, "SSE");
DrawHr(&pan.codehr, "CODE");
@ -1496,19 +1602,20 @@ static void Redraw(void) {
m->writeaddr + m->writesize);
DrawMemory(&pan.stack, stackzoom, stackstart, GetSp(),
GetSp() + GetPointerWidth());
DrawStatus(&pan.status);
PreventBufferbloat();
if (PrintPanels(ttyout, ARRAYLEN(pan.p), pan.p, tyn, txn) == -1) {
LOGF("PrintPanels Interrupted");
CHECK_EQ(EINTR, errno);
}
if (statusmessage && nowl() < statusexpires) {
TtyWriteString(statusmessage);
}
last_opcount = opcount;
last_seconds = nowl();
CopyMachineState(&laststate);
}
static void ReactiveDraw(void) {
if (tuimode) {
m->ip -= m->xedd->length;
SetupDraw();
Redraw();
m->ip += m->xedd->length;
tick = speed;
@ -1518,7 +1625,7 @@ static void ReactiveDraw(void) {
static void HandleAlarm(void) {
alarmed = false;
action &= ~ALARM;
pty->conf &= ~kMachinePtyBell;
pty->conf &= ~kPtyBell;
free(statusmessage);
statusmessage = NULL;
}
@ -1547,7 +1654,7 @@ static void HandleAppReadInterrupt(void) {
}
static int OnPtyFdClose(int fd) {
return 0;
return close(fd);
}
static bool HasPendingInput(int fd) {
@ -1564,7 +1671,7 @@ static ssize_t ReadPtyFdDirect(int fd, void *data, size_t size) {
ssize_t rc;
DEBUGF("ReadPtyFdDirect");
buf = malloc(PAGESIZE);
pty->conf |= kMachinePtyBlinkcursor;
pty->conf |= kPtyBlinkcursor;
if (tuimode) DisableMouseTracking();
for (;;) {
ReactiveDraw();
@ -1573,11 +1680,11 @@ static ssize_t ReadPtyFdDirect(int fd, void *data, size_t size) {
HandleAppReadInterrupt();
}
if (tuimode) EnableMouseTracking();
pty->conf &= ~kMachinePtyBlinkcursor;
pty->conf &= ~kPtyBlinkcursor;
if (rc > 0) {
MachinePtyWriteInput(pty, buf, rc);
PtyWriteInput(pty, buf, rc);
ReactiveDraw();
rc = MachinePtyRead(pty, data, size);
rc = PtyRead(pty, data, size);
}
free(buf);
return rc;
@ -1596,7 +1703,7 @@ static ssize_t OnPtyFdReadv(int fd, const struct iovec *iov, int iovlen) {
}
}
if (size) {
if (!(rc = MachinePtyRead(pty, data, size))) {
if (!(rc = PtyRead(pty, data, size))) {
rc = ReadPtyFdDirect(fd, data, size);
}
return rc;
@ -1605,14 +1712,16 @@ static ssize_t OnPtyFdReadv(int fd, const struct iovec *iov, int iovlen) {
}
}
static void DrawTerminalOnly(void) {
static void DrawDisplayOnly(struct Panel *p) {
struct Buffer b;
int i, y, yn, xn, tly, tlx, conf;
conf = pty->conf & kMachinePtyNocursor;
pty->conf |= kMachinePtyNocursor;
yn = MIN(tyn, p->bottom - p->top);
xn = MIN(txn, p->right - p->left);
for (i = 0; i < yn; ++i) {
p->lines[i].i = 0;
}
DrawDisplay(p);
memset(&b, 0, sizeof(b));
yn = MIN(tyn, pty->yn);
xn = MIN(txn, pty->xn);
tly = tyn / 2 - yn / 2;
tlx = txn / 2 - xn / 2;
AppendStr(&b, "\e[0m\e[H");
@ -1622,24 +1731,21 @@ static void DrawTerminalOnly(void) {
for (i = 0; i < tlx; ++i) {
AppendChar(&b, ' ');
}
MachinePtyAppendLine(pty, &b, y - tly);
AppendData(&b, p->lines[y - tly].p, p->lines[y - tly].i);
}
AppendStr(&b, "\e[0m\e[K");
}
AppendFmt(&b, "\e[%d;%dH", tly + pty->y + 1, tlx + pty->x + 1);
write(ttyout, b.p, b.i);
free(b.p);
pty->conf |= conf;
}
static ssize_t OnPtyFdWritev(int fd, const struct iovec *iov, int iovlen) {
int i;
size_t size;
for (size = i = 0; i < iovlen; ++i) {
MachinePtyWrite(pty, iov[i].iov_base, iov[i].iov_len);
PtyWrite(pty, iov[i].iov_base, iov[i].iov_len);
size += iov[i].iov_len;
}
if (!tuimode) DrawTerminalOnly();
return size;
}
@ -1651,27 +1757,27 @@ static int OnPtyFdTiocgwinsz(int fd, struct winsize *ws) {
static int OnPtyFdTcgets(int fd, struct termios *c) {
memset(c, 0, sizeof(*c));
if (!(pty->conf & kMachinePtyNocanon)) c->c_iflag |= ICANON;
if (!(pty->conf & kMachinePtyNoecho)) c->c_iflag |= ECHO;
if (!(pty->conf & kMachinePtyNoopost)) c->c_oflag |= OPOST;
if (!(pty->conf & kPtyNocanon)) c->c_iflag |= ICANON;
if (!(pty->conf & kPtyNoecho)) c->c_iflag |= ECHO;
if (!(pty->conf & kPtyNoopost)) c->c_oflag |= OPOST;
return 0;
}
static int OnPtyFdTcsets(int fd, uint64_t request, struct termios *c) {
if (c->c_iflag & ICANON) {
pty->conf &= ~kMachinePtyNocanon;
pty->conf &= ~kPtyNocanon;
} else {
pty->conf |= kMachinePtyNocanon;
pty->conf |= kPtyNocanon;
}
if (c->c_iflag & ECHO) {
pty->conf &= ~kMachinePtyNoecho;
pty->conf &= ~kPtyNoecho;
} else {
pty->conf |= kMachinePtyNoecho;
pty->conf |= kPtyNoecho;
}
if (c->c_oflag & OPOST) {
pty->conf &= ~kMachinePtyNoopost;
pty->conf &= ~kPtyNoopost;
} else {
pty->conf |= kMachinePtyNoopost;
pty->conf |= kPtyNoopost;
}
return 0;
}
@ -1732,14 +1838,13 @@ static void OnSimdException(void) {
}
static void OnUndefinedInstruction(void) {
die();
strcpy(systemfailure, "UNDEFINED INSTRUCTION");
LaunchDebuggerReactively();
}
static void OnDecodeError(void) {
strcpy(stpcpy(systemfailure, "DECODE: "),
indexdoublenulstring(kXedErrorNames, m->xedd->op.error));
IndexDoubleNulString(kXedErrorNames, m->xedd->op.error));
LaunchDebuggerReactively();
}
@ -1854,15 +1959,15 @@ static void OnVidyaServiceGetMode(void) {
}
static void OnVidyaServiceSetCursorPosition(void) {
MachinePtySetY(pty, m->dx[1]);
MachinePtySetX(pty, m->dx[0]);
PtySetY(pty, m->dx[1]);
PtySetX(pty, m->dx[0]);
}
static void OnVidyaServiceGetCursorPosition(void) {
m->dx[1] = pty->y;
m->dx[0] = pty->x;
m->cx[1] = 5; // cursor ▂ scan lines 5..7 of 0..7
m->cx[0] = 7 | !!(pty->conf & kMachinePtyNocursor) << 5;
m->cx[0] = 7 | !!(pty->conf & kPtyNocursor) << 5;
}
static int GetVidyaByte(unsigned char b) {
@ -1880,7 +1985,7 @@ static void OnVidyaServiceWriteCharacter(void) {
p += tpencode(p, 8, GetVidyaByte(m->ax[0]), false);
p = stpcpy(p, "\e8");
for (i = Read16(m->cx); i--;) {
MachinePtyWrite(pty, buf, p - buf);
PtyWrite(pty, buf, p - buf);
}
}
@ -1902,7 +2007,7 @@ static void OnVidyaServiceTeletypeOutput(void) {
char buf[12];
n = FormatCga(m->bx[0], buf);
n += tpencode(buf + n, 6, VidyaServiceXlatTeletype(m->ax[0]), false);
MachinePtyWrite(pty, buf, n);
PtyWrite(pty, buf, n);
}
static void OnVidyaService(void) {
@ -1933,7 +2038,7 @@ static void OnVidyaService(void) {
static void OnKeyboardServiceReadKeyPress(void) {
uint8_t b;
ssize_t rc;
pty->conf |= kMachinePtyBlinkcursor;
pty->conf |= kPtyBlinkcursor;
if (tuimode) DisableMouseTracking();
for (;;) {
ReactiveDraw();
@ -1942,7 +2047,7 @@ static void OnKeyboardServiceReadKeyPress(void) {
HandleAppReadInterrupt();
}
if (tuimode) EnableMouseTracking();
pty->conf &= ~kMachinePtyBlinkcursor;
pty->conf &= ~kPtyBlinkcursor;
ReactiveDraw();
if (b == 0x7F) b = '\b';
m->ax[0] = b;
@ -2065,16 +2170,12 @@ static void SetStatus(const char *fmt, ...) {
va_list va;
int y, x, n;
va_start(va, fmt);
s = gc(xvasprintf(fmt, va));
s = xvasprintf(fmt, va);
va_end(va);
n = strwidth(s);
y = tyn - (n / txn + 1);
x = txn / 2 - n / 2;
free(statusmessage);
statusmessage = xasprintf("\e[0m\e[%d;%dH%s", y + 1, x + 1, s);
TtyWriteString(statusmessage);
setitimer(ITIMER_REAL, &((struct itimerval){{0, 0}, {1, 0}}), NULL);
statusmessage = s;
statusexpires = nowl() + 1;
setitimer(ITIMER_REAL, &((struct itimerval){{0, 0}, {1, 0}}), NULL);
}
static void OnTurbo(void) {
@ -2201,8 +2302,7 @@ static void Sleep(int ms) {
}
static void OnMouse(char *p) {
enum Mouse e;
int i, x, y, dy;
int e, i, x, y, dy;
struct Panel *ep;
e = strtol(p, &p, 10);
if (*p == ';') ++p;
@ -2251,7 +2351,10 @@ static void OnMouse(char *p) {
static void ReadKeyboard(void) {
char buf[64], *p = buf;
if (readansi(ttyin, buf, sizeof(buf)) == -1) {
if (errno == EINTR) return;
if (errno == EINTR) {
LOGF("readkeyboard interrupted");
return;
}
FATALF("readkeyboard failed: %s", strerror(errno));
}
switch (*p++) {
@ -2384,39 +2487,42 @@ static void Exec(void) {
if (!(interrupt = setjmp(m->onhalt))) {
if (!(action & CONTINUE) &&
(bp = IsAtBreakpoint(&breakpoints, GetIp())) != -1) {
LOGF("BREAK %p", breakpoints.p[bp].addr);
LOGF("BREAK1 %p", breakpoints.p[bp].addr);
tuimode = true;
LoadInstruction(m);
ExecuteInstruction(m);
++opcount;
CheckFramePointer();
ops++;
} else {
action &= ~CONTINUE;
for (;;) {
LoadInstruction(m);
if ((bp = IsAtBreakpoint(&breakpoints, GetIp())) != -1) {
LOGF("BREAK2 %p", breakpoints.p[bp].addr);
action &= ~(FINISH | NEXT | CONTINUE);
tuimode = true;
break;
}
ExecuteInstruction(m);
++opcount;
KeepGoing:
CheckFramePointer();
ops++;
if (action || breakpoints.i) {
if (action & EXIT) {
LOGF("EXEC EXIT");
break;
}
if (action & INT) {
LOGF("EXEC INT");
if (react) {
LOGF("REACT");
action &= ~(INT | STEP | FINISH | NEXT);
tuimode = true;
}
break;
}
if ((bp = IsAtBreakpoint(&breakpoints, GetIp())) != -1) {
LOGF("BREAK %p", breakpoints.p[bp].addr);
if (action & ALARM) {
DrawDisplayOnly(&pan.display);
action &= ~ALARM;
}
if (action & EXIT) {
LOGF("EXEC EXIT");
break;
}
if (action & INT) {
LOGF("EXEC INT");
if (react) {
LOGF("REACT");
action &= ~(INT | STEP | FINISH | NEXT);
tuimode = true;
break;
}
break;
}
}
}
@ -2441,6 +2547,12 @@ static void Tui(void) {
if (!(action & FAILURE)) {
LoadInstruction(m);
UpdateXmmType();
if ((action & (FINISH | NEXT | CONTINUE)) &&
(bp = IsAtBreakpoint(&breakpoints, GetIp())) != -1) {
action &= ~(FINISH | NEXT | CONTINUE);
LOGF("BREAK %p", breakpoints.p[bp].addr);
break;
}
} else {
m->xedd = (struct XedDecodedInst *)m->icache[0];
m->xedd->length = 1;
@ -2466,14 +2578,17 @@ static void Tui(void) {
}
if (!(action & CONTINUE) || interactive) {
tick = 0;
GetDisIndex();
SetupDraw();
Redraw();
}
if (action & FAILURE) {
LOGF("TUI FAILURE");
PrintMessageBox(ttyout, systemfailure, tyn, txn);
ReadKeyboard();
if (action & INT) {
LOGF("TUI INT");
LeaveScreen();
exit(1);
}
} else if (!IsExecuting() || (!(action & CONTINUE) && !(action & INT) &&
HasPendingKeyboard())) {
ReadKeyboard();
@ -2505,10 +2620,6 @@ static void Tui(void) {
break;
}
if (IsExecuting()) {
op = GetDisIndex();
ScrollOp(&pan.disassembly, op);
VERBOSEF("%s", DisGetLine(dis, m, op));
CopyMachineState(&laststate);
if (!(action & CONTINUE)) {
action &= ~STEP;
if (action & NEXT) {
@ -2529,6 +2640,7 @@ static void Tui(void) {
}
if (!IsDebugBreak()) {
ExecuteInstruction(m);
++opcount;
if (!(action & CONTINUE) || interactive) {
ScrollCode(&pan.code);
ScrollStack(&pan.stack);
@ -2546,7 +2658,6 @@ static void Tui(void) {
}
KeepGoing:
CheckFramePointer();
ops++;
if (!(action & CONTINUE)) {
ScrollOp(&pan.disassembly, GetDisIndex());
if ((action & FINISH) && IsRet()) action &= ~FINISH;
@ -2554,12 +2665,6 @@ static void Tui(void) {
action &= ~NEXT;
}
}
if ((action & (FINISH | NEXT | CONTINUE)) &&
(bp = IsAtBreakpoint(&breakpoints, GetIp())) != -1) {
action &= ~(FINISH | NEXT | CONTINUE);
LOGF("BREAK %p", breakpoints.p[bp].addr);
break;
}
}
}
} else {
@ -2611,25 +2716,30 @@ static void GetOpts(int argc, char *argv[]) {
setvbuf(g_logfile, xmalloc(PAGESIZE), _IOLBF, PAGESIZE);
}
static int OpenDevTty(void) {
return open("/dev/tty", O_RDWR | O_NOCTTY);
}
static void AddHostFd(int fd) {
int i = m->fds.i++;
CHECK_NE(-1, (m->fds.p[i].fd = fd));
m->fds.p[i].cb = &kMachineFdCbHost;
}
int Emulator(int argc, char *argv[]) {
void *code;
int rc, fd;
codepath = argv[optind++];
pty = MachinePtyNew();
m->fds.p = xcalloc((m->fds.n = 8), sizeof(struct MachineFd));
Restart:
action = 0;
LoadProgram(m, codepath, argv + optind, environ, elf);
m->fds.i = 3;
m->fds.p[0].fd = STDIN_FILENO;
m->fds.p[0].cb = &kMachineFdCbHost;
m->fds.p[1].fd = STDOUT_FILENO;
m->fds.p[1].cb = &kMachineFdCbHost;
m->fds.p[2].fd = STDERR_FILENO;
m->fds.p[2].cb = &kMachineFdCbHost;
AddHostFd(STDIN_FILENO);
AddHostFd(STDOUT_FILENO);
AddHostFd(STDERR_FILENO);
if (tuimode) {
ttyin = isatty(0) ? 0 : open("/dev/tty", O_RDWR | O_NOCTTY);
ttyout = isatty(1) ? 1 : open("/dev/tty", O_RDWR | O_NOCTTY);
ttyin = isatty(STDIN_FILENO) ? STDIN_FILENO : OpenDevTty();
ttyout = isatty(STDOUT_FILENO) ? STDOUT_FILENO : OpenDevTty();
} else {
ttyin = -1;
ttyout = -1;
@ -2640,18 +2750,9 @@ Restart:
tyn = 24;
txn = 80;
GetTtySize(ttyout);
if (isatty(0)) {
m->fds.p[0].fd = 0;
m->fds.p[0].cb = &kMachineFdCbPty;
}
if (isatty(1)) {
m->fds.p[1].fd = 1;
m->fds.p[1].cb = &kMachineFdCbPty;
}
if (isatty(2)) {
m->fds.p[2].fd = 2;
m->fds.p[2].cb = &kMachineFdCbPty;
}
if (isatty(STDIN_FILENO)) m->fds.p[STDIN_FILENO].cb = &kMachineFdCbPty;
if (isatty(STDOUT_FILENO)) m->fds.p[STDOUT_FILENO].cb = &kMachineFdCbPty;
if (isatty(STDERR_FILENO)) m->fds.p[STDERR_FILENO].cb = &kMachineFdCbPty;
}
while (!(action & EXIT)) {
if (!tuimode) {
@ -2669,7 +2770,7 @@ Restart:
if (printstats) {
fprintf(stderr, "taken: %,ld\n", taken);
fprintf(stderr, "ntaken: %,ld\n", ntaken);
fprintf(stderr, "ops: %,ld\n", ops);
fprintf(stderr, "ops: %,ld\n", opcount);
}
munmap(elf->ehdr, elf->size);
DisFree(dis);
@ -2682,12 +2783,13 @@ static void OnlyRunOnFirstCpu(void) {
}
int main(int argc, char *argv[]) {
if (!NoDebug()) showcrashreports();
pty = NewPty();
m = NewMachine();
m->mode = XED_MACHINE_MODE_LONG_64;
speed = 16;
SetXmmSize(2);
SetXmmDisp(kXmmHex);
if (!NoDebug()) showcrashreports();
/* OnlyRunOnFirstCpu(); */
if ((colorize = cancolor())) {
g_high.keyword = 155;
g_high.reg = 215;
@ -2697,6 +2799,7 @@ int main(int argc, char *argv[]) {
g_high.quote = 215;
}
GetOpts(argc, argv);
xsigaction(SIGALRM, OnSigAlarm, 0, 0, 0);
if (optind == argc) PrintUsage(EX_USAGE, stderr);
return Emulator(argc, argv);
}