mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-13 06:29:11 +00:00
Make minor improvements
- Work towards simplifying ape.S startup process - Rewrote ar because it took minutes to build cosmopolitan.a
This commit is contained in:
parent
95bc650be8
commit
aea89fe832
70 changed files with 1037 additions and 456 deletions
255
tool/build/ar.c
Normal file
255
tool/build/ar.c
Normal file
|
@ -0,0 +1,255 @@
|
|||
/*-*- 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 "libc/bits/bits.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/iovec.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/conv/conv.h"
|
||||
#include "libc/conv/itoa.h"
|
||||
#include "libc/elf/def.h"
|
||||
#include "libc/elf/elf.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/madv.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
/**
|
||||
* @fileoverview System Five Static Archive Builder.
|
||||
*
|
||||
* GNU ar has a bug which causes it to take hundreds of milliseconds to
|
||||
* build archives like ntdll.a and several minutes for cosmopolitan.a.
|
||||
* This goes quadratically faster taking 1ms to do ntdll w/ hot cache.
|
||||
*
|
||||
* Compared to LLVM ar this tool goes 10x faster because it uses madvise
|
||||
* and copy_file_range which give us the optimal page cached file system
|
||||
* beahvior that a build environment needs.
|
||||
*
|
||||
* This tool also adds a feature: it ignores directory parameters. This
|
||||
* is important because good Makefiles on Linux will generally have the
|
||||
* directory be a .a prerequisite so archives rebuild on file deletion.
|
||||
*/
|
||||
|
||||
struct String {
|
||||
size_t i, n;
|
||||
char *p;
|
||||
};
|
||||
|
||||
struct Ints {
|
||||
size_t i, n;
|
||||
int *p;
|
||||
};
|
||||
|
||||
struct Header {
|
||||
char name[16];
|
||||
char date[12];
|
||||
char uid[6];
|
||||
char gid[6];
|
||||
char mode[8];
|
||||
char size[10];
|
||||
char fmag[2];
|
||||
};
|
||||
|
||||
static void MakeHeader(struct Header *h, const char *name, int ref, int mode,
|
||||
int size) {
|
||||
size_t n;
|
||||
char buf[21];
|
||||
memset(h, ' ', sizeof(*h));
|
||||
n = strlen(name);
|
||||
memcpy(h->name, name, n);
|
||||
if (ref != -1) {
|
||||
memcpy(h->name + n, buf, uint64toarray_radix10(ref, buf));
|
||||
}
|
||||
if (strcmp(name, "//") != 0) {
|
||||
h->date[0] = '0';
|
||||
h->uid[0] = '0';
|
||||
h->gid[0] = '0';
|
||||
memcpy(h->mode, buf, uint64toarray_radix8(mode & 0777, buf));
|
||||
}
|
||||
h->fmag[0] = '`';
|
||||
h->fmag[1] = '\n';
|
||||
memcpy(h->size, buf, uint64toarray_radix10(size, buf));
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
void *elf;
|
||||
char *strs;
|
||||
ssize_t rc;
|
||||
struct stat *st;
|
||||
uint32_t outpos;
|
||||
Elf64_Sym *syms;
|
||||
uint64_t outsize;
|
||||
char **objectargs;
|
||||
uint8_t *tablebuf;
|
||||
struct iovec iov[7];
|
||||
const char *symname;
|
||||
Elf64_Xword symcount;
|
||||
struct Ints symnames;
|
||||
struct String symbols;
|
||||
struct String filenames;
|
||||
const char *options, *outpath;
|
||||
struct Header *header1, *header2;
|
||||
size_t wrote, remain, objectargcount;
|
||||
int *offsets, *modes, *sizes, *names;
|
||||
int i, j, fd, err, name, outfd, tablebufsize;
|
||||
|
||||
st = xmalloc(sizeof(struct stat));
|
||||
symbols.i = 0;
|
||||
symbols.n = 4096;
|
||||
symbols.p = xmalloc(symbols.n);
|
||||
filenames.i = 0;
|
||||
filenames.n = 1024;
|
||||
filenames.p = xmalloc(filenames.n);
|
||||
symnames.i = 0;
|
||||
symnames.n = 1024;
|
||||
symnames.p = xmalloc(symnames.n * sizeof(int));
|
||||
|
||||
CHECK_GT(argc, 3);
|
||||
options = argv[1];
|
||||
outpath = argv[2];
|
||||
objectargs = argv + 3;
|
||||
objectargcount = argc - 3;
|
||||
CHECK_EQ(0, strcmp(options, "rcsD"));
|
||||
modes = xmalloc(sizeof(int) * objectargcount);
|
||||
names = xmalloc(sizeof(int) * objectargcount);
|
||||
sizes = xmalloc(sizeof(int) * objectargcount);
|
||||
|
||||
// load global symbols and populate page cache
|
||||
for (i = 0; i < objectargcount; ++i) {
|
||||
TryAgain:
|
||||
CHECK_NE(-1, (fd = open(objectargs[i], O_RDONLY)));
|
||||
CHECK_NE(-1, fstat(fd, st));
|
||||
CHECK_LT(st->st_size, 0x7ffff000);
|
||||
if (!st->st_size || S_ISDIR(st->st_mode) ||
|
||||
endswith(objectargs[i], ".pkg")) {
|
||||
close(fd);
|
||||
for (j = i; j + 1 < objectargcount; ++j) {
|
||||
objectargs[j] = objectargs[j + 1];
|
||||
}
|
||||
--objectargcount;
|
||||
goto TryAgain;
|
||||
}
|
||||
names[i] = filenames.i;
|
||||
sizes[i] = st->st_size;
|
||||
modes[i] = st->st_mode;
|
||||
CONCAT(&filenames.p, &filenames.i, &filenames.n, basename(objectargs[i]),
|
||||
strlen(basename(objectargs[i])));
|
||||
CONCAT(&filenames.p, &filenames.i, &filenames.n, "/\n", 2);
|
||||
CHECK_NE(MAP_FAILED,
|
||||
(elf = mmap(NULL, st->st_size, PROT_READ, MAP_PRIVATE, fd, 0)));
|
||||
madvise(elf, st->st_size, MADV_WILLNEED);
|
||||
CHECK(IsElf64Binary(elf, st->st_size));
|
||||
CHECK_NOTNULL((strs = GetElfStringTable(elf, st->st_size)));
|
||||
CHECK_NOTNULL((syms = GetElfSymbolTable(elf, st->st_size, &symcount)));
|
||||
for (j = 0; j < symcount; ++j) {
|
||||
if (syms[j].st_shndx == SHN_UNDEF) continue;
|
||||
if (syms[j].st_other == STV_INTERNAL) continue;
|
||||
if (ELF64_ST_BIND(syms[j].st_info) == STB_LOCAL) continue;
|
||||
symname = GetElfString(elf, st->st_size, strs, syms[j].st_name);
|
||||
CONCAT(&symbols.p, &symbols.i, &symbols.n, symname, strlen(symname) + 1);
|
||||
APPEND(&symnames.p, &symnames.i, &symnames.n, &i);
|
||||
}
|
||||
CHECK_NE(-1, munmap(elf, st->st_size));
|
||||
close(fd);
|
||||
}
|
||||
APPEND(&filenames.p, &filenames.i, &filenames.n, "\n");
|
||||
|
||||
// compute length of output archive
|
||||
outsize = 0;
|
||||
tablebufsize = 4 + symnames.i * 4;
|
||||
tablebuf = xmalloc(tablebufsize);
|
||||
offsets = xmalloc(objectargcount * 4);
|
||||
header1 = xmalloc(sizeof(struct Header));
|
||||
header2 = xmalloc(sizeof(struct Header));
|
||||
iov[0].iov_base = "!<arch>\n";
|
||||
outsize += (iov[0].iov_len = 8);
|
||||
iov[1].iov_base = header1;
|
||||
outsize += (iov[1].iov_len = 60);
|
||||
iov[2].iov_base = tablebuf;
|
||||
outsize += (iov[2].iov_len = tablebufsize);
|
||||
iov[3].iov_base = symbols.p;
|
||||
outsize += (iov[3].iov_len = symbols.i);
|
||||
iov[4].iov_base = "\n";
|
||||
outsize += (iov[4].iov_len = outsize & 1);
|
||||
iov[5].iov_base = header2;
|
||||
outsize += (iov[5].iov_len = 60);
|
||||
iov[6].iov_base = filenames.p;
|
||||
outsize += (iov[6].iov_len = filenames.i);
|
||||
for (i = 0; i < objectargcount; ++i) {
|
||||
outsize += outsize & 1;
|
||||
offsets[i] = outsize;
|
||||
outsize += 60;
|
||||
outsize += sizes[i];
|
||||
}
|
||||
CHECK_LE(outsize, 0x7ffff000);
|
||||
|
||||
// serialize metadata
|
||||
MakeHeader(header1, "/", -1, 0, tablebufsize + symbols.i);
|
||||
MakeHeader(header2, "//", -1, 0, filenames.i);
|
||||
WRITE32BE(tablebuf, symnames.i);
|
||||
for (i = 0; i < symnames.i; ++i) {
|
||||
WRITE32BE(tablebuf + 4 + i * 4, offsets[symnames.p[i]]);
|
||||
}
|
||||
|
||||
// write output archive
|
||||
CHECK_NE(-1, (outfd = open(outpath, O_WRONLY | O_TRUNC | O_CREAT, 0644)));
|
||||
ftruncate(outfd, outsize);
|
||||
if ((outsize = writev(outfd, iov, ARRAYLEN(iov))) == -1) goto fail;
|
||||
for (i = 0; i < objectargcount; ++i) {
|
||||
if ((fd = open(objectargs[i], O_RDONLY)) == -1) goto fail;
|
||||
iov[0].iov_base = "\n";
|
||||
outsize += (iov[0].iov_len = outsize & 1);
|
||||
iov[1].iov_base = header1;
|
||||
outsize += (iov[1].iov_len = 60);
|
||||
MakeHeader(header1, "/", names[i], modes[i], sizes[i]);
|
||||
if (writev(outfd, iov, 2) == -1) goto fail;
|
||||
outsize += (remain = sizes[i]);
|
||||
if (copy_file_range(fd, NULL, outfd, NULL, remain, 0) != remain) goto fail;
|
||||
close(fd);
|
||||
}
|
||||
close(outfd);
|
||||
|
||||
free(header2);
|
||||
free(header1);
|
||||
free(offsets);
|
||||
free(tablebuf);
|
||||
free(sizes);
|
||||
free(names);
|
||||
free(modes);
|
||||
free(symbols.p);
|
||||
free(filenames.p);
|
||||
free(symnames.p);
|
||||
free(st);
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
err = errno;
|
||||
if (!err) err = 1;
|
||||
unlink(outpath);
|
||||
fputs("error: ar failed\n", stderr);
|
||||
return err;
|
||||
}
|
|
@ -21,6 +21,7 @@
|
|||
#include "dsp/tty/tty.h"
|
||||
#include "libc/alg/arraylist2.h"
|
||||
#include "libc/assert.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
|
@ -165,7 +166,7 @@ FEATURES\n\
|
|||
|
||||
struct MemoryView {
|
||||
int64_t start;
|
||||
unsigned zoom;
|
||||
int zoom;
|
||||
};
|
||||
|
||||
struct MachineState {
|
||||
|
@ -1158,10 +1159,17 @@ static void ScrollMemoryView(struct Panel *p, struct MemoryView *v, int64_t a) {
|
|||
}
|
||||
}
|
||||
|
||||
static void ZoomMemoryView(struct MemoryView *v, int dy) {
|
||||
v->start *= (DUMPWIDTH * (1ull << v->zoom));
|
||||
v->zoom = MIN(MAXZOOM, MAX(0, v->zoom + dy));
|
||||
v->start /= (DUMPWIDTH * (1ull << v->zoom));
|
||||
static void ZoomMemoryView(struct MemoryView *v, long y, long x, int dy) {
|
||||
long a, b, i, s;
|
||||
s = v->start;
|
||||
a = v->zoom;
|
||||
b = MIN(MAXZOOM, MAX(0, a + dy));
|
||||
i = y * DUMPWIDTH - x;
|
||||
s *= DUMPWIDTH * (1L << a);
|
||||
s += i * (1L << a) - i * (1L << b);
|
||||
s /= DUMPWIDTH * (1L << b);
|
||||
v->zoom = b;
|
||||
v->start = s;
|
||||
}
|
||||
|
||||
static void ScrollMemoryViews(void) {
|
||||
|
@ -1171,15 +1179,15 @@ static void ScrollMemoryViews(void) {
|
|||
ScrollMemoryView(&pan.stack, &stackview, GetSp());
|
||||
}
|
||||
|
||||
static void ZoomMemoryViews(struct Panel *p, int dy) {
|
||||
static void ZoomMemoryViews(struct Panel *p, int y, int x, int dy) {
|
||||
if (p == &pan.code) {
|
||||
ZoomMemoryView(&codeview, dy);
|
||||
ZoomMemoryView(&codeview, y, x, dy);
|
||||
} else if (p == &pan.readdata) {
|
||||
ZoomMemoryView(&readview, dy);
|
||||
ZoomMemoryView(&readview, y, x, dy);
|
||||
} else if (p == &pan.writedata) {
|
||||
ZoomMemoryView(&writeview, dy);
|
||||
ZoomMemoryView(&writeview, y, x, dy);
|
||||
} else if (p == &pan.stack) {
|
||||
ZoomMemoryView(&stackview, dy);
|
||||
ZoomMemoryView(&stackview, y, x, dy);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1798,14 +1806,18 @@ static void OnDiskServiceGetParams(void) {
|
|||
static void OnDiskServiceReadSectors(void) {
|
||||
static int x;
|
||||
uint64_t addr, size;
|
||||
int64_t drive, head, track, sector, offset;
|
||||
int64_t sectors, drive, head, track, sector, offset;
|
||||
sectors = m->ax[0];
|
||||
drive = m->dx[0];
|
||||
head = m->dx[1];
|
||||
track = (m->cx[0] & 0b11000000) << 2 | m->cx[1];
|
||||
sector = (m->cx[0] & 0b00111111) - 1;
|
||||
offset = head * track * sector * 512;
|
||||
size = m->ax[0] * 512;
|
||||
size = sectors * 512;
|
||||
offset = sector * 512 + track * 512 * 63 + head * 512 * 63 * 1024;
|
||||
VERBOSEF("bios read sectors %d "
|
||||
"@ sector %ld track %ld head %ld drive %ld offset %#lx",
|
||||
sectors, sector, track, head, drive, offset);
|
||||
if (0 <= sector && offset + size <= elf->mapsize) {
|
||||
addr = Read64(m->es) + Read16(m->bx);
|
||||
if (addr + size <= m->real.n) {
|
||||
|
@ -1819,6 +1831,8 @@ static void OnDiskServiceReadSectors(void) {
|
|||
SetCarry(true);
|
||||
}
|
||||
} else {
|
||||
WARNF("bios read sector failed 0 <= %d && %lx + %lx <= %lx", sector, offset,
|
||||
size, elf->mapsize);
|
||||
m->ax[0] = 0x00;
|
||||
m->ax[1] = 0x0d;
|
||||
SetCarry(true);
|
||||
|
@ -2074,7 +2088,9 @@ static void OnBinbase(struct Machine *m) {
|
|||
}
|
||||
|
||||
static void OnLongBranch(struct Machine *m) {
|
||||
Disassemble();
|
||||
if (tuimode) {
|
||||
Disassemble();
|
||||
}
|
||||
}
|
||||
|
||||
static void OnPageUp(void) {
|
||||
|
@ -2098,20 +2114,28 @@ static void SetStatus(const char *fmt, ...) {
|
|||
setitimer(ITIMER_REAL, &((struct itimerval){{0, 0}, {1, 0}}), NULL);
|
||||
}
|
||||
|
||||
static int ClampSpeed(int s) {
|
||||
return MAX(-0x1000, MIN(0x40000000, s));
|
||||
}
|
||||
|
||||
static void OnTurbo(void) {
|
||||
if (speed >= -1) {
|
||||
speed = MIN(0x40000000, MAX(1, speed) << 1); // 1..40mips skip
|
||||
if (!speed || speed == -1) {
|
||||
speed = 1;
|
||||
} else if (speed > 0) {
|
||||
speed = ClampSpeed(speed << 1);
|
||||
} else {
|
||||
speed >>= 1;
|
||||
speed = ClampSpeed(speed >> 1);
|
||||
}
|
||||
SetStatus("speed %,d", speed);
|
||||
}
|
||||
|
||||
static void OnSlowmo(void) {
|
||||
if (speed > 0) {
|
||||
speed >>= 1;
|
||||
if (!speed || speed == 1) {
|
||||
speed = -1;
|
||||
} else if (speed > 0) {
|
||||
speed = ClampSpeed(speed >> 1);
|
||||
} else {
|
||||
speed = MAX(-(5 * 1000), MIN(-1, speed) << 1); // 1ms..5s delay
|
||||
speed = ClampSpeed(speed << 1);
|
||||
}
|
||||
SetStatus("speed %,d", speed);
|
||||
}
|
||||
|
@ -2221,7 +2245,7 @@ static void Sleep(int ms) {
|
|||
poll((struct pollfd[]){{ttyin, POLLIN}}, 1, ms);
|
||||
}
|
||||
|
||||
static void OnMouseWheelUp(struct Panel *p) {
|
||||
static void OnMouseWheelUp(struct Panel *p, int y, int x) {
|
||||
if (p == &pan.disassembly) {
|
||||
opstart -= WHEELDELTA;
|
||||
} else if (p == &pan.code) {
|
||||
|
@ -2241,7 +2265,7 @@ static void OnMouseWheelUp(struct Panel *p) {
|
|||
}
|
||||
}
|
||||
|
||||
static void OnMouseWheelDown(struct Panel *p) {
|
||||
static void OnMouseWheelDown(struct Panel *p, int y, int x) {
|
||||
if (p == &pan.disassembly) {
|
||||
opstart += WHEELDELTA;
|
||||
} else if (p == &pan.code) {
|
||||
|
@ -2261,12 +2285,12 @@ static void OnMouseWheelDown(struct Panel *p) {
|
|||
}
|
||||
}
|
||||
|
||||
static void OnMouseCtrlWheelUp(struct Panel *p) {
|
||||
ZoomMemoryViews(p, -1);
|
||||
static void OnMouseCtrlWheelUp(struct Panel *p, int y, int x) {
|
||||
ZoomMemoryViews(p, y, x, -1);
|
||||
}
|
||||
|
||||
static void OnMouseCtrlWheelDown(struct Panel *p) {
|
||||
ZoomMemoryViews(p, +1);
|
||||
static void OnMouseCtrlWheelDown(struct Panel *p, int y, int x) {
|
||||
ZoomMemoryViews(p, y, x, +1);
|
||||
}
|
||||
|
||||
static struct Panel *LocatePanel(int y, int x) {
|
||||
|
@ -2290,18 +2314,20 @@ static void OnMouse(char *p) {
|
|||
y = min(tyn, max(1, strtol(p, &p, 10))) - 1;
|
||||
e |= (*p == 'm') << 2;
|
||||
if ((ep = LocatePanel(y, x))) {
|
||||
y -= ep->top;
|
||||
x -= ep->left;
|
||||
switch (e) {
|
||||
case kMouseWheelUp:
|
||||
OnMouseWheelUp(ep);
|
||||
OnMouseWheelUp(ep, y, x);
|
||||
break;
|
||||
case kMouseWheelDown:
|
||||
OnMouseWheelDown(ep);
|
||||
OnMouseWheelDown(ep, y, x);
|
||||
break;
|
||||
case kMouseCtrlWheelUp:
|
||||
OnMouseCtrlWheelUp(ep);
|
||||
OnMouseCtrlWheelUp(ep, y, x);
|
||||
break;
|
||||
case kMouseCtrlWheelDown:
|
||||
OnMouseCtrlWheelDown(ep);
|
||||
OnMouseCtrlWheelDown(ep, y, x);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
55
tool/build/dropcache.c
Normal file
55
tool/build/dropcache.c
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*-*- 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/calls/calls.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
|
||||
/**
|
||||
* Removes file system caches from RAM.
|
||||
*
|
||||
* make o//tool/build/dropcache.com
|
||||
* sudo mv o//tool/build/dropcache.com /usr/local/bin/
|
||||
* sudo chown root /usr/local/bin/dropcache.com
|
||||
* sudo chmod u+s /usr/local/bin/dropcache.com
|
||||
*/
|
||||
|
||||
static void Write(int fd, const char *s) {
|
||||
write(fd, s, strlen(s));
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int fd;
|
||||
sync();
|
||||
fd = open("/proc/sys/vm/drop_caches", O_WRONLY);
|
||||
if (fd == -1) {
|
||||
if (errno == EACCES) {
|
||||
Write(1, "error: need root privileges\n");
|
||||
} else if (errno == ENOENT) {
|
||||
Write(1, "error: need /proc filesystem\n");
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
Write(fd, "3\n");
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
|
@ -74,8 +74,8 @@ static void DisLoadElfSyms(struct Dis *d, struct Elf *elf) {
|
|||
const Elf64_Sym *st, *sym;
|
||||
bool isabs, iscode, isweak, islocal, ishidden, isprotected, isfunc, isobject;
|
||||
j = 0;
|
||||
if ((d->syms.stab = getelfstringtable(elf->ehdr, elf->size)) &&
|
||||
(st = getelfsymboltable(elf->ehdr, elf->size, &n))) {
|
||||
if ((d->syms.stab = GetElfStringTable(elf->ehdr, elf->size)) &&
|
||||
(st = GetElfSymbolTable(elf->ehdr, elf->size, &n))) {
|
||||
stablen = (intptr_t)elf->ehdr + elf->size - (intptr_t)d->syms.stab;
|
||||
if (d->syms.n < n) {
|
||||
d->syms.n = n;
|
||||
|
|
|
@ -238,8 +238,8 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) {
|
|||
RCASE(0xCB, "lret");
|
||||
RCASE(0xCC, "int3");
|
||||
RCASE(0xCD, "int Ib");
|
||||
RCASE(0xD0, "BIT Eb $1");
|
||||
RCASE(0xD1, "BIT Evqp $1");
|
||||
RCASE(0xD0, "BIT Eb");
|
||||
RCASE(0xD1, "BIT Evqp");
|
||||
RCASE(0xD2, "BIT Evqp %cl");
|
||||
RCASE(0xD3, "BIT Evqp %cl");
|
||||
RCASE(0xD4, x->op.uimm0 == 0x0a ? "aam" : "aam Ib");
|
||||
|
|
|
@ -178,7 +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, msync(elf->map, elf->wrote, MS_ASYNC));
|
||||
CHECK_NE(-1, munmap(elf->map, elf->mapsize));
|
||||
CHECK_NE(-1, ftruncate(elf->fd, elf->wrote));
|
||||
CHECK_NE(-1, close(elf->fd));
|
||||
|
|
|
@ -137,40 +137,24 @@ void LoadProgram(struct Machine *m, const char *prog, char **args, char **vars,
|
|||
int fd;
|
||||
ssize_t rc;
|
||||
int64_t sp;
|
||||
char *real;
|
||||
void *stack;
|
||||
struct stat st;
|
||||
size_t i, codesize, mappedsize, extrasize;
|
||||
size_t i, mappedsize;
|
||||
DCHECK_NOTNULL(prog);
|
||||
elf->prog = prog;
|
||||
if ((fd = open(prog, O_RDONLY)) == -1 ||
|
||||
(fstat(fd, &st) == -1 || !st.st_size) /* || !S_ISREG(st.st_mode) */) {
|
||||
(fstat(fd, &st) == -1 || !st.st_size)) {
|
||||
fputs(prog, stderr);
|
||||
fputs(": not found\n", stderr);
|
||||
exit(1);
|
||||
}
|
||||
codesize = st.st_size;
|
||||
elf->mapsize = ROUNDDOWN(codesize, FRAMESIZE);
|
||||
extrasize = codesize - elf->mapsize;
|
||||
elf->map = real = (char *)0x0000400000000000;
|
||||
if (elf->mapsize) {
|
||||
CHECK_NE(MAP_FAILED, mmap(real, elf->mapsize, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_FIXED, fd, 0));
|
||||
real += elf->mapsize;
|
||||
}
|
||||
if (extrasize) {
|
||||
CHECK_NE(MAP_FAILED,
|
||||
mmap(real, ROUNDUP(extrasize, FRAMESIZE), PROT_READ | PROT_WRITE,
|
||||
MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0));
|
||||
for (i = 0; i < extrasize; i += (size_t)rc) {
|
||||
CHECK_NE(-1, (rc = pread(fd, real + i, extrasize - i, elf->mapsize + i)));
|
||||
}
|
||||
elf->mapsize += ROUNDUP(extrasize, FRAMESIZE);
|
||||
}
|
||||
elf->mapsize = st.st_size;
|
||||
CHECK_NE(MAP_FAILED,
|
||||
(elf->map = mmap(NULL, elf->mapsize, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE, fd, 0)));
|
||||
CHECK_NE(-1, close(fd));
|
||||
ResetCpu(m);
|
||||
if ((m->mode & 3) == XED_MODE_REAL) {
|
||||
BootProgram(m, elf, codesize);
|
||||
BootProgram(m, elf, elf->mapsize);
|
||||
} else {
|
||||
sp = 0x800000000000;
|
||||
Write64(m->sp, sp);
|
||||
|
@ -179,13 +163,13 @@ void LoadProgram(struct Machine *m, const char *prog, char **args, char **vars,
|
|||
LoadArgv(m, prog, args, vars);
|
||||
if (memcmp(elf->map, "\177ELF", 4) == 0) {
|
||||
elf->ehdr = (void *)elf->map;
|
||||
elf->size = codesize;
|
||||
elf->size = elf->mapsize;
|
||||
LoadElf(m, elf);
|
||||
} else {
|
||||
elf->base = IMAGE_BASE_VIRTUAL;
|
||||
elf->ehdr = NULL;
|
||||
elf->size = 0;
|
||||
LoadBin(m, elf->base, prog, elf->map, codesize);
|
||||
LoadBin(m, elf->base, prog, elf->map, elf->mapsize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -109,24 +109,24 @@ struct Packages {
|
|||
struct Package {
|
||||
uint32_t magic;
|
||||
int32_t abi;
|
||||
uint32_t path; /* pkg->strings.p[path] */
|
||||
int64_t fd; /* not persisted */
|
||||
void *addr; /* not persisted */
|
||||
size_t size; /* not persisted */
|
||||
uint32_t path; // pkg->strings.p[path]
|
||||
int64_t fd; // not persisted
|
||||
void *addr; // not persisted
|
||||
size_t size; // not persisted
|
||||
struct Strings {
|
||||
size_t i, n;
|
||||
char *p; /* persisted as pkg+RVA */
|
||||
} strings; /* TODO(jart): interning? */
|
||||
char *p; // persisted as pkg+RVA
|
||||
} strings; // TODO(jart): interning?
|
||||
struct Objects {
|
||||
size_t i, n;
|
||||
struct Object {
|
||||
uint32_t path; /* pkg->strings.p[path] */
|
||||
int64_t fd; /* not persisted */
|
||||
struct Elf64_Ehdr *elf; /* not persisted */
|
||||
size_t size; /* not persisted */
|
||||
char *strs; /* not persisted */
|
||||
Elf64_Sym *syms; /* not persisted */
|
||||
Elf64_Xword symcount; /* not persisted */
|
||||
uint32_t path; // pkg->strings.p[path]
|
||||
unsigned mode; // not persisted
|
||||
struct Elf64_Ehdr *elf; // not persisted
|
||||
size_t size; // not persisted
|
||||
char *strs; // not persisted
|
||||
Elf64_Sym *syms; // not persisted
|
||||
Elf64_Xword symcount; // not persisted
|
||||
struct Sections {
|
||||
size_t i, n;
|
||||
struct Section {
|
||||
|
@ -149,20 +149,20 @@ struct Packages {
|
|||
} * p;
|
||||
} ops;
|
||||
} * p;
|
||||
} sections; /* not persisted */
|
||||
} * p; /* persisted as pkg+RVA */
|
||||
} sections; // not persisted
|
||||
} * p; // persisted as pkg+RVA
|
||||
} objects;
|
||||
struct Symbols {
|
||||
size_t i, n;
|
||||
struct Symbol {
|
||||
uint32_t name; /* pkg->strings.p[name] */
|
||||
uint32_t name; // pkg->strings.p[name]
|
||||
enum SectionKind kind : 8;
|
||||
uint8_t bind : 4;
|
||||
uint8_t type : 4;
|
||||
uint16_t object; /* pkg->objects.p[object] */
|
||||
} * p; /* persisted as pkg+RVA */
|
||||
} symbols, undefs; /* TODO(jart): hash undefs? */
|
||||
} * *p; /* persisted across multiple files */
|
||||
uint16_t object; // pkg->objects.p[object]
|
||||
} * p; // persisted as pkg+RVA
|
||||
} symbols, undefs; // TODO(jart): hash undefs?
|
||||
} * *p; // persisted across multiple files
|
||||
};
|
||||
|
||||
int CompareSymbolName(const struct Symbol *a, const struct Symbol *b,
|
||||
|
@ -265,7 +265,7 @@ void IndexSections(struct Object *obj) {
|
|||
memset(§, 0, sizeof(sect));
|
||||
CHECK_NOTNULL((shdr = getelfsectionheaderaddress(obj->elf, obj->size, i)));
|
||||
if (shdr->sh_type != SHT_NULL) {
|
||||
CHECK_NOTNULL((name = getelfsectionname(obj->elf, obj->size, shdr)));
|
||||
CHECK_NOTNULL((name = GetElfSectionName(obj->elf, obj->size, shdr)));
|
||||
if (startswith(name, ".sort.")) name += 5;
|
||||
if ((strcmp(name, ".piro.relo") == 0 ||
|
||||
startswith(name, ".piro.relo.")) ||
|
||||
|
@ -329,7 +329,7 @@ void LoadSymbols(struct Package *pkg, uint32_t object) {
|
|||
if (symbol.bind != STB_LOCAL &&
|
||||
(symbol.type == STT_OBJECT || symbol.type == STT_FUNC ||
|
||||
symbol.type == STT_COMMON || symbol.type == STT_NOTYPE)) {
|
||||
name = getelfstring(obj->elf, obj->size, obj->strs, obj->syms[i].st_name);
|
||||
name = GetElfString(obj->elf, obj->size, obj->strs, obj->syms[i].st_name);
|
||||
DEBUGF("%s", name);
|
||||
if (strcmp(name, "_GLOBAL_OFFSET_TABLE_") != 0) {
|
||||
symbol.kind = ClassifySection(obj, symbol.type, obj->syms[i].st_shndx);
|
||||
|
@ -347,23 +347,25 @@ void OpenObject(struct Package *pkg, struct Object *obj, int mode, int prot,
|
|||
int flags) {
|
||||
int fd;
|
||||
struct stat st;
|
||||
CHECK_NE(-1, (fd = open(&pkg->strings.p[obj->path], mode)), "path=%`'s",
|
||||
&pkg->strings.p[obj->path]);
|
||||
CHECK_NE(-1, (fd = open(&pkg->strings.p[obj->path], (obj->mode = mode))),
|
||||
"path=%`'s", &pkg->strings.p[obj->path]);
|
||||
CHECK_NE(-1, fstat(fd, &st));
|
||||
CHECK_NE(MAP_FAILED, (obj->elf = mmap(NULL, (obj->size = st.st_size), prot,
|
||||
flags, fd, 0)));
|
||||
CHECK_NE(-1, close(fd));
|
||||
CHECK(iself64binary(obj->elf, obj->size), "path=%`'s",
|
||||
CHECK(IsElf64Binary(obj->elf, obj->size), "path=%`'s",
|
||||
&pkg->strings.p[obj->path]);
|
||||
CHECK_NOTNULL((obj->strs = getelfstringtable(obj->elf, obj->size)));
|
||||
CHECK_NOTNULL((obj->strs = GetElfStringTable(obj->elf, obj->size)));
|
||||
CHECK_NOTNULL(
|
||||
(obj->syms = getelfsymboltable(obj->elf, obj->size, &obj->symcount)));
|
||||
(obj->syms = GetElfSymbolTable(obj->elf, obj->size, &obj->symcount)));
|
||||
CHECK_NE(0, obj->symcount);
|
||||
IndexSections(obj);
|
||||
}
|
||||
|
||||
void CloseObject(struct Object *obj) {
|
||||
msync(obj->elf, obj->size, MS_SYNC);
|
||||
if ((obj->mode & O_ACCMODE) != O_RDONLY) {
|
||||
CHECK_NE(-1, msync(obj->elf, obj->size, MS_ASYNC | MS_INVALIDATE));
|
||||
}
|
||||
CHECK_NE(-1, munmap(obj->elf, obj->size));
|
||||
}
|
||||
|
||||
|
@ -477,7 +479,7 @@ void OptimizeRelocations(struct Package *pkg, struct Packages *deps,
|
|||
if ((ELF64_R_TYPE(rela->r_info) == R_X86_64_PC32 ||
|
||||
ELF64_R_TYPE(rela->r_info) == R_X86_64_GOTPCREL) &&
|
||||
FindSymbol(
|
||||
getelfstring(obj->elf, obj->size, obj->strs,
|
||||
GetElfString(obj->elf, obj->size, obj->strs,
|
||||
obj->syms[ELF64_R_SYM(rela->r_info)].st_name),
|
||||
pkg, deps, &refpkg, &refsym) &&
|
||||
(refsym->kind == kData || refsym->kind == kBss) &&
|
||||
|
@ -500,7 +502,7 @@ void OptimizeRelocations(struct Package *pkg, struct Packages *deps,
|
|||
* Then libc/runtime/ftrace.greg.c morphs it back at runtime.
|
||||
*/
|
||||
if (ELF64_R_TYPE(rela->r_info) == R_X86_64_GOTPCRELX &&
|
||||
strcmp(getelfstring(obj->elf, obj->size, obj->strs,
|
||||
strcmp(GetElfString(obj->elf, obj->size, obj->strs,
|
||||
obj->syms[ELF64_R_SYM(rela->r_info)].st_name),
|
||||
"mcount") == 0) {
|
||||
rela->r_info = R_X86_64_NONE;
|
||||
|
@ -518,7 +520,7 @@ void OptimizeRelocations(struct Package *pkg, struct Packages *deps,
|
|||
*/
|
||||
if ((ELF64_R_TYPE(rela->r_info) == R_X86_64_PC32 ||
|
||||
ELF64_R_TYPE(rela->r_info) == R_X86_64_PLT32) &&
|
||||
strcmp(getelfstring(obj->elf, obj->size, obj->strs,
|
||||
strcmp(GetElfString(obj->elf, obj->size, obj->strs,
|
||||
obj->syms[ELF64_R_SYM(rela->r_info)].st_name),
|
||||
"mcount") == 0) {
|
||||
rela->r_info = R_X86_64_NONE;
|
||||
|
@ -598,7 +600,7 @@ void CompressLowEntropyReadOnlyDataSections(struct Package *pkg,
|
|||
!(shdr->sh_flags &
|
||||
(SHF_WRITE | SHF_MERGE | SHF_STRINGS | SHF_COMPRESSED))) &&
|
||||
(p = getelfsectionaddress(obj->elf, obj->size, shdr)) &&
|
||||
startswith((name = getelfsectionname(obj->elf, obj->size, shdr)),
|
||||
startswith((name = GetElfSectionName(obj->elf, obj->size, shdr)),
|
||||
".rodata") &&
|
||||
rlencode(&rle, p, shdr->sh_size) != -1) {
|
||||
isprofitable = rle.i * sizeof(rle.p[0]) <= shdr->sh_size / 2;
|
||||
|
|
|
@ -312,6 +312,7 @@ void zipobj(int argc, char **argv) {
|
|||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
showcrashreports();
|
||||
zipobj(argc, argv);
|
||||
return 0;
|
||||
}
|
||||
|
|
146
tool/decode/ar.c
Normal file
146
tool/decode/ar.c
Normal file
|
@ -0,0 +1,146 @@
|
|||
/*-*- 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/bits/bits.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/conv/conv.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
#define AR_MAGIC1 "!<arch>\n"
|
||||
#define AR_MAGIC2 "`\n"
|
||||
|
||||
/**
|
||||
* ar rU doge.a NOTICE # create archive and use non-deterministic stuff
|
||||
* o//tool/decode/ar.com doge.a
|
||||
*/
|
||||
|
||||
static int fd;
|
||||
static uint8_t *data;
|
||||
static long size;
|
||||
static const char *path;
|
||||
static struct stat st;
|
||||
|
||||
static void PrintString(uint8_t *p, long n, const char *name) {
|
||||
char *s;
|
||||
s = xmalloc(n + 1);
|
||||
s[n] = '\0';
|
||||
memcpy(s, p, n);
|
||||
printf("\t.ascii\t%`'.*s\t\t\t# %s\n", n, s, name);
|
||||
free(s);
|
||||
}
|
||||
|
||||
static void Open(void) {
|
||||
if ((fd = open(path, O_RDONLY)) == -1) {
|
||||
fprintf(stderr, "error: open() failed: %s\n", path);
|
||||
exit(1);
|
||||
}
|
||||
CHECK_NE(-1, fstat(fd, &st));
|
||||
if (!(size = st.st_size)) exit(0);
|
||||
CHECK_NE(MAP_FAILED,
|
||||
(data = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0)));
|
||||
LOGIFNEG1(close(fd));
|
||||
}
|
||||
|
||||
static void Close(void) {
|
||||
LOGIFNEG1(munmap(data, size));
|
||||
}
|
||||
|
||||
static void Check(void) {
|
||||
if (size < 8 + 60 + 4 ||
|
||||
(memcmp(data, AR_MAGIC1, strlen(AR_MAGIC1)) != 0 ||
|
||||
memcmp(data + 66, AR_MAGIC2, strlen(AR_MAGIC2)) != 0)) {
|
||||
fprintf(stderr, "error: not a unix archive: %s\n", path);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
static void PrintTable(void) {
|
||||
}
|
||||
|
||||
static void PrintHeader(uint8_t *p) {
|
||||
PrintString(p + 0, 16, "file identifier [ascii]");
|
||||
PrintString(p + 16, 12, "file modification timestamp [decimal]");
|
||||
PrintString(p + 28, 6, "owner id [decimal]");
|
||||
PrintString(p + 34, 6, "group id [decimal]");
|
||||
PrintString(p + 40, 8, "file mode [octal] (type and permission)");
|
||||
PrintString(p + 48, 10, "file size in bytes [decimal]");
|
||||
PrintString(p + 58, 2, "ending characters");
|
||||
}
|
||||
|
||||
static void Print(void) {
|
||||
int arsize;
|
||||
uint8_t *b, *p;
|
||||
uint64_t offset;
|
||||
uint32_t i, n, o, table, entries, symbols, symbolslen;
|
||||
arsize = atoi((char *)(data + 8 + 48));
|
||||
CHECK_LE(4, arsize);
|
||||
CHECK_LE(8 + 60 + arsize, size);
|
||||
entries = read32be(data + 8 + 60);
|
||||
CHECK_LE(4 + entries * 4 + 1, arsize);
|
||||
printf("\t# %'s\n", path);
|
||||
PrintString(data, 8, "file signature");
|
||||
PrintHeader(data + 8);
|
||||
|
||||
printf("\n");
|
||||
printf("\t.long\t%u\t\t\t# %s\n", entries, "symbol table entries");
|
||||
table = 8 + 60 + 4;
|
||||
for (i = 0; i < entries; ++i) {
|
||||
printf("\t.long\t%#x\t\t\t\t# %u\n", read32be(data + table + i * 4), i);
|
||||
}
|
||||
symbols = table + entries * 4;
|
||||
symbolslen = arsize - (4 + entries * 4);
|
||||
for (i = o = 0; o < symbolslen; ++i, o += n + 1) {
|
||||
b = data + symbols + o;
|
||||
CHECK_NOTNULL((p = memchr(b, '\0', symbolslen - (symbols + o))));
|
||||
n = p - b;
|
||||
printf("\t.asciz\t%#`'.*s\t\t\t# %u\n", n, b, i);
|
||||
}
|
||||
|
||||
offset = 8 + 60 + arsize;
|
||||
while (offset < size) {
|
||||
offset += offset & 1;
|
||||
CHECK_LE(offset + 60, size);
|
||||
CHECK_EQ(0, memcmp(data + offset + 58, AR_MAGIC2, strlen(AR_MAGIC2)));
|
||||
arsize = atoi((char *)(data + offset + 48));
|
||||
CHECK_LE(offset + 60 + arsize, size);
|
||||
printf("\n");
|
||||
PrintHeader(data + offset);
|
||||
offset += 60 + arsize;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc < 2) return 1;
|
||||
path = argv[1];
|
||||
Open();
|
||||
Check();
|
||||
Print();
|
||||
Close();
|
||||
return 0;
|
||||
}
|
|
@ -134,8 +134,8 @@ static void printelfsectionheader(int i, char *shstrtab) {
|
|||
printf(".Lsh%d:", i);
|
||||
show(".long", format(b1, "%d", shdr->sh_name),
|
||||
format(b2,
|
||||
"%`'s == getelfstring(elf, st->st_size, shstrtab, shdr->sh_name)",
|
||||
getelfstring(elf, st->st_size, shstrtab, shdr->sh_name)));
|
||||
"%`'s == GetElfString(elf, st->st_size, shstrtab, shdr->sh_name)",
|
||||
GetElfString(elf, st->st_size, shstrtab, shdr->sh_name)));
|
||||
show(".long",
|
||||
firstnonnull(findnamebyid(kElfSectionTypeNames, shdr->sh_type),
|
||||
format(b1, "%d", shdr->sh_type)),
|
||||
|
@ -167,7 +167,7 @@ static void printelfsectionheaders(void) {
|
|||
->sh_offset);
|
||||
for (i = 0; i < elf->e_shnum; ++i) {
|
||||
Elf64_Shdr *shdr = getelfsectionheaderaddress(elf, st->st_size, i);
|
||||
const char *str = getelfstring(elf, st->st_size, shstrtab, shdr->sh_name);
|
||||
const char *str = GetElfString(elf, st->st_size, shstrtab, shdr->sh_name);
|
||||
show(".asciz", format(b1, "%`'s", str), NULL);
|
||||
}
|
||||
}
|
||||
|
@ -199,14 +199,14 @@ static void printelfsymbolother(Elf64_Sym *sym) {
|
|||
static void printelfsymbol(Elf64_Sym *sym, char *strtab, char *shstrtab) {
|
||||
show(".long", format(b1, "%d", sym->st_name),
|
||||
format(b2, "%`'s (sym->st_name)",
|
||||
getelfstring(elf, st->st_size, strtab, sym->st_name)));
|
||||
GetElfString(elf, st->st_size, strtab, sym->st_name)));
|
||||
printelfsymbolinfo(sym);
|
||||
printelfsymbolother(sym);
|
||||
show(".short", format(b1, "%d", sym->st_shndx),
|
||||
format(b2, "%s sym->st_shndx",
|
||||
sym->st_shndx < 0xff00
|
||||
? format(b1, "%`'s",
|
||||
getelfstring(elf, st->st_size, shstrtab,
|
||||
GetElfString(elf, st->st_size, shstrtab,
|
||||
getelfsectionheaderaddress(
|
||||
elf, st->st_size, sym->st_shndx)
|
||||
->sh_name))
|
||||
|
@ -217,8 +217,8 @@ static void printelfsymbol(Elf64_Sym *sym, char *strtab, char *shstrtab) {
|
|||
|
||||
static void printelfsymboltable(void) {
|
||||
size_t i, symcount = 0;
|
||||
Elf64_Sym *symtab = getelfsymboltable(elf, st->st_size, &symcount);
|
||||
char *strtab = getelfstringtable(elf, st->st_size);
|
||||
Elf64_Sym *symtab = GetElfSymbolTable(elf, st->st_size, &symcount);
|
||||
char *strtab = GetElfStringTable(elf, st->st_size);
|
||||
char *shstrtab = getelfsectionnamestringtable(elf, st->st_size);
|
||||
if (symtab && strtab) {
|
||||
printf("\n\n");
|
||||
|
@ -239,8 +239,8 @@ static char *getelfsymbolname(const Elf64_Ehdr *elf, size_t mapsize,
|
|||
((shstrtab && !sym->st_name &&
|
||||
ELF64_ST_TYPE(sym->st_info) == STT_SECTION &&
|
||||
(shdr = getelfsectionheaderaddress(elf, mapsize, sym->st_shndx)) &&
|
||||
(res = getelfstring(elf, mapsize, shstrtab, shdr->sh_name))) ||
|
||||
(strtab && (res = getelfstring(elf, mapsize, strtab, sym->st_name))))) {
|
||||
(res = GetElfString(elf, mapsize, shstrtab, shdr->sh_name))) ||
|
||||
(strtab && (res = GetElfString(elf, mapsize, strtab, sym->st_name))))) {
|
||||
return res;
|
||||
} else {
|
||||
return NULL;
|
||||
|
@ -254,13 +254,13 @@ static void printelfrelocations(void) {
|
|||
const Elf64_Rela *rela;
|
||||
const Elf64_Shdr *shdr, *boop;
|
||||
char *strtab, *shstrtab, *symbolname;
|
||||
strtab = getelfstringtable(elf, st->st_size);
|
||||
strtab = GetElfStringTable(elf, st->st_size);
|
||||
shstrtab = getelfsectionnamestringtable(elf, st->st_size);
|
||||
for (i = 0; i < elf->e_shnum; ++i) {
|
||||
if ((shdr = getelfsectionheaderaddress(elf, st->st_size, i)) &&
|
||||
shdr->sh_type == SHT_RELA &&
|
||||
(rela = getelfsectionaddress(elf, st->st_size, shdr))) {
|
||||
printf("\n/\t%s\n", getelfsectionname(elf, st->st_size, shdr));
|
||||
printf("\n/\t%s\n", GetElfSectionName(elf, st->st_size, shdr));
|
||||
printf("\t.org\t%#x\n", (intptr_t)rela - (intptr_t)elf);
|
||||
for (j = 0; ((uintptr_t)rela + sizeof(Elf64_Rela) <=
|
||||
min((uintptr_t)elf + st->st_size,
|
||||
|
@ -272,7 +272,7 @@ static void printelfrelocations(void) {
|
|||
symbolname =
|
||||
getelfsymbolname(elf, st->st_size, strtab, shstrtab, &syms[sym]);
|
||||
printf("/\t%s+%#lx → %s%c%#lx\n",
|
||||
getelfstring(
|
||||
GetElfString(
|
||||
elf, st->st_size, shstrtab,
|
||||
getelfsectionheaderaddress(elf, st->st_size, shdr->sh_info)
|
||||
->sh_name),
|
||||
|
|
|
@ -68,6 +68,6 @@ kPollNames:
|
|||
lodsl
|
||||
add %rbx,%rax # %rbx is image base (cosmo abi)
|
||||
stosq
|
||||
loop 0b
|
||||
.loop 0b
|
||||
add $16,%rdi
|
||||
.init.end 301,_init_kPollNames
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue