Bug 1333361 - Fix static fuzzing builds r=franziskus
authorTim Taubert <ttaubert@mozilla.com>
Wed, 25 Jan 2017 15:40:32 +0100
changeset 13058 be2b4287467076d42bb41021a3a10aa47a3eeb47
parent 13057 0106c7de03b8c068a3b1becf6e189344ad9b32a0
child 13059 ca40360a2cce0a2d87c3229abd324c47f0d4781b
push id1955
push userttaubert@mozilla.com
push dateWed, 25 Jan 2017 14:41:06 +0000
reviewersfranziskus
bugs1333361
Bug 1333361 - Fix static fuzzing builds r=franziskus Differential Revision: https://nss-review.dev.mozaws.net/D170
automation/taskcluster/graph/src/extend.js
cmd/mpitests/mpitests.gyp
coreconf/config.gypi
coreconf/fuzz.sh
fuzz/fuzz.gyp
fuzz/shared.h
gtests/der_gtest/der_gtest.gyp
gtests/freebl_gtest/freebl_gtest.gyp
gtests/google_test/google_test.gyp
gtests/pk11_gtest/pk11_gtest.gyp
gtests/ssl_gtest/ssl_gtest.gyp
gtests/util_gtest/util_gtest.gyp
lib/freebl/freebl.gyp
lib/freebl/freebl_base.gypi
lib/pk11wrap/pk11load.c
lib/pk11wrap/pk11wrap.gyp
lib/softoken/pkcs11.c
lib/softoken/softoken.gyp
lib/ssl/ssl.gyp
nss.gyp
--- a/automation/taskcluster/graph/src/extend.js
+++ b/automation/taskcluster/graph/src/extend.js
@@ -120,17 +120,16 @@ export default async function main() {
 
   await scheduleLinux("Linux 64 (debug, gyp, asan, ubsan)", {
     command: [
       "/bin/bash",
       "-c",
       "bin/checkout.sh && nss/automation/taskcluster/scripts/build_gyp.sh -g -v --ubsan --asan"
     ],
     env: {
-      ASAN_OPTIONS: "detect_odr_violation=0", // bug 1316276
       UBSAN_OPTIONS: "print_stacktrace=1",
       NSS_DISABLE_ARENA_FREE_LIST: "1",
       NSS_DISABLE_UNLOAD: "1",
       CC: "clang",
       CCC: "clang++"
     },
     platform: "linux64",
     collection: "gyp-asan",
@@ -267,18 +266,17 @@ async function scheduleLinux(name, base)
   return queue.submit();
 }
 
 /*****************************************************************************/
 
 async function scheduleFuzzing() {
   let base = {
     env: {
-       // bug 1316276
-      ASAN_OPTIONS: "allocator_may_return_null=1:detect_odr_violation=0",
+      ASAN_OPTIONS: "allocator_may_return_null=1",
       UBSAN_OPTIONS: "print_stacktrace=1",
       NSS_DISABLE_ARENA_FREE_LIST: "1",
       NSS_DISABLE_UNLOAD: "1",
       CC: "clang",
       CCC: "clang++"
     },
     platform: "linux64",
     collection: "fuzz",
@@ -329,18 +327,20 @@ async function scheduleFuzzing() {
     parent: task_build,
     name: "QuickDER",
     command: [
       "/bin/bash",
       "-c",
       "bin/checkout.sh && nss/automation/taskcluster/scripts/fuzz.sh " +
         "quickder nss/fuzz/corpus/quickder -max_total_time=300"
     ],
-    // Need a privileged docker container to remove this.
-    env: {ASAN_OPTIONS: "detect_leaks=0"},
+    // Need a privileged docker container to remove detect_leaks=0.
+    env: {
+      ASAN_OPTIONS: "allocator_may_return_null=1:detect_leaks=0",
+    },
     symbol: "QuickDER",
     kind: "test"
   }));
 
   return queue.submit();
 }
 
 /*****************************************************************************/
--- a/cmd/mpitests/mpitests.gyp
+++ b/cmd/mpitests/mpitests.gyp
@@ -9,17 +9,26 @@
   'targets': [
     {
       'target_name': 'mpi_tests',
       'type': 'executable',
       'sources': [
         'mpi-test.c',
       ],
       'dependencies': [
-        '<(DEPTH)/lib/freebl/freebl.gyp:<(freebl_name)',
+        '<(DEPTH)/exports.gyp:nss_exports',
+        '<(DEPTH)/lib/util/util.gyp:nssutil3',
+        '<(DEPTH)/lib/nss/nss.gyp:nss_static',
+        '<(DEPTH)/lib/pk11wrap/pk11wrap.gyp:pk11wrap_static',
+        '<(DEPTH)/lib/cryptohi/cryptohi.gyp:cryptohi',
+        '<(DEPTH)/lib/certhigh/certhigh.gyp:certhi',
+        '<(DEPTH)/lib/certdb/certdb.gyp:certdb',
+        '<(DEPTH)/lib/base/base.gyp:nssb',
+        '<(DEPTH)/lib/dev/dev.gyp:nssdev',
+        '<(DEPTH)/lib/pki/pki.gyp:nsspki',
       ]
     }
   ],
   'target_defaults': {
     'include_dirs': [
       '<(DEPTH)/lib/freebl/mpi',
       '<(DEPTH)/lib/util',
     ]
--- a/coreconf/config.gypi
+++ b/coreconf/config.gypi
@@ -147,17 +147,17 @@
       [ '_type=="shared_library"', {
         'product_dir': '<(nss_dist_obj_dir)/lib'
       }, '_type=="executable"', {
         'product_dir': '<(nss_dist_obj_dir)/bin'
       }, '_standalone_static_library==1', {
         'product_dir': '<(nss_dist_obj_dir)/lib'
       }],
       # mapfile handling
-      [ 'test_build==0 and mapfile!=""', {
+      [ 'mapfile!=""', {
         # Work around a gyp bug. Fixed upstream but not in Ubuntu packages:
         # https://chromium.googlesource.com/external/gyp/+/b85ad3e578da830377dbc1843aa4fbc5af17a192%5E%21/
         'sources': [
           '<(DEPTH)/coreconf/empty.c',
         ],
         'xcode_settings': {
           'OTHER_LDFLAGS': [
             '-exported_symbols_list',
@@ -355,16 +355,21 @@
                 '<!@(<(python) <(DEPTH)/coreconf/werror.py)',
               ],
             },
           }],
           [ 'fuzz_tls==1', {
             'cflags': [
               '-Wno-unused-function',
             ],
+            'xcode_settings': {
+              'OTHER_CFLAGS': [
+                '-Wno-unused-function',
+              ],
+            },
           }],
           [ 'sanitizer_flags!=0', {
             'cflags': ['<@(sanitizer_flags)'],
             'ldflags': ['<@(sanitizer_flags)'],
             'xcode_settings': {
               'OTHER_CFLAGS': ['<@(sanitizer_flags)'],
               # We want to pass -fsanitize=... to our final link call,
               # but not to libtool. OTHER_LDFLAGS is passed to both.
--- a/coreconf/fuzz.sh
+++ b/coreconf/fuzz.sh
@@ -10,17 +10,17 @@ if [ -z "$CC" ]; then
         echo "Fuzzing requires clang!"
         exit 1
     fi
     export CC=clang
     export CCC=clang++
     export CXX=clang++
 fi
 
-gyp_params+=(-Dtest_build=1 -Dfuzz=1)
+gyp_params+=(-Dtest_build=1 -Dfuzz=1 -Dsign_libs=0)
 
 # Add debug symbols even for opt builds.
 nspr_params+=(--enable-debug-symbols)
 
 if [ "$fuzz_oss" = 1 ]; then
   gyp_params+=(-Dno_zdefs=1)
 else
   enable_sanitizer asan
--- a/fuzz/fuzz.gyp
+++ b/fuzz/fuzz.gyp
@@ -32,18 +32,19 @@
         '<(DEPTH)/lib/certdb/certdb.gyp:certdb',
         '<(DEPTH)/lib/certhigh/certhigh.gyp:certhi',
         '<(DEPTH)/lib/cryptohi/cryptohi.gyp:cryptohi',
         '<(DEPTH)/lib/base/base.gyp:nssb',
         '<(DEPTH)/lib/dev/dev.gyp:nssdev',
         '<(DEPTH)/lib/pki/pki.gyp:nsspki',
         '<(DEPTH)/lib/util/util.gyp:nssutil',
         '<(DEPTH)/lib/nss/nss.gyp:nss_static',
-        '<(DEPTH)/lib/pk11wrap/pk11wrap.gyp:pk11wrap',
         '<(DEPTH)/lib/pkcs7/pkcs7.gyp:pkcs7',
+        # This is a static build of pk11wrap, softoken, and freebl.
+        '<(DEPTH)/lib/pk11wrap/pk11wrap.gyp:pk11wrap_static',
       ],
       'conditions': [
         ['use_fuzzing_engine==0', {
           'type': 'static_library',
           'sources': [
             'libFuzzer/FuzzerCrossOver.cpp',
             'libFuzzer/FuzzerDriver.cpp',
             'libFuzzer/FuzzerExtFunctionsDlsym.cpp',
--- a/fuzz/shared.h
+++ b/fuzz/shared.h
@@ -8,18 +8,18 @@
 #define shared_h__
 
 #include "FuzzerRandom.h"
 #include "cert.h"
 #include "nss.h"
 
 class NSSDatabase {
  public:
-  NSSDatabase() { NSS_NoDB_Init(nullptr); }
-  ~NSSDatabase() { NSS_Shutdown(); }
+  NSSDatabase() { assert(NSS_NoDB_Init(nullptr) == SECSuccess); }
+  ~NSSDatabase() { assert(NSS_Shutdown() == SECSuccess); }
 };
 
 size_t CustomMutate(std::vector<decltype(LLVMFuzzerCustomMutator) *> mutators,
                     uint8_t *Data, size_t Size, size_t MaxSize,
                     unsigned int Seed) {
   fuzzer::Random R(Seed);
 
   if (R.RandBool()) {
--- a/gtests/der_gtest/der_gtest.gyp
+++ b/gtests/der_gtest/der_gtest.gyp
@@ -13,16 +13,19 @@
       'sources': [
         'der_getint_unittest.cc',
         'der_private_key_import_unittest.cc',
         '<(DEPTH)/gtests/common/gtests.cc'
       ],
       'dependencies': [
         '<(DEPTH)/exports.gyp:nss_exports',
         '<(DEPTH)/gtests/google_test/google_test.gyp:gtest',
+        '<(DEPTH)/lib/util/util.gyp:nssutil3',
+        '<(DEPTH)/lib/ssl/ssl.gyp:ssl3',
+        '<(DEPTH)/lib/nss/nss.gyp:nss3',
       ]
     }
   ],
   'target_defaults': {
     'include_dirs': [
       '../../gtests/google_test/gtest/include',
       '../../gtests/common'
     ]
--- a/gtests/freebl_gtest/freebl_gtest.gyp
+++ b/gtests/freebl_gtest/freebl_gtest.gyp
@@ -11,18 +11,27 @@
       'target_name': 'freebl_gtest',
       'type': 'executable',
       'sources': [
         'mpi_unittest.cc',
         '<(DEPTH)/gtests/common/gtests.cc'
       ],
       'dependencies': [
         '<(DEPTH)/exports.gyp:nss_exports',
-        '<(DEPTH)/lib/freebl/freebl.gyp:<(freebl_name)',
+        '<(DEPTH)/lib/util/util.gyp:nssutil3',
         '<(DEPTH)/gtests/google_test/google_test.gyp:gtest',
+        '<(DEPTH)/lib/nss/nss.gyp:nss_static',
+        '<(DEPTH)/lib/pk11wrap/pk11wrap.gyp:pk11wrap_static',
+        '<(DEPTH)/lib/cryptohi/cryptohi.gyp:cryptohi',
+        '<(DEPTH)/lib/certhigh/certhigh.gyp:certhi',
+        '<(DEPTH)/lib/certdb/certdb.gyp:certdb',
+        '<(DEPTH)/lib/base/base.gyp:nssb',
+        '<(DEPTH)/lib/dev/dev.gyp:nssdev',
+        '<(DEPTH)/lib/pki/pki.gyp:nsspki',
+        '<(DEPTH)/lib/ssl/ssl.gyp:ssl',
       ],
       'conditions': [
         [ 'ct_verif==1', {
           'defines': [
             'CT_VERIF',
           ],
         }],
       ],
--- a/gtests/google_test/google_test.gyp
+++ b/gtests/google_test/google_test.gyp
@@ -8,49 +8,17 @@
   ],
   'targets': [
     {
       'target_name': 'gtest',
       'type': 'static_library',
       'sources': [
         'gtest/src/gtest-all.cc'
       ],
-      'dependencies': [
-        '<(DEPTH)/lib/nss/nss.gyp:nss3',
-        '<(DEPTH)/lib/util/util.gyp:nssutil3',
-        '<(DEPTH)/lib/smime/smime.gyp:smime3',
-        '<(DEPTH)/lib/ssl/ssl.gyp:ssl3',
-        '<(DEPTH)/cmd/lib/lib.gyp:sectool'
-      ]
     },
-    {
-      'target_name': 'gtest1',
-      'type': 'shared_library',
-      'dependencies': [
-        'gtest'
-      ],
-      # Work around a gyp bug. Fixed upstream in gyp:
-      # https://chromium.googlesource.com/external/gyp/+/93cc6e2c23e4d5ebd179f388e67aa907d0dfd43d
-      'conditions': [
-        ['OS!="win"', {
-          'libraries': [
-            '-lstdc++',
-          ],
-        }],
-      ],
-      # For some reason when just linking static libraries into
-      # a DLL the link fails without this.
-      'msvs_settings': {
-        'VCLinkerTool': {
-          'AdditionalDependencies': [
-            '/DEFAULTLIB:MSVCRT',
-          ],
-        },
-      },
-    }
   ],
   'target_defaults': {
     'include_dirs': [
       'gtest/include/',
       'gtest'
     ],
   },
   'variables': {
--- a/gtests/pk11_gtest/pk11_gtest.gyp
+++ b/gtests/pk11_gtest/pk11_gtest.gyp
@@ -16,19 +16,39 @@
         'pk11_pbkdf2_unittest.cc',
         'pk11_prf_unittest.cc',
         'pk11_prng_unittest.cc',
         'pk11_rsapss_unittest.cc',
         '<(DEPTH)/gtests/common/gtests.cc'
       ],
       'dependencies': [
         '<(DEPTH)/exports.gyp:nss_exports',
-        '<(DEPTH)/lib/freebl/freebl.gyp:<(freebl_name)',
+        '<(DEPTH)/lib/util/util.gyp:nssutil3',
         '<(DEPTH)/gtests/google_test/google_test.gyp:gtest',
       ],
+      'conditions': [
+        [ 'test_build==1', {
+          'dependencies': [
+            '<(DEPTH)/lib/nss/nss.gyp:nss_static',
+            '<(DEPTH)/lib/pk11wrap/pk11wrap.gyp:pk11wrap_static',
+            '<(DEPTH)/lib/cryptohi/cryptohi.gyp:cryptohi',
+            '<(DEPTH)/lib/certhigh/certhigh.gyp:certhi',
+            '<(DEPTH)/lib/certdb/certdb.gyp:certdb',
+            '<(DEPTH)/lib/base/base.gyp:nssb',
+            '<(DEPTH)/lib/dev/dev.gyp:nssdev',
+            '<(DEPTH)/lib/pki/pki.gyp:nsspki',
+            '<(DEPTH)/lib/ssl/ssl.gyp:ssl',
+          ],
+        }, {
+          'dependencies': [
+            '<(DEPTH)/lib/nss/nss.gyp:nss3',
+            '<(DEPTH)/lib/ssl/ssl.gyp:ssl3',
+          ],
+        }],
+      ],
     }
   ],
   'target_defaults': {
     'include_dirs': [
       '../../gtests/google_test/gtest/include',
       '../../gtests/common'
     ]
   },
--- a/gtests/ssl_gtest/ssl_gtest.gyp
+++ b/gtests/ssl_gtest/ssl_gtest.gyp
@@ -42,37 +42,43 @@
         'tls_filter.cc',
         'tls_hkdf_unittest.cc',
         'tls_parser.cc',
         'tls_protect.cc'
       ],
       'dependencies': [
         '<(DEPTH)/exports.gyp:nss_exports',
         '<(DEPTH)/lib/util/util.gyp:nssutil3',
-        '<(DEPTH)/lib/sqlite/sqlite.gyp:sqlite3',
         '<(DEPTH)/gtests/google_test/google_test.gyp:gtest',
-        '<(DEPTH)/lib/softoken/softoken.gyp:softokn',
         '<(DEPTH)/lib/smime/smime.gyp:smime',
         '<(DEPTH)/lib/ssl/ssl.gyp:ssl',
         '<(DEPTH)/lib/nss/nss.gyp:nss_static',
-        '<(DEPTH)/cmd/lib/lib.gyp:sectool',
         '<(DEPTH)/lib/pkcs12/pkcs12.gyp:pkcs12',
         '<(DEPTH)/lib/pkcs7/pkcs7.gyp:pkcs7',
         '<(DEPTH)/lib/certhigh/certhigh.gyp:certhi',
         '<(DEPTH)/lib/cryptohi/cryptohi.gyp:cryptohi',
-        '<(DEPTH)/lib/pk11wrap/pk11wrap.gyp:pk11wrap',
-        '<(DEPTH)/lib/softoken/softoken.gyp:softokn',
         '<(DEPTH)/lib/certdb/certdb.gyp:certdb',
         '<(DEPTH)/lib/pki/pki.gyp:nsspki',
         '<(DEPTH)/lib/dev/dev.gyp:nssdev',
         '<(DEPTH)/lib/base/base.gyp:nssb',
-        '<(DEPTH)/lib/freebl/freebl.gyp:<(freebl_name)',
         '<(DEPTH)/lib/zlib/zlib.gyp:nss_zlib'
       ],
       'conditions': [
+        [ 'test_build==1', {
+          'dependencies': [
+            '<(DEPTH)/lib/pk11wrap/pk11wrap.gyp:pk11wrap_static',
+          ],
+        }, {
+          'dependencies': [
+            '<(DEPTH)/lib/sqlite/sqlite.gyp:sqlite3',
+            '<(DEPTH)/lib/pk11wrap/pk11wrap.gyp:pk11wrap',
+            '<(DEPTH)/lib/softoken/softoken.gyp:softokn',
+            '<(DEPTH)/lib/freebl/freebl.gyp:freebl',
+          ],
+        }],
         [ 'disable_dbm==0', {
           'dependencies': [
             '<(DEPTH)/lib/dbm/src/src.gyp:dbm',
           ],
         }],
         [ 'disable_libpkix==0', {
           'dependencies': [
             '<(DEPTH)/lib/libpkix/pkix/certsel/certsel.gyp:pkixcertsel',
@@ -98,11 +104,10 @@
       '../../lib/ssl'
     ],
     'defines': [
       'NSS_USE_STATIC_LIBS'
     ],
   },
   'variables': {
     'module': 'nss',
-    'use_static_libs': 1,
   }
 }
--- a/gtests/util_gtest/util_gtest.gyp
+++ b/gtests/util_gtest/util_gtest.gyp
@@ -13,16 +13,25 @@
       'sources': [
         'util_utf8_unittest.cc',
         '<(DEPTH)/gtests/common/gtests.cc'
       ],
       'dependencies': [
         '<(DEPTH)/exports.gyp:nss_exports',
         '<(DEPTH)/gtests/google_test/google_test.gyp:gtest',
         '<(DEPTH)/lib/util/util.gyp:nssutil',
+        '<(DEPTH)/lib/nss/nss.gyp:nss_static',
+        '<(DEPTH)/lib/pk11wrap/pk11wrap.gyp:pk11wrap_static',
+        '<(DEPTH)/lib/cryptohi/cryptohi.gyp:cryptohi',
+        '<(DEPTH)/lib/certhigh/certhigh.gyp:certhi',
+        '<(DEPTH)/lib/certdb/certdb.gyp:certdb',
+        '<(DEPTH)/lib/base/base.gyp:nssb',
+        '<(DEPTH)/lib/dev/dev.gyp:nssdev',
+        '<(DEPTH)/lib/pki/pki.gyp:nsspki',
+        '<(DEPTH)/lib/ssl/ssl.gyp:ssl',
       ]
     }
   ],
   'target_defaults': {
     'include_dirs': [
       '../../gtests/google_test/gtest/include',
       '../../gtests/common',
       '../../lib/util'
--- a/lib/freebl/freebl.gyp
+++ b/lib/freebl/freebl.gyp
@@ -27,253 +27,98 @@
       'type': 'static_library',
       'sources': [
         'loader.c'
       ],
       'dependencies': [
         '<(DEPTH)/exports.gyp:nss_exports'
       ]
     },
+    # For test builds, build a static freebl library so we can statically
+    # link it into the test build binary. This way we don't have to
+    # dlopen() the shared lib but can directly call freebl functions.
+    {
+      'target_name': 'freebl_static',
+      'type': 'static_library',
+      'includes': [
+        'freebl_base.gypi',
+      ],
+      'dependencies': [
+        '<(DEPTH)/exports.gyp:nss_exports',
+      ],
+      'conditions': [
+        [ 'OS=="linux"', {
+          'defines!': [
+            'FREEBL_NO_DEPEND',
+            'FREEBL_LOWHASH',
+            'USE_HW_AES',
+            'INTEL_GCM',
+          ],
+          'conditions': [
+            [ 'target_arch=="x64"', {
+              # The AES assembler code doesn't work in static test builds.
+              # The linker complains about non-relocatable code, and I
+              # currently don't know how to fix this properly.
+              'sources!': [
+                'intel-aes.s',
+                'intel-gcm.s',
+              ],
+            }],
+          ],
+        }],
+      ],
+    },
     {
       'target_name': '<(freebl_name)',
       'type': 'shared_library',
-      'sources': [
-        'aeskeywrap.c',
-        'alg2268.c',
-        'alghmac.c',
-        'arcfive.c',
-        'arcfour.c',
-        'camellia.c',
-        'chacha20poly1305.c',
-        'ctr.c',
-        'cts.c',
-        'des.c',
-        'desblapi.c',
-        'dh.c',
-        'drbg.c',
-        'dsa.c',
-        'ec.c',
-        'ecdecode.c',
-        'ecl/ec_naf.c',
-        'ecl/ecl.c',
-        'ecl/ecl_curve.c',
-        'ecl/ecl_gf.c',
-        'ecl/ecl_mult.c',
-        'ecl/ecp_25519.c',
-        'ecl/ecp_256.c',
-        'ecl/ecp_256_32.c',
-        'ecl/ecp_384.c',
-        'ecl/ecp_521.c',
-        'ecl/ecp_aff.c',
-        'ecl/ecp_jac.c',
-        'ecl/ecp_jm.c',
-        'ecl/ecp_mont.c',
-        'fipsfreebl.c',
-        'freeblver.c',
-        'gcm.c',
-        'hmacct.c',
-        'jpake.c',
-        'ldvector.c',
-        'md2.c',
-        'md5.c',
-        'mpi/mp_gf2m.c',
-        'mpi/mpcpucache.c',
-        'mpi/mpi.c',
-        'mpi/mplogic.c',
-        'mpi/mpmontg.c',
-        'mpi/mpprime.c',
-        'pqg.c',
-        'rawhash.c',
-        'rijndael.c',
-        'rsa.c',
-        'rsapkcs.c',
-        'seed.c',
-        'sha512.c',
-        'sha_fast.c',
-        'shvfy.c',
-        'sysrand.c',
-        'tlsprfalg.c'
+      'includes': [
+        'freebl_base.gypi',
+      ],
+      'dependencies': [
+        '<(DEPTH)/exports.gyp:nss_exports',
       ],
       'conditions': [
-        [ 'OS=="linux"', {
-          'sources': [
-            'nsslowhash.c',
-            'stubs.c',
-          ],
-          'conditions': [
-            [ 'test_build==1', {
-              'dependencies': [
-                '<(DEPTH)/lib/util/util.gyp:nssutil3',
-              ],
-            }],
-          ]
-        }],
-        [ 'OS=="linux" or OS=="android"', {
-          'conditions': [
-            [ 'target_arch=="x64"', {
-              'sources': [
-                'arcfour-amd64-gas.s',
-                'intel-aes.s',
-                'intel-gcm.s',
-                'mpi/mpi_amd64.c',
-                'mpi/mpi_amd64_gas.s',
-                'mpi/mp_comba.c',
-              ],
-              'dependencies': [
-                'intel-gcm-wrap_c_lib',
-              ],
-              'conditions': [
-                [ 'cc_is_clang==1', {
-                  'cflags': [
-                    '-no-integrated-as',
-                  ],
-                  'cflags_mozilla': [
-                    '-no-integrated-as',
-                  ],
-                  'asflags_mozilla': [
-                    '-no-integrated-as',
-                  ],
-                }],
-              ],
-            }],
-            [ 'target_arch=="ia32"', {
-              'sources': [
-                'mpi/mpi_x86.s',
-              ],
-            }],
-            [ 'target_arch=="arm"', {
-              'sources': [
-                'mpi/mpi_arm.c',
-              ],
-            }],
-          ],
-        }, {
-          # not Linux or Android
+        [ 'OS!="linux" and OS!="android"', {
           'conditions': [
             [ 'moz_fold_libs==0', {
               'dependencies': [
-                '../util/util.gyp:nssutil3',
+                '<(DEPTH)/lib/util/util.gyp:nssutil3',
               ],
             }, {
               'libraries': [
                 '<(moz_folded_library_name)',
               ],
             }],
           ],
-        }],
-        [ 'OS=="win"', {
-          'sources': [
-            #TODO: building with mingw should not need this.
-            'ecl/uint128.c',
-          ],
-          'libraries': [
-            'advapi32.lib',
-          ],
-          'conditions': [
-            [ 'target_arch=="x64"', {
-              'sources': [
-                'arcfour-amd64-masm.asm',
-                'mpi/mpi_amd64.c',
-                'mpi/mpi_amd64_masm.asm',
-                'mpi/mp_comba_amd64_masm.asm',
-                'intel-aes-x64-masm.asm',
-                'intel-gcm-x64-masm.asm',
-              ],
-            }, {
-              # not x64
-              'sources': [
-                'mpi/mpi_x86_asm.c',
-                'intel-aes-x86-masm.asm',
-                'intel-gcm-x86-masm.asm',
-              ],
-            }],
-            [ 'cc_is_clang==1', {
-              'dependencies': [
-                'intel-gcm-wrap_c_lib',
-              ],
-            }, {
-              # MSVC
-              'sources': [
-                'intel-gcm-wrap.c',
-              ],
-            }],
+        }, 'target_arch=="x64"', {
+          'dependencies': [
+            'intel-gcm-wrap_c_lib',
           ],
         }],
-        ['target_arch=="ia32" or target_arch=="x64"', {
-          'sources': [
-            # All intel architectures get the 64 bit version
-            'ecl/curve25519_64.c',
-          ],
-        }, {
-          'sources': [
-            # All non intel architectures get the generic 32 bit implementation (slow!)
-            'ecl/curve25519_32.c',
-          ],
-        }],
-        #TODO uint128.c
-        [ 'disable_chachapoly==0', {
-          'conditions': [
-            [ 'OS!="win" and target_arch=="x64"', {
-              'sources': [
-                'chacha20_vec.c',
-                'poly1305-donna-x64-sse2-incremental-source.c',
-              ],
-            }, {
-              # not x64
-              'sources': [
-                'chacha20.c',
-                'poly1305.c',
-              ],
-            }],
+        [ 'OS=="win" and cc_is_clang==1', {
+          'dependencies': [
+            'intel-gcm-wrap_c_lib',
           ],
         }],
-        [ 'fuzz_tls==1', {
+        [ 'OS=="linux"', {
           'sources': [
-            'det_rng.c',
-          ],
-          'defines': [
-            'UNSAFE_FUZZER_MODE',
-          ],
-        }],
-        [ 'ct_verif==1', {
-          'defines': [
-            'CT_VERIF',
+            'nsslowhash.c',
+            'stubs.c',
           ],
         }],
-        [ 'OS=="mac"', {
-          'conditions': [
-            [ 'target_arch=="ia32"', {
-              'sources': [
-                'mpi/mpi_sse2.s',
-              ],
-              'defines': [
-                'MP_USE_UINT_DIGIT',
-                'MP_ASSEMBLY_MULTIPLY',
-                'MP_ASSEMBLY_SQUARE',
-                'MP_ASSEMBLY_DIV_2DX1D',
-              ],
-            }],
-          ],
-        }],
-      ],
-      'dependencies': [
-        '<(DEPTH)/exports.gyp:nss_exports',
       ],
       'variables': {
        'conditions': [
          [ 'OS=="linux"', {
            'mapfile': 'freebl_hash_vector.def',
          }, {
            'mapfile': 'freebl.def',
          }],
        ]
       },
-      'ldflags': [
-        '-Wl,-Bsymbolic'
-      ]
     },
   ],
   'conditions': [
     [ 'OS=="linux"', {
       # stub build
       'targets': [
         {
           'target_name': 'freebl3',
@@ -366,23 +211,17 @@
               'NSS_X86',
             ],
           }],
         ],
       }],
       [ 'OS=="linux"', {
         'defines': [
           'FREEBL_LOWHASH',
-        ],
-        'conditions': [
-          [ 'test_build==0', {
-            'defines': [
-              'FREEBL_NO_DEPEND',
-            ],
-          }],
+          'FREEBL_NO_DEPEND',
         ],
       }],
       [ 'OS=="linux" or OS=="android"', {
         'conditions': [
           [ 'target_arch=="x64"', {
             'defines': [
               'MP_IS_LITTLE_ENDIAN',
               'NSS_BEVAND_ARCFOUR',
new file mode 100644
--- /dev/null
+++ b/lib/freebl/freebl_base.gypi
@@ -0,0 +1,194 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+{
+  'sources': [
+    'aeskeywrap.c',
+    'alg2268.c',
+    'alghmac.c',
+    'arcfive.c',
+    'arcfour.c',
+    'camellia.c',
+    'chacha20poly1305.c',
+    'ctr.c',
+    'cts.c',
+    'des.c',
+    'desblapi.c',
+    'dh.c',
+    'drbg.c',
+    'dsa.c',
+    'ec.c',
+    'ecdecode.c',
+    'ecl/ec_naf.c',
+    'ecl/ecl.c',
+    'ecl/ecl_curve.c',
+    'ecl/ecl_gf.c',
+    'ecl/ecl_mult.c',
+    'ecl/ecp_25519.c',
+    'ecl/ecp_256.c',
+    'ecl/ecp_256_32.c',
+    'ecl/ecp_384.c',
+    'ecl/ecp_521.c',
+    'ecl/ecp_aff.c',
+    'ecl/ecp_jac.c',
+    'ecl/ecp_jm.c',
+    'ecl/ecp_mont.c',
+    'fipsfreebl.c',
+    'freeblver.c',
+    'gcm.c',
+    'hmacct.c',
+    'jpake.c',
+    'ldvector.c',
+    'md2.c',
+    'md5.c',
+    'mpi/mp_gf2m.c',
+    'mpi/mpcpucache.c',
+    'mpi/mpi.c',
+    'mpi/mplogic.c',
+    'mpi/mpmontg.c',
+    'mpi/mpprime.c',
+    'pqg.c',
+    'rawhash.c',
+    'rijndael.c',
+    'rsa.c',
+    'rsapkcs.c',
+    'seed.c',
+    'sha512.c',
+    'sha_fast.c',
+    'shvfy.c',
+    'sysrand.c',
+    'tlsprfalg.c'
+  ],
+  'conditions': [
+    [ 'OS=="linux" or OS=="android"', {
+      'conditions': [
+        [ 'target_arch=="x64"', {
+          'sources': [
+            'arcfour-amd64-gas.s',
+            'intel-aes.s',
+            'intel-gcm.s',
+            'mpi/mpi_amd64.c',
+            'mpi/mpi_amd64_gas.s',
+            'mpi/mp_comba.c',
+          ],
+          'conditions': [
+            [ 'cc_is_clang==1', {
+              'cflags': [
+                '-no-integrated-as',
+              ],
+              'cflags_mozilla': [
+                '-no-integrated-as',
+              ],
+              'asflags_mozilla': [
+                '-no-integrated-as',
+              ],
+            }],
+          ],
+        }],
+        [ 'target_arch=="ia32"', {
+          'sources': [
+            'mpi/mpi_x86.s',
+          ],
+        }],
+        [ 'target_arch=="arm"', {
+          'sources': [
+            'mpi/mpi_arm.c',
+          ],
+        }],
+      ],
+    }],
+    [ 'OS=="win"', {
+      'sources': [
+        #TODO: building with mingw should not need this.
+        'ecl/uint128.c',
+      ],
+      'libraries': [
+        'advapi32.lib',
+      ],
+      'conditions': [
+        [ 'target_arch=="x64"', {
+          'sources': [
+            'arcfour-amd64-masm.asm',
+            'mpi/mpi_amd64.c',
+            'mpi/mpi_amd64_masm.asm',
+            'mpi/mp_comba_amd64_masm.asm',
+            'intel-aes-x64-masm.asm',
+            'intel-gcm-x64-masm.asm',
+          ],
+        }, {
+          # not x64
+          'sources': [
+            'mpi/mpi_x86_asm.c',
+            'intel-aes-x86-masm.asm',
+            'intel-gcm-x86-masm.asm',
+          ],
+        }],
+        [ 'cc_is_clang!=1', {
+          # MSVC
+          'sources': [
+            'intel-gcm-wrap.c',
+          ],
+        }],
+      ],
+    }],
+    ['target_arch=="ia32" or target_arch=="x64"', {
+      'sources': [
+        # All intel architectures get the 64 bit version
+        'ecl/curve25519_64.c',
+      ],
+    }, {
+      'sources': [
+        # All non intel architectures get the generic 32 bit implementation (slow!)
+        'ecl/curve25519_32.c',
+      ],
+    }],
+    #TODO uint128.c
+    [ 'disable_chachapoly==0', {
+      'conditions': [
+        [ 'OS!="win" and target_arch=="x64"', {
+          'sources': [
+            'chacha20_vec.c',
+            'poly1305-donna-x64-sse2-incremental-source.c',
+          ],
+        }, {
+          # not x64
+          'sources': [
+            'chacha20.c',
+            'poly1305.c',
+          ],
+        }],
+      ],
+    }],
+    [ 'fuzz_tls==1', {
+      'sources': [
+        'det_rng.c',
+      ],
+      'defines': [
+        'UNSAFE_FUZZER_MODE',
+      ],
+    }],
+    [ 'ct_verif==1', {
+      'defines': [
+        'CT_VERIF',
+      ],
+    }],
+    [ 'OS=="mac"', {
+      'conditions': [
+        [ 'target_arch=="ia32"', {
+          'sources': [
+            'mpi/mpi_sse2.s',
+          ],
+          'defines': [
+            'MP_USE_UINT_DIGIT',
+            'MP_ASSEMBLY_MULTIPLY',
+            'MP_ASSEMBLY_SQUARE',
+            'MP_ASSEMBLY_DIV_2DX1D',
+          ],
+        }],
+      ],
+    }],
+  ],
+ 'ldflags': [
+   '-Wl,-Bsymbolic'
+ ],
+}
--- a/lib/pk11wrap/pk11load.c
+++ b/lib/pk11wrap/pk11load.c
@@ -12,16 +12,20 @@
 #include "prlink.h"
 #include "pk11func.h"
 #include "secmodi.h"
 #include "secmodti.h"
 #include "nssilock.h"
 #include "secerr.h"
 #include "prenv.h"
 #include "utilparst.h"
+#include "prio.h"
+#include "prprf.h"
+#include <stdio.h>
+#include "prsystem.h"
 
 #define DEBUG_MODULE 1
 
 #ifdef DEBUG_MODULE
 static char *modToDBG = NULL;
 
 #include "debug_module.c"
 #endif
@@ -345,46 +349,46 @@ SECMOD_SetRootCerts(PK11SlotInfo *slot, 
             /* increment module count & store new list */
             mod->slotInfo = psi_list;
             mod->slotInfoCount++;
         }
         psi->hasRootCerts = 1;
     }
 }
 
+#ifndef NSS_TEST_BUILD
 static const char *my_shlib_name =
     SHLIB_PREFIX "nss" SHLIB_VERSION "." SHLIB_SUFFIX;
 static const char *softoken_shlib_name =
     SHLIB_PREFIX "softokn" SOFTOKEN_SHLIB_VERSION "." SHLIB_SUFFIX;
 static const PRCallOnceType pristineCallOnce;
 static PRCallOnceType loadSoftokenOnce;
 static PRLibrary *softokenLib;
 static PRInt32 softokenLoadCount;
 
-#include "prio.h"
-#include "prprf.h"
-#include <stdio.h>
-#include "prsystem.h"
-
 /* This function must be run only once. */
 /*  determine if hybrid platform, then actually load the DSO. */
 static PRStatus
 softoken_LoadDSO(void)
 {
     PRLibrary *handle;
 
     handle = PORT_LoadLibraryFromOrigin(my_shlib_name,
                                         (PRFuncPtr)&softoken_LoadDSO,
                                         softoken_shlib_name);
     if (handle) {
         softokenLib = handle;
         return PR_SUCCESS;
     }
     return PR_FAILURE;
 }
+#else
+CK_RV NSC_GetFunctionList(CK_FUNCTION_LIST_PTR *pFunctionList);
+char **NSC_ModuleDBFunc(unsigned long function, char *parameters, void *args);
+#endif
 
 /*
  * load a new module into our address space and initialize it.
  */
 SECStatus
 secmod_LoadPKCS11Module(SECMODModule *mod, SECMODModule **oldModule)
 {
     PRLibrary *library = NULL;
@@ -393,18 +397,21 @@ secmod_LoadPKCS11Module(SECMODModule *mo
     CK_ULONG slotCount = 0;
     SECStatus rv;
     PRBool alreadyLoaded = PR_FALSE;
     char *disableUnload = NULL;
 
     if (mod->loaded)
         return SECSuccess;
 
-    /* intenal modules get loaded from their internal list */
+    /* internal modules get loaded from their internal list */
     if (mod->internal && (mod->dllName == NULL)) {
+#ifdef NSS_TEST_BUILD
+        entry = (CK_C_GetFunctionList)NSC_GetFunctionList;
+#else
         /*
          * Loads softoken as a dynamic library,
          * even though the rest of NSS assumes this as the "internal" module.
          */
         if (!softokenLib &&
             PR_SUCCESS != PR_CallOnce(&loadSoftokenOnce, &softoken_LoadDSO))
             return SECFailure;
 
@@ -415,20 +422,25 @@ secmod_LoadPKCS11Module(SECMODModule *mo
                 PR_FindSymbol(softokenLib, "FC_GetFunctionList");
         } else {
             entry = (CK_C_GetFunctionList)
                 PR_FindSymbol(softokenLib, "NSC_GetFunctionList");
         }
 
         if (!entry)
             return SECFailure;
+#endif
 
         if (mod->isModuleDB) {
             mod->moduleDBFunc = (CK_C_GetFunctionList)
+#ifdef NSS_TEST_BUILD
+                NSC_ModuleDBFunc;
+#else
                 PR_FindSymbol(softokenLib, "NSC_ModuleDBFunc");
+#endif
         }
 
         if (mod->moduleDBOnly) {
             mod->loaded = PR_TRUE;
             return SECSuccess;
         }
     } else {
         /* Not internal, load the DLL and look up C_GetFunctionList */
@@ -596,31 +608,33 @@ SECMOD_UnloadModule(SECMODModule *mod)
     }
     mod->moduleID = 0;
     mod->loaded = PR_FALSE;
 
     /* do we want the semantics to allow unloading the internal library?
      * if not, we should change this to SECFailure and move it above the
      * mod->loaded = PR_FALSE; */
     if (mod->internal && (mod->dllName == NULL)) {
+#ifndef NSS_TEST_BUILD
         if (0 == PR_ATOMIC_DECREMENT(&softokenLoadCount)) {
             if (softokenLib) {
                 disableUnload = PR_GetEnvSecure("NSS_DISABLE_UNLOAD");
                 if (!disableUnload) {
 #ifdef DEBUG
                     PRStatus status = PR_UnloadLibrary(softokenLib);
                     PORT_Assert(PR_SUCCESS == status);
 #else
                     PR_UnloadLibrary(softokenLib);
 #endif
                 }
                 softokenLib = NULL;
             }
             loadSoftokenOnce = pristineCallOnce;
         }
+#endif
         return SECSuccess;
     }
 
     library = (PRLibrary *)mod->library;
     /* paranoia */
     if (library == NULL) {
         return SECFailure;
     }
--- a/lib/pk11wrap/pk11wrap.gyp
+++ b/lib/pk11wrap/pk11wrap.gyp
@@ -2,50 +2,69 @@
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 {
   'includes': [
     '../../coreconf/config.gypi'
   ],
   'targets': [
     {
+      'target_name': 'pk11wrap_static',
+      'type': 'static_library',
+      'defines': [
+        'NSS_TEST_BUILD',
+      ],
+      'dependencies': [
+        'pk11wrap_base',
+        '<(DEPTH)/exports.gyp:nss_exports',
+        '<(DEPTH)/lib/softoken/softoken.gyp:softokn_static',
+      ],
+    },
+    {
       'target_name': 'pk11wrap',
       'type': 'static_library',
-      'sources': [
-        'dev3hack.c',
-        'pk11akey.c',
-        'pk11auth.c',
-        'pk11cert.c',
-        'pk11cxt.c',
-        'pk11err.c',
-        'pk11kea.c',
-        'pk11list.c',
-        'pk11load.c',
-        'pk11mech.c',
-        'pk11merge.c',
-        'pk11nobj.c',
-        'pk11obj.c',
-        'pk11pars.c',
-        'pk11pbe.c',
-        'pk11pk12.c',
-        'pk11pqg.c',
-        'pk11sdr.c',
-        'pk11skey.c',
-        'pk11slot.c',
-        'pk11util.c'
+      'dependencies': [
+        'pk11wrap_base',
+        '<(DEPTH)/exports.gyp:nss_exports',
       ],
-      'dependencies': [
-        '<(DEPTH)/exports.gyp:nss_exports'
-      ]
-    }
+    },
+    {
+      'target_name': 'pk11wrap_base',
+      'type': 'none',
+      'direct_dependent_settings': {
+        'sources': [
+          'dev3hack.c',
+          'pk11akey.c',
+          'pk11auth.c',
+          'pk11cert.c',
+          'pk11cxt.c',
+          'pk11err.c',
+          'pk11kea.c',
+          'pk11list.c',
+          'pk11load.c',
+          'pk11mech.c',
+          'pk11merge.c',
+          'pk11nobj.c',
+          'pk11obj.c',
+          'pk11pars.c',
+          'pk11pbe.c',
+          'pk11pk12.c',
+          'pk11pqg.c',
+          'pk11sdr.c',
+          'pk11skey.c',
+          'pk11slot.c',
+          'pk11util.c'
+        ],
+      },
+    },
   ],
   'target_defaults': {
     'defines': [
       'SHLIB_SUFFIX=\"<(dll_suffix)\"',
       'SHLIB_PREFIX=\"<(dll_prefix)\"',
       'SHLIB_VERSION=\"3\"',
       'SOFTOKEN_SHLIB_VERSION=\"3\"'
     ]
   },
   'variables': {
     'module': 'nss'
   }
-}
\ No newline at end of file
+}
--- a/lib/softoken/pkcs11.c
+++ b/lib/softoken/pkcs11.c
@@ -3144,19 +3144,21 @@ nsc_CommonFinalize(CK_VOID_PTR pReserved
 
     /* tell freeBL to clean up after itself */
     BL_Cleanup();
 
     /* reset fork status in freebl. We must do this before BL_Unload so that
      * this call doesn't force freebl to be reloaded. */
     BL_SetForkState(PR_FALSE);
 
+#ifndef NSS_TEST_BUILD
     /* unload freeBL shared library from memory. This may only decrement the
      * OS refcount if it's been loaded multiple times, eg. by libssl */
     BL_Unload();
+#endif
 
     /* clean up the default OID table */
     SECOID_Shutdown();
 
     /* reset fork status in util */
     UTIL_SetForkState(PR_FALSE);
 
     nsc_init = PR_FALSE;
--- a/lib/softoken/softoken.gyp
+++ b/lib/softoken/softoken.gyp
@@ -2,45 +2,75 @@
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 {
   'includes': [
     '../../coreconf/config.gypi'
   ],
   'targets': [
     {
+      'target_name': 'softokn_static',
+      'type': 'static_library',
+      'defines': [
+        'NSS_TEST_BUILD',
+      ],
+      'dependencies': [
+        'softokn_base',
+        '<(DEPTH)/exports.gyp:nss_exports',
+        '<(DEPTH)/lib/freebl/freebl.gyp:freebl_static',
+      ],
+      'conditions': [
+        [ 'use_system_sqlite==1', {
+          'dependencies': [
+            '<(DEPTH)/lib/sqlite/sqlite.gyp:sqlite3',
+          ],
+        }, {
+          'dependencies': [
+            '<(DEPTH)/lib/sqlite/sqlite.gyp:sqlite',
+          ],
+        }],
+      ],
+    },
+    {
       'target_name': 'softokn',
       'type': 'static_library',
-      'sources': [
-        'fipsaudt.c',
-        'fipstest.c',
-        'fipstokn.c',
-        'jpakesftk.c',
-        'lgglue.c',
-        'lowkey.c',
-        'lowpbe.c',
-        'padbuf.c',
-        'pkcs11.c',
-        'pkcs11c.c',
-        'pkcs11u.c',
-        'sdb.c',
-        'sftkdb.c',
-        'sftkhmac.c',
-        'sftkpars.c',
-        'sftkpwd.c',
-        'softkver.c',
-        'tlsprf.c'
-      ],
       'dependencies': [
+        'softokn_base',
         '<(DEPTH)/exports.gyp:nss_exports',
         '<(DEPTH)/lib/sqlite/sqlite.gyp:sqlite3',
         '<(DEPTH)/lib/freebl/freebl.gyp:freebl',
       ]
     },
     {
+      'target_name': 'softokn_base',
+      'type': 'none',
+      'direct_dependent_settings': {
+        'sources': [
+          'fipsaudt.c',
+          'fipstest.c',
+          'fipstokn.c',
+          'jpakesftk.c',
+          'lgglue.c',
+          'lowkey.c',
+          'lowpbe.c',
+          'padbuf.c',
+          'pkcs11.c',
+          'pkcs11c.c',
+          'pkcs11u.c',
+          'sdb.c',
+          'sftkdb.c',
+          'sftkhmac.c',
+          'sftkpars.c',
+          'sftkpwd.c',
+          'softkver.c',
+          'tlsprf.c'
+        ],
+      },
+    },
+    {
       'target_name': 'softokn3',
       'type': 'shared_library',
       'dependencies': [
         'softokn',
       ],
       'conditions': [
         [ 'moz_fold_libs==0', {
           'dependencies': [
--- a/lib/ssl/ssl.gyp
+++ b/lib/ssl/ssl.gyp
@@ -71,26 +71,26 @@
         [ 'mozilla_client==1', {
           'defines': [
             'NSS_ENABLE_TLS13_SHORT_HEADERS',
           ],
         }],
       ],
       'dependencies': [
         '<(DEPTH)/exports.gyp:nss_exports',
-        '<(DEPTH)/lib/freebl/freebl.gyp:freebl',
       ],
     },
     {
       'target_name': 'ssl3',
       'type': 'shared_library',
       'dependencies': [
         'ssl',
         '<(DEPTH)/lib/nss/nss.gyp:nss3',
         '<(DEPTH)/lib/util/util.gyp:nssutil3',
+        '<(DEPTH)/lib/freebl/freebl.gyp:freebl',
       ],
       'variables': {
         'mapfile': 'ssl.def'
       }
     }
   ],
   'target_defaults': {
     'defines': [
--- a/nss.gyp
+++ b/nss.gyp
@@ -172,17 +172,16 @@
             'cmd/tests/tests.gyp:dertimetest',
             'cmd/tests/tests.gyp:encodeinttest',
             'cmd/tests/tests.gyp:nonspr10',
             'cmd/tests/tests.gyp:remtest',
             'cmd/tests/tests.gyp:secmodtest',
             'cmd/tstclnt/tstclnt.gyp:tstclnt',
             'cmd/vfychain/vfychain.gyp:vfychain',
             'cmd/vfyserv/vfyserv.gyp:vfyserv',
-            'gtests/google_test/google_test.gyp:gtest1',
             'gtests/der_gtest/der_gtest.gyp:der_gtest',
             'gtests/pk11_gtest/pk11_gtest.gyp:pk11_gtest',
             'gtests/ssl_gtest/ssl_gtest.gyp:ssl_gtest',
             'gtests/util_gtest/util_gtest.gyp:util_gtest',
             'gtests/nss_bogo_shim/nss_bogo_shim.gyp:nss_bogo_shim'
           ],
           'conditions': [
             [ 'OS=="linux"', {