mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-16 07:39:56 +00:00
Add tool for viewing memory
https://justine.storage.googleapis.com/memzoom/index.html
This commit is contained in:
parent
2d80bbc802
commit
9fe95ef12b
22 changed files with 1511 additions and 1028 deletions
|
@ -49,13 +49,16 @@ void AppendStr(struct Buffer *b, const char *s) {
|
|||
}
|
||||
|
||||
void AppendWide(struct Buffer *b, wint_t wc) {
|
||||
unsigned i;
|
||||
uint64_t wb;
|
||||
wb = wc;
|
||||
if (!isascii(wb)) wb = tpenc(wb);
|
||||
char buf[8];
|
||||
i = 0;
|
||||
wb = tpenc(wc);
|
||||
do {
|
||||
AppendChar(b, wb & 0xFF);
|
||||
buf[i++] = wb & 0xFF;
|
||||
wb >>= 8;
|
||||
} while (wb);
|
||||
AppendData(b, buf, i);
|
||||
}
|
||||
|
||||
int AppendFmt(struct Buffer *b, const char *fmt, ...) {
|
||||
|
@ -72,24 +75,31 @@ int AppendFmt(struct Buffer *b, const char *fmt, ...) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Writes buffer until completion, interrupt, or error occurs.
|
||||
* Writes buffer until completion, or error occurs.
|
||||
*/
|
||||
ssize_t WriteBuffer(struct Buffer *b, int fd) {
|
||||
bool t;
|
||||
char *p;
|
||||
ssize_t rc;
|
||||
size_t wrote, n;
|
||||
p = b->p;
|
||||
n = b->i;
|
||||
t = false;
|
||||
do {
|
||||
if ((rc = write(fd, p, n)) != -1) {
|
||||
wrote = rc;
|
||||
p += wrote;
|
||||
n -= wrote;
|
||||
} else if (errno == EINTR) {
|
||||
break;
|
||||
t = true;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
} while (n);
|
||||
return 0;
|
||||
if (!t) {
|
||||
return 0;
|
||||
} else {
|
||||
errno = EINTR;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/mremap.h"
|
||||
#include "libc/sysv/consts/msync.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/ok.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
|
@ -177,6 +178,7 @@ struct ElfWriter *elfwriter_open(const char *path, int mode) {
|
|||
void elfwriter_close(struct ElfWriter *elf) {
|
||||
size_t i;
|
||||
FlushTables(elf);
|
||||
CHECK_NE(-1, msync(elf->map, elf->wrote, MS_SYNC));
|
||||
CHECK_NE(-1, munmap(elf->map, elf->mapsize));
|
||||
CHECK_NE(-1, ftruncate(elf->fd, elf->wrote));
|
||||
CHECK_NE(-1, close(elf->fd));
|
||||
|
|
|
@ -1632,6 +1632,7 @@ static void OpMovRqCq(struct Machine *m, uint32_t rde) {
|
|||
}
|
||||
|
||||
static void OpMovCqRq(struct Machine *m, uint32_t rde) {
|
||||
int64_t cr3;
|
||||
switch (ModrmReg(rde)) {
|
||||
case 0:
|
||||
m->cr0 = Read64(RegRexbRm(m, rde));
|
||||
|
@ -1640,7 +1641,12 @@ static void OpMovCqRq(struct Machine *m, uint32_t rde) {
|
|||
m->cr2 = Read64(RegRexbRm(m, rde));
|
||||
break;
|
||||
case 3:
|
||||
m->cr3 = Read64(RegRexbRm(m, rde));
|
||||
cr3 = Read64(RegRexbRm(m, rde));
|
||||
if (0 <= cr3 && cr3 + 512 * 8 <= m->real.n) {
|
||||
m->cr3 = cr3;
|
||||
} else {
|
||||
ThrowProtectionFault(m);
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
m->cr4 = Read64(RegRexbRm(m, rde));
|
||||
|
|
63
tool/build/lib/pml4t.c
Normal file
63
tool/build/lib/pml4t.c
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ 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. │
|
||||
│ │
|
||||
│ 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 │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/alg/arraylist2.h"
|
||||
#include "tool/build/lib/endian.h"
|
||||
#include "tool/build/lib/machine.h"
|
||||
#include "tool/build/lib/pml4t.h"
|
||||
|
||||
static void AppendContiguousMemoryRange(struct ContiguousMemoryRanges *ranges,
|
||||
int64_t a, int64_t b) {
|
||||
APPEND(&ranges->p, &ranges->i, &ranges->n,
|
||||
(&(struct ContiguousMemoryRange){a, b}));
|
||||
}
|
||||
|
||||
static void FindContiguousMemoryRangesImpl(
|
||||
struct Machine *m, struct ContiguousMemoryRanges *ranges, int64_t addr,
|
||||
unsigned level, int64_t pt, int64_t a, int64_t b) {
|
||||
int64_t i, page, entry;
|
||||
for (i = a; i < b; ++i) {
|
||||
entry = Read64(m->real.p + pt + i * 8);
|
||||
if (!(entry & 1)) continue;
|
||||
entry &= 0x7ffffffff000;
|
||||
page = (addr | i << level) << 16 >> 16;
|
||||
if (level == 12) {
|
||||
if (ranges->i && page == ranges->p[ranges->i - 1].b) {
|
||||
ranges->p[ranges->i - 1].b += 0x1000;
|
||||
} else {
|
||||
AppendContiguousMemoryRange(ranges, page, page + 0x1000);
|
||||
}
|
||||
} else if (entry + 512 * 8 <= m->real.n) {
|
||||
FindContiguousMemoryRangesImpl(m, ranges, page, level - 9, entry, 0, 512);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FindContiguousMemoryRanges(struct Machine *m,
|
||||
struct ContiguousMemoryRanges *ranges) {
|
||||
uint64_t cr3;
|
||||
ranges->i = 0;
|
||||
if ((m->mode & 3) == XED_MODE_LONG) {
|
||||
cr3 = m->cr3 & 0x7ffffffff000;
|
||||
FindContiguousMemoryRangesImpl(m, ranges, 0, 39, cr3, 256, 512);
|
||||
FindContiguousMemoryRangesImpl(m, ranges, 0, 39, cr3, 0, 256);
|
||||
} else {
|
||||
AppendContiguousMemoryRange(ranges, 0, m->real.n);
|
||||
}
|
||||
}
|
|
@ -8,6 +8,17 @@ COSMOPOLITAN_C_START_
|
|||
#define UnmaskPageAddr(x) SignExtendAddr(MaskPageAddr(x))
|
||||
#define SignExtendAddr(x) ((int64_t)((uint64_t)(x) << 16) >> 16)
|
||||
|
||||
struct ContiguousMemoryRanges {
|
||||
size_t i, n;
|
||||
struct ContiguousMemoryRange {
|
||||
int64_t a;
|
||||
int64_t b;
|
||||
} * p;
|
||||
};
|
||||
|
||||
void FindContiguousMemoryRanges(struct Machine *,
|
||||
struct ContiguousMemoryRanges *);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_PML4T_H_ */
|
||||
|
|
179
tool/build/lib/xmmtype.c
Normal file
179
tool/build/lib/xmmtype.c
Normal file
|
@ -0,0 +1,179 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ 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. │
|
||||
│ │
|
||||
│ 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 │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "tool/build/lib/modrm.h"
|
||||
#include "tool/build/lib/xmmtype.h"
|
||||
|
||||
static void UpdateXmmTypes(struct Machine *m, struct XmmType *xt, int regtype,
|
||||
int rmtype) {
|
||||
xt->type[RexrReg(m->xedd->op.rde)] = regtype;
|
||||
if (IsModrmRegister(m->xedd->op.rde)) {
|
||||
xt->type[RexbRm(m->xedd->op.rde)] = rmtype;
|
||||
}
|
||||
}
|
||||
|
||||
static void UpdateXmmSizes(struct Machine *m, struct XmmType *xt, int regsize,
|
||||
int rmsize) {
|
||||
xt->size[RexrReg(m->xedd->op.rde)] = regsize;
|
||||
if (IsModrmRegister(m->xedd->op.rde)) {
|
||||
xt->size[RexbRm(m->xedd->op.rde)] = rmsize;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateXmmType(struct Machine *m, struct XmmType *xt) {
|
||||
switch (m->xedd->op.dispatch) {
|
||||
case 0x12E: // UCOMIS
|
||||
case 0x12F: // COMIS
|
||||
case 0x151: // SQRT
|
||||
case 0x152: // RSQRT
|
||||
case 0x153: // RCP
|
||||
case 0x158: // ADD
|
||||
case 0x159: // MUL
|
||||
case 0x15C: // SUB
|
||||
case 0x15D: // MIN
|
||||
case 0x15E: // DIV
|
||||
case 0x15F: // MAX
|
||||
case 0x1C2: // CMP
|
||||
if (Osz(m->xedd->op.rde) || Rep(m->xedd->op.rde) == 2) {
|
||||
UpdateXmmTypes(m, xt, kXmmDouble, kXmmDouble);
|
||||
} else {
|
||||
UpdateXmmTypes(m, xt, kXmmFloat, kXmmFloat);
|
||||
}
|
||||
break;
|
||||
case 0x12A: // CVTPI2PS,CVTSI2SS,CVTPI2PD,CVTSI2SD
|
||||
if (Osz(m->xedd->op.rde) || Rep(m->xedd->op.rde) == 2) {
|
||||
UpdateXmmSizes(m, xt, 8, 4);
|
||||
UpdateXmmTypes(m, xt, kXmmDouble, kXmmIntegral);
|
||||
} else {
|
||||
UpdateXmmSizes(m, xt, 4, 4);
|
||||
UpdateXmmTypes(m, xt, kXmmFloat, kXmmIntegral);
|
||||
}
|
||||
break;
|
||||
case 0x15A: // CVT{P,S}{S,D}2{P,S}{S,D}
|
||||
if (Osz(m->xedd->op.rde) || Rep(m->xedd->op.rde) == 2) {
|
||||
UpdateXmmTypes(m, xt, kXmmFloat, kXmmDouble);
|
||||
} else {
|
||||
UpdateXmmTypes(m, xt, kXmmDouble, kXmmFloat);
|
||||
}
|
||||
break;
|
||||
case 0x15B: // CVT{,T}{DQ,PS}2{PS,DQ}
|
||||
UpdateXmmSizes(m, xt, 4, 4);
|
||||
if (Osz(m->xedd->op.rde) || Rep(m->xedd->op.rde) == 3) {
|
||||
UpdateXmmTypes(m, xt, kXmmIntegral, kXmmFloat);
|
||||
} else {
|
||||
UpdateXmmTypes(m, xt, kXmmFloat, kXmmIntegral);
|
||||
}
|
||||
break;
|
||||
case 0x17C: // HADD
|
||||
case 0x17D: // HSUB
|
||||
case 0x1D0: // ADDSUB
|
||||
if (Osz(m->xedd->op.rde)) {
|
||||
UpdateXmmTypes(m, xt, kXmmDouble, kXmmDouble);
|
||||
} else {
|
||||
UpdateXmmTypes(m, xt, kXmmFloat, kXmmFloat);
|
||||
}
|
||||
break;
|
||||
case 0x164: // PCMPGTB
|
||||
case 0x174: // PCMPEQB
|
||||
case 0x1D8: // PSUBUSB
|
||||
case 0x1DA: // PMINUB
|
||||
case 0x1DC: // PADDUSB
|
||||
case 0x1DE: // PMAXUB
|
||||
case 0x1E0: // PAVGB
|
||||
case 0x1E8: // PSUBSB
|
||||
case 0x1EC: // PADDSB
|
||||
case 0x1F8: // PSUBB
|
||||
case 0x1FC: // PADDB
|
||||
UpdateXmmSizes(m, xt, 1, 1);
|
||||
UpdateXmmTypes(m, xt, kXmmIntegral, kXmmIntegral);
|
||||
break;
|
||||
case 0x165: // PCMPGTW
|
||||
case 0x175: // PCMPEQW
|
||||
case 0x171: // PSRLW,PSRAW,PSLLW
|
||||
case 0x1D1: // PSRLW
|
||||
case 0x1D5: // PMULLW
|
||||
case 0x1D9: // PSUBUSW
|
||||
case 0x1DD: // PADDUSW
|
||||
case 0x1E1: // PSRAW
|
||||
case 0x1E3: // PAVGW
|
||||
case 0x1E4: // PMULHUW
|
||||
case 0x1E5: // PMULHW
|
||||
case 0x1E9: // PSUBSW
|
||||
case 0x1EA: // PMINSW
|
||||
case 0x1ED: // PADDSW
|
||||
case 0x1EE: // PMAXSW
|
||||
case 0x1F1: // PSLLW
|
||||
case 0x1F6: // PSADBW
|
||||
case 0x1F9: // PSUBW
|
||||
case 0x1FD: // PADDW
|
||||
UpdateXmmSizes(m, xt, 2, 2);
|
||||
UpdateXmmTypes(m, xt, kXmmIntegral, kXmmIntegral);
|
||||
break;
|
||||
case 0x166: // PCMPGTD
|
||||
case 0x176: // PCMPEQD
|
||||
case 0x172: // PSRLD,PSRAD,PSLLD
|
||||
case 0x1D2: // PSRLD
|
||||
case 0x1E2: // PSRAD
|
||||
case 0x1F2: // PSLLD
|
||||
case 0x1FA: // PSUBD
|
||||
case 0x1FE: // PADDD
|
||||
UpdateXmmSizes(m, xt, 4, 4);
|
||||
UpdateXmmTypes(m, xt, kXmmIntegral, kXmmIntegral);
|
||||
break;
|
||||
case 0x173: // PSRLQ,PSRLQ,PSRLDQ,PSLLQ,PSLLDQ
|
||||
case 0x1D3: // PSRLQ
|
||||
case 0x1D4: // PADDQ
|
||||
case 0x1F3: // PSLLQ
|
||||
case 0x1F4: // PMULUDQ
|
||||
case 0x1FB: // PSUBQ
|
||||
UpdateXmmSizes(m, xt, 8, 8);
|
||||
UpdateXmmTypes(m, xt, kXmmIntegral, kXmmIntegral);
|
||||
break;
|
||||
case 0x16B: // PACKSSDW
|
||||
case 0x1F5: // PMADDWD
|
||||
UpdateXmmSizes(m, xt, 4, 2);
|
||||
UpdateXmmTypes(m, xt, kXmmIntegral, kXmmIntegral);
|
||||
break;
|
||||
case 0x163: // PACKSSWB
|
||||
case 0x167: // PACKUSWB
|
||||
UpdateXmmSizes(m, xt, 1, 2);
|
||||
UpdateXmmTypes(m, xt, kXmmIntegral, kXmmIntegral);
|
||||
break;
|
||||
case 0x128: // MOVAPS Vps Wps
|
||||
if (IsModrmRegister(m->xedd->op.rde)) {
|
||||
xt->type[RexrReg(m->xedd->op.rde)] = xt->type[RexbRm(m->xedd->op.rde)];
|
||||
xt->size[RexrReg(m->xedd->op.rde)] = xt->size[RexbRm(m->xedd->op.rde)];
|
||||
}
|
||||
break;
|
||||
case 0x129: // MOVAPS Wps Vps
|
||||
if (IsModrmRegister(m->xedd->op.rde)) {
|
||||
xt->type[RexbRm(m->xedd->op.rde)] = xt->type[RexrReg(m->xedd->op.rde)];
|
||||
xt->size[RexbRm(m->xedd->op.rde)] = xt->size[RexrReg(m->xedd->op.rde)];
|
||||
}
|
||||
break;
|
||||
case 0x16F: // MOVDQA Vdq Wdq
|
||||
if (Osz(m->xedd->op.rde) && IsModrmRegister(m->xedd->op.rde)) {
|
||||
xt->type[RexrReg(m->xedd->op.rde)] = xt->type[RexbRm(m->xedd->op.rde)];
|
||||
xt->size[RexrReg(m->xedd->op.rde)] = xt->size[RexbRm(m->xedd->op.rde)];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
21
tool/build/lib/xmmtype.h
Normal file
21
tool/build/lib/xmmtype.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_XMMTYPE_H_
|
||||
#define COSMOPOLITAN_TOOL_BUILD_LIB_XMMTYPE_H_
|
||||
#include "tool/build/lib/machine.h"
|
||||
|
||||
#define kXmmIntegral 0
|
||||
#define kXmmDouble 1
|
||||
#define kXmmFloat 2
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
struct XmmType {
|
||||
uint8_t type[16];
|
||||
uint8_t size[16];
|
||||
};
|
||||
|
||||
void UpdateXmmType(struct Machine *, struct XmmType *);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_XMMTYPE_H_ */
|
Loading…
Add table
Add a link
Reference in a new issue