mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-03 09:48:29 +00:00
Add fixes performance and static web server
This commit is contained in:
parent
b6793d42d5
commit
c45e46f871
108 changed files with 2927 additions and 819 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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) */
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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 *);
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue