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

@ -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;