Introduce Python objectifier (#259)

This commit is contained in:
Justine Tunney 2021-09-04 15:44:00 -07:00
parent 34b68f1945
commit 81287b7ec0
13 changed files with 1702 additions and 1564 deletions

View file

@ -143,8 +143,8 @@ include third_party/mbedtls/test/test.mk
include third_party/quickjs/quickjs.mk
include third_party/lz4cli/lz4cli.mk
include third_party/infozip/infozip.mk
include third_party/python/python.mk
include tool/build/lib/buildlib.mk
include third_party/python/python.mk
include third_party/chibicc/chibicc.mk
include third_party/chibicc/test/test.mk
include tool/build/emucrt/emucrt.mk

View file

@ -173,6 +173,9 @@ DEFAULT_LDFLAGS = \
ZIPOBJ_FLAGS = \
-b$(IMAGE_BASE_VIRTUAL)
PYFLAGS = \
-b$(IMAGE_BASE_VIRTUAL)
ASONLYFLAGS = \
-c \
-g \

View file

@ -80,8 +80,11 @@ o/$(MODE)/%-gcc.asm: %.c ; @$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.c) -S
o/$(MODE)/%-clang.asm: %.c ; @$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.c) -S -g0 $(OUTPUT_OPTION) $< || echo / need $(CLANG) >$@
o/$(MODE)/%-clang.asm: CC = $(CLANG)
o/$(MODE)/%.o: %.py o/$(MODE)/third_party/python/pyobj
@$(COMPILE) -APYOBJ o/$(MODE)/third_party/python/pyobj $(PYFLAGS) -o $@ $<
o/$(MODE)/%.pyc: %.py o/$(MODE)/third_party/python/pycomp
@$(COMPILE) -APYCOMP o/$(MODE)/third_party/python/pycomp $(PYFLAGS) -o $@ $<
@$(COMPILE) -APYCOMP o/$(MODE)/third_party/python/pycomp $(PYCFLAGS) -o $@ $<
o/$(MODE)/%.lua: %.lua o/$(MODE)/third_party/lua/luac
@$(COMPILE) -ALUAC -T$@ o/$(MODE)/third_party/lua/luac.com -s -o $@ $<
@$(COMPILE) -ALUAC -T$@ o/$(MODE)/third_party/lua/luac -s -o $@ $<

View file

@ -2,17 +2,9 @@
#define COSMOPOLITAN_THIRD_PARTY_PYTHON_INCLUDE_YOINK_H_
#include "libc/dce.h"
#if !IsTiny()
#define PYTHON_YOINK(s) \
__asm__(".section .yoink\n\t" \
"nopl\t\"" s "\"\n\t" \
"nopl\t\"" s "c\"\n\t" \
#define PYTHON_YOINK(s) \
__asm__(".section .yoink\n\t" \
"nopl\t\"py:" s "\"\n\t" \
".previous")
#else
#define PYTHON_YOINK(s) \
__asm__(".section .yoink\n\t" \
"nopl\t\"" s "c\"\n\t" \
".previous")
#endif
#endif /* COSMOPOLITAN_THIRD_PARTY_PYTHON_INCLUDE_YOINK_H_ */

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -38,6 +38,7 @@
#include "third_party/python/Include/pylifecycle.h"
#include "third_party/python/Include/pymacro.h"
#include "third_party/python/Include/pythonrun.h"
#include "tool/build/lib/stripcomponents.h"
/* clang-format off */
#define MANUAL "\
@ -67,21 +68,6 @@ int optimize;
char *inpath;
char *outpath;
char *
StripComponents(const char *path, int n)
{
const char *p;
while (n-- > 0) {
for (p = path; *p; ++p) {
if (*p == '/') {
path = p + 1;
break;
}
}
}
return (char *)path;
}
void
GetOpts(int argc, char *argv[])
{

251
third_party/python/pyobj.c vendored Normal file
View file

@ -0,0 +1,251 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=4 sts=4 sw=4 fenc=utf-8 :vi
Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.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/elf/def.h"
#include "libc/fmt/conv.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/runtime/gc.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/consts/o.h"
#include "libc/x/x.h"
#include "third_party/getopt/getopt.h"
#include "third_party/python/Include/bytesobject.h"
#include "third_party/python/Include/compile.h"
#include "third_party/python/Include/fileutils.h"
#include "third_party/python/Include/import.h"
#include "third_party/python/Include/marshal.h"
#include "third_party/python/Include/pydebug.h"
#include "third_party/python/Include/pylifecycle.h"
#include "third_party/python/Include/pymacro.h"
#include "third_party/python/Include/pythonrun.h"
#include "tool/build/lib/elfwriter.h"
#include "tool/build/lib/stripcomponents.h"
/* clang-format off */
#define MANUAL "\
SYNOPSIS\n\
\n\
pyobj.com [FLAGS] SOURCE\n\
\n\
OVERVIEW\n\
\n\
Python Objectifier\n\
\n\
FLAGS\n\
\n\
-o PATH output elf object file\n\
-P STR prefix fake directory in zip\n\
-C INT strip directory components from src in zip\n\
-O0 don't optimize [default]\n\
-O1 remove debug statements\n\
-O2 remove debug statements and docstrings\n\
-b binary only (don't include .py file)\n\
-0 zip uncompressed\n\
-n do nothing\n\
-h help\n\
\n"
bool binonly;
int optimize;
char *pyfile;
char *outpath;
bool nocompress;
uint64_t image_base;
int strip_components;
const char *path_prefix;
static void
GetOpts(int argc, char *argv[])
{
int opt;
while ((opt = getopt(argc, argv, "hn0Bb:O:o:C:P:")) != -1) {
switch (opt) {
case 'O':
optimize = atoi(optarg);
break;
case 'o':
outpath = optarg;
break;
case 'P':
path_prefix = optarg;
break;
case 'C':
strip_components = atoi(optarg);
break;
case 'b':
image_base = strtoul(optarg, NULL, 0);
break;
case 'B':
binonly = true;
break;
case '0':
nocompress = true;
break;
case 'n':
exit(0);
case 'h':
fputs(MANUAL, stdout);
exit(0);
default:
fputs(MANUAL, stderr);
exit(1);
}
}
if (argc - optind != 1) {
fputs("error: need one input file\n", stderr);
exit(1);
}
pyfile = argv[optind];
if (!outpath) {
outpath = xstrcat(pyfile, ".o");
}
}
static char *
Dotify(char *s)
{
size_t i;
for (i = 0; s[i]; ++i) {
if (s[i] == '/') {
s[i] = '.';
}
}
return s;
}
static void
Yoink(struct ElfWriter *elf, const char *symbol)
{
elfwriter_align(elf, 1, 0);
elfwriter_startsection(elf, ".yoink", SHT_PROGBITS,
SHF_ALLOC | SHF_EXECINSTR);
elfwriter_yoink(elf, symbol);
elfwriter_finishsection(elf);
}
static char *
GetZipFile(void)
{
const char *zipfile;
zipfile = pyfile;
zipfile = StripComponents(zipfile, strip_components);
if (path_prefix) {
zipfile = gc(xjoinpaths(path_prefix, zipfile));
}
return strdup(zipfile);
}
static char *
GetZipDir(void)
{
return xstrcat(gc(xdirname(gc(GetZipFile()))), '/');
}
static char *
GetSynFile(void)
{
return xstrcat("/zip/", gc(GetZipFile()));
}
static char *
GetModName(bool *ispkg)
{
char *mod;
mod = Dotify(xstripexts(StripComponents(pyfile, strip_components)));
if ((*ispkg = endswith(mod, ".__init__"))) {
mod[strlen(mod) - strlen(".__init__")] = 0;
}
return mod;
}
int
main(int argc, char *argv[])
{
char t[12];
bool ispkg;
ssize_t rc;
struct stat st;
struct ElfWriter *elf;
struct timespec timestamp;
PyObject *code, *marshalled;
size_t i, pysize, pycsize, marsize;
char *s, *pydata, *pycdata, *mardata, *zipfile, *zipdir, *synfile, *modname;
ShowCrashReports();
GetOpts(argc, argv);
marshalled = 0;
if (stat(pyfile, &st) == -1) perror(pyfile), exit(1);
CHECK_NOTNULL((pydata = gc(xslurp(pyfile, &pysize))));
Py_NoUserSiteDirectory++;
Py_NoSiteFlag++;
Py_IgnoreEnvironmentFlag++;
Py_FrozenFlag++;
Py_SetProgramName(gc(utf8toutf32(argv[0], -1, 0)));
_Py_InitializeEx_Private(1, 0);
zipdir = gc(GetZipDir());
zipfile = gc(GetZipFile());
synfile = gc(GetSynFile());
modname = gc(GetModName(&ispkg));
code = Py_CompileStringExFlags(pydata, synfile, Py_file_input, NULL, optimize);
if (!code) goto error;
marshalled = PyMarshal_WriteObjectToString(code, Py_MARSHAL_VERSION);
Py_CLEAR(code);
if (!marshalled) goto error;
memset(&timestamp, 0, sizeof(timestamp));
assert(PyBytes_CheckExact(marshalled));
mardata = PyBytes_AS_STRING(marshalled);
marsize = PyBytes_GET_SIZE(marshalled);
elf = elfwriter_open(outpath, 0644);
elfwriter_cargoculting(elf);
WRITE16LE(t+0, 3379); /* Python 3.6rc1 */
WRITE16LE(t+2, READ16LE("\r\n"));
WRITE32LE(t+4, timestamp.tv_sec);
WRITE32LE(t+8, marsize);
pycsize = sizeof(t) + marsize;
pycdata = gc(malloc(pycsize));
memcpy(pycdata, t, sizeof(t));
memcpy(pycdata + sizeof(t), mardata, marsize);
if (ispkg) {
elfwriter_zip(elf, zipdir, zipdir, strlen(zipdir),
pydata, pysize, 040755, timestamp, timestamp,
timestamp, nocompress, image_base);
}
if (!binonly) {
elfwriter_zip(elf, gc(xstrcat("py:", modname)), zipfile,
strlen(zipfile), pydata, pysize, st.st_mode, timestamp,
timestamp, timestamp, nocompress, image_base);
}
elfwriter_zip(elf, gc(xstrcat("pyc:", modname)), gc(xstrcat(zipfile, 'c')),
strlen(zipfile) + 1, pycdata, pycsize, st.st_mode, timestamp,
timestamp, timestamp, nocompress, image_base);
Yoink(elf, "__zip_start");
elfwriter_close(elf);
Py_CLEAR(marshalled);
Py_Finalize();
return 0;
error:
PyErr_Print();
Py_Finalize();
if (marshalled) Py_DECREF(marshalled);
return 1;
}

View file

@ -11,8 +11,6 @@ THIRD_PARTY_PYTHON_STAGE2 = \
$(THIRD_PARTY_PYTHON_STAGE2_A_DEPS) \
$(THIRD_PARTY_PYTHON_STAGE2_A) \
$(THIRD_PARTY_PYTHON_STDLIB_PYS_A) \
$(THIRD_PARTY_PYTHON_STDLIB_PYCS_A) \
$(THIRD_PARTY_PYTHON_STDLIB_DIRS_A) \
$(THIRD_PARTY_PYTHON_STDLIB_DATA_A)
THIRD_PARTY_PYTHON_ARTIFACTS = \
@ -26,6 +24,7 @@ THIRD_PARTY_PYTHON_BINS = \
THIRD_PARTY_PYTHON_COMS = \
o/$(MODE)/third_party/python/python.com \
o/$(MODE)/third_party/python/freeze.com \
o/$(MODE)/third_party/python/pyobj.com \
o/$(MODE)/third_party/python/pycomp.com \
o/$(MODE)/third_party/python/pythontester.com
@ -37,17 +36,12 @@ THIRD_PARTY_PYTHON_CHECKS = \
THIRD_PARTY_PYTHON_STAGE1_A = o/$(MODE)/third_party/python/python-stage1.a
THIRD_PARTY_PYTHON_STAGE2_A = o/$(MODE)/third_party/python/python-stage2.a
THIRD_PARTY_PYTHON_STDLIB_PYS_A = o/$(MODE)/third_party/python/python-stdlib-pys.a
THIRD_PARTY_PYTHON_STDLIB_PYCS_A = o/$(MODE)/third_party/python/python-stdlib-pycs.a
THIRD_PARTY_PYTHON_STDLIB_DIRS_A = o/$(MODE)/third_party/python/python-stdlib-dirs.a
THIRD_PARTY_PYTHON_STDLIB_DATA_A = o/$(MODE)/third_party/python/python-stdlib-data.a
THIRD_PARTY_PYTHON_STAGE1_A_OBJS = $(THIRD_PARTY_PYTHON_STAGE1_A_SRCS:%.c=o/$(MODE)/%.o)
THIRD_PARTY_PYTHON_STAGE2_A_OBJS = $(THIRD_PARTY_PYTHON_STAGE2_A_SRCS:%.c=o/$(MODE)/%.o)
THIRD_PARTY_PYTHON_STDLIB_PYS_OBJS = $(THIRD_PARTY_PYTHON_STDLIB_PYS:%=o/$(MODE)/%.zip.o)
THIRD_PARTY_PYTHON_STDLIB_PYCS_OBJS = $(THIRD_PARTY_PYTHON_STDLIB_PYCS:%=%.zip.o)
THIRD_PARTY_PYTHON_STDLIB_DIRS_OBJS = $(THIRD_PARTY_PYTHON_STDLIB_DIRS:%=o/$(MODE)/%.zip.o)
THIRD_PARTY_PYTHON_STDLIB_PYS_OBJS = $(THIRD_PARTY_PYTHON_STDLIB_PYS:%.py=o/$(MODE)/%.o)
THIRD_PARTY_PYTHON_STDLIB_DATA_OBJS = $(THIRD_PARTY_PYTHON_STDLIB_DATA:%=o/$(MODE)/%.zip.o)
THIRD_PARTY_PYTHON_STDLIB_PYCS = $(THIRD_PARTY_PYTHON_STDLIB_PYS:%=o/$(MODE)/%c)
THIRD_PARTY_PYTHON_HDRS = \
third_party/python/Include/yoink.h \
@ -71,7 +65,7 @@ THIRD_PARTY_PYTHON_HDRS = \
third_party/python/Include/codecs.h \
third_party/python/Include/compile.h \
third_party/python/Include/complexobject.h \
third_party/python/Include/cosmo.h \
third_party/python/Include/cosmo.h \
third_party/python/Include/datetime.h \
third_party/python/Include/descrobject.h \
third_party/python/Include/dictobject.h \
@ -533,98 +527,8 @@ THIRD_PARTY_PYTHON_STAGE2_A_SRCS = \
third_party/python/Python/pyfpe.c \
third_party/python/Python/sigcheck.c
THIRD_PARTY_PYTHON_STDLIB_DIRS = \
third_party/python/Lib/ \
third_party/python/Lib/asyncio/ \
third_party/python/Lib/collections/ \
third_party/python/Lib/dbm/ \
third_party/python/Lib/distutils/ \
third_party/python/Lib/distutils/command/ \
third_party/python/Lib/distutils/tests/ \
third_party/python/Lib/email/ \
third_party/python/Lib/email/mime/ \
third_party/python/Lib/encodings/ \
third_party/python/Lib/ensurepip/ \
third_party/python/Lib/ensurepip/_bundled/ \
third_party/python/Lib/html/ \
third_party/python/Lib/http/ \
third_party/python/Lib/importlib/ \
third_party/python/Lib/json/ \
third_party/python/Lib/logging/ \
third_party/python/Lib/msilib/ \
third_party/python/Lib/multiprocessing/ \
third_party/python/Lib/multiprocessing/dummy/ \
third_party/python/Lib/sqlite3/ \
third_party/python/Lib/unittest/ \
third_party/python/Lib/urllib/ \
third_party/python/Lib/venv/ \
third_party/python/Lib/venv/scripts/common/ \
third_party/python/Lib/venv/scripts/nt/ \
third_party/python/Lib/venv/scripts/posix/ \
third_party/python/Lib/wsgiref/ \
third_party/python/Lib/xml/ \
third_party/python/Lib/xml/dom/ \
third_party/python/Lib/xml/etree/ \
third_party/python/Lib/xml/parsers/ \
third_party/python/Lib/xml/sax/ \
third_party/python/Lib/xmlrpc/ \
third_party/python/Lib/test/ \
third_party/python/Lib/test/xmltestdata/ \
third_party/python/Lib/test/test_email/ \
third_party/python/Lib/test/test_email/data/ \
third_party/python/Lib/test/sndhdrdata/ \
third_party/python/Lib/test/test_asyncio/ \
third_party/python/Lib/test/audiodata/ \
third_party/python/Lib/test/imghdrdata/ \
third_party/python/Lib/test/decimaltestdata/ \
third_party/python/Lib/test/test_import/ \
third_party/python/Lib/test/test_import/data/ \
third_party/python/Lib/test/test_import/data/package/ \
third_party/python/Lib/test/test_import/data/package2/ \
third_party/python/Lib/test/test_import/data/circular_imports/ \
third_party/python/Lib/test/test_import/data/circular_imports/subpkg/ \
third_party/python/Lib/test/libregrtest/ \
third_party/python/Lib/test/leakers/ \
third_party/python/Lib/test/test_json/ \
third_party/python/Lib/test/eintrdata/ \
third_party/python/Lib/test/support/ \
third_party/python/Lib/test/test_importlib/ \
third_party/python/Lib/test/test_importlib/extension/ \
third_party/python/Lib/test/test_importlib/frozen/ \
third_party/python/Lib/test/test_importlib/import_/ \
third_party/python/Lib/test/test_importlib/builtin/ \
third_party/python/Lib/test/test_importlib/source/ \
third_party/python/Lib/test/test_importlib/namespace_pkgs/ \
third_party/python/Lib/test/test_importlib/namespace_pkgs/project2/ \
third_party/python/Lib/test/test_importlib/namespace_pkgs/project2/parent/ \
third_party/python/Lib/test/test_importlib/namespace_pkgs/project2/parent/child/ \
third_party/python/Lib/test/test_importlib/namespace_pkgs/portion2/ \
third_party/python/Lib/test/test_importlib/namespace_pkgs/portion2/foo/ \
third_party/python/Lib/test/test_importlib/namespace_pkgs/project3/ \
third_party/python/Lib/test/test_importlib/namespace_pkgs/project3/parent/ \
third_party/python/Lib/test/test_importlib/namespace_pkgs/project3/parent/child/ \
third_party/python/Lib/test/test_importlib/namespace_pkgs/portion1/ \
third_party/python/Lib/test/test_importlib/namespace_pkgs/portion1/foo/ \
third_party/python/Lib/test/test_importlib/namespace_pkgs/both_portions/ \
third_party/python/Lib/test/test_importlib/namespace_pkgs/both_portions/foo/ \
third_party/python/Lib/test/test_importlib/namespace_pkgs/project1/ \
third_party/python/Lib/test/test_importlib/namespace_pkgs/project1/parent/ \
third_party/python/Lib/test/test_importlib/namespace_pkgs/project1/parent/child/ \
third_party/python/Lib/test/test_importlib/namespace_pkgs/not_a_namespace_pkg/ \
third_party/python/Lib/test/test_importlib/namespace_pkgs/not_a_namespace_pkg/foo/ \
third_party/python/Lib/test/test_importlib/namespace_pkgs/module_and_namespace_package/ \
third_party/python/Lib/test/test_importlib/namespace_pkgs/module_and_namespace_package/a_test/ \
third_party/python/Lib/test/test_warnings/ \
third_party/python/Lib/test/test_warnings/data/ \
third_party/python/Lib/test/capath/ \
third_party/python/Lib/test/dtracedata/ \
third_party/python/Lib/test/subprocessdata/ \
third_party/python/Lib/test/crashers/ \
third_party/python/Lib/test/cjkencodings/ \
third_party/python/Lib/test/test_tools/ \
third_party/python/Lib/test/tracedmodules/
THIRD_PARTY_PYTHON_STDLIB_DATA = \
third_party/python/Lib/ \
third_party/python/Lib/distutils/command/command_template \
third_party/python/Lib/distutils/tests/Setup.sample \
third_party/python/Lib/email/architecture.rst \
@ -2181,6 +2085,7 @@ THIRD_PARTY_PYTHON_STAGE1_A_DIRECTDEPS = \
LIBC_TINYMATH \
LIBC_UNICODE \
LIBC_X \
TOOL_BUILD_LIB \
THIRD_PARTY_GETOPT
THIRD_PARTY_PYTHON_STAGE1_A_DEPS = \
@ -2220,6 +2125,14 @@ THIRD_PARTY_PYTHON_STAGE2_A_DIRECTDEPS = \
THIRD_PARTY_PYTHON_STAGE2_A_DEPS = \
$(call uniq,$(foreach x,$(THIRD_PARTY_PYTHON_STAGE2_A_DIRECTDEPS),$($(x))))
o/$(MODE)/third_party/python/pyobj.com.dbg: \
$(THIRD_PARTY_PYTHON_STAGE1) \
$(THIRD_PARTY_PYTHON_STAGE1_A).pkg \
o/$(MODE)/third_party/python/pyobj.o \
$(CRT) \
$(APE)
@$(APELINK)
o/$(MODE)/third_party/python/pycomp.com.dbg: \
$(THIRD_PARTY_PYTHON_STAGE1) \
$(THIRD_PARTY_PYTHON_STAGE1_A).pkg \
@ -2256,6 +2169,11 @@ o/$(MODE)/third_party/python/pythontester.com.dbg: \
$(APE)
@$(APELINK)
o/$(MODE)/third_party/python/pyobj: \
o/$(MODE)/third_party/python/pyobj.com
@cp -f $< $@
@$@ -n
o/$(MODE)/third_party/python/pycomp: \
o/$(MODE)/third_party/python/pycomp.com
@cp -f $< $@
@ -2287,9 +2205,7 @@ $(THIRD_PARTY_PYTHON_STAGE2_A): \
$(THIRD_PARTY_PYTHON_STAGE2_A_OBJS)
$(THIRD_PARTY_PYTHON_STDLIB_PYS_A): $(THIRD_PARTY_PYTHON_STDLIB_PYS_OBJS)
$(THIRD_PARTY_PYTHON_STDLIB_DIRS_A): $(THIRD_PARTY_PYTHON_STDLIB_DIRS_OBJS)
$(THIRD_PARTY_PYTHON_STDLIB_DATA_A): $(THIRD_PARTY_PYTHON_STDLIB_DATA_OBJS)
$(THIRD_PARTY_PYTHON_STDLIB_PYCS_A): $(THIRD_PARTY_PYTHON_STDLIB_PYCS_OBJS)
$(THIRD_PARTY_PYTHON_STAGE1_A).pkg: \
$(THIRD_PARTY_PYTHON_STAGE1_A_OBJS) \
@ -2332,11 +2248,8 @@ o/$(MODE)/third_party/python/Modules/faulthandler.o: \
OVERRIDE_CFLAGS += \
-fno-optimize-sibling-calls
$(THIRD_PARTY_PYTHON_STDLIB_PYS_OBJS): ZIPOBJ_FLAGS += -P.python -C3
$(THIRD_PARTY_PYTHON_STDLIB_DIRS_OBJS): ZIPOBJ_FLAGS += -P.python -C3
$(THIRD_PARTY_PYTHON_STDLIB_PYS_OBJS): PYFLAGS += -P.python -C3
$(THIRD_PARTY_PYTHON_STDLIB_DATA_OBJS): ZIPOBJ_FLAGS += -P.python -C3
$(THIRD_PARTY_PYTHON_STDLIB_PYCS_OBJS): ZIPOBJ_FLAGS += -P.python -C5
.PRECIOUS: $(THIRD_PARTY_PYTHON_STDLIB_PYCS)
o/$(MODE)/third_party/python/Python/ceval.o: QUOTA = -M512m
o/$(MODE)/third_party/python/Objects/unicodeobject.o: QUOTA += -C16
@ -2352,6 +2265,7 @@ THIRD_PARTY_PYTHON_LIBS = \
THIRD_PARTY_PYTHON_OBJS = \
$(foreach x,$(THIRD_PARTY_PYTHON_ARTIFACTS),$($(x)_OBJS)) \
o/$(MODE)/third_party/python/pyobj.o \
o/$(MODE)/third_party/python/pycomp.o \
o/$(MODE)/third_party/python/Programs/freeze.o \
o/$(MODE)/third_party/python/Programs/python.o \
@ -2359,6 +2273,7 @@ THIRD_PARTY_PYTHON_OBJS = \
THIRD_PARTY_PYTHON_SRCS = \
$(foreach x,$(THIRD_PARTY_PYTHON_ARTIFACTS),$($(x)_SRCS)) \
third_party/python/pyobj.c \
third_party/python/pycomp.c \
third_party/python/Programs/freeze.c \
third_party/python/Programs/python.c \

View file

@ -48,7 +48,8 @@ TOOL_BUILD_LIB_A_DIRECTDEPS = \
NET_HTTPS \
THIRD_PARTY_COMPILER_RT \
THIRD_PARTY_MBEDTLS \
THIRD_PARTY_XED
THIRD_PARTY_XED \
THIRD_PARTY_ZLIB
TOOL_BUILD_LIB_A_DEPS := \
$(call uniq,$(foreach x,$(TOOL_BUILD_LIB_A_DIRECTDEPS),$($(x))))

View file

@ -1,5 +1,6 @@
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_ELFWRITER_H_
#define COSMOPOLITAN_TOOL_BUILD_LIB_ELFWRITER_H_
#include "libc/calls/struct/timespec.h"
#include "libc/elf/struct/ehdr.h"
#include "libc/elf/struct/rela.h"
#include "libc/elf/struct/shdr.h"
@ -48,7 +49,7 @@ struct ElfWriter {
struct ElfWriterSyms syms[3][1];
struct {
size_t i, j, n;
struct ElfWriterRela * p;
struct ElfWriterRela *p;
} relas[1];
struct Interner *strtab;
struct Interner *shstrtab;
@ -70,6 +71,9 @@ struct ElfWriterSymRef elfwriter_appendsym(struct ElfWriter *, const char *,
int, int, size_t, size_t);
void elfwriter_yoink(struct ElfWriter *, const char *);
void elfwriter_setsection(struct ElfWriter *, struct ElfWriterSymRef, uint16_t);
void elfwriter_zip(struct ElfWriter *, const char *, const char *, size_t,
const void *, size_t, uint32_t, struct timespec,
struct timespec, struct timespec, bool, uint64_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -0,0 +1,221 @@
/*-*- 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 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/bits/bits.h"
#include "libc/calls/calls.h"
#include "libc/calls/struct/timespec.h"
#include "libc/dos.h"
#include "libc/elf/def.h"
#include "libc/fmt/conv.h"
#include "libc/limits.h"
#include "libc/log/check.h"
#include "libc/nexgen32e/crc32.h"
#include "libc/nt/enum/fileflagandattributes.h"
#include "libc/rand/rand.h"
#include "libc/runtime/gc.internal.h"
#include "libc/time/struct/tm.h"
#include "libc/time/time.h"
#include "libc/x/x.h"
#include "libc/zip.h"
#include "third_party/zlib/zlib.h"
#include "tool/build/lib/elfwriter.h"
#include "tool/build/lib/isnocompressext.h"
#define ZIP_LOCALFILE_SECTION ".zip.2."
#define ZIP_DIRECTORY_SECTION ".zip.4."
static bool ShouldCompress(const char *name, size_t namesize,
const unsigned char *data, size_t datasize,
bool nocompress) {
return !nocompress && datasize >= 64 && !IsNoCompressExt(name, namesize) &&
(datasize < 1000 || MeasureEntropy((void *)data, 1000) < 7);
}
static void GetDosLocalTime(int64_t utcunixts, uint16_t *out_time,
uint16_t *out_date) {
struct tm tm;
CHECK_NOTNULL(localtime_r(&utcunixts, &tm));
*out_time = DOS_TIME(tm.tm_hour, tm.tm_min, tm.tm_sec);
*out_date = DOS_DATE(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday + 1);
}
static int DetermineVersionNeededToExtract(int method) {
if (method == kZipCompressionDeflate) {
return kZipEra1993;
} else {
return kZipEra1989;
}
}
static unsigned char *EmitZipLfileHdr(unsigned char *p, const void *name,
size_t namesize, uint32_t crc,
uint8_t era, uint16_t gflags,
uint16_t method, uint16_t mtime,
uint16_t mdate, size_t compsize,
size_t uncompsize) {
p = WRITE32LE(p, kZipLfileHdrMagic);
*p++ = era;
*p++ = kZipOsDos;
p = WRITE16LE(p, gflags);
p = WRITE16LE(p, method);
p = WRITE16LE(p, mtime);
p = WRITE16LE(p, mdate);
p = WRITE32LE(p, crc);
p = WRITE32LE(p, compsize);
p = WRITE32LE(p, uncompsize);
p = WRITE16LE(p, namesize);
p = WRITE16LE(p, 0); /* extra */
return mempcpy(p, name, namesize);
}
static void EmitZipCdirHdr(unsigned char *p, const void *name, size_t namesize,
uint32_t crc, uint8_t era, uint16_t gflags,
uint16_t method, uint16_t mtime, uint16_t mdate,
uint16_t iattrs, uint16_t dosmode, uint16_t unixmode,
size_t compsize, size_t uncompsize,
size_t commentsize, struct timespec mtim,
struct timespec atim, struct timespec ctim) {
uint64_t mt, at, ct;
p = WRITE32LE(p, kZipCfileHdrMagic);
*p++ = kZipCosmopolitanVersion;
*p++ = kZipOsUnix;
*p++ = era;
*p++ = kZipOsDos;
p = WRITE16LE(p, gflags);
p = WRITE16LE(p, method);
p = WRITE16LE(p, mtime);
p = WRITE16LE(p, mdate);
/* 16 */
p = WRITE32LE(p, crc);
p = WRITE32LE(p, compsize);
p = WRITE32LE(p, uncompsize);
p = WRITE16LE(p, namesize);
#define CFILE_HDR_SIZE (kZipCfileHdrMinSize + 36)
p = WRITE16LE(p, 36); /* extra size */
/* 32 */
p = WRITE16LE(p, commentsize);
p = WRITE16LE(p, 0); /* disk */
p = WRITE16LE(p, iattrs);
p = WRITE16LE(p, dosmode);
p = WRITE16LE(p, unixmode);
p = WRITE32LE(p, 0); /* RELOCATE ME (kZipCfileOffsetOffset) */
/* 46 */
memcpy(p, name, namesize);
p += namesize;
p = WRITE16LE(p, kZipExtraNtfs);
p = WRITE16LE(p, 32);
p = WRITE32LE(p, 0);
p = WRITE16LE(p, 1);
p = WRITE16LE(p, 24);
mt = TimeSpecToWindowsTime(mtim);
at = TimeSpecToWindowsTime(atim);
ct = TimeSpecToWindowsTime(ctim);
p = WRITE64LE(p, mt);
p = WRITE64LE(p, at);
p = WRITE64LE(p, ct);
}
/**
* Embeds zip file in elf object.
*/
void elfwriter_zip(struct ElfWriter *elf, const char *symbol, const char *name,
size_t namesize, const void *data, size_t size,
uint32_t mode, struct timespec mtim, struct timespec atim,
struct timespec ctim, bool nocompress, uint64_t imagebase) {
z_stream zs;
uint8_t era;
uint32_t crc;
unsigned char *lfile, *cfile;
struct ElfWriterSymRef lfilesym;
size_t lfilehdrsize, uncompsize, compsize, commentsize;
uint16_t method, gflags, mtime, mdate, iattrs, dosmode;
gflags = 0;
iattrs = 0;
compsize = size;
uncompsize = size;
CHECK_LE(uncompsize, UINT32_MAX);
lfilehdrsize = kZipLfileHdrMinSize + namesize;
crc = crc32_z(0, data, uncompsize);
GetDosLocalTime(mtim.tv_sec, &mtime, &mdate);
if (IsUtf8(name, namesize)) gflags |= kZipGflagUtf8;
if (S_ISREG(mode) && IsText(data, size)) {
iattrs |= kZipIattrText;
}
commentsize = kZipCdirHdrLinkableSize - (CFILE_HDR_SIZE + namesize);
dosmode = !(mode & 0200) ? kNtFileAttributeReadonly : 0;
method = ShouldCompress(name, namesize, data, size, nocompress)
? kZipCompressionDeflate
: kZipCompressionNone;
/* emit embedded file content w/ pkzip local file header */
elfwriter_align(elf, 1, 0);
elfwriter_startsection(elf,
gc(xasprintf("%s%s", ZIP_LOCALFILE_SECTION, name)),
SHT_PROGBITS, SHF_ALLOC);
if (method == kZipCompressionDeflate) {
CHECK_EQ(Z_OK, deflateInit2(memset(&zs, 0, sizeof(zs)),
Z_DEFAULT_COMPRESSION, Z_DEFLATED, -MAX_WBITS,
MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY));
zs.next_in = data;
zs.avail_in = uncompsize;
zs.next_out = ((lfile = elfwriter_reserve(
elf, (lfilehdrsize +
(zs.avail_out = compressBound(uncompsize))))) +
lfilehdrsize);
CHECK_EQ(Z_STREAM_END, deflate(&zs, Z_FINISH));
CHECK_EQ(Z_OK, deflateEnd(&zs));
if (zs.total_out < uncompsize) {
compsize = zs.total_out;
} else {
method = kZipCompressionNone;
}
} else {
lfile = elfwriter_reserve(elf, lfilehdrsize + uncompsize);
}
if (method == kZipCompressionNone) {
memcpy(lfile + lfilehdrsize, data, uncompsize);
}
era = method ? kZipEra1993 : kZipEra1989;
EmitZipLfileHdr(lfile, name, namesize, crc, era, gflags, method, mtime, mdate,
compsize, uncompsize);
elfwriter_commit(elf, lfilehdrsize + compsize);
lfilesym = elfwriter_appendsym(elf, gc(xasprintf("%s%s", "zip+lfile:", name)),
ELF64_ST_INFO(STB_LOCAL, STT_OBJECT),
STV_DEFAULT, 0, lfilehdrsize);
elfwriter_appendsym(elf, symbol, ELF64_ST_INFO(STB_GLOBAL, STT_OBJECT),
STV_DEFAULT, lfilehdrsize, compsize);
elfwriter_finishsection(elf);
/* emit central directory record */
elfwriter_align(elf, 1, 0);
elfwriter_startsection(elf,
gc(xasprintf("%s%s", ZIP_DIRECTORY_SECTION, name)),
SHT_PROGBITS, SHF_ALLOC);
EmitZipCdirHdr((cfile = elfwriter_reserve(elf, kZipCdirHdrLinkableSize)),
name, namesize, crc, era, gflags, method, mtime, mdate, iattrs,
dosmode, mode, compsize, uncompsize, commentsize, mtim, atim,
ctim);
elfwriter_appendsym(elf, gc(xasprintf("%s%s", "zip+cdir:", name)),
ELF64_ST_INFO(STB_LOCAL, STT_OBJECT), STV_DEFAULT, 0,
kZipCdirHdrLinkableSize);
elfwriter_appendrela(elf, kZipCfileOffsetOffset, lfilesym, R_X86_64_32,
-imagebase);
elfwriter_commit(elf, kZipCdirHdrLinkableSize);
elfwriter_finishsection(elf);
}

View file

@ -16,50 +16,25 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/alg/arraylist.internal.h"
#include "libc/bits/bits.h"
#include "libc/bits/bswap.h"
#include "libc/bits/safemacros.internal.h"
#include "libc/calls/calls.h"
#include "libc/calls/struct/stat.h"
#include "libc/calls/struct/timespec.h"
#include "libc/dos.h"
#include "libc/elf/def.h"
#include "libc/fmt/conv.h"
#include "libc/limits.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/macros.internal.h"
#include "libc/mem/alloca.h"
#include "libc/nexgen32e/crc32.h"
#include "libc/nt/enum/fileflagandattributes.h"
#include "libc/nt/struct/imageauxsymbolex.internal.h"
#include "libc/rand/rand.h"
#include "libc/runtime/gc.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/symbols.internal.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/ex.h"
#include "libc/sysv/consts/exit.h"
#include "libc/sysv/consts/fileno.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/ok.h"
#include "libc/sysv/consts/prot.h"
#include "libc/time/struct/tm.h"
#include "libc/time/time.h"
#include "libc/x/x.h"
#include "libc/zip.h"
#include "third_party/getopt/getopt.h"
#include "third_party/zlib/zlib.h"
#include "tool/build/lib/elfwriter.h"
#include "tool/build/lib/isnocompressext.h"
#include "tool/build/lib/stripcomponents.h"
#define ZIP_LOCALFILE_SECTION ".zip.2."
#define ZIP_DIRECTORY_SECTION ".zip.4."
char *name_;
char *yoink_;
char *symbol_;
@ -124,187 +99,13 @@ void GetOpts(int *argc, char ***argv) {
CHECK_NOTNULL(outpath_);
}
bool ShouldCompress(const char *name, size_t namesize,
const unsigned char *data, size_t datasize) {
return !nocompress_ && datasize >= 64 && !IsNoCompressExt(name, namesize) &&
(datasize < 1000 || MeasureEntropy((void *)data, 1000) < 7);
}
void GetDosLocalTime(int64_t utcunixts, uint16_t *out_time,
uint16_t *out_date) {
struct tm tm;
CHECK_NOTNULL(localtime_r(&utcunixts, &tm));
*out_time = DOS_TIME(tm.tm_hour, tm.tm_min, tm.tm_sec);
*out_date = DOS_DATE(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday + 1);
}
static int DetermineVersionNeededToExtract(int method) {
if (method == kZipCompressionDeflate) {
return kZipEra1993;
} else {
return kZipEra1989;
}
}
static unsigned char *EmitZipLfileHdr(unsigned char *p, const void *name,
size_t namesize, uint32_t crc,
uint8_t era, uint16_t gflags,
uint16_t method, uint16_t mtime,
uint16_t mdate, size_t compsize,
size_t uncompsize) {
p = WRITE32LE(p, kZipLfileHdrMagic);
*p++ = era;
*p++ = kZipOsDos;
p = WRITE16LE(p, gflags);
p = WRITE16LE(p, method);
p = WRITE16LE(p, mtime);
p = WRITE16LE(p, mdate);
p = WRITE32LE(p, crc);
p = WRITE32LE(p, compsize);
p = WRITE32LE(p, uncompsize);
p = WRITE16LE(p, namesize);
p = WRITE16LE(p, 0); /* extra */
return mempcpy(p, name, namesize);
}
static void EmitZipCdirHdr(unsigned char *p, const void *name, size_t namesize,
uint32_t crc, uint8_t era, uint16_t gflags,
uint16_t method, uint16_t mtime, uint16_t mdate,
uint16_t iattrs, uint16_t dosmode, uint16_t unixmode,
size_t compsize, size_t uncompsize,
size_t commentsize, struct stat *st) {
uint64_t mt, at, ct;
p = WRITE32LE(p, kZipCfileHdrMagic);
*p++ = kZipCosmopolitanVersion;
*p++ = kZipOsUnix;
*p++ = era;
*p++ = kZipOsDos;
p = WRITE16LE(p, gflags);
p = WRITE16LE(p, method);
p = WRITE16LE(p, mtime);
p = WRITE16LE(p, mdate);
/* 16 */
p = WRITE32LE(p, crc);
p = WRITE32LE(p, compsize);
p = WRITE32LE(p, uncompsize);
p = WRITE16LE(p, namesize);
#define CFILE_HDR_SIZE (kZipCfileHdrMinSize + 36)
p = WRITE16LE(p, 36); /* extra size */
/* 32 */
p = WRITE16LE(p, commentsize);
p = WRITE16LE(p, 0); /* disk */
p = WRITE16LE(p, iattrs);
p = WRITE16LE(p, dosmode);
p = WRITE16LE(p, unixmode);
p = WRITE32LE(p, 0); /* RELOCATE ME (kZipCfileOffsetOffset) */
/* 46 */
memcpy(p, name, namesize);
p += namesize;
p = WRITE16LE(p, kZipExtraNtfs);
p = WRITE16LE(p, 32);
p = WRITE32LE(p, 0);
p = WRITE16LE(p, 1);
p = WRITE16LE(p, 24);
#define NTTIME(t) \
(t.tv_sec + MODERNITYSECONDS) * HECTONANOSECONDS + t.tv_nsec / 100
mt = NTTIME(st->st_mtim);
at = NTTIME(st->st_atim);
ct = NTTIME(st->st_ctim);
p = WRITE64LE(p, mt);
p = WRITE64LE(p, at);
p = WRITE64LE(p, ct);
}
void EmitZip(struct ElfWriter *elf, const char *name, size_t namesize,
const unsigned char *data, struct stat *st) {
z_stream zs;
uint8_t era;
uint32_t crc;
unsigned char *lfile, *cfile;
struct ElfWriterSymRef lfilesym;
size_t lfilehdrsize, uncompsize, compsize, commentsize;
uint16_t method, gflags, mtime, mdate, iattrs, dosmode;
gflags = 0;
iattrs = 0;
compsize = st->st_size;
uncompsize = st->st_size;
CHECK_LE(uncompsize, UINT32_MAX);
lfilehdrsize = kZipLfileHdrMinSize + namesize;
crc = crc32_z(0, data, uncompsize);
GetDosLocalTime(st->st_mtim.tv_sec, &mtime, &mdate);
if (IsUtf8(name, namesize)) gflags |= kZipGflagUtf8;
if (S_ISREG(st->st_mode) && IsText(data, st->st_size)) {
iattrs |= kZipIattrText;
}
commentsize = kZipCdirHdrLinkableSize - (CFILE_HDR_SIZE + namesize);
dosmode = !(st->st_mode & 0200) ? kNtFileAttributeReadonly : 0;
method = ShouldCompress(name, namesize, data, st->st_size)
? kZipCompressionDeflate
: kZipCompressionNone;
/* emit embedded file content w/ pkzip local file header */
elfwriter_align(elf, 1, 0);
elfwriter_startsection(elf,
gc(xasprintf("%s%s", ZIP_LOCALFILE_SECTION, name)),
SHT_PROGBITS, SHF_ALLOC);
if (method == kZipCompressionDeflate) {
CHECK_EQ(Z_OK, deflateInit2(memset(&zs, 0, sizeof(zs)),
Z_DEFAULT_COMPRESSION, Z_DEFLATED, -MAX_WBITS,
MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY));
zs.next_in = data;
zs.avail_in = uncompsize;
zs.next_out = ((lfile = elfwriter_reserve(
elf, (lfilehdrsize +
(zs.avail_out = compressBound(uncompsize))))) +
lfilehdrsize);
CHECK_EQ(Z_STREAM_END, deflate(&zs, Z_FINISH));
CHECK_EQ(Z_OK, deflateEnd(&zs));
if (zs.total_out < uncompsize) {
compsize = zs.total_out;
} else {
method = kZipCompressionNone;
}
} else {
lfile = elfwriter_reserve(elf, lfilehdrsize + uncompsize);
}
if (method == kZipCompressionNone) {
memcpy(lfile + lfilehdrsize, data, uncompsize);
}
era = method ? kZipEra1993 : kZipEra1989;
EmitZipLfileHdr(lfile, name, namesize, crc, era, gflags, method, mtime, mdate,
compsize, uncompsize);
elfwriter_commit(elf, lfilehdrsize + compsize);
lfilesym = elfwriter_appendsym(elf, gc(xasprintf("%s%s", "zip+lfile:", name)),
ELF64_ST_INFO(STB_LOCAL, STT_OBJECT),
STV_DEFAULT, 0, lfilehdrsize);
elfwriter_appendsym(elf, name, ELF64_ST_INFO(STB_GLOBAL, STT_OBJECT),
STV_DEFAULT, lfilehdrsize, compsize);
elfwriter_finishsection(elf);
/* emit central directory record */
elfwriter_align(elf, 1, 0);
elfwriter_startsection(elf,
gc(xasprintf("%s%s", ZIP_DIRECTORY_SECTION, name)),
SHT_PROGBITS, SHF_ALLOC);
EmitZipCdirHdr((cfile = elfwriter_reserve(elf, kZipCdirHdrLinkableSize)),
name, namesize, crc, era, gflags, method, mtime, mdate, iattrs,
dosmode, st->st_mode, compsize, uncompsize, commentsize, st);
elfwriter_appendsym(elf, gc(xasprintf("%s%s", "zip+cdir:", name)),
ELF64_ST_INFO(STB_LOCAL, STT_OBJECT), STV_DEFAULT, 0,
kZipCdirHdrLinkableSize);
elfwriter_appendrela(elf, kZipCfileOffsetOffset, lfilesym, R_X86_64_32,
-image_base_);
elfwriter_commit(elf, kZipCdirHdrLinkableSize);
elfwriter_finishsection(elf);
}
void ProcessFile(struct ElfWriter *elf, const char *path) {
int fd;
void *map;
size_t pathlen;
struct stat st;
const char *name;
struct timespec timestamp;
CHECK_NE(-1, (fd = open(path, O_RDONLY)));
CHECK_NE(-1, fstat(fd, &st));
if (S_ISDIR(st.st_mode)) {
@ -329,7 +130,9 @@ void ProcessFile(struct ElfWriter *elf, const char *path) {
name = gc(xasprintf("%s/", name));
}
}
EmitZip(elf, name, strlen(name), map, &st);
memset(&timestamp, 0, sizeof(timestamp));
elfwriter_zip(elf, name, name, strlen(name), map, st.st_size, st.st_mode,
timestamp, timestamp, timestamp, nocompress_, image_base_);
if (st.st_size) CHECK_NE(-1, munmap(map, st.st_size));
close(fd);
}
@ -362,7 +165,6 @@ void zipobj(int argc, char **argv) {
}
int main(int argc, char **argv) {
showcrashreports();
zipobj(argc, argv);
return 0;
}