Skip to content

Commit 3cefd65

Browse files
bnoordhuisMyles Borins
authored and
Myles Borins
committed
build: export openssl symbols on windows
Export symbols from the bundled openssl for add-ons to link against. Fixes: nodejs/node-v0.x-archive#4051 PR-URL: #6274 Reviewed-By: James M Snell <[email protected]>
1 parent 279e30c commit 3cefd65

File tree

5 files changed

+154
-0
lines changed

5 files changed

+154
-0
lines changed

node.gyp

+58
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,15 @@
9393
'deps/v8/tools/SourceMap.js',
9494
'deps/v8/tools/tickprocessor-driver.js',
9595
],
96+
'conditions': [
97+
[ 'OS=="win" and '
98+
'node_use_openssl=="true" and '
99+
'node_shared_openssl=="false"', {
100+
'use_openssl_def': 1,
101+
}, {
102+
'use_openssl_def': 0,
103+
}],
104+
],
96105
},
97106

98107
'targets': [
@@ -291,6 +300,9 @@
291300
'-Wl,--no-whole-archive',
292301
],
293302
}],
303+
['use_openssl_def==1', {
304+
'sources': ['<(SHARED_INTERMEDIATE_DIR)/openssl.def'],
305+
}],
294306
],
295307
}],
296308
],
@@ -464,6 +476,52 @@
464476
}
465477
},
466478
},
479+
{
480+
'target_name': 'mkssldef',
481+
'type': 'none',
482+
# TODO(bnoordhuis) Make all platforms export the same list of symbols.
483+
# Teach mkssldef.py to generate linker maps that UNIX linkers understand.
484+
'conditions': [
485+
[ 'use_openssl_def==1', {
486+
'variables': {
487+
'mkssldef_flags': [
488+
# Categories to export.
489+
'-CAES,BF,BIO,DES,DH,DSA,EC,ECDH,ECDSA,ENGINE,EVP,HMAC,MD4,MD5,'
490+
'NEXTPROTONEG,PSK,RC2,RC4,RSA,SHA,SHA0,SHA1,SHA256,SHA512,TLSEXT',
491+
# Defines.
492+
'-DWIN32',
493+
# Symbols to filter from the export list.
494+
'-X^DSO',
495+
'-X^_',
496+
'-X^private_',
497+
],
498+
},
499+
'conditions': [
500+
['openssl_fips!=""', {
501+
'variables': { 'mkssldef_flags': ['-DOPENSSL_FIPS'] },
502+
}],
503+
],
504+
'actions': [
505+
{
506+
'action_name': 'mkssldef',
507+
'inputs': [
508+
'deps/openssl/openssl/util/libeay.num',
509+
'deps/openssl/openssl/util/ssleay.num',
510+
],
511+
'outputs': ['<(SHARED_INTERMEDIATE_DIR)/openssl.def'],
512+
'action': [
513+
'python',
514+
'tools/mkssldef.py',
515+
'<@(mkssldef_flags)',
516+
'-o',
517+
'<@(_outputs)',
518+
'<@(_inputs)',
519+
],
520+
},
521+
],
522+
}],
523+
],
524+
},
467525
# generate ETW header and resource files
468526
{
469527
'target_name': 'node_etw',
+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#include "node.h"
2+
#include "../../../src/util.h"
3+
#include "../../../src/util-inl.h"
4+
5+
#include <assert.h>
6+
#include <openssl/rand.h>
7+
8+
namespace {
9+
10+
inline void RandomBytes(const v8::FunctionCallbackInfo<v8::Value>& info) {
11+
assert(info[0]->IsArrayBufferView());
12+
auto view = info[0].As<v8::ArrayBufferView>();
13+
auto byte_offset = view->ByteOffset();
14+
auto byte_length = view->ByteLength();
15+
assert(view->HasBuffer());
16+
auto buffer = view->Buffer();
17+
auto contents = buffer->GetContents();
18+
auto data = static_cast<unsigned char*>(contents.Data()) + byte_offset;
19+
assert(RAND_poll());
20+
auto rval = RAND_bytes(data, static_cast<int>(byte_length));
21+
info.GetReturnValue().Set(rval > 0);
22+
}
23+
24+
inline void Initialize(v8::Local<v8::Object> exports,
25+
v8::Local<v8::Value> module,
26+
v8::Local<v8::Context> context) {
27+
auto isolate = context->GetIsolate();
28+
auto key = v8::String::NewFromUtf8(isolate, "randomBytes");
29+
auto value = v8::FunctionTemplate::New(isolate, RandomBytes)->GetFunction();
30+
assert(exports->Set(context, key, value).IsJust());
31+
}
32+
33+
} // anonymous namespace
34+
35+
NODE_MODULE_CONTEXT_AWARE(binding, Initialize)
+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
'targets': [
3+
{
4+
'target_name': 'binding',
5+
'sources': ['binding.cc'],
6+
'include_dirs': ['../../../deps/openssl/openssl/include'],
7+
},
8+
]
9+
}

test/addons/openssl-binding/test.js

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
'use strict';
2+
3+
require('../../common');
4+
const assert = require('assert');
5+
const binding = require('./build/Release/binding');
6+
const bytes = new Uint8Array(1024);
7+
assert(binding.randomBytes(bytes));
8+
assert(bytes.reduce((v, a) => v + a) > 0);

tools/mkssldef.py

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#!/usr/bin/env python
2+
3+
from __future__ import print_function
4+
import re
5+
import sys
6+
7+
categories = []
8+
defines = []
9+
excludes = []
10+
11+
if __name__ == '__main__':
12+
out = sys.stdout
13+
filenames = sys.argv[1:]
14+
15+
while filenames and filenames[0].startswith('-'):
16+
option = filenames.pop(0)
17+
if option == '-o': out = open(filenames.pop(0), 'w')
18+
elif option.startswith('-C'): categories += option[2:].split(',')
19+
elif option.startswith('-D'): defines += option[2:].split(',')
20+
elif option.startswith('-X'): excludes += option[2:].split(',')
21+
22+
excludes = map(re.compile, excludes)
23+
exported = []
24+
25+
for filename in filenames:
26+
for line in open(filename).readlines():
27+
name, _, meta, _ = re.split('\s+', line)
28+
if any(map(lambda p: p.match(name), excludes)): continue
29+
meta = meta.split(':')
30+
assert meta[0] in ('EXIST', 'NOEXIST')
31+
assert meta[2] in ('FUNCTION', 'VARIABLE')
32+
if meta[0] != 'EXIST': continue
33+
if meta[2] != 'FUNCTION': continue
34+
def satisfy(expr, rules):
35+
def test(expr):
36+
if expr.startswith('!'): return not expr[1:] in rules
37+
return expr == '' or expr in rules
38+
return all(map(test, expr.split(',')))
39+
if not satisfy(meta[1], defines): continue
40+
if not satisfy(meta[3], categories): continue
41+
exported.append(name)
42+
43+
print('EXPORTS', file=out)
44+
for name in sorted(exported): print(' ', name, file=out)

0 commit comments

Comments
 (0)