quick jump to the end of executable image - reduces load time by 100ms

This commit is contained in:
igorklopov 2016-09-28 16:13:46 +03:00
parent 76c90cc24b
commit 4b7206f032

View File

@ -348,7 +348,7 @@
--- node/src/node_javascript.cc
+++ node/src/node_javascript.cc
@@ -31,8 +31,58 @@
@@ -31,8 +31,59 @@
env->isolate(), reinterpret_cast<const char*>(native.source),
NewStringType::kNormal, native.source_len).ToLocalChecked();
target->Set(name, source);
@ -359,7 +359,7 @@
+ auto source = String::NewFromUtf8(env->isolate(),
+ "var fs = require('fs');\n" \
+ "var vm = require('vm');\n" \
+ "function readPayload() {\n" \
+ "function readPayload (fd) {\n" \
+ " var position = process.env.PKG_PAYLOAD_POSITION;\n" \
+ " if (position === undefined) {\n" \
+ " // no payload - remove entrypoint from argv[1]\n" \
@ -376,13 +376,11 @@
+ " delete process.env.PKG_PAYLOAD_POSITION;\n" \
+ " delete process.env.PKG_PAYLOAD_SIZE;\n" \
+ " var cd = new Buffer(size);\n" \
+ " var me = fs.openSync(process.execPath, 'r');\n" \
+ " var read = fs.readSync(me, cd, 0, size, position);\n" \
+ " var read = fs.readSync(fd, cd, 0, size, position);\n" \
+ " if (read !== size) {\n" \
+ " console.error('Pkg: Error reading from file.');\n" \
+ " process.exit(1);\n" \
+ " }\n" \
+ " fs.closeSync(me);\n" \
+ " var s = new vm.Script(undefined, {\n" \
+ " cachedData: cd,\n" \
+ " sourceless: true\n" \
@ -394,14 +392,17 @@
+ " var fn = s.runInThisContext();\n" \
+ " return fn(process, require, console);\n" \
+ "}\n" \
+ "\n" \
+ "var r = readPayload();\n" \
+ "if (!r || r.undoPatch) {\n" \
+ " // need to revert patch to node/lib/module.js\n" \
+ " var bindingFs = process.binding('fs');\n" \
+ " fs.internalModuleStat = bindingFs.internalModuleStat;\n" \
+ " fs.internalModuleReadFile = bindingFs.internalModuleReadFile;\n" \
+ "}\n"
+ "(function () {\n" \
+ " var fd = fs.openSync(process.execPath, 'r');\n" \
+ " var r = readPayload(fd);\n" \
+ " fs.closeSync(fd);\n" \
+ " if (!r || r.undoPatch) {\n" \
+ " // need to revert patch to node/lib/module.js\n" \
+ " var bindingFs = process.binding('fs');\n" \
+ " fs.internalModuleStat = bindingFs.internalModuleStat;\n" \
+ " fs.internalModuleReadFile = bindingFs.internalModuleReadFile;\n" \
+ " }\n" \
+ "}())\n"
+ );
+ target->Set(name, source);
}
@ -409,13 +410,48 @@
} // namespace node
--- node/src/node_main.cc
+++ node/src/node_main.cc
@@ -1,7 +1,175 @@
@@ -1,7 +1,208 @@
#include "node.h"
+#include <string.h>
+
+#define BOUNDARY 4096
+
+int FindMeatEnd(FILE* file) {
+
+ int read;
+ uint8_t buffer[1024];
+ uint16_t* buffer16 = (uint16_t*) &buffer;
+ uint32_t* buffer32 = (uint32_t*) &buffer;
+
+ if (fseek(file, 0, SEEK_SET) != 0) return 0;
+ read = static_cast<int>(fread(&buffer, 1, sizeof(buffer), file));
+ if (read != sizeof(buffer)) return 0;
+
+ if (buffer16[0 >> 1] == 0x5A4D) { // _IMAGE_DOS_HEADER.e_magic == MZ
+
+ uint32_t e_lfanew = buffer32[0x3c >> 2];
+ uint16_t NumberOfSections = buffer16[(e_lfanew + 0x04 + 0x02) >> 1];
+ uint16_t SizeOfOptionalHeader = buffer16[(e_lfanew + 0x04 + 0x10) >> 1];
+ uint16_t Section = e_lfanew + 0x18 + SizeOfOptionalHeader;
+
+ uint32_t MaxEnd = 0;
+ for (int i = 0; i < NumberOfSections; i += 1) {
+ uint32_t RawOffset = buffer32[(Section + 0x14) >> 2];
+ uint32_t RawSize = buffer32[(Section + 0x10) >> 2];
+ uint32_t RawEnd = RawOffset + RawSize;
+ if (RawEnd > MaxEnd) MaxEnd = RawEnd;
+ Section += 0x28;
+ }
+
+ return (MaxEnd / BOUNDARY) * BOUNDARY;
+
+ }
+
+ return 6 * 1024 * 1024;
+
+}
+
+bool GetSentryPosition(FILE* file, int start, uint32_t s1,
+ uint32_t s12, uint32_t s3, int* pposition, int* psize
+) {
@ -423,10 +459,7 @@
+ int read;
+ uint32_t sentry, length;
+
+ // start of search
+ if (file == NULL || fseek(file, start, SEEK_SET) != 0) {
+ return false;
+ }
+ if (fseek(file, start, SEEK_SET) != 0) return false;
+
+ while (true) {
+ read = static_cast<int>(fread(&sentry, 1, sizeof(sentry), file));
@ -456,6 +489,13 @@
+}
+
+
+#ifdef _WIN32
+void setenv(const char* name, const char* value, int overwrite) {
+ SetEnvironmentVariable(name, value);
+}
+#endif
+
+
+char* ReadOverlays(const char* filename) {
+
+ FILE* file = fopen(filename, "rb");
@ -464,7 +504,8 @@
+ exit(1);
+ }
+
+ int position = 6 * 1024 * 1024; int size;
+ char env[64];
+ int position = FindMeatEnd(file); int size;
+ char* bakery = NULL;
+
+ if (GetSentryPosition(file, position, 0x4818c4df,
@ -478,6 +519,7 @@
+ read = static_cast<int>(fread(&bakery[i], 1, size - i, file));
+ if (ferror(file) != 0) {
+ fprintf(stderr, "Pkg: Error reading from file.\n");
+ fclose(file);
+ exit(1);
+ }
+ i += read;
@ -491,22 +533,14 @@
+ 0x6713e24e, 0x3ea13ccf, &position, &size)
+ ) {
+
+ char value[64];
+ sprintf(value, "%d", position);
+#ifdef _WIN32
+ SetEnvironmentVariable("PKG_PAYLOAD_POSITION", value);
+#else
+ setenv("PKG_PAYLOAD_POSITION", value, 1);
+#endif
+ sprintf(value, "%d", size);
+#ifdef _WIN32
+ SetEnvironmentVariable("PKG_PAYLOAD_SIZE", value);
+#else
+ setenv("PKG_PAYLOAD_SIZE", value, 1);
+#endif
+ sprintf(env, "%d", position);
+ setenv("PKG_PAYLOAD_POSITION", env, 1);
+ sprintf(env, "%d", size);
+ setenv("PKG_PAYLOAD_SIZE", env, 1);
+
+ }
+
+ fclose(file);
+ return bakery;
+
+}
@ -585,7 +619,7 @@
int wmain(int argc, wchar_t *wargv[]) {
if (!IsWindows7OrGreater()) {
@@ -43,17 +211,17 @@
@@ -43,17 +244,17 @@
exit(1);
}
}