diff --git a/DEPS b/DEPS index ddaf345762b78..e083b783e2278 100644 --- a/DEPS +++ b/DEPS @@ -21,12 +21,12 @@ vars = { 'chromium_git': 'https://chromium.googlesource.com', 'dart_svn': 'https://dart.googlecode.com', 'skia_revision': '2ced78866fcadd98895777c8dffe92e229775181', - 'angle_revision': 'bdd419f9f5b006e913606e7363125942c8ae06bc', + 'angle_revision': '02df796f466cee47f42130bd8c7dbad6c72a1662', 'dart_revision': 'e5e3d161e70d862608e6597facdf5ac8ae9ab2c3', 'dart_observatory_packages_revision': '45565', - 'boringssl_revision': '642f1498d056dbba3e50ed5a232ab2f482626dec', + 'boringssl_revision': '7f15ff53d82a1991d6732d2303eb652b1cf7e023', - 'buildtools_revision': 'fa660d47fa1a6c649d5c29e001348447c55709e6', + 'buildtools_revision': '5215ee866bc3e8eb4a7f124212845abf4029e60b', 'archive_dart_revision': '07ffd98c5403b7f9ae067b57dc9487611be420f5', 'args_dart_revision': 'e0e8377412ee6cd6a5a4a8632848181c1db91f44', @@ -55,10 +55,10 @@ deps = { Var('chromium_git') + '/chromium/buildtools.git' + '@' + Var('buildtools_revision'), 'src/testing/gtest': - Var('chromium_git') + '/external/googletest.git' + '@' + 'be1868139ffe0ccd0e8e3b37292b84c821d9c8ad', # from svn revision 704 + Var('chromium_git') + '/external/googletest.git' + '@' + '23574bf2333f834ff665f894c97bef8a5b33a0a9', 'src/testing/gmock': - Var('chromium_git') + '/external/googlemock.git' + '@' + '29763965ab52f24565299976b936d1265cb6a271', # from svn revision 501 + Var('chromium_git') + '/external/googlemock.git' + '@' + '29763965ab52f24565299976b936d1265cb6a271', 'src/third_party/angle': Var('chromium_git') + '/angle/angle.git' + '@' + Var('angle_revision'), @@ -80,7 +80,7 @@ deps = { Var('chromium_git') + '/chromium/deps/yasm/patched-yasm.git' + '@' + '4671120cd8558ce62ee8672ebf3eb6f5216f909b', 'src/third_party/libjpeg_turbo': - Var('chromium_git') + '/chromium/deps/libjpeg_turbo.git' + '@' + '034e9a9747e0983bc19808ea70e469bc8342081f', + Var('chromium_git') + '/chromium/deps/libjpeg_turbo.git' + '@' + 'f4631b6ee8b1dbb05e51ae335a7886f9ac598ab6', 'src/third_party/smhasher/src': Var('chromium_git') + '/external/smhasher.git' + '@' + 'e87738e57558e0ec472b2fc3a643b838e5b6e88f', @@ -155,10 +155,7 @@ deps_os = { Var('chromium_git') + '/external/github.com/appurify/appurify-python.git' + '@' + 'ee7abd5c5ae3106f72b2a0b9d2cb55094688e867', 'src/third_party/freetype-android/src': - Var('chromium_git') + '/chromium/src/third_party/freetype.git' + '@' + 'd1028db70bea988d1022e4d463de66581c696160', - - 'src/third_party/requests/src': - Var('chromium_git') + '/external/github.com/kennethreitz/requests.git' + '@' + 'f172b30356d821d180fa4ecfa3e71c7274a32de4', + Var('chromium_git') + '/chromium/src/third_party/freetype2.git' + '@' + 'e186230678ee8e4ea4ac4797ece8125761e3225a', }, } diff --git a/bar.patch b/bar.patch new file mode 100644 index 0000000000000..837a5b430744a --- /dev/null +++ b/bar.patch @@ -0,0 +1,32 @@ +commit 2f12ff08cc9215273040893a9b6c2b3fabccfb6b +Author: Adam Barth +Date: Thu Jul 16 18:00:01 2015 -0700 + + Cherry-pick build fix from Mojo + +diff --git a/services/android/rules.gni b/services/android/rules.gni +index 350b421..c2c286b 100644 +--- a/services/android/rules.gni ++++ b/services/android/rules.gni +@@ -44,6 +44,10 @@ template("mojo_android_java_application") { + action(android_with_manifest_name) { + script = "${servicess_android_path}/add_manifest_entry.py" + ++ deps = [ ++ ":$android_standalone_name" ++ ] ++ + input = dex_output_path + inputs = [ + input, +@@ -74,6 +78,10 @@ template("mojo_android_java_application") { + action(target_name) { + script = rebase_path("mojo/public/tools/prepend.py", ".", mojo_root) + ++ deps = [ ++ ":$android_with_manifest_name" ++ ] ++ + input = dex_with_manifest_output_path + inputs = [ + input, diff --git a/base/BUILD.gn b/base/BUILD.gn index fea9027e4b396..238a89a78fb3d 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn @@ -39,7 +39,7 @@ source_set("base_paths") { "base_paths_win.h", ] - if (is_android || is_mac) { + if (is_android || is_mac || is_ios) { sources -= [ "base_paths_posix.cc" ] } @@ -83,6 +83,7 @@ component("base") { "android/content_uri_utils.cc", "android/content_uri_utils.h", "android/cpu_features.cc", + "android/cxa_demangle_stub.cc", "android/event_log.cc", "android/event_log.h", "android/field_trial_list.cc", @@ -139,11 +140,8 @@ component("base") { "atomic_ref_count.h", "atomic_sequence_num.h", "atomicops.h", - "atomicops_internals_gcc.h", "atomicops_internals_mac.h", "atomicops_internals_portable.h", - "atomicops_internals_x86_gcc.cc", - "atomicops_internals_x86_gcc.h", "atomicops_internals_x86_msvc.h", "auto_reset.h", "barrier_closure.cc", @@ -177,6 +175,7 @@ component("base") { "containers/linked_list.h", "containers/mru_cache.h", "containers/scoped_ptr_hash_map.h", + "containers/scoped_ptr_map.h", "containers/small_map.h", "containers/stack_container.h", "cpu.cc", @@ -270,6 +269,9 @@ component("base") { "mac/bind_objc_block.h", "mac/bundle_locations.h", "mac/bundle_locations.mm", + "mac/call_with_eh_frame.cc", + "mac/call_with_eh_frame.h", + "mac/call_with_eh_frame_asm.S", "mac/cocoa_protocols.h", "mac/dispatch_source_mach.cc", "mac/dispatch_source_mach.h", @@ -320,10 +322,8 @@ component("base") { "message_loop/incoming_task_queue.h", "message_loop/message_loop.cc", "message_loop/message_loop.h", - "message_loop/message_loop_proxy.cc", - "message_loop/message_loop_proxy.h", - "message_loop/message_loop_proxy_impl.cc", - "message_loop/message_loop_proxy_impl.h", + "message_loop/message_loop_task_runner.cc", + "message_loop/message_loop_task_runner.h", "message_loop/message_pump.cc", "message_loop/message_pump.h", "message_loop/message_pump_android.cc", @@ -366,7 +366,6 @@ component("base") { "pending_task.h", "pickle.cc", "pickle.h", - "port.h", "posix/eintr_wrapper.h", "posix/file_descriptor_shuffle.cc", "posix/global_descriptors.cc", @@ -429,6 +428,8 @@ component("base") { "strings/latin1_string_conversions.h", "strings/nullable_string16.cc", "strings/nullable_string16.h", + "strings/pattern.cc", + "strings/pattern.h", "strings/safe_sprintf.cc", "strings/safe_sprintf.h", "strings/string16.cc", @@ -644,6 +645,8 @@ component("base") { "sys_info_openbsd.cc", ] + data = [] + configs += [ ":base_implementation" ] deps = [ @@ -748,6 +751,30 @@ component("base") { "sha1_win.cc", ] + # Required for base/stack_trace_win.cc to symbolize correctly. + data += [ "$root_build_dir/dbghelp.dll" ] + + if (is_component_build) { + # Copy the VS runtime DLLs into the isolate so that they don't have to be + # preinstalled on the target machine. The debug runtimes have a "d" at + # the end. + if (is_debug) { + vcrt_suffix = "d" + } else { + vcrt_suffix = "" + } + + # These runtime files are copied to the output directory by the + # vs_toolchain script that runs as part of toolchain configuration. + data += [ + "$root_out_dir/msvcp120${vcrt_suffix}.dll", + "$root_out_dir/msvcr120${vcrt_suffix}.dll", + ] + if (is_asan) { + data += [ "//third_party/llvm-build/Release+Asserts/lib/clang/3.7.0/lib/windows/clang_rt.asan_dynamic-i386.dll" ] + } + } + # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. configs += [ "//build/config/compiler:no_size_t_to_int_warning" ] @@ -764,12 +791,25 @@ component("base") { } # Mac. - if (is_mac) { + if (is_mac || is_ios) { + # Common Desktop / iOS excludes sources -= [ "native_library_posix.cc", "strings/sys_string_conversions_posix.cc", "threading/platform_thread_internal_posix.cc", ] + + if (is_asan) { + # TODO(GYP) hook up asan on Mac. GYP has this extra dylib: + #data += [ "$root_out_dir/libclang_rt.asan_osx_dynamic.dylib" ] + } + + if (is_ios) { + sources -= [ + "files/file_path_watcher_fsevents.cc", + "files/file_path_watcher_fsevents.h", + ] + } } else { # Non-Mac. sources -= [ @@ -782,6 +822,11 @@ component("base") { # Linux. if (is_linux) { + if (is_asan || is_lsan || is_msan || is_tsan) { + # For llvm-sanitizer. + data += [ "//third_party/llvm-build/Release+Asserts/lib/libstdc++.so.6" ] + } + # TODO(brettw) this will need to be parameterized at some point. linux_configs = [] if (use_glib) { @@ -814,6 +859,48 @@ component("base") { } } + # iOS + if (is_ios) { + set_sources_assignment_filter([]) + + sources += [ + "atomicops_internals_mac.h", + "base_paths_mac.h", + "base_paths_mac.mm", + "file_version_info_mac.h", + "file_version_info_mac.mm", + "files/file_util_mac.mm", + "mac/bundle_locations.h", + "mac/bundle_locations.mm", + "mac/call_with_eh_frame.cc", + "mac/call_with_eh_frame.h", + "mac/foundation_util.h", + "mac/foundation_util.mm", + "mac/mac_logging.cc", + "mac/mac_logging.h", + "mac/mach_logging.cc", + "mac/mach_logging.h", + "mac/objc_property_releaser.h", + "mac/objc_property_releaser.mm", + "mac/scoped_mach_port.cc", + "mac/scoped_mach_port.h", + "mac/scoped_mach_vm.cc", + "mac/scoped_mach_vm.h", + "mac/scoped_nsautorelease_pool.h", + "mac/scoped_nsautorelease_pool.mm", + "mac/scoped_nsobject.h", + "mac/scoped_objc_class_swizzler.h", + "mac/scoped_objc_class_swizzler.mm", + "message_loop/message_pump_mac.h", + "message_loop/message_pump_mac.mm", + "strings/sys_string_conversions_mac.mm", + "threading/platform_thread_mac.mm", + "time/time_mac.cc", + ] + + set_sources_assignment_filter(sources_assignment_filter) + } + if (!use_glib) { sources -= [ "message_loop/message_pump_glib.cc", @@ -821,8 +908,18 @@ component("base") { ] } + if (is_asan || is_lsan || is_msan || is_tsan) { + data += [ "//tools/valgrind/asan/" ] + if (is_win) { + data += + [ "//third_party/llvm-build/Release+Asserts/bin/llvm-symbolizer.exe" ] + } else { + data += [ "//third_party/llvm-build/Release+Asserts/bin/llvm-symbolizer" ] + } + } + configs += [ "//build/config/compiler:wexit_time_destructors" ] - if (is_android && !is_debug) { + if (!is_debug) { configs -= [ "//build/config/compiler:optimize" ] configs += [ "//build/config/compiler:optimize_max" ] } @@ -841,7 +938,7 @@ source_set("base_static") { "win/pe_image.h", ] - if (is_android && !is_debug) { + if (!is_debug) { configs -= [ "//build/config/compiler:optimize" ] configs += [ "//build/config/compiler:optimize_max" ] } @@ -894,7 +991,7 @@ component("i18n") { "//third_party/icu", ] - if (is_android && !is_debug) { + if (!is_debug) { configs -= [ "//build/config/compiler:optimize" ] configs += [ "//build/config/compiler:optimize_max" ] } @@ -1006,7 +1103,7 @@ component("prefs") { ":base", ] - if (is_android && !is_debug) { + if (!is_debug) { configs -= [ "//build/config/compiler:optimize" ] configs += [ "//build/config/compiler:optimize_max" ] } @@ -1067,6 +1164,15 @@ if (is_win) { } } +# TODO(GYP): Delete this after we've converted everything to GN. +# The _run targets exist only for compatibility w/ GYP. +group("base_unittests_run") { + testonly = true + deps = [ + ":base_unittests", + ] +} + test("base_unittests") { sources = [ "android/application_status_listener_unittest.cc", @@ -1100,6 +1206,7 @@ test("base_unittests") { "containers/linked_list_unittest.cc", "containers/mru_cache_unittest.cc", "containers/scoped_ptr_hash_map_unittest.cc", + "containers/scoped_ptr_map_unittest.cc", "containers/small_map_unittest.cc", "containers/stack_container_unittest.cc", "cpu_unittest.cc", @@ -1147,6 +1254,7 @@ test("base_unittests") { "lazy_instance_unittest.cc", "logging_unittest.cc", "mac/bind_objc_block_unittest.mm", + "mac/call_with_eh_frame_unittest.mm", "mac/dispatch_source_mach_unittest.cc", "mac/foundation_util_unittest.mm", "mac/libdispatch_task_runner_unittest.cc", @@ -1170,8 +1278,7 @@ test("base_unittests") { "memory/singleton_unittest.cc", "memory/weak_ptr_unittest.cc", "memory/weak_ptr_unittest.nc", - "message_loop/message_loop_proxy_impl_unittest.cc", - "message_loop/message_loop_proxy_unittest.cc", + "message_loop/message_loop_task_runner_unittest.cc", "message_loop/message_loop_unittest.cc", "message_loop/message_pump_glib_unittest.cc", "message_loop/message_pump_io_ios_unittest.cc", @@ -1223,6 +1330,7 @@ test("base_unittests") { "sha1_unittest.cc", "stl_util_unittest.cc", "strings/nullable_string16_unittest.cc", + "strings/pattern_unittest.cc", "strings/safe_sprintf_unittest.cc", "strings/string16_unittest.cc", "strings/string_number_conversions_unittest.cc", @@ -1318,9 +1426,6 @@ test("base_unittests") { data = [ "test/data/", - - # TODO(dpranke): Remove when icu declares this directly. - "$root_out_dir/icudtl.dat", ] # Allow more direct string conversions on platforms with native utf8 @@ -1334,14 +1439,15 @@ test("base_unittests") { ":base_java", ":base_java_unittest_support", ] + + # TODO(brettw) I think this should not be here, we should not be using + # isolate files. isolate_file = "base_unittests.isolate" } if (is_ios) { sources -= [ "process/memory_unittest.cc", - "process/memory_unittest_mac.h", - "process/memory_unittest_mac.mm", "process/process_unittest.cc", "process/process_util_unittest.cc", ] @@ -1389,6 +1495,15 @@ test("base_unittests") { # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. configs += [ "//build/config/compiler:no_size_t_to_int_warning" ] + + # Symbols for crashes when running tests on swarming. + if (symbol_level > 0) { + if (is_win) { + data += [ "$root_out_dir/base_unittests.exe.pdb" ] + } else if (is_mac) { + data += [ "$root_out_dir/base_unittests.dSYM/" ] + } + } } if (is_android) { diff --git a/base/OWNERS b/base/OWNERS index 9890491e471bc..bcaa81bb64d74 100644 --- a/base/OWNERS +++ b/base/OWNERS @@ -1,13 +1,9 @@ mark@chromium.org -darin@chromium.org thakis@chromium.org danakj@chromium.org rvargas@chromium.org thestig@chromium.org -# On extended leave. -willchan@chromium.org - # Chromium is a very mature project, most things that are generally useful are # already here, and that things not here aren't generally useful. # @@ -21,8 +17,9 @@ willchan@chromium.org # writing the stuff you want to log in a regular logging statement, even # if it makes your calling code longer. Just add it to your own code. -per-file *.isolate=csharp@chromium.org per-file *.isolate=maruel@chromium.org +per-file *.isolate=tandrii@chromium.org +per-file *.isolate=vadimsh@chromium.org per-file security_unittest.cc=jln@chromium.org # For Android-specific changes: diff --git a/base/allocator/BUILD.gn b/base/allocator/BUILD.gn index a07a356e5d85a..c42de1a01a389 100644 --- a/base/allocator/BUILD.gn +++ b/base/allocator/BUILD.gn @@ -63,6 +63,17 @@ if (use_allocator == "tcmalloc") { "$tcmalloc_dir/src/base/abort.cc", "$tcmalloc_dir/src/base/abort.h", "$tcmalloc_dir/src/base/arm_instruction_set_select.h", + "$tcmalloc_dir/src/base/atomicops-internals-arm-generic.h", + "$tcmalloc_dir/src/base/atomicops-internals-arm-v6plus.h", + "$tcmalloc_dir/src/base/atomicops-internals-linuxppc.h", + "$tcmalloc_dir/src/base/atomicops-internals-macosx.h", + "$tcmalloc_dir/src/base/atomicops-internals-windows.h", + "$tcmalloc_dir/src/base/atomicops-internals-x86.cc", + "$tcmalloc_dir/src/base/atomicops-internals-x86.h", + "$tcmalloc_dir/src/base/atomicops.h", + "$tcmalloc_dir/src/base/basictypes.h", + "$tcmalloc_dir/src/base/commandlineflags.h", + "$tcmalloc_dir/src/base/cycleclock.h", # We don't list dynamic_annotations.c since its copy is already # present in the dynamic_annotations target. diff --git a/base/android/build_info.cc b/base/android/build_info.cc index 4d3cd559edeb5..68824b4c97b59 100644 --- a/base/android/build_info.cc +++ b/base/android/build_info.cc @@ -60,6 +60,8 @@ BuildInfo::BuildInfo(JNIEnv* env) env, GetApplicationContext()))), build_type_(StrDupJString(Java_BuildInfo_getBuildType(env))), sdk_int_(Java_BuildInfo_getSdkInt(env)), + has_language_apk_splits_(Java_BuildInfo_hasLanguageApkSplits( + env, GetApplicationContext())), java_exception_info_(NULL) { } diff --git a/base/android/build_info.h b/base/android/build_info.h index 093b832fdf784..834c98dddf1c6 100644 --- a/base/android/build_info.h +++ b/base/android/build_info.h @@ -96,6 +96,10 @@ class BASE_EXPORT BuildInfo { return sdk_int_; } + int has_language_apk_splits() const { + return has_language_apk_splits_; + } + const char* java_exception_info() const { return java_exception_info_; } @@ -127,6 +131,7 @@ class BASE_EXPORT BuildInfo { const char* const package_name_; const char* const build_type_; const int sdk_int_; + const bool has_language_apk_splits_; // This is set via set_java_exception_info, not at constructor time. const char* java_exception_info_; diff --git a/base/android/cxa_demangle_stub.cc b/base/android/cxa_demangle_stub.cc new file mode 100644 index 0000000000000..b0d2b87c59364 --- /dev/null +++ b/base/android/cxa_demangle_stub.cc @@ -0,0 +1,19 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include + +// LLVM's demangler is large, and we have no need of it. Overriding it with +// our own stub version here stops a lot of code being pulled in from libc++. +// More here: +// https://llvm.org/svn/llvm-project/libcxxabi/trunk/src/cxa_demangle.cpp +extern "C" char* __cxa_demangle(const char* mangled_name, + char* buf, + size_t* n, + int* status) { + static const int kMemoryAllocFailure = -1; // LLVM's memory_alloc_failure. + if (status) + *status = kMemoryAllocFailure; + return nullptr; +} diff --git a/base/android/java/src/org/chromium/base/BaseChromiumApplication.java b/base/android/java/src/org/chromium/base/BaseChromiumApplication.java index d7c7b05ea58d8..8ec4afa6637fc 100644 --- a/base/android/java/src/org/chromium/base/BaseChromiumApplication.java +++ b/base/android/java/src/org/chromium/base/BaseChromiumApplication.java @@ -8,7 +8,6 @@ import android.app.Application; import android.content.Context; import android.os.Bundle; -import android.view.KeyEvent; import android.view.Window; import java.lang.reflect.InvocationHandler; @@ -38,9 +37,6 @@ public interface WindowFocusChangedListener { /** * Intercepts calls to an existing Window.Callback. Most invocations are passed on directly * to the composed Window.Callback but enables intercepting/manipulating others. - * - * This is used to relay window focus changes throughout the app and remedy a bug in the - * appcompat library. */ private class WindowCallbackProxy implements InvocationHandler { private final Window.Callback mCallback; @@ -57,9 +53,6 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwabl && args[0] instanceof Boolean) { onWindowFocusChanged((boolean) args[0]); return null; - } else if (method.getName().equals("dispatchKeyEvent") && args.length == 1 - && args[0] instanceof KeyEvent) { - return dispatchKeyEvent((KeyEvent) args[0]); } else { try { return method.invoke(mCallback, args); @@ -85,15 +78,6 @@ public void onWindowFocusChanged(boolean hasFocus) { listener.onWindowFocusChanged(mActivity, hasFocus); } } - - public boolean dispatchKeyEvent(KeyEvent event) { - // TODO(aurimas): remove this once AppCompatDelegateImpl no longer steals - // KEYCODE_MENU. (see b/20529185) - if (event.getKeyCode() == KeyEvent.KEYCODE_MENU && mActivity.dispatchKeyEvent(event)) { - return true; - } - return mCallback.dispatchKeyEvent(event); - } } @Override public void onCreate() { diff --git a/base/android/java/src/org/chromium/base/BuildInfo.java b/base/android/java/src/org/chromium/base/BuildInfo.java index 54f611d5092ea..c6d248d4a3c59 100644 --- a/base/android/java/src/org/chromium/base/BuildInfo.java +++ b/base/android/java/src/org/chromium/base/BuildInfo.java @@ -4,12 +4,14 @@ package org.chromium.base; +import android.annotation.TargetApi; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.os.Build; +import android.text.TextUtils; import android.util.Log; /** @@ -122,4 +124,35 @@ public static String getBuildType() { public static int getSdkInt() { return Build.VERSION.SDK_INT; } + + /** + * @return Whether the Android build is M or later. + */ + public static boolean isMncOrLater() { + // TODO(bauerb): Update this once the SDK is updated. + return Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1 + || TextUtils.equals("MNC", Build.VERSION.CODENAME); + } + + private static boolean isLanguageSplit(String splitName) { + // Names look like "config.XX". + return splitName.length() == 9 && splitName.startsWith("config."); + } + + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + @CalledByNative + public static boolean hasLanguageApkSplits(Context context) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { + return false; + } + PackageInfo packageInfo = PackageUtils.getOwnPackageInfo(context); + if (packageInfo.splitNames != null) { + for (int i = 0; i < packageInfo.splitNames.length; ++i) { + if (isLanguageSplit(packageInfo.splitNames[i])) { + return true; + } + } + } + return false; + } } diff --git a/base/android/java/src/org/chromium/base/CollectionUtil.java b/base/android/java/src/org/chromium/base/CollectionUtil.java index 4a4c7540a58cb..2672d654cb217 100644 --- a/base/android/java/src/org/chromium/base/CollectionUtil.java +++ b/base/android/java/src/org/chromium/base/CollectionUtil.java @@ -31,6 +31,7 @@ public static ArrayList newArrayList(E... elements) { return list; } + @VisibleForTesting public static ArrayList newArrayList(Iterable iterable) { ArrayList list = new ArrayList(); for (E element : iterable) { diff --git a/base/android/java/src/org/chromium/base/Log.java b/base/android/java/src/org/chromium/base/Log.java index c83cfe79b65fc..3b46cdcd65f61 100644 --- a/base/android/java/src/org/chromium/base/Log.java +++ b/base/android/java/src/org/chromium/base/Log.java @@ -4,9 +4,7 @@ package org.chromium.base; -import android.text.TextUtils; - -import org.chromium.base.annotations.NoSideEffects; +import org.chromium.base.annotations.RemovableInRelease; import java.util.Locale; @@ -62,27 +60,6 @@ private static String formatLogWithStack(String messageTemplate, Object... param return "[" + getCallOrigin() + "] " + formatLog(messageTemplate, params); } - /** - * Returns a full tag for the provided group tag. Full tags longer than 23 characters - * will cause a runtime exception. - * - * @param groupTag {@code null} and empty string are allowed. - * - * @see android.util.Log#isLoggable(String, int) - * @throws IllegalArgumentException if the tag is too long. - * @deprecated Directly use a string (e.g. "cr.Tag") in your class. See http://crbug.com/485772 - */ - @Deprecated - public static String makeTag(String groupTag) { - if (TextUtils.isEmpty(groupTag)) return "cr"; - String tag = "cr." + groupTag; - if (tag.length() > 23) { - throw new IllegalArgumentException( - "The full tag (" + tag + ") is longer than 23 characters."); - } - return tag; - } - /** Convenience function, forwards to {@link android.util.Log#isLoggable(String, int)}. */ public static boolean isLoggable(String tag, int level) { return android.util.Log.isLoggable(tag, level); @@ -93,7 +70,7 @@ public static boolean isLoggable(String tag, int level) { * * For optimization purposes, only the fixed parameters versions are visible. If you need more * than 7 parameters, consider building your log message using a function annotated with - * {@link NoSideEffects}. + * {@link RemovableInRelease}. * * @param tag Used to identify the source of a log message. * @param messageTemplate The message you would like logged. It is to be specified as a format @@ -102,7 +79,7 @@ public static boolean isLoggable(String tag, int level) { * one is a {@link Throwable}, its trace will be printed. */ private static void verbose(String tag, String messageTemplate, Object... args) { - if (android.util.Log.isLoggable(tag, android.util.Log.VERBOSE)) { + if (Log.isLoggable(tag, Log.VERBOSE)) { String message = formatLogWithStack(messageTemplate, args); Throwable tr = getThrowableToLog(args); if (tr != null) { @@ -113,46 +90,62 @@ private static void verbose(String tag, String messageTemplate, Object... args) } } - /** Sends a {@link android.util.Log#VERBOSE} log message. 0 arg version. */ + /** Sends a {@link android.util.Log#VERBOSE} log message. 0 args version. */ + @RemovableInRelease + @VisibleForTesting public static void v(String tag, String message) { verbose(tag, message); } /** Sends a {@link android.util.Log#VERBOSE} log message. 1 arg version. */ + @RemovableInRelease + @VisibleForTesting public static void v(String tag, String messageTemplate, Object arg1) { verbose(tag, messageTemplate, arg1); } /** Sends a {@link android.util.Log#VERBOSE} log message. 2 args version */ + @RemovableInRelease + @VisibleForTesting public static void v(String tag, String messageTemplate, Object arg1, Object arg2) { verbose(tag, messageTemplate, arg1, arg2); } /** Sends a {@link android.util.Log#VERBOSE} log message. 3 args version */ + @RemovableInRelease + @VisibleForTesting public static void v( String tag, String messageTemplate, Object arg1, Object arg2, Object arg3) { verbose(tag, messageTemplate, arg1, arg2, arg3); } /** Sends a {@link android.util.Log#VERBOSE} log message. 4 args version */ + @RemovableInRelease + @VisibleForTesting public static void v(String tag, String messageTemplate, Object arg1, Object arg2, Object arg3, Object arg4) { verbose(tag, messageTemplate, arg1, arg2, arg3, arg4); } /** Sends a {@link android.util.Log#VERBOSE} log message. 5 args version */ + @RemovableInRelease + @VisibleForTesting public static void v(String tag, String messageTemplate, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) { verbose(tag, messageTemplate, arg1, arg2, arg3, arg4, arg5); } /** Sends a {@link android.util.Log#VERBOSE} log message. 6 args version */ + @RemovableInRelease + @VisibleForTesting public static void v(String tag, String messageTemplate, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6) { verbose(tag, messageTemplate, arg1, arg2, arg3, arg4, arg5, arg6); } /** Sends a {@link android.util.Log#VERBOSE} log message. 7 args version */ + @RemovableInRelease + @VisibleForTesting public static void v(String tag, String messageTemplate, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7) { verbose(tag, messageTemplate, arg1, arg2, arg3, arg4, arg5, arg6, arg7); @@ -163,7 +156,7 @@ public static void v(String tag, String messageTemplate, Object arg1, Object arg * * For optimization purposes, only the fixed parameters versions are visible. If you need more * than 7 parameters, consider building your log message using a function annotated with - * {@link NoSideEffects}. + * {@link RemovableInRelease}. * * @param tag Used to identify the source of a log message. * @param messageTemplate The message you would like logged. It is to be specified as a format @@ -172,7 +165,7 @@ public static void v(String tag, String messageTemplate, Object arg1, Object arg * one is a {@link Throwable}, its trace will be printed. */ private static void debug(String tag, String messageTemplate, Object... args) { - if (android.util.Log.isLoggable(tag, android.util.Log.VERBOSE)) { + if (isLoggable(tag, Log.DEBUG)) { String message = formatLogWithStack(messageTemplate, args); Throwable tr = getThrowableToLog(args); if (tr != null) { @@ -183,44 +176,60 @@ private static void debug(String tag, String messageTemplate, Object... args) { } } - /** Sends a {@link android.util.Log#DEBUG} log message. 0 arg version. */ + /** Sends a {@link android.util.Log#DEBUG} log message. 0 args version. */ + @RemovableInRelease + @VisibleForTesting public static void d(String tag, String message) { debug(tag, message); } /** Sends a {@link android.util.Log#DEBUG} log message. 1 arg version. */ + @RemovableInRelease + @VisibleForTesting public static void d(String tag, String messageTemplate, Object arg1) { debug(tag, messageTemplate, arg1); } /** Sends a {@link android.util.Log#DEBUG} log message. 2 args version */ + @RemovableInRelease + @VisibleForTesting public static void d(String tag, String messageTemplate, Object arg1, Object arg2) { debug(tag, messageTemplate, arg1, arg2); } /** Sends a {@link android.util.Log#DEBUG} log message. 3 args version */ + @RemovableInRelease + @VisibleForTesting public static void d( String tag, String messageTemplate, Object arg1, Object arg2, Object arg3) { debug(tag, messageTemplate, arg1, arg2, arg3); } /** Sends a {@link android.util.Log#DEBUG} log message. 4 args version */ + @RemovableInRelease + @VisibleForTesting public static void d(String tag, String messageTemplate, Object arg1, Object arg2, Object arg3, Object arg4) { debug(tag, messageTemplate, arg1, arg2, arg3, arg4); } /** Sends a {@link android.util.Log#DEBUG} log message. 5 args version */ + @RemovableInRelease + @VisibleForTesting public static void d(String tag, String messageTemplate, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) { debug(tag, messageTemplate, arg1, arg2, arg3, arg4, arg5); } /** Sends a {@link android.util.Log#DEBUG} log message. 6 args version */ + @RemovableInRelease + @VisibleForTesting public static void d(String tag, String messageTemplate, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6) { debug(tag, messageTemplate, arg1, arg2, arg3, arg4, arg5, arg6); } /** Sends a {@link android.util.Log#DEBUG} log message. 7 args version */ + @RemovableInRelease + @VisibleForTesting public static void d(String tag, String messageTemplate, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7) { debug(tag, messageTemplate, arg1, arg2, arg3, arg4, arg5, arg6, arg7); @@ -235,8 +244,9 @@ public static void d(String tag, String messageTemplate, Object arg1, Object arg * @param args Arguments referenced by the format specifiers in the format string. If the last * one is a {@link Throwable}, its trace will be printed. */ + @VisibleForTesting public static void i(String tag, String messageTemplate, Object... args) { - if (android.util.Log.isLoggable(tag, android.util.Log.INFO)) { + if (Log.isLoggable(tag, Log.INFO)) { String message = formatLog(messageTemplate, args); Throwable tr = getThrowableToLog(args); if (tr != null) { @@ -256,8 +266,9 @@ public static void i(String tag, String messageTemplate, Object... args) { * @param args Arguments referenced by the format specifiers in the format string. If the last * one is a {@link Throwable}, its trace will be printed. */ + @VisibleForTesting public static void w(String tag, String messageTemplate, Object... args) { - if (android.util.Log.isLoggable(tag, android.util.Log.WARN)) { + if (Log.isLoggable(tag, Log.WARN)) { String message = formatLog(messageTemplate, args); Throwable tr = getThrowableToLog(args); if (tr != null) { @@ -277,8 +288,9 @@ public static void w(String tag, String messageTemplate, Object... args) { * @param args Arguments referenced by the format specifiers in the format string. If the last * one is a {@link Throwable}, its trace will be printed. */ + @VisibleForTesting public static void e(String tag, String messageTemplate, Object... args) { - if (android.util.Log.isLoggable(tag, android.util.Log.ERROR)) { + if (Log.isLoggable(tag, Log.ERROR)) { String message = formatLog(messageTemplate, args); Throwable tr = getThrowableToLog(args); if (tr != null) { @@ -302,8 +314,9 @@ public static void e(String tag, String messageTemplate, Object... args) { * @param args Arguments referenced by the format specifiers in the format string. If the last * one is a {@link Throwable}, its trace will be printed. */ + @VisibleForTesting public static void wtf(String tag, String messageTemplate, Object... args) { - if (android.util.Log.isLoggable(tag, android.util.Log.ERROR)) { + if (Log.isLoggable(tag, Log.ASSERT)) { String message = formatLog(messageTemplate, args); Throwable tr = getThrowableToLog(args); if (tr != null) { diff --git a/base/android/java/src/org/chromium/base/MemoryPressureListener.java b/base/android/java/src/org/chromium/base/MemoryPressureListener.java index e7c2030a8f777..7979287b4d62e 100644 --- a/base/android/java/src/org/chromium/base/MemoryPressureListener.java +++ b/base/android/java/src/org/chromium/base/MemoryPressureListener.java @@ -72,10 +72,10 @@ public static boolean handleDebugIntent(Activity activity, String action) { } else if (ACTION_TRIM_MEMORY.equals(action)) { simulateTrimMemoryPressureSignal(activity, ComponentCallbacks2.TRIM_MEMORY_COMPLETE); } else if (ACTION_TRIM_MEMORY_RUNNING_CRITICAL.equals(action)) { - simulateTrimMemoryPressureSignal(activity, ComponentCallbacks2.TRIM_MEMORY_MODERATE); - } else if (ACTION_TRIM_MEMORY_MODERATE.equals(action)) { simulateTrimMemoryPressureSignal(activity, ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL); + } else if (ACTION_TRIM_MEMORY_MODERATE.equals(action)) { + simulateTrimMemoryPressureSignal(activity, ComponentCallbacks2.TRIM_MEMORY_MODERATE); } else { return false; } diff --git a/base/android/java/src/org/chromium/base/PathUtils.java b/base/android/java/src/org/chromium/base/PathUtils.java index e46fc300e8409..77affe1054137 100644 --- a/base/android/java/src/org/chromium/base/PathUtils.java +++ b/base/android/java/src/org/chromium/base/PathUtils.java @@ -9,12 +9,14 @@ import android.os.AsyncTask; import android.os.Environment; +import java.io.File; import java.util.concurrent.ExecutionException; /** * This class provides the path related methods for the native library. */ public abstract class PathUtils { + private static final String THUMBNAIL_DIRECTORY = "textures"; private static final int DATA_DIRECTORY = 0; private static final int DATABASE_DIRECTORY = 1; @@ -22,6 +24,8 @@ public abstract class PathUtils { private static final int NUM_DIRECTORIES = 3; private static AsyncTask sDirPathFetchTask; + private static File sThumbnailDirectory; + // Prevent instantiation. private PathUtils() {} @@ -91,6 +95,18 @@ public static String getCacheDirectory(Context appContext) { return getDirectoryPath(CACHE_DIRECTORY); } + public static File getThumbnailCacheDirectory(Context appContext) { + if (sThumbnailDirectory == null) { + sThumbnailDirectory = appContext.getDir(THUMBNAIL_DIRECTORY, Context.MODE_PRIVATE); + } + return sThumbnailDirectory; + } + + @CalledByNative + public static String getThumbnailCacheDirectoryPath(Context appContext) { + return getThumbnailCacheDirectory(appContext).getAbsolutePath(); + } + /** * @return the public downloads directory. */ diff --git a/base/android/java/src/org/chromium/base/README_logging.md b/base/android/java/src/org/chromium/base/README_logging.md index a795b6b69aa80..6104bf0e63656 100644 --- a/base/android/java/src/org/chromium/base/README_logging.md +++ b/base/android/java/src/org/chromium/base/README_logging.md @@ -43,6 +43,20 @@ throws a RuntimeException. Level here is either `VERBOSE`, `DEBUG`, `INFO`, `WARN`, `ERROR`, `ASSERT`, or `SUPPRESS` By default, the level for all tags is `INFO`. +### An exception trace is printed when the exception is the last parameter ### + +As with `java.util.Log`, putting a throwable as last parameter will dump the corresponding stack +trace: + + Log.i(TAG, "An error happened: %s", e) + + I/cr.YourModuleTag: ( 999): An error happened: This is the exception's message + I/cr.YourModuleTag: ( 999): java.lang.Exception: This is the exception's message + I/cr.YourModuleTag: ( 999): at foo.bar.MyClass.test(MyClass.java:42) + I/cr.YourModuleTag: ( 999): ... + +Having the exception as last parameter doesn't prevent it from being used for string formatting. + ### Logging Best Practices #### Rule #1: Never log PII (Personal Identification Information): @@ -111,7 +125,7 @@ complementary ways: while the previous method can enable or disable debugging for a whole feature without changing any source file. -- Annotate debug functions with the `@NoSideEffects` annotation. +- Annotate debug functions with the `@RemovableInRelease` annotation. That annotation tells Proguard to assume that a given function has no side effects, and is called only for its returned value. If this value is unused, the call will be removed. If the @@ -121,7 +135,7 @@ complementary ways: /* If that function is only used in Log.d calls, proguard should completely remove it from * the release builds. */ - @NoSideEffects + @RemovableInRelease private static String getSomeDebugLogString(Thing[] things) { /* Still needs to be guarded to avoid impacting debug builds, or in case it's used for * some other log levels. But at least it is done only once, inside the function. */ diff --git a/base/android/java/src/org/chromium/base/ResourceExtractor.java b/base/android/java/src/org/chromium/base/ResourceExtractor.java index d44f2fc7c22bd..e0a0e17634def 100644 --- a/base/android/java/src/org/chromium/base/ResourceExtractor.java +++ b/base/android/java/src/org/chromium/base/ResourceExtractor.java @@ -6,18 +6,17 @@ import android.annotation.TargetApi; import android.content.Context; -import android.content.SharedPreferences; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; -import android.content.res.AssetManager; import android.os.AsyncTask; import android.os.Build; import android.os.Handler; import android.os.Looper; import android.os.Trace; -import android.preference.PreferenceManager; import android.util.Log; +import org.chromium.base.annotations.SuppressFBWarnings; + import java.io.File; import java.io.FileOutputStream; import java.io.FilenameFilter; @@ -28,7 +27,6 @@ import java.util.List; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; -import java.util.regex.Pattern; /** * Handles extracting the necessary resources bundled in an APK and moving them to a location on @@ -37,23 +35,25 @@ public class ResourceExtractor { private static final String LOGTAG = "ResourceExtractor"; - private static final String LAST_LANGUAGE = "Last language"; - private static final String PAK_FILENAMES_LEGACY_NOREUSE = "Pak filenames"; private static final String ICU_DATA_FILENAME = "icudtl.dat"; private static final String V8_NATIVES_DATA_FILENAME = "natives_blob.bin"; private static final String V8_SNAPSHOT_DATA_FILENAME = "snapshot_blob.bin"; - private static String[] sMandatoryPaks = null; - - // By default, we attempt to extract a pak file for the users - // current device locale. Use setExtractImplicitLocale() to - // change this behavior. - private static boolean sExtractImplicitLocalePak = true; + private static ResourceEntry[] sResourcesToExtract = new ResourceEntry[0]; - private static boolean isAppDataFile(String file) { - return ICU_DATA_FILENAME.equals(file) - || V8_NATIVES_DATA_FILENAME.equals(file) - || V8_SNAPSHOT_DATA_FILENAME.equals(file); + /** + * Holds information about a res/raw file (e.g. locale .pak files). + */ + public static final class ResourceEntry { + public final int resourceId; + public final String pathWithinApk; + public final String extractedFileName; + + public ResourceEntry(int resourceId, String pathWithinApk, String extractedFileName) { + this.resourceId = resourceId; + this.pathWithinApk = pathWithinApk; + this.extractedFileName = extractedFileName; + } } private class ExtractTask extends AsyncTask { @@ -61,12 +61,38 @@ private class ExtractTask extends AsyncTask { private final List mCompletionCallbacks = new ArrayList(); - public ExtractTask() { + private void extractResourceHelper(InputStream is, File outFile, byte[] buffer) + throws IOException { + OutputStream os = null; + try { + os = new FileOutputStream(outFile); + Log.i(LOGTAG, "Extracting resource " + outFile); + + int count = 0; + while ((count = is.read(buffer, 0, BUFFER_SIZE)) != -1) { + os.write(buffer, 0, count); + } + os.flush(); + + // Ensure something reasonable was written. + if (outFile.length() == 0) { + throw new IOException(outFile + " extracted with 0 length!"); + } + } finally { + try { + if (is != null) { + is.close(); + } + } finally { + if (os != null) { + os.close(); + } + } + } } private void doInBackgroundImpl() { final File outputDir = getOutputDir(); - final File appDataDir = getAppDataDir(); if (!outputDir.exists() && !outputDir.mkdirs()) { Log.e(LOGTAG, "Unable to create pak resources directory!"); return; @@ -83,97 +109,22 @@ private void doInBackgroundImpl() { deleteFiles(); } - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext); - String currentLocale = LocaleUtils.getDefaultLocale(); - String currentLanguage = currentLocale.split("-", 2)[0]; - // If everything we need is already there (and the locale hasn't - // changed), quick exit. - if (prefs.getString(LAST_LANGUAGE, "").equals(currentLanguage)) { - boolean filesPresent = true; - for (String file : sMandatoryPaks) { - File directory = isAppDataFile(file) ? appDataDir : outputDir; - if (!new File(directory, file).exists()) { - filesPresent = false; - break; - } - } - if (filesPresent) return; - } else { - prefs.edit().putString(LAST_LANGUAGE, currentLanguage).apply(); - } - - StringBuilder p = new StringBuilder(); - for (String mandatoryPak : sMandatoryPaks) { - if (p.length() > 0) p.append('|'); - p.append("\\Q" + mandatoryPak + "\\E"); - } - - if (sExtractImplicitLocalePak) { - if (p.length() > 0) p.append('|'); - // As well as the minimum required set of .paks above, we'll - // also add all .paks that we have for the user's currently - // selected language. - p.append(currentLanguage); - p.append("(-\\w+)?\\.pak"); - } - - Pattern paksToInstall = Pattern.compile(p.toString()); - - AssetManager manager = mContext.getResources().getAssets(); beginTraceSection("WalkAssets"); + byte[] buffer = new byte[BUFFER_SIZE]; try { - // Loop through every asset file that we have in the APK, and look for the - // ones that we need to extract by trying to match the Patterns that we - // created above. - byte[] buffer = null; - String[] files = manager.list(""); - for (String file : files) { - if (!paksToInstall.matcher(file).matches()) { - continue; - } - File output = new File(isAppDataFile(file) ? appDataDir : outputDir, file); + // Extract all files that don't already exist. + for (ResourceEntry entry : sResourcesToExtract) { + File output = new File(outputDir, entry.extractedFileName); if (output.exists()) { continue; } - - InputStream is = null; - OutputStream os = null; beginTraceSection("ExtractResource"); + InputStream inputStream = mContext.getResources().openRawResource( + entry.resourceId); try { - is = manager.open(file); - os = new FileOutputStream(output); - Log.i(LOGTAG, "Extracting resource " + file); - if (buffer == null) { - buffer = new byte[BUFFER_SIZE]; - } - - int count = 0; - while ((count = is.read(buffer, 0, BUFFER_SIZE)) != -1) { - os.write(buffer, 0, count); - } - os.flush(); - - // Ensure something reasonable was written. - if (output.length() == 0) { - throw new IOException(file + " extracted with 0 length!"); - } - - if (isAppDataFile(file)) { - // icu and V8 data need to be accessed by a renderer - // process. - output.setReadable(true, false); - } + extractResourceHelper(inputStream, output, buffer); } finally { - try { - if (is != null) { - is.close(); - } - } finally { - if (os != null) { - os.close(); - } - endTraceSection(); // ExtractResource - } + endTraceSection(); // ExtractResource } } } catch (IOException e) { @@ -303,53 +254,19 @@ public static ResourceExtractor get(Context context) { } /** - * Specifies the .pak files that should be extracted from the APK's asset resources directory - * and moved to {@link #getOutputDirFromContext(Context)}. - * @param mandatoryPaks The list of pak files to be loaded. If no pak files are - * required, pass a single empty string. - */ - public static void setMandatoryPaksToExtract(String... mandatoryPaks) { - assert (sInstance == null || sInstance.mExtractTask == null) - : "Must be called before startExtractingResources is called"; - sMandatoryPaks = mandatoryPaks; - - } - - /** - * By default the ResourceExtractor will attempt to extract a pak resource for the users - * currently specified locale. This behavior can be changed with this function and is - * only needed by tests. - * @param extract False if we should not attempt to extract a pak file for - * the users currently selected locale and try to extract only the - * pak files specified in sMandatoryPaks. + * Specifies the files that should be extracted from the APK. + * and moved to {@link #getOutputDir()}. */ - @VisibleForTesting - public static void setExtractImplicitLocaleForTesting(boolean extract) { + @SuppressFBWarnings("EI_EXPOSE_STATIC_REP2") + public static void setResourcesToExtract(ResourceEntry[] entries) { assert (sInstance == null || sInstance.mExtractTask == null) : "Must be called before startExtractingResources is called"; - sExtractImplicitLocalePak = extract; + sResourcesToExtract = entries; } - /** - * Marks all the 'pak' resources, packaged as assets, for extraction during - * running the tests. - */ - @VisibleForTesting - public void setExtractAllPaksAndV8SnapshotForTesting() { - List pakAndSnapshotFileAssets = new ArrayList(); - AssetManager manager = mContext.getResources().getAssets(); - try { - String[] files = manager.list(""); - for (String file : files) { - if (file.endsWith(".pak")) pakAndSnapshotFileAssets.add(file); - } - } catch (IOException e) { - Log.w(LOGTAG, "Exception while accessing assets: " + e.getMessage(), e); - } - pakAndSnapshotFileAssets.add("natives_blob.bin"); - pakAndSnapshotFileAssets.add("snapshot_blob.bin"); - setMandatoryPaksToExtract(pakAndSnapshotFileAssets.toArray( - new String[pakAndSnapshotFileAssets.size()])); + // TODO(agrieve): Delete this method ones all usages of it are updated. + public static void setMandatoryPaksToExtract(String... paths) { + assert paths.length == 1 && "".equals(paths[0]); } private ResourceExtractor(Context context) { @@ -421,6 +338,10 @@ public void startExtractingResources() { return; } + // If a previous release extracted resources, and the current release does not, + // deleteFiles() will not run and some files will be left. This currently + // can happen for ContentShell, but not for Chrome proper, since we always extract + // locale pak files. if (shouldSkipPakExtraction()) { return; } @@ -473,12 +394,9 @@ private void deleteFiles() { } /** - * Pak extraction not necessarily required by the embedder; we allow them to skip - * this process if they call setMandatoryPaksToExtract with a single empty String. + * Pak extraction not necessarily required by the embedder. */ private static boolean shouldSkipPakExtraction() { - // Must call setMandatoryPaksToExtract before beginning resource extraction. - assert sMandatoryPaks != null; - return sMandatoryPaks.length == 1 && "".equals(sMandatoryPaks[0]); + return sResourcesToExtract.length == 0; } } diff --git a/base/android/java/src/org/chromium/base/StreamUtil.java b/base/android/java/src/org/chromium/base/StreamUtil.java new file mode 100644 index 0000000000000..f8cbfeeb9ede2 --- /dev/null +++ b/base/android/java/src/org/chromium/base/StreamUtil.java @@ -0,0 +1,28 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.base; + +import java.io.Closeable; +import java.io.IOException; + +/** + * Helper methods to deal with stream related tasks. + */ +public class StreamUtil { + /** + * Handle closing a {@link java.io.Closeable} via {@link java.io.Closeable#close()} and catch + * the potentially thrown {@link java.io.IOException}. + * @param closeable The Closeable to be closed. + */ + public static void closeQuietly(Closeable closeable) { + if (closeable == null) return; + + try { + closeable.close(); + } catch (IOException ex) { + // Ignore the exception on close. + } + } +} diff --git a/base/android/java/src/org/chromium/base/ThreadUtils.java b/base/android/java/src/org/chromium/base/ThreadUtils.java index c0b91721bd45f..647e33e684215 100644 --- a/base/android/java/src/org/chromium/base/ThreadUtils.java +++ b/base/android/java/src/org/chromium/base/ThreadUtils.java @@ -29,6 +29,7 @@ public static void setWillOverrideUiThread() { } } + @VisibleForTesting public static void setUiThread(Looper looper) { synchronized (sLock) { if (sUiThreadHandler != null && sUiThreadHandler.getLooper() != looper) { diff --git a/base/android/java/src/org/chromium/base/TraceEvent.java b/base/android/java/src/org/chromium/base/TraceEvent.java index 3d3b11a04196c..9ace4a17de518 100644 --- a/base/android/java/src/org/chromium/base/TraceEvent.java +++ b/base/android/java/src/org/chromium/base/TraceEvent.java @@ -20,6 +20,7 @@ public class TraceEvent { private static volatile boolean sEnabled = false; + private static volatile boolean sATraceEnabled = false; // True when taking an Android systrace. private static class BasicLooperMonitor implements Printer { @Override @@ -176,6 +177,8 @@ public static void registerNativeEnabledObserver() { @CalledByNative public static void setEnabled(boolean enabled) { sEnabled = enabled; + // Android M+ systrace logs this on its own. Only log it if not writing to Android systrace. + if (sATraceEnabled) return; ThreadUtils.getUiThreadLooper().setMessageLogging( enabled ? LooperMonitorHolder.sInstance : null); } @@ -186,10 +189,15 @@ public static void setEnabled(boolean enabled) { * systrace, this is for WebView only. */ public static void setATraceEnabled(boolean enabled) { - if (sEnabled == enabled) return; + if (sATraceEnabled == enabled) return; + sATraceEnabled = enabled; if (enabled) { + // Calls TraceEvent.setEnabled(true) via + // TraceLog::EnabledStateObserver::OnTraceLogEnabled nativeStartATrace(); } else { + // Calls TraceEvent.setEnabled(false) via + // TraceLog::EnabledStateObserver::OnTraceLogDisabled nativeStopATrace(); } } diff --git a/base/android/java/src/org/chromium/base/annotations/NoSideEffects.java b/base/android/java/src/org/chromium/base/annotations/NoSideEffects.java deleted file mode 100644 index 803c3f959638f..0000000000000 --- a/base/android/java/src/org/chromium/base/annotations/NoSideEffects.java +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.base.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Target; - -/** - * Annotation used to indicate to proguard methods that have no side effects and can be - * safely removed if their return value is not used. This is to be used with - * {@link org.chromium.base.Log}'s method, that can also be removed by proguard. That way - * expensive calls can be left in debug builds but removed in release. - */ -@Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) -public @interface NoSideEffects {} diff --git a/base/android/java/src/org/chromium/base/annotations/RemovableInRelease.java b/base/android/java/src/org/chromium/base/annotations/RemovableInRelease.java new file mode 100644 index 0000000000000..2191334a4dfa4 --- /dev/null +++ b/base/android/java/src/org/chromium/base/annotations/RemovableInRelease.java @@ -0,0 +1,18 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.base.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; + +/** + * The annotated function can be removed in release builds. + * + * Calls to this function will be removed if its return value is not used. If all calls are removed, + * the function definition itself will be candidate for removal. + * It works by indicating to Proguard that the function has no side effects. + */ +@Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) +public @interface RemovableInRelease {} diff --git a/base/android/java/src/org/chromium/base/library_loader/LegacyLinker.java b/base/android/java/src/org/chromium/base/library_loader/LegacyLinker.java new file mode 100644 index 0000000000000..a3a5e16d8ee0b --- /dev/null +++ b/base/android/java/src/org/chromium/base/library_loader/LegacyLinker.java @@ -0,0 +1,755 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.base.library_loader; + +import android.os.Bundle; +import android.os.Parcel; + +import org.chromium.base.CalledByNative; +import org.chromium.base.Log; +import org.chromium.base.SysUtils; +import org.chromium.base.ThreadUtils; + +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +import javax.annotation.Nullable; + +/* + * For more, see Technical note, Security considerations, and the explanation + * of how this class is supposed to be used in Linker.java. + */ + +/** + * Provides a concrete implementation of the Chromium Linker. + * + * This Linker implementation uses the crazy linker to map and then run Chrome + * for Android. + * + * For more on the operations performed by the Linker, see {@link Linker}. + */ +class LegacyLinker extends Linker { + // Log tag for this class. + private static final String TAG = "cr.library_loader"; + + // Name of the library that contains our JNI code. + private static final String LINKER_JNI_LIBRARY = "chromium_android_linker"; + + // Becomes true after linker initialization. + private boolean mInitialized = false; + + // Set to true to indicate that the system supports safe sharing of RELRO sections. + private boolean mRelroSharingSupported = false; + + // Set to true if this runs in the browser process. Disabled by initServiceProcess(). + // TODO(petrcermak): This flag can be incorrectly set to false (even though this might run in + // the browser process) on low-memory devices. + private boolean mInBrowserProcess = true; + + // Becomes true to indicate this process needs to wait for a shared RELRO in + // finishLibraryLoad(). + private boolean mWaitForSharedRelros = false; + + // Becomes true when initialization determines that the browser process can use the + // shared RELRO. + private boolean mBrowserUsesSharedRelro = false; + + // The map of all RELRO sections either created or used in this process. + private Bundle mSharedRelros = null; + + // Current common random base load address. + private long mBaseLoadAddress = 0; + + // Current fixed-location load address for the next library called by loadLibrary(). + private long mCurrentLoadAddress = 0; + + // Becomes true once prepareLibraryLoad() has been called. + private boolean mPrepareLibraryLoadCalled = false; + + // The map of libraries that are currently loaded in this process. + protected HashMap mLoadedLibraries = null; + + // Used internally to initialize the linker's static data. Assume lock is held. + private void ensureInitializedLocked() { + assert Thread.holdsLock(mLock); + + if (mInitialized) { + return; + } + + mRelroSharingSupported = false; + if (NativeLibraries.sUseLinker) { + if (DEBUG) { + Log.i(TAG, "Loading lib" + LINKER_JNI_LIBRARY + ".so"); + } + try { + System.loadLibrary(LINKER_JNI_LIBRARY); + } catch (UnsatisfiedLinkError e) { + // In a component build, the ".cr" suffix is added to each library name. + Log.w(TAG, "Couldn't load lib" + LINKER_JNI_LIBRARY + ".so, " + + "trying lib" + LINKER_JNI_LIBRARY + ".cr.so"); + System.loadLibrary(LINKER_JNI_LIBRARY + ".cr"); + } + mRelroSharingSupported = nativeCanUseSharedRelro(); + if (!mRelroSharingSupported) { + Log.w(TAG, "This system cannot safely share RELRO sections"); + } else { + if (DEBUG) { + Log.i(TAG, "This system supports safe shared RELRO sections"); + } + } + + if (mMemoryDeviceConfig == MEMORY_DEVICE_CONFIG_INIT) { + if (SysUtils.isLowEndDevice()) { + mMemoryDeviceConfig = MEMORY_DEVICE_CONFIG_LOW; + } else { + mMemoryDeviceConfig = MEMORY_DEVICE_CONFIG_NORMAL; + } + } + + switch (BROWSER_SHARED_RELRO_CONFIG) { + case BROWSER_SHARED_RELRO_CONFIG_NEVER: + mBrowserUsesSharedRelro = false; + break; + case BROWSER_SHARED_RELRO_CONFIG_LOW_RAM_ONLY: + if (mMemoryDeviceConfig == MEMORY_DEVICE_CONFIG_LOW) { + mBrowserUsesSharedRelro = true; + Log.w(TAG, "Low-memory device: shared RELROs used in all processes"); + } else { + mBrowserUsesSharedRelro = false; + } + break; + case BROWSER_SHARED_RELRO_CONFIG_ALWAYS: + Log.w(TAG, "Beware: shared RELROs used in all processes!"); + mBrowserUsesSharedRelro = true; + break; + default: + assert false : "Unreached"; + break; + } + } else { + if (DEBUG) { + Log.i(TAG, "Linker disabled"); + } + } + + if (!mRelroSharingSupported) { + // Sanity. + mBrowserUsesSharedRelro = false; + mWaitForSharedRelros = false; + } + + mInitialized = true; + } + + /** + * Call this method to determine if this chromium project must + * use this linker. If not, System.loadLibrary() should be used to load + * libraries instead. + */ + @Override + public boolean isUsed() { + // Only GYP targets that are APKs and have the 'use_chromium_linker' variable + // defined as 1 will use this linker. For all others (the default), the + // auto-generated NativeLibraries.sUseLinker variable will be false. + if (!NativeLibraries.sUseLinker) return false; + + synchronized (mLock) { + ensureInitializedLocked(); + // At the moment, there is also no point in using this linker if the + // system does not support RELRO sharing safely. + return mRelroSharingSupported; + } + } + + /** + * Call this method to determine if the linker will try to use shared RELROs + * for the browser process. + */ + @Override + public boolean isUsingBrowserSharedRelros() { + synchronized (mLock) { + ensureInitializedLocked(); + return mBrowserUsesSharedRelro; + } + } + + /** + * Call this method to determine if the chromium project must load + * the library directly from the zip file. + */ + @Override + public boolean isInZipFile() { + return NativeLibraries.sUseLibraryInZipFile; + } + + /** + * Call this method just before loading any native shared libraries in this process. + */ + @Override + public void prepareLibraryLoad() { + if (DEBUG) { + Log.i(TAG, "prepareLibraryLoad() called"); + } + synchronized (mLock) { + mPrepareLibraryLoadCalled = true; + + if (mInBrowserProcess) { + // Force generation of random base load address, as well + // as creation of shared RELRO sections in this process. + setupBaseLoadAddressLocked(); + } + } + } + + /** + * Call this method just after loading all native shared libraries in this process. + * Note that when in a service process, this will block until the RELRO bundle is + * received, i.e. when another thread calls useSharedRelros(). + */ + @Override + public void finishLibraryLoad() { + if (DEBUG) { + Log.i(TAG, "finishLibraryLoad() called"); + } + synchronized (mLock) { + if (DEBUG) { + Log.i(TAG, String.format( + Locale.US, + "mInBrowserProcess=%s mBrowserUsesSharedRelro=%s mWaitForSharedRelros=%s", + mInBrowserProcess ? "true" : "false", + mBrowserUsesSharedRelro ? "true" : "false", + mWaitForSharedRelros ? "true" : "false")); + } + + if (mLoadedLibraries == null) { + if (DEBUG) { + Log.i(TAG, "No libraries loaded"); + } + } else { + if (mInBrowserProcess) { + // Create new Bundle containing RELRO section information + // for all loaded libraries. Make it available to getSharedRelros(). + mSharedRelros = createBundleFromLibInfoMap(mLoadedLibraries); + if (DEBUG) { + Log.i(TAG, "Shared RELRO created"); + dumpBundle(mSharedRelros); + } + + if (mBrowserUsesSharedRelro) { + useSharedRelrosLocked(mSharedRelros); + } + } + + if (mWaitForSharedRelros) { + assert !mInBrowserProcess; + + // Wait until the shared relro bundle is received from useSharedRelros(). + while (mSharedRelros == null) { + try { + mLock.wait(); + } catch (InterruptedException ie) { + // no-op + } + } + useSharedRelrosLocked(mSharedRelros); + // Clear the Bundle to ensure its file descriptor references can't be reused. + mSharedRelros.clear(); + mSharedRelros = null; + } + } + + if (NativeLibraries.sEnableLinkerTests && mTestRunnerClassName != null) { + // The TestRunner implementation must be instantiated _after_ + // all libraries are loaded to ensure that its native methods + // are properly registered. + if (DEBUG) { + Log.i(TAG, "Instantiating " + mTestRunnerClassName); + } + TestRunner testRunner = null; + try { + testRunner = (TestRunner) + Class.forName(mTestRunnerClassName).newInstance(); + } catch (Exception e) { + Log.e(TAG, "Could not extract test runner class name", e); + testRunner = null; + } + if (testRunner != null) { + if (!testRunner.runChecks(mMemoryDeviceConfig, mInBrowserProcess)) { + Log.wtf(TAG, "Linker runtime tests failed in this process!!"); + assert false; + } else { + Log.i(TAG, "All linker tests passed!"); + } + } + } + } + if (DEBUG) { + Log.i(TAG, "finishLibraryLoad() exiting"); + } + } + + /** + * Call this to send a Bundle containing the shared RELRO sections to be + * used in this process. If initServiceProcess() was previously called, + * finishLibraryLoad() will not exit until this method is called in another + * thread with a non-null value. + * @param bundle The Bundle instance containing a map of shared RELRO sections + * to use in this process. + */ + @Override + public void useSharedRelros(Bundle bundle) { + // Ensure the bundle uses the application's class loader, not the framework + // one which doesn't know anything about LibInfo. + // Also, hold a fresh copy of it so the caller can't recycle it. + Bundle clonedBundle = null; + if (bundle != null) { + bundle.setClassLoader(LibInfo.class.getClassLoader()); + clonedBundle = new Bundle(LibInfo.class.getClassLoader()); + Parcel parcel = Parcel.obtain(); + bundle.writeToParcel(parcel, 0); + parcel.setDataPosition(0); + clonedBundle.readFromParcel(parcel); + parcel.recycle(); + } + if (DEBUG) { + Log.i(TAG, "useSharedRelros() called with " + bundle + + ", cloned " + clonedBundle); + } + synchronized (mLock) { + // Note that in certain cases, this can be called before + // initServiceProcess() in service processes. + mSharedRelros = clonedBundle; + // Tell any listener blocked in finishLibraryLoad() about it. + mLock.notifyAll(); + } + } + + /** + * Call this to retrieve the shared RELRO sections created in this process, + * after loading all libraries. + * @return a new Bundle instance, or null if RELRO sharing is disabled on + * this system, or if initServiceProcess() was called previously. + */ + @Override + public Bundle getSharedRelros() { + if (DEBUG) { + Log.i(TAG, "getSharedRelros() called"); + } + synchronized (mLock) { + if (!mInBrowserProcess) { + if (DEBUG) { + Log.i(TAG, "... returning null Bundle"); + } + return null; + } + + // Return the Bundle created in finishLibraryLoad(). + if (DEBUG) { + Log.i(TAG, "... returning " + mSharedRelros); + } + return mSharedRelros; + } + } + + /** + * Call this method before loading any libraries to indicate that this + * process shall neither create or reuse shared RELRO sections. + */ + @Override + public void disableSharedRelros() { + if (DEBUG) { + Log.i(TAG, "disableSharedRelros() called"); + } + synchronized (mLock) { + mInBrowserProcess = false; + mWaitForSharedRelros = false; + mBrowserUsesSharedRelro = false; + } + } + + /** + * Call this method before loading any libraries to indicate that this + * process is ready to reuse shared RELRO sections from another one. + * Typically used when starting service processes. + * @param baseLoadAddress the base library load address to use. + */ + @Override + public void initServiceProcess(long baseLoadAddress) { + if (DEBUG) { + Log.i(TAG, String.format( + Locale.US, "initServiceProcess(0x%x) called", + baseLoadAddress)); + } + synchronized (mLock) { + ensureInitializedLocked(); + mInBrowserProcess = false; + mBrowserUsesSharedRelro = false; + if (mRelroSharingSupported) { + mWaitForSharedRelros = true; + mBaseLoadAddress = baseLoadAddress; + mCurrentLoadAddress = baseLoadAddress; + } + } + } + + /** + * Retrieve the base load address of all shared RELRO sections. + * This also enforces the creation of shared RELRO sections in + * prepareLibraryLoad(), which can later be retrieved with getSharedRelros(). + * @return a common, random base load address, or 0 if RELRO sharing is + * disabled. + */ + @Override + public long getBaseLoadAddress() { + synchronized (mLock) { + ensureInitializedLocked(); + if (!mInBrowserProcess) { + Log.w(TAG, "Shared RELRO sections are disabled in this process!"); + return 0; + } + + setupBaseLoadAddressLocked(); + if (DEBUG) { + Log.i(TAG, String.format( + Locale.US, "getBaseLoadAddress() returns 0x%x", + mBaseLoadAddress)); + } + return mBaseLoadAddress; + } + } + + // Used internally to lazily setup the common random base load address. + private void setupBaseLoadAddressLocked() { + assert Thread.holdsLock(mLock); + if (mBaseLoadAddress == 0) { + long address = computeRandomBaseLoadAddress(); + mBaseLoadAddress = address; + mCurrentLoadAddress = address; + if (address == 0) { + // If the computed address is 0, there are issues with finding enough + // free address space, so disable RELRO shared / fixed load addresses. + Log.w(TAG, "Disabling shared RELROs due address space pressure"); + mBrowserUsesSharedRelro = false; + mWaitForSharedRelros = false; + } + } + } + + + /** + * Compute a random base load address at which to place loaded libraries. + * @return new base load address, or 0 if the system does not support + * RELRO sharing. + */ + private long computeRandomBaseLoadAddress() { + // nativeGetRandomBaseLoadAddress() returns an address at which it has previously + // successfully mapped an area of the given size, on the basis that we will be + // able, with high probability, to map our library into it. + // + // One issue with this is that we do not yet know the size of the library that + // we will load is. So here we pass a value that we expect will always be larger + // than that needed. If it is smaller the library mapping may still succeed. The + // other issue is that although highly unlikely, there is no guarantee that + // something else does not map into the area we are going to use between here and + // when we try to map into it. + // + // The above notes mean that all of this is probablistic. It is however okay to do + // because if, worst case and unlikely, we get unlucky in our choice of address, + // the back-out and retry without the shared RELRO in the ChildProcessService will + // keep things running. + final long maxExpectedBytes = 192 * 1024 * 1024; + final long address = nativeGetRandomBaseLoadAddress(maxExpectedBytes); + if (DEBUG) { + Log.i(TAG, String.format( + Locale.US, "Random native base load address: 0x%x", + address)); + } + return address; + } + + // Used for debugging only. + private void dumpBundle(Bundle bundle) { + if (DEBUG) { + Log.i(TAG, "Bundle has " + bundle.size() + " items: " + bundle); + } + } + + /** + * Use the shared RELRO section from a Bundle received form another process. + * Call this after calling setBaseLoadAddress() then loading all libraries + * with loadLibrary(). + * @param bundle Bundle instance generated with createSharedRelroBundle() in + * another process. + */ + private void useSharedRelrosLocked(Bundle bundle) { + assert Thread.holdsLock(mLock); + + if (DEBUG) { + Log.i(TAG, "Linker.useSharedRelrosLocked() called"); + } + + if (bundle == null) { + if (DEBUG) { + Log.i(TAG, "null bundle!"); + } + return; + } + + if (!mRelroSharingSupported) { + if (DEBUG) { + Log.i(TAG, "System does not support RELRO sharing"); + } + return; + } + + if (mLoadedLibraries == null) { + if (DEBUG) { + Log.i(TAG, "No libraries loaded!"); + } + return; + } + + if (DEBUG) { + dumpBundle(bundle); + } + HashMap relroMap = createLibInfoMapFromBundle(bundle); + + // Apply the RELRO section to all libraries that were already loaded. + for (Map.Entry entry : relroMap.entrySet()) { + String libName = entry.getKey(); + LibInfo libInfo = entry.getValue(); + if (!nativeUseSharedRelro(libName, libInfo)) { + Log.w(TAG, "Could not use shared RELRO section for " + libName); + } else { + if (DEBUG) { + Log.i(TAG, "Using shared RELRO section for " + libName); + } + } + } + + // In service processes, close all file descriptors from the map now. + if (!mInBrowserProcess) closeLibInfoMap(relroMap); + + if (DEBUG) { + Log.i(TAG, "Linker.useSharedRelrosLocked() exiting"); + } + } + + /** + * Load a native shared library with the Chromium linker. If the zip file + * is not null, the shared library must be uncompressed and page aligned + * inside the zipfile. Note the crazy linker treats libraries and files as + * equivalent, so you can only open one library in a given zip file. The + * library must not be the Chromium linker library. + * + * @param zipFilePath The path of the zip file containing the library (or null). + * @param libFilePath The path of the library (possibly in the zip file). + */ + @Override + public void loadLibrary(@Nullable String zipFilePath, String libFilePath) { + if (DEBUG) { + Log.i(TAG, "loadLibrary: " + zipFilePath + ", " + libFilePath); + } + + synchronized (mLock) { + ensureInitializedLocked(); + + // Security: Ensure prepareLibraryLoad() was called before. + // In theory, this can be done lazily here, but it's more consistent + // to use a pair of functions (i.e. prepareLibraryLoad() + finishLibraryLoad()) + // that wrap all calls to loadLibrary() in the library loader. + assert mPrepareLibraryLoadCalled; + + if (mLoadedLibraries == null) { + mLoadedLibraries = new HashMap(); + } + + if (mLoadedLibraries.containsKey(libFilePath)) { + if (DEBUG) { + Log.i(TAG, "Not loading " + libFilePath + " twice"); + } + return; + } + + LibInfo libInfo = new LibInfo(); + long loadAddress = 0; + if ((mInBrowserProcess && mBrowserUsesSharedRelro) || mWaitForSharedRelros) { + // Load the library at a fixed address. + loadAddress = mCurrentLoadAddress; + } + + String sharedRelRoName = libFilePath; + if (zipFilePath != null) { + if (!nativeLoadLibraryInZipFile(zipFilePath, libFilePath, loadAddress, libInfo)) { + String errorMessage = "Unable to load library: " + libFilePath + + ", in: " + zipFilePath; + Log.e(TAG, errorMessage); + throw new UnsatisfiedLinkError(errorMessage); + } + sharedRelRoName = zipFilePath; + } else { + if (!nativeLoadLibrary(libFilePath, loadAddress, libInfo)) { + String errorMessage = "Unable to load library: " + libFilePath; + Log.e(TAG, errorMessage); + throw new UnsatisfiedLinkError(errorMessage); + } + } + + // Print the load address to the logcat when testing the linker. The format + // of the string is expected by the Python test_runner script as one of: + // BROWSER_LIBRARY_ADDRESS:
+ // RENDERER_LIBRARY_ADDRESS:
+ // Where is the library name, and
is the hexadecimal load + // address. + if (NativeLibraries.sEnableLinkerTests) { + Log.i(TAG, String.format( + Locale.US, "%s_LIBRARY_ADDRESS: %s %x", + mInBrowserProcess ? "BROWSER" : "RENDERER", + libFilePath, + libInfo.mLoadAddress)); + } + + if (mInBrowserProcess) { + // Create a new shared RELRO section at the 'current' fixed load address. + if (!nativeCreateSharedRelro(sharedRelRoName, mCurrentLoadAddress, libInfo)) { + Log.w(TAG, String.format( + Locale.US, "Could not create shared RELRO for %s at %x", + libFilePath, + mCurrentLoadAddress)); + } else { + if (DEBUG) { + Log.i(TAG, String.format( + Locale.US, + "Created shared RELRO for %s at %x: %s", + sharedRelRoName, + mCurrentLoadAddress, + libInfo.toString())); + } + } + } + + if (mCurrentLoadAddress != 0) { + // Compute the next current load address. If mBaseLoadAddress + // is not 0, this is an explicit library load address. Otherwise, + // this is an explicit load address for relocated RELRO sections + // only. + mCurrentLoadAddress = libInfo.mLoadAddress + libInfo.mLoadSize; + } + + mLoadedLibraries.put(sharedRelRoName, libInfo); + if (DEBUG) { + Log.i(TAG, "Library details " + libInfo.toString()); + } + } + } + + /** + * Determine whether a library is the linker library. Also deal with the + * component build that adds a .cr suffix to the name. + */ + @Override + public boolean isChromiumLinkerLibrary(String library) { + return library.equals(LINKER_JNI_LIBRARY) + || library.equals(LINKER_JNI_LIBRARY + ".cr"); + } + + /** + * Move activity from the native thread to the main UI thread. + * Called from native code on its own thread. Posts a callback from + * the UI thread back to native code. + * + * @param opaque Opaque argument. + */ + @CalledByNative + public static void postCallbackOnMainThread(final long opaque) { + ThreadUtils.postOnUiThread(new Runnable() { + @Override + public void run() { + nativeRunCallbackOnUiThread(opaque); + } + }); + } + + /** + * Native method to run callbacks on the main UI thread. + * Supplied by the crazy linker and called by postCallbackOnMainThread. + * @param opaque Opaque crazy linker arguments. + */ + private static native void nativeRunCallbackOnUiThread(long opaque); + + /** + * Native method used to load a library. + * @param library Platform specific library name (e.g. libfoo.so) + * @param loadAddress Explicit load address, or 0 for randomized one. + * @param libInfo If not null, the mLoadAddress and mLoadSize fields + * of this LibInfo instance will set on success. + * @return true for success, false otherwise. + */ + private static native boolean nativeLoadLibrary(String library, + long loadAddress, + LibInfo libInfo); + + /** + * Native method used to load a library which is inside a zipfile. + * @param zipfileName Filename of the zip file containing the library. + * @param library Platform specific library name (e.g. libfoo.so) + * @param loadAddress Explicit load address, or 0 for randomized one. + * @param libInfo If not null, the mLoadAddress and mLoadSize fields + * of this LibInfo instance will set on success. + * @return true for success, false otherwise. + */ + private static native boolean nativeLoadLibraryInZipFile(String zipfileName, + String libraryName, + long loadAddress, + LibInfo libInfo); + + /** + * Native method used to create a shared RELRO section. + * If the library was already loaded at the same address using + * nativeLoadLibrary(), this creates the RELRO for it. Otherwise, + * this loads a new temporary library at the specified address, + * creates and extracts the RELRO section from it, then unloads it. + * @param library Library name. + * @param loadAddress load address, which can be different from the one + * used to load the library in the current process! + * @param libInfo libInfo instance. On success, the mRelroStart, mRelroSize + * and mRelroFd will be set. + * @return true on success, false otherwise. + */ + private static native boolean nativeCreateSharedRelro(String library, + long loadAddress, + LibInfo libInfo); + + /** + * Native method used to use a shared RELRO section. + * @param library Library name. + * @param libInfo A LibInfo instance containing valid RELRO information + * @return true on success. + */ + private static native boolean nativeUseSharedRelro(String library, + LibInfo libInfo); + + /** + * Checks that the system supports shared RELROs. Old Android kernels + * have a bug in the way they check Ashmem region protection flags, which + * makes using shared RELROs unsafe. This method performs a simple runtime + * check for this misfeature, even though nativeEnableSharedRelro() will + * always fail if this returns false. + */ + private static native boolean nativeCanUseSharedRelro(); + + /** + * Return a random address that should be free to be mapped with the given size. + * Maps an area of size bytes, and if successful then unmaps it and returns + * the address of the area allocated by the system (with ASLR). The idea is + * that this area should remain free of other mappings until we map our library + * into it. + * @param sizeBytes Size of area in bytes to search for. + * @return address to pass to future mmap, or 0 on error. + */ + private static native long nativeGetRandomBaseLoadAddress(long sizeBytes); +} diff --git a/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java b/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java index a789eff611f68..b17b1a11b6c36 100644 --- a/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java +++ b/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java @@ -11,16 +11,17 @@ import android.os.AsyncTask; import android.os.Build; import android.os.SystemClock; -import android.util.Log; import org.chromium.base.CalledByNative; import org.chromium.base.CommandLine; import org.chromium.base.JNINamespace; +import org.chromium.base.Log; import org.chromium.base.PackageUtils; import org.chromium.base.TraceEvent; -import org.chromium.base.VisibleForTesting; import org.chromium.base.metrics.RecordHistogram; +import java.util.concurrent.atomic.AtomicBoolean; + import javax.annotation.Nullable; /** @@ -39,7 +40,7 @@ */ @JNINamespace("base::android") public class LibraryLoader { - private static final String TAG = "LibraryLoader"; + private static final String TAG = "cr.library_loader"; // Set to true to enable debug logs. private static final boolean DEBUG = false; @@ -73,15 +74,19 @@ public class LibraryLoader { // APK file directly. private boolean mLibraryWasLoadedFromApk; - // One-way switch becomes false if the Chromium library should be loaded - // directly from the APK file but it was compressed or not aligned. - private boolean mLibraryIsMappableInApk = true; - // The type of process the shared library is loaded in. // This member can be accessed from multiple threads simultaneously, so it have to be // final (like now) or be protected in some way (volatile of synchronized). private final int mLibraryProcessType; + // One-way switch that becomes true once + // {@link asyncPrefetchLibrariesToMemory} has been called. + private final AtomicBoolean mPrefetchLibraryHasBeenCalled; + + // The number of milliseconds it took to load all the native libraries, which + // will be reported via UMA. Set once when the libraries are done loading. + private long mLibraryLoadTimeMs; + /** * @param libraryProcessType the process the shared library is loaded in. refer to * LibraryProcessType for possible values. @@ -101,38 +106,21 @@ public static LibraryLoader get(int libraryProcessType) throws ProcessInitExcept private LibraryLoader(int libraryProcessType) { mLibraryProcessType = libraryProcessType; - } - - /** - * The same as ensureInitialized(null, false), should only be called - * by non-browser processes. - * - * @throws ProcessInitException - */ - @VisibleForTesting - public void ensureInitialized() throws ProcessInitException { - ensureInitialized(null, false); + mPrefetchLibraryHasBeenCalled = new AtomicBoolean(); } /** * This method blocks until the library is fully loaded and initialized. * - * @param context The context in which the method is called, the caller - * may pass in a null context if it doesn't know in which context it - * is running. - * - * @param shouldDeleteFallbackLibraries The flag tells whether the method - * should delete the fallback libraries or not. + * @param context The context in which the method is called. */ - public void ensureInitialized( - Context context, boolean shouldDeleteFallbackLibraries) - throws ProcessInitException { + public void ensureInitialized(Context context) throws ProcessInitException { synchronized (sLock) { if (mInitialized) { // Already initialized, nothing to do. return; } - loadAlreadyLocked(context, shouldDeleteFallbackLibraries); + loadAlreadyLocked(context); initializeAlreadyLocked(); } } @@ -144,16 +132,6 @@ public static boolean isInitialized() { return sInstance != null && sInstance.mInitialized; } - /** - * The same as loadNow(null, false), should only be called by - * non-browser process. - * - * @throws ProcessInitException - */ - public void loadNow() throws ProcessInitException { - loadNow(null, false); - } - /** * Loads the library and blocks until the load completes. The caller is responsible * for subsequently calling ensureInitialized(). @@ -161,16 +139,13 @@ public void loadNow() throws ProcessInitException { * this is called on will be the thread that runs the native code's static initializers. * See the comment in doInBackground() for more considerations on this. * - * @param context The context the code is running, or null if it doesn't have one. - * @param shouldDeleteFallbackLibraries The flag tells whether the method - * should delete the old fallback libraries or not. + * @param context The context the code is running. * * @throws ProcessInitException if the native library failed to load. */ - public void loadNow(Context context, boolean shouldDeleteFallbackLibraries) - throws ProcessInitException { + public void loadNow(Context context) throws ProcessInitException { synchronized (sLock) { - loadAlreadyLocked(context, shouldDeleteFallbackLibraries); + loadAlreadyLocked(context); } } @@ -193,10 +168,9 @@ public void initialize() throws ProcessInitException { * * This is done this way, as testing shows that fadvise(FADV_WILLNEED) is * detrimental to the startup time. - * - * @param context the application context. */ - public void asyncPrefetchLibrariesToMemory(final Context context) { + public void asyncPrefetchLibrariesToMemory() { + if (!mPrefetchLibraryHasBeenCalled.compareAndSet(false, true)) return; new AsyncTask() { @Override protected Void doInBackground(Void... params) { @@ -213,34 +187,26 @@ protected Void doInBackground(Void... params) { } // Invoke System.loadLibrary(...), triggering JNI_OnLoad in native code - private void loadAlreadyLocked( - Context context, boolean shouldDeleteFallbackLibraries) - throws ProcessInitException { + private void loadAlreadyLocked(Context context) throws ProcessInitException { try { if (!mLoaded) { assert !mInitialized; long startTime = SystemClock.uptimeMillis(); - boolean useChromiumLinker = Linker.isUsed(); - boolean fallbackWasUsed = false; + Linker linker = Linker.getInstance(); + boolean useChromiumLinker = linker.isUsed(); if (useChromiumLinker) { // Determine the APK file path. - String apkFilePath = null; - if (context != null) { - apkFilePath = getLibraryApkPath(context); - } else { - Log.w(TAG, "could not check load from APK support due to null context"); - } - + String apkFilePath = getLibraryApkPath(context); // Load libraries using the Chromium linker. - Linker.prepareLibraryLoad(); + linker.prepareLibraryLoad(); for (String library : NativeLibraries.LIBRARIES) { // Don't self-load the linker. This is because the build system is // not clever enough to understand that all the libraries packaged // in the final .apk don't need to be explicitly loaded. - if (Linker.isChromiumLinkerLibrary(library)) { + if (linker.isChromiumLinkerLibrary(library)) { if (DEBUG) Log.i(TAG, "ignoring self-linker load"); continue; } @@ -248,26 +214,11 @@ private void loadAlreadyLocked( // Determine where the library should be loaded from. String zipFilePath = null; String libFilePath = System.mapLibraryName(library); - if (apkFilePath != null && Linker.isInZipFile()) { - // The library is in the APK file. - if (!Linker.checkLibraryIsMappableInApk(apkFilePath, libFilePath)) { - mLibraryIsMappableInApk = false; - } - if (mLibraryIsMappableInApk) { - // Load directly from the APK. - zipFilePath = apkFilePath; - Log.i(TAG, "Loading " + library + " directly from within " - + apkFilePath); - } else { - // Unpack library fallback. - Log.i(TAG, "Loading " + library - + " using unpack library fallback from within " - + apkFilePath); - libFilePath = LibraryLoaderHelper.buildFallbackLibrary( - context, library); - fallbackWasUsed = true; - Log.i(TAG, "Built fallback library " + libFilePath); - } + if (linker.isInZipFile()) { + // Load directly from the APK. + zipFilePath = apkFilePath; + Log.i(TAG, + "Loading " + library + " directly from within " + apkFilePath); } else { // The library is in its own file. Log.i(TAG, "Loading " + library); @@ -275,7 +226,7 @@ private void loadAlreadyLocked( // Load the library. boolean isLoaded = false; - if (Linker.isUsingBrowserSharedRelros()) { + if (linker.isUsingBrowserSharedRelros()) { mIsUsingBrowserSharedRelros = true; try { loadLibrary(zipFilePath, libFilePath); @@ -283,7 +234,7 @@ private void loadAlreadyLocked( } catch (UnsatisfiedLinkError e) { Log.w(TAG, "Failed to load native library with shared RELRO, " + "retrying without"); - Linker.disableSharedRelros(); + linker.disableSharedRelros(); mLoadAtFixedAddressFailed = true; } } @@ -292,7 +243,7 @@ private void loadAlreadyLocked( } } - Linker.finishLibraryLoad(); + linker.finishLibraryLoad(); } else { // Load libraries using the system linker. for (String library : NativeLibraries.LIBRARIES) { @@ -300,15 +251,10 @@ private void loadAlreadyLocked( } } - if (!fallbackWasUsed && context != null - && shouldDeleteFallbackLibraries) { - LibraryLoaderHelper.deleteLibrariesAsynchronously( - context, LibraryLoaderHelper.LOAD_FROM_APK_FALLBACK_DIR); - } - long stopTime = SystemClock.uptimeMillis(); + mLibraryLoadTimeMs = stopTime - startTime; Log.i(TAG, String.format("Time to load native libraries: %d ms (timestamps %d-%d)", - stopTime - startTime, + mLibraryLoadTimeMs, startTime % 10000, stopTime % 10000)); @@ -319,7 +265,7 @@ private void loadAlreadyLocked( } // Check that the version of the library we have loaded matches the version we expect Log.i(TAG, String.format( - "Expected native library version number \"%s\"," + "Expected native library version number \"%s\", " + "actual native library version number \"%s\"", NativeLibraries.sVersionNumber, nativeGetVersionNumber())); @@ -356,7 +302,7 @@ private static String getLibraryApkPath(Context context) { // Load a native shared library with the Chromium linker. If the zip file // path is not null, the library is loaded directly from the zip file. private void loadLibrary(@Nullable String zipFilePath, String libFilePath) { - Linker.loadLibrary(zipFilePath, libFilePath); + Linker.getInstance().loadLibrary(zipFilePath, libFilePath); if (zipFilePath != null) { mLibraryWasLoadedFromApk = true; } @@ -426,26 +372,23 @@ public void onNativeInitializationComplete(Context context) { // Record Chromium linker histogram state for the main browser process. Called from // onNativeInitializationComplete(). private void recordBrowserProcessHistogram(Context context) { - if (Linker.isUsed()) { + if (Linker.getInstance().isUsed()) { nativeRecordChromiumAndroidLinkerBrowserHistogram(mIsUsingBrowserSharedRelros, mLoadAtFixedAddressFailed, - getLibraryLoadFromApkStatus(context)); + getLibraryLoadFromApkStatus(context), + mLibraryLoadTimeMs); } } // Returns the device's status for loading a library directly from the APK file. // This method can only be called when the Chromium linker is used. private int getLibraryLoadFromApkStatus(Context context) { - assert Linker.isUsed(); + assert Linker.getInstance().isUsed(); if (mLibraryWasLoadedFromApk) { return LibraryLoadFromApkStatusCodes.SUCCESSFUL; } - if (!mLibraryIsMappableInApk) { - return LibraryLoadFromApkStatusCodes.USED_UNPACK_LIBRARY_FALLBACK; - } - // There were no libraries to be loaded directly from the APK file. return LibraryLoadFromApkStatusCodes.UNKNOWN; } @@ -456,9 +399,10 @@ private int getLibraryLoadFromApkStatus(Context context) { // RecordChromiumAndroidLinkerRendererHistogram() will record it correctly. public void registerRendererProcessHistogram(boolean requestedSharedRelro, boolean loadAtFixedAddressFailed) { - if (Linker.isUsed()) { + if (Linker.getInstance().isUsed()) { nativeRegisterChromiumAndroidLinkerRendererHistogram(requestedSharedRelro, - loadAtFixedAddressFailed); + loadAtFixedAddressFailed, + mLibraryLoadTimeMs); } } @@ -485,18 +429,22 @@ public static int getLibraryProcessType() { // Method called to record statistics about the Chromium linker operation for the main // browser process. Indicates whether the linker attempted relro sharing for the browser, // and if it did, whether the library failed to load at a fixed address. Also records - // support for loading a library directly from the APK file. + // support for loading a library directly from the APK file, and the number of milliseconds + // it took to load the libraries. private native void nativeRecordChromiumAndroidLinkerBrowserHistogram( boolean isUsingBrowserSharedRelros, boolean loadAtFixedAddressFailed, - int libraryLoadFromApkStatus); + int libraryLoadFromApkStatus, + long libraryLoadTime); // Method called to register (for later recording) statistics about the Chromium linker // operation for a renderer process. Indicates whether the linker attempted relro sharing, - // and if it did, whether the library failed to load at a fixed address. + // and if it did, whether the library failed to load at a fixed address. Also records the + // number of milliseconds it took to load the libraries. private native void nativeRegisterChromiumAndroidLinkerRendererHistogram( boolean requestedSharedRelro, - boolean loadAtFixedAddressFailed); + boolean loadAtFixedAddressFailed, + long libraryLoadTime); // Get the version of the native library. This is needed so that we can check we // have the right version before initializing the (rest of the) JNI. diff --git a/base/android/java/src/org/chromium/base/library_loader/LibraryLoaderHelper.java b/base/android/java/src/org/chromium/base/library_loader/LibraryLoaderHelper.java deleted file mode 100644 index 7dd1a29a0eafe..0000000000000 --- a/base/android/java/src/org/chromium/base/library_loader/LibraryLoaderHelper.java +++ /dev/null @@ -1,338 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - - -package org.chromium.base.library_loader; - -import android.content.Context; -import android.util.Log; - -import java.io.BufferedOutputStream; -import java.io.Closeable; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.zip.ZipEntry; -import java.util.zip.ZipException; -import java.util.zip.ZipFile; - -/** - * Class representing an exception which occured during the unpacking process. - */ -class UnpackingException extends Exception { - public UnpackingException(String message, Throwable cause) { - super(message, cause); - } - - public UnpackingException(String message) { - super(message); - } -} - -/** - * The class provides helper functions to extract native libraries from APK, - * and load libraries from there. - */ -class LibraryLoaderHelper { - private static final String TAG = "LibraryLoaderHelper"; - - // Fallback directories. - static final String LOAD_FROM_APK_FALLBACK_DIR = "fallback"; - - private static final int BUFFER_SIZE = 16384; - - /** - * Returns the directory for holding extracted native libraries. - * It may create the directory if it doesn't exist. - * - * @param context The context the code is running. - * @param dirName The name of the directory containing the libraries. - * @return The directory file object. - */ - static File getLibDir(Context context, String dirName) { - return context.getDir(dirName, Context.MODE_PRIVATE); - } - - /** - * Delete libraries and their directory synchronously. - */ - private static void deleteLibrariesSynchronously(Context context, String dirName) { - File libDir = getLibDir(context, dirName); - deleteObsoleteLibraries(libDir, Collections.emptyList()); - } - - /** - * Delete libraries and their directory asynchronously. - * The actual deletion is done in a background thread. - */ - static void deleteLibrariesAsynchronously( - final Context context, final String dirName) { - // Child process should not reach here. - new Thread() { - @Override - public void run() { - deleteLibrariesSynchronously(context, dirName); - } - }.start(); - } - - /** - * Copy a library from a zip file to the application's private directory. - * This is used as a fallback when we are unable to load the library - * directly from the APK file (crbug.com/390618). - * - * @param context The context the code is running in. - * @param library Library name. - * @return name of the fallback copy of the library. - */ - static String buildFallbackLibrary(Context context, String library) { - try { - String libName = System.mapLibraryName(library); - File fallbackLibDir = getLibDir(context, LOAD_FROM_APK_FALLBACK_DIR); - File fallbackLibFile = new File(fallbackLibDir, libName); - String pathInZipFile = Linker.getLibraryFilePathInZipFile(libName); - Map dstFiles = Collections.singletonMap(pathInZipFile, fallbackLibFile); - - deleteObsoleteLibraries(fallbackLibDir, dstFiles.values()); - unpackLibraries(context, dstFiles); - - return fallbackLibFile.getAbsolutePath(); - } catch (Exception e) { - String errorMessage = "Unable to load fallback for library " + library - + " (" + (e.getMessage() == null ? e.toString() : e.getMessage()) + ")"; - Log.e(TAG, errorMessage, e); - throw new UnsatisfiedLinkError(errorMessage); - } - } - - // Delete obsolete libraries from a library folder. - private static void deleteObsoleteLibraries(File libDir, Collection keptFiles) { - try { - // Build a list of libraries that should NOT be deleted. - Set keptFileNames = new HashSet(); - for (File k : keptFiles) { - keptFileNames.add(k.getName()); - } - - // Delete the obsolete libraries. - Log.i(TAG, "Deleting obsolete libraries in " + libDir.getPath()); - File[] files = libDir.listFiles(); - if (files != null) { - for (File f : files) { - if (!keptFileNames.contains(f.getName())) { - delete(f); - } - } - } else { - Log.e(TAG, "Failed to list files in " + libDir.getPath()); - } - - // Delete the folder if no libraries were kept. - if (keptFileNames.isEmpty()) { - delete(libDir); - } - } catch (Exception e) { - Log.e(TAG, "Failed to remove obsolete libraries from " + libDir.getPath()); - } - } - - // Unpack libraries from a zip file to the file system. - private static void unpackLibraries(Context context, - Map dstFiles) throws UnpackingException { - String zipFilePath = context.getApplicationInfo().sourceDir; - Log.i(TAG, "Opening zip file " + zipFilePath); - File zipFile = new File(zipFilePath); - ZipFile zipArchive = openZipFile(zipFile); - - try { - for (Entry d : dstFiles.entrySet()) { - String pathInZipFile = d.getKey(); - File dstFile = d.getValue(); - Log.i(TAG, "Unpacking " + pathInZipFile - + " to " + dstFile.getAbsolutePath()); - ZipEntry packedLib = zipArchive.getEntry(pathInZipFile); - - if (needToUnpackLibrary(zipFile, packedLib, dstFile)) { - unpackLibraryFromZipFile(zipArchive, packedLib, dstFile); - setLibraryFilePermissions(dstFile); - } - } - } finally { - closeZipFile(zipArchive); - } - } - - // Open a zip file. - private static ZipFile openZipFile(File zipFile) throws UnpackingException { - try { - return new ZipFile(zipFile); - } catch (ZipException e) { - throw new UnpackingException("Failed to open zip file " + zipFile.getPath()); - } catch (IOException e) { - throw new UnpackingException("Failed to open zip file " + zipFile.getPath()); - } - } - - // Determine whether it is necessary to unpack a library from a zip file. - private static boolean needToUnpackLibrary( - File zipFile, ZipEntry packedLib, File dstFile) { - // Check if the fallback library already exists. - if (!dstFile.exists()) { - Log.i(TAG, "File " + dstFile.getPath() + " does not exist yet"); - return true; - } - - // Check last modification dates. - long zipTime = zipFile.lastModified(); - long fallbackLibTime = dstFile.lastModified(); - if (zipTime > fallbackLibTime) { - Log.i(TAG, "Not using existing fallback file because " - + "the APK file " + zipFile.getPath() - + " (timestamp=" + zipTime + ") is newer than " - + "the fallback library " + dstFile.getPath() - + "(timestamp=" + fallbackLibTime + ")"); - return true; - } - - // Check file sizes. - long packedLibSize = packedLib.getSize(); - long fallbackLibSize = dstFile.length(); - if (fallbackLibSize != packedLibSize) { - Log.i(TAG, "Not using existing fallback file because " - + "the library in the APK " + zipFile.getPath() - + " (" + packedLibSize + "B) has a different size than " - + "the fallback library " + dstFile.getPath() - + "(" + fallbackLibSize + "B)"); - return true; - } - - Log.i(TAG, "Reusing existing file " + dstFile.getPath()); - return false; - } - - // Unpack a library from a zip file to the filesystem. - private static void unpackLibraryFromZipFile(ZipFile zipArchive, ZipEntry packedLib, - File dstFile) throws UnpackingException { - // Open input stream for the library file inside the zip file. - InputStream in; - try { - in = zipArchive.getInputStream(packedLib); - } catch (IOException e) { - throw new UnpackingException( - "IO exception when locating library in the zip file", e); - } - - // Ensure that the input stream is closed at the end. - try { - // Delete existing file if it exists. - if (dstFile.exists()) { - Log.i(TAG, "Deleting existing unpacked library file " + dstFile.getPath()); - if (!dstFile.delete()) { - throw new UnpackingException( - "Failed to delete existing unpacked library file " + dstFile.getPath()); - } - } - - // Ensure that the library folder exists. Since this is added - // for increased robustness, we log errors and carry on. - try { - dstFile.getParentFile().mkdirs(); - } catch (Exception e) { - Log.e(TAG, "Failed to make library folder", e); - } - - // Create the destination file. - try { - if (!dstFile.createNewFile()) { - throw new UnpackingException("existing unpacked library file was not deleted"); - } - } catch (IOException e) { - throw new UnpackingException("failed to create unpacked library file", e); - } - - // Open the output stream for the destination file. - OutputStream out; - try { - out = new BufferedOutputStream(new FileOutputStream(dstFile)); - } catch (FileNotFoundException e) { - throw new UnpackingException( - "failed to open output stream for unpacked library file", e); - } - - // Ensure that the output stream is closed at the end. - try { - // Copy the library from the zip file to the destination file. - Log.i(TAG, "Copying " + packedLib.getName() + " from " + zipArchive.getName() - + " to " + dstFile.getPath()); - byte[] buffer = new byte[BUFFER_SIZE]; - int len; - while ((len = in.read(buffer)) != -1) { - out.write(buffer, 0, len); - } - } catch (IOException e) { - throw new UnpackingException( - "failed to copy the library from the zip file", e); - } finally { - close(out, "output stream"); - } - } finally { - close(in, "input stream"); - } - } - - // Set up library file permissions. - private static void setLibraryFilePermissions(File libFile) { - // Change permission to rwxr-xr-x - Log.i(TAG, "Setting file permissions for " + libFile.getPath()); - if (!libFile.setReadable(/* readable */ true, /* ownerOnly */ false)) { - Log.e(TAG, "failed to chmod a+r the temporary file"); - } - if (!libFile.setExecutable(/* executable */ true, /* ownerOnly */ false)) { - Log.e(TAG, "failed to chmod a+x the temporary file"); - } - if (!libFile.setWritable(/* writable */ true)) { - Log.e(TAG, "failed to chmod +w the temporary file"); - } - } - - // Close a closable and log a warning if it fails. - private static void close(Closeable closeable, String name) { - try { - closeable.close(); - } catch (IOException e) { - // Warn and ignore. - Log.w(TAG, "IO exception when closing " + name, e); - } - } - - // Close a zip file and log a warning if it fails. - // This needs to be a separate method because ZipFile is not Closeable in - // Java 6 (used on some older devices). - private static void closeZipFile(ZipFile file) { - try { - file.close(); - } catch (IOException e) { - // Warn and ignore. - Log.w(TAG, "IO exception when closing zip file", e); - } - } - - // Delete a file and log it. - private static void delete(File file) { - if (file.delete()) { - Log.i(TAG, "Deleted " + file.getPath()); - } else { - Log.w(TAG, "Failed to delete " + file.getPath()); - } - } -} diff --git a/base/android/java/src/org/chromium/base/library_loader/Linker.java b/base/android/java/src/org/chromium/base/library_loader/Linker.java index 9a64a3fddbfd3..b4ea3fdfba2a9 100644 --- a/base/android/java/src/org/chromium/base/library_loader/Linker.java +++ b/base/android/java/src/org/chromium/base/library_loader/Linker.java @@ -1,4 +1,4 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. +// Copyright 2015 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -8,14 +8,10 @@ import android.os.Parcel; import android.os.ParcelFileDescriptor; import android.os.Parcelable; -import android.util.Log; -import org.chromium.base.CalledByNative; -import org.chromium.base.SysUtils; -import org.chromium.base.ThreadUtils; +import org.chromium.base.Log; import org.chromium.base.annotations.AccessedByNative; -import java.io.FileNotFoundException; import java.util.HashMap; import java.util.Locale; import java.util.Map; @@ -153,13 +149,19 @@ * * This method also ensures the process uses the shared RELROs. */ -public class Linker { - - // Log tag for this class. This must match the name of the linker's native library. - private static final String TAG = "chromium_android_linker"; +public abstract class Linker { + // Log tag for this class. + private static final String TAG = "cr.library_loader"; // Set to true to enable debug logs. - private static final boolean DEBUG = false; + protected static final boolean DEBUG = false; + + // Used to pass the shared RELRO Bundle through Binder. + public static final String EXTRA_LINKER_SHARED_RELROS = + "org.chromium.base.android.linker.shared_relros"; + + // Guards all access to the linker. + protected final Object mLock = new Object(); // Constants used to control the behaviour of the browser process with // regards to the shared RELRO section. @@ -188,96 +190,24 @@ public class Linker { // Indicates if this is a low-memory device or not. The default is to // determine this by probing the system at runtime, but this can be forced // for testing by calling setMemoryDeviceConfig(). - private static int sMemoryDeviceConfig = MEMORY_DEVICE_CONFIG_INIT; - - // Becomes true after linker initialization. - private static boolean sInitialized = false; - - // Set to true to indicate that the system supports safe sharing of RELRO sections. - private static boolean sRelroSharingSupported = false; - - // Set to true if this runs in the browser process. Disabled by initServiceProcess(). - // TODO(petrcermak): This flag can be incorrectly set to false (even though this might run in - // the browser process) on low-memory devices. - private static boolean sInBrowserProcess = true; - - // Becomes true to indicate this process needs to wait for a shared RELRO in - // finishLibraryLoad(). - private static boolean sWaitForSharedRelros = false; - - // Becomes true when initialization determines that the browser process can use the - // shared RELRO. - private static boolean sBrowserUsesSharedRelro = false; - - // The map of all RELRO sections either created or used in this process. - private static Bundle sSharedRelros = null; - - // Current common random base load address. - private static long sBaseLoadAddress = 0; - - // Current fixed-location load address for the next library called by loadLibrary(). - private static long sCurrentLoadAddress = 0; - - // Becomes true once prepareLibraryLoad() has been called. - private static boolean sPrepareLibraryLoadCalled = false; - - // Used internally to initialize the linker's static data. Assume lock is held. - private static void ensureInitializedLocked() { - assert Thread.holdsLock(Linker.class); - - if (!sInitialized) { - sRelroSharingSupported = false; - if (NativeLibraries.sUseLinker) { - if (DEBUG) Log.i(TAG, "Loading lib" + TAG + ".so"); - try { - System.loadLibrary(TAG); - } catch (UnsatisfiedLinkError e) { - // In a component build, the ".cr" suffix is added to each library name. - Log.w(TAG, "Couldn't load lib" + TAG + ".so, trying lib" + TAG + ".cr.so"); - System.loadLibrary(TAG + ".cr"); - } - sRelroSharingSupported = nativeCanUseSharedRelro(); - if (!sRelroSharingSupported) { - Log.w(TAG, "This system cannot safely share RELRO sections"); - } else { - if (DEBUG) Log.i(TAG, "This system supports safe shared RELRO sections"); - } - - if (sMemoryDeviceConfig == MEMORY_DEVICE_CONFIG_INIT) { - sMemoryDeviceConfig = SysUtils.isLowEndDevice() - ? MEMORY_DEVICE_CONFIG_LOW : MEMORY_DEVICE_CONFIG_NORMAL; - } - - switch (BROWSER_SHARED_RELRO_CONFIG) { - case BROWSER_SHARED_RELRO_CONFIG_NEVER: - sBrowserUsesSharedRelro = false; - break; - case BROWSER_SHARED_RELRO_CONFIG_LOW_RAM_ONLY: - sBrowserUsesSharedRelro = - (sMemoryDeviceConfig == MEMORY_DEVICE_CONFIG_LOW); - if (sBrowserUsesSharedRelro) { - Log.w(TAG, "Low-memory device: shared RELROs used in all processes"); - } - break; - case BROWSER_SHARED_RELRO_CONFIG_ALWAYS: - Log.w(TAG, "Beware: shared RELROs used in all processes!"); - sBrowserUsesSharedRelro = true; - break; - default: - assert false : "Unreached"; - break; - } - } else { - if (DEBUG) Log.i(TAG, "Linker disabled"); + protected int mMemoryDeviceConfig = MEMORY_DEVICE_CONFIG_INIT; + + // Singleton. + private static Linker sSingleton = null; + private static Object sSingletonLock = new Object(); + + // Protected singleton constructor. + protected Linker() { } + + // Get singleton instance. + public static final Linker getInstance() { + synchronized (sSingletonLock) { + if (sSingleton == null) { + // TODO(simonb): Extend later to return either a LegacyLinker + // or a ModernLinker instance. + sSingleton = new LegacyLinker(); } - - if (!sRelroSharingSupported) { - // Sanity. - sBrowserUsesSharedRelro = false; - sWaitForSharedRelros = false; - } - - sInitialized = true; + return sSingleton; } } @@ -297,7 +227,7 @@ public interface TestRunner { } // The name of a class that implements TestRunner. - static String sTestRunnerClassName = null; + String mTestRunnerClassName = null; /** * Set the TestRunner by its class name. It will be instantiated at @@ -305,17 +235,18 @@ public interface TestRunner { * @param testRunnerClassName null or a String for the class name of the * TestRunner to use. */ - public static void setTestRunnerClassName(String testRunnerClassName) { - if (DEBUG) Log.i(TAG, "setTestRunnerByClassName(" + testRunnerClassName + ") called"); - + public void setTestRunnerClassName(String testRunnerClassName) { + if (DEBUG) { + Log.i(TAG, "setTestRunnerByClassName(" + testRunnerClassName + ") called"); + } if (!NativeLibraries.sEnableLinkerTests) { - // Ignore this in production code to prevent malvolent runtime injection. + // Ignore this in production code to prevent malevolent runtime injection. return; } - synchronized (Linker.class) { - assert sTestRunnerClassName == null; - sTestRunnerClassName = testRunnerClassName; + synchronized (mLock) { + assert mTestRunnerClassName == null; + mTestRunnerClassName = testRunnerClassName; } } @@ -326,9 +257,9 @@ public static void setTestRunnerClassName(String testRunnerClassName) { * @return null or a String holding the name of the class implementing * the TestRunner set by calling setTestRunnerClassName() previously. */ - public static String getTestRunnerClassName() { - synchronized (Linker.class) { - return sTestRunnerClassName; + public String getTestRunnerClassName() { + synchronized (mLock) { + return mTestRunnerClassName; } } @@ -337,12 +268,14 @@ public static String getTestRunnerClassName() { * memory device configuration. Should only be used for testing. * @param memoryDeviceConfig either MEMORY_DEVICE_CONFIG_LOW or MEMORY_DEVICE_CONFIG_NORMAL. */ - public static void setMemoryDeviceConfig(int memoryDeviceConfig) { - if (DEBUG) Log.i(TAG, "setMemoryDeviceConfig(" + memoryDeviceConfig + ") called"); + public void setMemoryDeviceConfig(int memoryDeviceConfig) { + if (DEBUG) { + Log.i(TAG, "setMemoryDeviceConfig(" + memoryDeviceConfig + ") called"); + } // Sanity check. This method should only be called during tests. assert NativeLibraries.sEnableLinkerTests; - synchronized (Linker.class) { - assert sMemoryDeviceConfig == MEMORY_DEVICE_CONFIG_INIT; + synchronized (mLock) { + assert mMemoryDeviceConfig == MEMORY_DEVICE_CONFIG_INIT; assert memoryDeviceConfig == MEMORY_DEVICE_CONFIG_LOW || memoryDeviceConfig == MEMORY_DEVICE_CONFIG_NORMAL; if (DEBUG) { @@ -352,7 +285,7 @@ public static void setMemoryDeviceConfig(int memoryDeviceConfig) { Log.i(TAG, "Simulating a regular-memory device"); } } - sMemoryDeviceConfig = memoryDeviceConfig; + mMemoryDeviceConfig = memoryDeviceConfig; } } @@ -361,130 +294,31 @@ public static void setMemoryDeviceConfig(int memoryDeviceConfig) { * use this linker. If not, System.loadLibrary() should be used to load * libraries instead. */ - public static boolean isUsed() { - // Only GYP targets that are APKs and have the 'use_chromium_linker' variable - // defined as 1 will use this linker. For all others (the default), the - // auto-generated NativeLibraries.sUseLinker variable will be false. - if (!NativeLibraries.sUseLinker) return false; - - synchronized (Linker.class) { - ensureInitializedLocked(); - // At the moment, there is also no point in using this linker if the - // system does not support RELRO sharing safely. - return sRelroSharingSupported; - } - } + public abstract boolean isUsed(); /** * Call this method to determine if the linker will try to use shared RELROs * for the browser process. */ - public static boolean isUsingBrowserSharedRelros() { - synchronized (Linker.class) { - ensureInitializedLocked(); - return sBrowserUsesSharedRelro; - } - } + public abstract boolean isUsingBrowserSharedRelros(); /** * Call this method to determine if the chromium project must load * the library directly from the zip file. */ - public static boolean isInZipFile() { - return NativeLibraries.sUseLibraryInZipFile; - } + public abstract boolean isInZipFile(); /** * Call this method just before loading any native shared libraries in this process. */ - public static void prepareLibraryLoad() { - if (DEBUG) Log.i(TAG, "prepareLibraryLoad() called"); - synchronized (Linker.class) { - sPrepareLibraryLoadCalled = true; - - if (sInBrowserProcess) { - // Force generation of random base load address, as well - // as creation of shared RELRO sections in this process. - setupBaseLoadAddressLocked(); - } - } - } + public abstract void prepareLibraryLoad(); /** * Call this method just after loading all native shared libraries in this process. * Note that when in a service process, this will block until the RELRO bundle is * received, i.e. when another thread calls useSharedRelros(). */ - public static void finishLibraryLoad() { - if (DEBUG) Log.i(TAG, "finishLibraryLoad() called"); - synchronized (Linker.class) { - if (DEBUG) Log.i(TAG, String.format( - Locale.US, - "sInBrowserProcess=%s sBrowserUsesSharedRelro=%s sWaitForSharedRelros=%s", - sInBrowserProcess ? "true" : "false", - sBrowserUsesSharedRelro ? "true" : "false", - sWaitForSharedRelros ? "true" : "false")); - - if (sLoadedLibraries == null) { - if (DEBUG) Log.i(TAG, "No libraries loaded"); - } else { - if (sInBrowserProcess) { - // Create new Bundle containing RELRO section information - // for all loaded libraries. Make it available to getSharedRelros(). - sSharedRelros = createBundleFromLibInfoMap(sLoadedLibraries); - if (DEBUG) { - Log.i(TAG, "Shared RELRO created"); - dumpBundle(sSharedRelros); - } - - if (sBrowserUsesSharedRelro) { - useSharedRelrosLocked(sSharedRelros); - } - } - - if (sWaitForSharedRelros) { - assert !sInBrowserProcess; - - // Wait until the shared relro bundle is received from useSharedRelros(). - while (sSharedRelros == null) { - try { - Linker.class.wait(); - } catch (InterruptedException ie) { - // no-op - } - } - useSharedRelrosLocked(sSharedRelros); - // Clear the Bundle to ensure its file descriptor references can't be reused. - sSharedRelros.clear(); - sSharedRelros = null; - } - } - - if (NativeLibraries.sEnableLinkerTests && sTestRunnerClassName != null) { - // The TestRunner implementation must be instantiated _after_ - // all libraries are loaded to ensure that its native methods - // are properly registered. - if (DEBUG) Log.i(TAG, "Instantiating " + sTestRunnerClassName); - TestRunner testRunner = null; - try { - testRunner = (TestRunner) - Class.forName(sTestRunnerClassName).newInstance(); - } catch (Exception e) { - Log.e(TAG, "Could not extract test runner class name", e); - testRunner = null; - } - if (testRunner != null) { - if (!testRunner.runChecks(sMemoryDeviceConfig, sInBrowserProcess)) { - Log.wtf(TAG, "Linker runtime tests failed in this process!!"); - assert false; - } else { - Log.i(TAG, "All linker tests passed!"); - } - } - } - } - if (DEBUG) Log.i(TAG, "finishLibraryLoad() exiting"); - } + public abstract void finishLibraryLoad(); /** * Call this to send a Bundle containing the shared RELRO sections to be @@ -494,32 +328,7 @@ public static void finishLibraryLoad() { * @param bundle The Bundle instance containing a map of shared RELRO sections * to use in this process. */ - public static void useSharedRelros(Bundle bundle) { - // Ensure the bundle uses the application's class loader, not the framework - // one which doesn't know anything about LibInfo. - // Also, hold a fresh copy of it so the caller can't recycle it. - Bundle clonedBundle = null; - if (bundle != null) { - bundle.setClassLoader(LibInfo.class.getClassLoader()); - clonedBundle = new Bundle(LibInfo.class.getClassLoader()); - Parcel parcel = Parcel.obtain(); - bundle.writeToParcel(parcel, 0); - parcel.setDataPosition(0); - clonedBundle.readFromParcel(parcel); - parcel.recycle(); - } - if (DEBUG) { - Log.i(TAG, "useSharedRelros() called with " + bundle - + ", cloned " + clonedBundle); - } - synchronized (Linker.class) { - // Note that in certain cases, this can be called before - // initServiceProcess() in service processes. - sSharedRelros = clonedBundle; - // Tell any listener blocked in finishLibraryLoad() about it. - Linker.class.notifyAll(); - } - } + public abstract void useSharedRelros(Bundle bundle); /** * Call this to retrieve the shared RELRO sections created in this process, @@ -527,33 +336,14 @@ public static void useSharedRelros(Bundle bundle) { * @return a new Bundle instance, or null if RELRO sharing is disabled on * this system, or if initServiceProcess() was called previously. */ - public static Bundle getSharedRelros() { - if (DEBUG) Log.i(TAG, "getSharedRelros() called"); - synchronized (Linker.class) { - if (!sInBrowserProcess) { - if (DEBUG) Log.i(TAG, "... returning null Bundle"); - return null; - } - - // Return the Bundle created in finishLibraryLoad(). - if (DEBUG) Log.i(TAG, "... returning " + sSharedRelros); - return sSharedRelros; - } - } + public abstract Bundle getSharedRelros(); /** * Call this method before loading any libraries to indicate that this * process shall neither create or reuse shared RELRO sections. */ - public static void disableSharedRelros() { - if (DEBUG) Log.i(TAG, "disableSharedRelros() called"); - synchronized (Linker.class) { - sInBrowserProcess = false; - sWaitForSharedRelros = false; - sBrowserUsesSharedRelro = false; - } - } + public abstract void disableSharedRelros(); /** * Call this method before loading any libraries to indicate that this @@ -561,22 +351,7 @@ public static void disableSharedRelros() { * Typically used when starting service processes. * @param baseLoadAddress the base library load address to use. */ - public static void initServiceProcess(long baseLoadAddress) { - if (DEBUG) { - Log.i(TAG, String.format( - Locale.US, "initServiceProcess(0x%x) called", baseLoadAddress)); - } - synchronized (Linker.class) { - ensureInitializedLocked(); - sInBrowserProcess = false; - sBrowserUsesSharedRelro = false; - if (sRelroSharingSupported) { - sWaitForSharedRelros = true; - sBaseLoadAddress = baseLoadAddress; - sCurrentLoadAddress = baseLoadAddress; - } - } - } + public abstract void initServiceProcess(long baseLoadAddress); /** * Retrieve the base load address of all shared RELRO sections. @@ -585,119 +360,7 @@ public static void initServiceProcess(long baseLoadAddress) { * @return a common, random base load address, or 0 if RELRO sharing is * disabled. */ - public static long getBaseLoadAddress() { - synchronized (Linker.class) { - ensureInitializedLocked(); - if (!sInBrowserProcess) { - Log.w(TAG, "Shared RELRO sections are disabled in this process!"); - return 0; - } - - setupBaseLoadAddressLocked(); - if (DEBUG) Log.i(TAG, String.format(Locale.US, "getBaseLoadAddress() returns 0x%x", - sBaseLoadAddress)); - return sBaseLoadAddress; - } - } - - // Used internally to lazily setup the common random base load address. - private static void setupBaseLoadAddressLocked() { - assert Thread.holdsLock(Linker.class); - if (sBaseLoadAddress == 0) { - long address = computeRandomBaseLoadAddress(); - sBaseLoadAddress = address; - sCurrentLoadAddress = address; - if (address == 0) { - // If the computed address is 0, there are issues with finding enough - // free address space, so disable RELRO shared / fixed load addresses. - Log.w(TAG, "Disabling shared RELROs due address space pressure"); - sBrowserUsesSharedRelro = false; - sWaitForSharedRelros = false; - } - } - } - - - /** - * Compute a random base load address at which to place loaded libraries. - * @return new base load address, or 0 if the system does not support - * RELRO sharing. - */ - private static long computeRandomBaseLoadAddress() { - // nativeGetRandomBaseLoadAddress() returns an address at which it has previously - // successfully mapped an area of the given size, on the basis that we will be - // able, with high probability, to map our library into it. - // - // One issue with this is that we do not yet know the size of the library that - // we will load is. So here we pass a value that we expect will always be larger - // than that needed. If it is smaller the library mapping may still succeed. The - // other issue is that although highly unlikely, there is no guarantee that - // something else does not map into the area we are going to use between here and - // when we try to map into it. - // - // The above notes mean that all of this is probablistic. It is however okay to do - // because if, worst case and unlikely, we get unlucky in our choice of address, - // the back-out and retry without the shared RELRO in the ChildProcessService will - // keep things running. - final long maxExpectedBytes = 192 * 1024 * 1024; - final long address = nativeGetRandomBaseLoadAddress(maxExpectedBytes); - if (DEBUG) { - Log.i(TAG, String.format(Locale.US, "Random native base load address: 0x%x", address)); - } - return address; - } - - // Used for debugging only. - private static void dumpBundle(Bundle bundle) { - if (DEBUG) Log.i(TAG, "Bundle has " + bundle.size() + " items: " + bundle); - } - - /** - * Use the shared RELRO section from a Bundle received form another process. - * Call this after calling setBaseLoadAddress() then loading all libraries - * with loadLibrary(). - * @param bundle Bundle instance generated with createSharedRelroBundle() in - * another process. - */ - private static void useSharedRelrosLocked(Bundle bundle) { - assert Thread.holdsLock(Linker.class); - - if (DEBUG) Log.i(TAG, "Linker.useSharedRelrosLocked() called"); - - if (bundle == null) { - if (DEBUG) Log.i(TAG, "null bundle!"); - return; - } - - if (!sRelroSharingSupported) { - if (DEBUG) Log.i(TAG, "System does not support RELRO sharing"); - return; - } - - if (sLoadedLibraries == null) { - if (DEBUG) Log.i(TAG, "No libraries loaded!"); - return; - } - - if (DEBUG) dumpBundle(bundle); - HashMap relroMap = createLibInfoMapFromBundle(bundle); - - // Apply the RELRO section to all libraries that were already loaded. - for (Map.Entry entry : relroMap.entrySet()) { - String libName = entry.getKey(); - LibInfo libInfo = entry.getValue(); - if (!nativeUseSharedRelro(libName, libInfo)) { - Log.w(TAG, "Could not use shared RELRO section for " + libName); - } else { - if (DEBUG) Log.i(TAG, "Using shared RELRO section for " + libName); - } - } - - // In service processes, close all file descriptors from the map now. - if (!sInBrowserProcess) closeLibInfoMap(relroMap); - - if (DEBUG) Log.i(TAG, "Linker.useSharedRelrosLocked() exiting"); - } + public abstract long getBaseLoadAddress(); /** * Load a native shared library with the Chromium linker. If the zip file @@ -709,254 +372,13 @@ private static void useSharedRelrosLocked(Bundle bundle) { * @param zipFilePath The path of the zip file containing the library (or null). * @param libFilePath The path of the library (possibly in the zip file). */ - public static void loadLibrary(@Nullable String zipFilePath, String libFilePath) { - if (DEBUG) Log.i(TAG, "loadLibrary: " + zipFilePath + ", " + libFilePath); - - synchronized (Linker.class) { - ensureInitializedLocked(); - - // Security: Ensure prepareLibraryLoad() was called before. - // In theory, this can be done lazily here, but it's more consistent - // to use a pair of functions (i.e. prepareLibraryLoad() + finishLibraryLoad()) - // that wrap all calls to loadLibrary() in the library loader. - assert sPrepareLibraryLoadCalled; - - if (sLoadedLibraries == null) sLoadedLibraries = new HashMap(); - - if (sLoadedLibraries.containsKey(libFilePath)) { - if (DEBUG) Log.i(TAG, "Not loading " + libFilePath + " twice"); - return; - } - - LibInfo libInfo = new LibInfo(); - long loadAddress = 0; - if ((sInBrowserProcess && sBrowserUsesSharedRelro) || sWaitForSharedRelros) { - // Load the library at a fixed address. - loadAddress = sCurrentLoadAddress; - } - - String sharedRelRoName = libFilePath; - if (zipFilePath != null) { - if (!nativeLoadLibraryInZipFile(zipFilePath, libFilePath, loadAddress, libInfo)) { - String errorMessage = "Unable to load library: " + libFilePath - + ", in: " + zipFilePath; - Log.e(TAG, errorMessage); - throw new UnsatisfiedLinkError(errorMessage); - } - sharedRelRoName = zipFilePath; - } else { - if (!nativeLoadLibrary(libFilePath, loadAddress, libInfo)) { - String errorMessage = "Unable to load library: " + libFilePath; - Log.e(TAG, errorMessage); - throw new UnsatisfiedLinkError(errorMessage); - } - } - - // Print the load address to the logcat when testing the linker. The format - // of the string is expected by the Python test_runner script as one of: - // BROWSER_LIBRARY_ADDRESS:
- // RENDERER_LIBRARY_ADDRESS:
- // Where is the library name, and
is the hexadecimal load - // address. - if (NativeLibraries.sEnableLinkerTests) { - Log.i(TAG, String.format( - Locale.US, - "%s_LIBRARY_ADDRESS: %s %x", - sInBrowserProcess ? "BROWSER" : "RENDERER", - libFilePath, - libInfo.mLoadAddress)); - } - - if (sInBrowserProcess) { - // Create a new shared RELRO section at the 'current' fixed load address. - if (!nativeCreateSharedRelro(sharedRelRoName, sCurrentLoadAddress, libInfo)) { - Log.w(TAG, String.format(Locale.US, - "Could not create shared RELRO for %s at %x", libFilePath, - sCurrentLoadAddress)); - } else { - if (DEBUG) Log.i(TAG, - String.format( - Locale.US, - "Created shared RELRO for %s at %x: %s", - sharedRelRoName, - sCurrentLoadAddress, - libInfo.toString())); - } - } - - if (sCurrentLoadAddress != 0) { - // Compute the next current load address. If sBaseLoadAddress - // is not 0, this is an explicit library load address. Otherwise, - // this is an explicit load address for relocated RELRO sections - // only. - sCurrentLoadAddress = libInfo.mLoadAddress + libInfo.mLoadSize; - } - - sLoadedLibraries.put(sharedRelRoName, libInfo); - if (DEBUG) Log.i(TAG, "Library details " + libInfo.toString()); - } - } + public abstract void loadLibrary(@Nullable String zipFilePath, String libFilePath); /** * Determine whether a library is the linker library. Also deal with the * component build that adds a .cr suffix to the name. */ - public static boolean isChromiumLinkerLibrary(String library) { - return library.equals(TAG) || library.equals(TAG + ".cr"); - } - - /** - * Get the full library path in zip file (lib//crazy.). - * - * @param library The library's base name. - * @return the library path. - */ - public static String getLibraryFilePathInZipFile(String library) throws FileNotFoundException { - synchronized (Linker.class) { - ensureInitializedLocked(); - - String path = nativeGetLibraryFilePathInZipFile(library); - if (path.equals("")) { - throw new FileNotFoundException( - "Failed to retrieve path in zip file for library " + library); - } - return path; - } - } - - /** - * Check whether a library is page aligned and uncompressed in the APK file. - * - * @param apkFile Filename of the APK. - * @param library The library's base name. - * @return true if page aligned and uncompressed. - */ - public static boolean checkLibraryIsMappableInApk(String apkFile, String library) { - synchronized (Linker.class) { - ensureInitializedLocked(); - - if (DEBUG) Log.i(TAG, "checkLibraryIsMappableInApk: " + apkFile + ", " + library); - boolean aligned = nativeCheckLibraryIsMappableInApk(apkFile, library); - if (DEBUG) Log.i(TAG, library + " is " + (aligned ? "" : "NOT ") - + "page aligned in " + apkFile); - return aligned; - } - } - - /** - * Move activity from the native thread to the main UI thread. - * Called from native code on its own thread. Posts a callback from - * the UI thread back to native code. - * - * @param opaque Opaque argument. - */ - @CalledByNative - public static void postCallbackOnMainThread(final long opaque) { - ThreadUtils.postOnUiThread(new Runnable() { - @Override - public void run() { - nativeRunCallbackOnUiThread(opaque); - } - }); - } - - /** - * Native method to run callbacks on the main UI thread. - * Supplied by the crazy linker and called by postCallbackOnMainThread. - * @param opaque Opaque crazy linker arguments. - */ - private static native void nativeRunCallbackOnUiThread(long opaque); - - /** - * Native method used to load a library. - * @param library Platform specific library name (e.g. libfoo.so) - * @param loadAddress Explicit load address, or 0 for randomized one. - * @param libInfo If not null, the mLoadAddress and mLoadSize fields - * of this LibInfo instance will set on success. - * @return true for success, false otherwise. - */ - private static native boolean nativeLoadLibrary(String library, - long loadAddress, - LibInfo libInfo); - - /** - * Native method used to load a library which is inside a zipfile. - * @param zipfileName Filename of the zip file containing the library. - * @param library Platform specific library name (e.g. libfoo.so) - * @param loadAddress Explicit load address, or 0 for randomized one. - * @param libInfo If not null, the mLoadAddress and mLoadSize fields - * of this LibInfo instance will set on success. - * @return true for success, false otherwise. - */ - private static native boolean nativeLoadLibraryInZipFile(String zipfileName, - String libraryName, - long loadAddress, - LibInfo libInfo); - - /** - * Native method used to create a shared RELRO section. - * If the library was already loaded at the same address using - * nativeLoadLibrary(), this creates the RELRO for it. Otherwise, - * this loads a new temporary library at the specified address, - * creates and extracts the RELRO section from it, then unloads it. - * @param library Library name. - * @param loadAddress load address, which can be different from the one - * used to load the library in the current process! - * @param libInfo libInfo instance. On success, the mRelroStart, mRelroSize - * and mRelroFd will be set. - * @return true on success, false otherwise. - */ - private static native boolean nativeCreateSharedRelro(String library, - long loadAddress, - LibInfo libInfo); - - /** - * Native method used to use a shared RELRO section. - * @param library Library name. - * @param libInfo A LibInfo instance containing valid RELRO information - * @return true on success. - */ - private static native boolean nativeUseSharedRelro(String library, - LibInfo libInfo); - - /** - * Checks that the system supports shared RELROs. Old Android kernels - * have a bug in the way they check Ashmem region protection flags, which - * makes using shared RELROs unsafe. This method performs a simple runtime - * check for this misfeature, even though nativeEnableSharedRelro() will - * always fail if this returns false. - */ - private static native boolean nativeCanUseSharedRelro(); - - /** - * Return a random address that should be free to be mapped with the given size. - * Maps an area of size bytes, and if successful then unmaps it and returns - * the address of the area allocated by the system (with ASLR). The idea is - * that this area should remain free of other mappings until we map our library - * into it. - * @param sizeBytes Size of area in bytes to search for. - * @return address to pass to future mmap, or 0 on error. - */ - private static native long nativeGetRandomBaseLoadAddress(long sizeBytes); - - /** - * Native method used to get the full library path in zip file - * (lib//crazy.). - * - * @param library The library's base name. - * @return the library path (or empty string on failure). - */ - private static native String nativeGetLibraryFilePathInZipFile(String library); - - /** - * Native method which checks whether a library is page aligned and - * uncompressed in the APK file. - * - * @param apkFile Filename of the APK. - * @param library The library's base name. - * @return true if page aligned and uncompressed. - */ - private static native boolean nativeCheckLibraryIsMappableInApk(String apkFile, String library); + public abstract boolean isChromiumLinkerLibrary(String library); /** * Record information for a given library. @@ -979,7 +401,9 @@ public void close() { try { ParcelFileDescriptor.adoptFd(mRelroFd).close(); } catch (java.io.IOException e) { - if (DEBUG) Log.e(TAG, "Failed to close fd: " + mRelroFd); + if (DEBUG) { + Log.e(TAG, "Failed to close fd: " + mRelroFd); + } } mRelroFd = -1; } @@ -1060,7 +484,7 @@ public String toString() { } // Create a Bundle from a map of LibInfo objects. - private static Bundle createBundleFromLibInfoMap(HashMap map) { + protected Bundle createBundleFromLibInfoMap(HashMap map) { Bundle bundle = new Bundle(map.size()); for (Map.Entry entry : map.entrySet()) { bundle.putParcelable(entry.getKey(), entry.getValue()); @@ -1070,7 +494,7 @@ private static Bundle createBundleFromLibInfoMap(HashMap map) { } // Create a new LibInfo map from a Bundle. - private static HashMap createLibInfoMapFromBundle(Bundle bundle) { + protected HashMap createLibInfoMapFromBundle(Bundle bundle) { HashMap map = new HashMap(); for (String library : bundle.keySet()) { LibInfo libInfo = bundle.getParcelable(library); @@ -1080,16 +504,9 @@ private static HashMap createLibInfoMapFromBundle(Bundle bundle } // Call the close() method on all values of a LibInfo map. - private static void closeLibInfoMap(HashMap map) { + protected void closeLibInfoMap(HashMap map) { for (Map.Entry entry : map.entrySet()) { entry.getValue().close(); } } - - // The map of libraries that are currently loaded in this process. - private static HashMap sLoadedLibraries = null; - - // Used to pass the shared RELRO Bundle through Binder. - public static final String EXTRA_LINKER_SHARED_RELROS = - "org.chromium.base.android.linker.shared_relros"; } diff --git a/base/android/javatests/src/org/chromium/base/metrics/RecordHistogramTest.java b/base/android/javatests/src/org/chromium/base/metrics/RecordHistogramTest.java index 24af056f1cee0..1bf9c216145da 100644 --- a/base/android/javatests/src/org/chromium/base/metrics/RecordHistogramTest.java +++ b/base/android/javatests/src/org/chromium/base/metrics/RecordHistogramTest.java @@ -20,7 +20,8 @@ public class RecordHistogramTest extends InstrumentationTestCase { @Override protected void setUp() throws Exception { super.setUp(); - LibraryLoader.get(LibraryProcessType.PROCESS_BROWSER).ensureInitialized(); + LibraryLoader.get(LibraryProcessType.PROCESS_BROWSER) + .ensureInitialized(getInstrumentation().getTargetContext()); RecordHistogram.initialize(); } diff --git a/base/android/jni_generator/java/src/org/chromium/example/jni_generator/SampleForTests.java b/base/android/jni_generator/java/src/org/chromium/example/jni_generator/SampleForTests.java index f54944b1ff24d..dad59ce9c3ee9 100644 --- a/base/android/jni_generator/java/src/org/chromium/example/jni_generator/SampleForTests.java +++ b/base/android/jni_generator/java/src/org/chromium/example/jni_generator/SampleForTests.java @@ -125,7 +125,7 @@ public void finishExample() { // This is triggered by the @CalledByNative annotation; the methods may be named as you wish. // Exported to C++ as: - // Java_Example_javaMethod(JNIEnv* env, jobject obj, jint foo, jint bar) + // Java_Example_javaMethod(JNIEnv* env, jobject caller, jint foo, jint bar) // Typically the C++ code would have obtained the jobject via the Init() call described above. @CalledByNative public int javaMethod(int foo, int bar) { @@ -177,7 +177,7 @@ void methodThatThrowsException() throws Exception {} // signatures. Besides these constraints the methods can be freely named. // This declares a C++ function which the application code must implement: - // static jint Init(JNIEnv* env, jobject obj); + // static jint Init(JNIEnv* env, jobject caller); // The jobject parameter refers back to this java side object instance. // The implementation must return the pointer to the C++ object cast to jint. // The caller of this method should store it, and supply it as a the nativeCPPClass param to @@ -195,7 +195,7 @@ void methodThatThrowsException() throws Exception {} private native void nativeDestroy(long nativeCPPClass); // This declares a C++ function which the application code must implement: - // static jdouble GetDoubleFunction(JNIEnv* env, jobject obj); + // static jdouble GetDoubleFunction(JNIEnv* env, jobject caller); // The jobject parameter refers back to this java side object instance. private native double nativeGetDoubleFunction(); @@ -209,7 +209,7 @@ void methodThatThrowsException() throws Exception {} private native void nativeSetNonPODDatatype(Rect rect); // This declares a C++ function which the application code must implement: - // static ScopedJavaLocalRef GetNonPODDatatype(JNIEnv* env, jobject obj); + // static ScopedJavaLocalRef GetNonPODDatatype(JNIEnv* env, jobject caller); // The jobject parameter refers back to this java side object instance. // Note that it returns a ScopedJavaLocalRef so that you don' have to worry about // deleting the JNI local reference. This is similar with Strings and arrays. diff --git a/base/android/jni_generator/jni_generator.py b/base/android/jni_generator/jni_generator.py index d1f14baa42899..74d0117495dd9 100755 --- a/base/android/jni_generator/jni_generator.py +++ b/base/android/jni_generator/jni_generator.py @@ -236,6 +236,9 @@ def JavaToJni(param): 'Ljava/lang/Object', 'Ljava/lang/String', 'Ljava/lang/Class', + 'Ljava/lang/CharSequence', + 'Ljava/lang/Runnable', + 'Ljava/lang/Throwable', ] prefix = '' diff --git a/base/android/jni_generator/jni_generator_tests.py b/base/android/jni_generator/jni_generator_tests.py index 60148470b31f0..21534ef44585f 100755 --- a/base/android/jni_generator/jni_generator_tests.py +++ b/base/android/jni_generator/jni_generator_tests.py @@ -1085,29 +1085,6 @@ def willRaise(): TestOptions()) self.assertRaises(SyntaxError, willRaise) - def testImplicitImport(self): - test_data = """ - package org.chromium.android_webview; - - %(IMPORT)s - - @CalledByNative - private static void clientCertificatesCleared(Runnable callback) { - if (callbaback == null) return; - callback.run(); - } - """ - def generate(import_clause): - jni_generator.JNIFromJavaSource( - test_data % {'IMPORT': import_clause}, - 'org/chromium/android_webview/AwContentStatics', - TestOptions()) - # Ensure it raises without the import. - self.assertRaises(SyntaxError, lambda: generate('')) - - # Ensure it's fine with the import. - generate('import java.lang.Runnable;') - def testSingleJNIAdditionalImport(self): test_data = """ package org.chromium.foo; diff --git a/base/android/jni_generator/sample_for_tests.cc b/base/android/jni_generator/sample_for_tests.cc index 3c5ca028906c8..61dd7f38eb2cf 100644 --- a/base/android/jni_generator/sample_for_tests.cc +++ b/base/android/jni_generator/sample_for_tests.cc @@ -18,7 +18,7 @@ using base::android::ScopedJavaLocalRef; namespace base { namespace android { -jdouble CPPClass::InnerClass::MethodOtherP0(JNIEnv* env, jobject obj) { +jdouble CPPClass::InnerClass::MethodOtherP0(JNIEnv* env, jobject caller) { return 0.0; } @@ -33,22 +33,22 @@ bool CPPClass::RegisterJNI(JNIEnv* env) { return RegisterNativesImpl(env); // Generated in SampleForTests_jni.h } -void CPPClass::Destroy(JNIEnv* env, jobject obj) { +void CPPClass::Destroy(JNIEnv* env, jobject caller) { delete this; } -jint CPPClass::Method(JNIEnv* env, jobject obj) { +jint CPPClass::Method(JNIEnv* env, jobject caller) { return 0; } -void CPPClass::AddStructB(JNIEnv* env, jobject obj, jobject structb) { +void CPPClass::AddStructB(JNIEnv* env, jobject caller, jobject structb) { long key = Java_InnerStructB_getKey(env, structb); std::string value = ConvertJavaStringToUTF8( env, Java_InnerStructB_getValue(env, structb).obj()); map_[key] = value; } -void CPPClass::IterateAndDoSomethingWithStructB(JNIEnv* env, jobject obj) { +void CPPClass::IterateAndDoSomethingWithStructB(JNIEnv* env, jobject caller) { // Iterate over the elements and do something with them. for (std::map::const_iterator it = map_.begin(); it != map_.end(); ++it) { @@ -59,14 +59,14 @@ void CPPClass::IterateAndDoSomethingWithStructB(JNIEnv* env, jobject obj) { } base::android::ScopedJavaLocalRef CPPClass::ReturnAString( - JNIEnv* env, jobject obj) { + JNIEnv* env, jobject caller) { base::android::ScopedJavaLocalRef ret = ConvertUTF8ToJavaString( env, "test"); return ret; } // Static free functions declared and called directly from java. -static jlong Init(JNIEnv* env, jobject obj, jstring param) { +static jlong Init(JNIEnv* env, jobject caller, jstring param) { return 0; } diff --git a/base/android/jni_generator/sample_for_tests.h b/base/android/jni_generator/sample_for_tests.h index e878e56cf6a42..5366faf2a8897 100644 --- a/base/android/jni_generator/sample_for_tests.h +++ b/base/android/jni_generator/sample_for_tests.h @@ -148,19 +148,19 @@ class CPPClass { class InnerClass { public: - jdouble MethodOtherP0(JNIEnv* env, jobject obj); + jdouble MethodOtherP0(JNIEnv* env, jobject caller); }; - void Destroy(JNIEnv* env, jobject obj); + void Destroy(JNIEnv* env, jobject caller); - jint Method(JNIEnv* env, jobject obj); + jint Method(JNIEnv* env, jobject caller); - void AddStructB(JNIEnv* env, jobject obj, jobject structb); + void AddStructB(JNIEnv* env, jobject caller, jobject structb); - void IterateAndDoSomethingWithStructB(JNIEnv* env, jobject obj); + void IterateAndDoSomethingWithStructB(JNIEnv* env, jobject caller); base::android::ScopedJavaLocalRef ReturnAString( - JNIEnv* env, jobject obj); + JNIEnv* env, jobject caller); private: std::map map_; diff --git a/base/android/junit/src/org/chromium/base/BaseChromiumApplicationTest.java b/base/android/junit/src/org/chromium/base/BaseChromiumApplicationTest.java index d3441f7895fed..0aa9ccd388faa 100644 --- a/base/android/junit/src/org/chromium/base/BaseChromiumApplicationTest.java +++ b/base/android/junit/src/org/chromium/base/BaseChromiumApplicationTest.java @@ -8,7 +8,6 @@ import static org.mockito.Mockito.verify; import android.app.Activity; -import android.view.KeyEvent; import junit.framework.Assert; @@ -39,12 +38,6 @@ public static class TrackingShadowActivity extends ShadowActivity { public void onWindowFocusChanged(@SuppressWarnings("unused") boolean hasFocus) { mWindowFocusCalls++; } - - @Implementation - public boolean dispatchKeyEvent(@SuppressWarnings("unused") KeyEvent event) { - mDispatchKeyEventCalls++; - return mReturnValueForKeyDispatch; - } } @Test @@ -65,30 +58,4 @@ public void testWindowsFocusChanged() throws Exception { // Also ensure that the original activity is forwarded the notification. Assert.assertEquals(1, shadow.mWindowFocusCalls); } - - @Test - public void testDispatchKeyEvent() throws Exception { - ActivityController controller = - Robolectric.buildActivity(Activity.class).create().start().visible(); - TrackingShadowActivity shadow = - (TrackingShadowActivity) Robolectric.shadowOf(controller.get()); - - final KeyEvent menuKey = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MENU); - - // Ensure that key events are forwarded. - Assert.assertFalse(controller.get().getWindow().getCallback().dispatchKeyEvent(menuKey)); - // This gets called twice - once to see if the activity is swallowing it, and again to - // dispatch it. - Assert.assertEquals(2, shadow.mDispatchKeyEventCalls); - - // Ensure that our activity can swallow the event. - shadow.mReturnValueForKeyDispatch = true; - Assert.assertTrue(controller.get().getWindow().getCallback().dispatchKeyEvent(menuKey)); - Assert.assertEquals(3, shadow.mDispatchKeyEventCalls); - - // A non-enter key only dispatches once. - Assert.assertTrue(controller.get().getWindow().getCallback().dispatchKeyEvent( - new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_SPACE))); - Assert.assertEquals(4, shadow.mDispatchKeyEventCalls); - } } diff --git a/base/android/junit/src/org/chromium/base/LogTest.java b/base/android/junit/src/org/chromium/base/LogTest.java index 46bdc67e62dcf..e5ce239d04822 100644 --- a/base/android/junit/src/org/chromium/base/LogTest.java +++ b/base/android/junit/src/org/chromium/base/LogTest.java @@ -9,6 +9,7 @@ import static org.junit.Assert.assertTrue; import org.chromium.testing.local.LocalRobolectricTestRunner; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.annotation.Config; @@ -22,20 +23,6 @@ @RunWith(LocalRobolectricTestRunner.class) @Config(manifest = Config.NONE, shadows = {LogTest.PermissiveShadowLog.class}) public class LogTest { - /** Test method for {@link Log#makeTag(String)} */ - @Test - public void testMakeTag() { - assertEquals("cr.Foo", Log.makeTag("Foo")); - assertEquals("cr", Log.makeTag(null)); - assertEquals("cr", Log.makeTag("")); - } - - /** Test method for {@link Log#makeTag(String)} */ - @Test(expected = IllegalArgumentException.class) - public void testMakeTagFailure() { - Log.makeTag("ThisIs21Char.....Long"); - } - /** Tests that the computed call origin is the correct one. */ @Test public void callOriginTest() { @@ -88,12 +75,138 @@ public String toString() { assertEquals("Bar MyThrowable MyOtherThrowable", logs.get(logs.size() - 1).msg); } + public void verboseLoggingTest() { + PermissiveShadowLog.setLevel(Log.VERBOSE); + List logs = ShadowLog.getLogs(); + + Log.wtf("Foo", "Bar"); + Log.e("Foo", "Bar"); + Log.w("Foo", "Bar"); + Log.i("Foo", "Bar"); + Log.d("Foo", "Bar"); + Log.v("Foo", "Bar"); + + assertEquals(Log.ASSERT, logs.get(0).type); + assertEquals(Log.ERROR, logs.get(1).type); + assertEquals(Log.WARN, logs.get(2).type); + assertEquals(Log.INFO, logs.get(3).type); + assertEquals(Log.DEBUG, logs.get(4).type); + assertEquals(Log.VERBOSE, logs.get(5).type); + assertEquals(6, logs.size()); + } + + @Test + public void debugLoggingTest() { + PermissiveShadowLog.setLevel(Log.DEBUG); + List logs = ShadowLog.getLogs(); + + Log.wtf("Foo", "Bar"); + Log.e("Foo", "Bar"); + Log.w("Foo", "Bar"); + Log.i("Foo", "Bar"); + Log.d("Foo", "Bar"); + Log.v("Foo", "Bar"); + + assertEquals(Log.ASSERT, logs.get(0).type); + assertEquals(Log.ERROR, logs.get(1).type); + assertEquals(Log.WARN, logs.get(2).type); + assertEquals(Log.INFO, logs.get(3).type); + assertEquals(Log.DEBUG, logs.get(4).type); + assertEquals(5, logs.size()); + } + + @Test + public void infoLoggingTest() { + PermissiveShadowLog.setLevel(Log.INFO); + List logs = ShadowLog.getLogs(); + + Log.wtf("Foo", "Bar"); + Log.e("Foo", "Bar"); + Log.w("Foo", "Bar"); + Log.i("Foo", "Bar"); + Log.d("Foo", "Bar"); + Log.v("Foo", "Bar"); + + assertEquals(Log.ASSERT, logs.get(0).type); + assertEquals(Log.ERROR, logs.get(1).type); + assertEquals(Log.WARN, logs.get(2).type); + assertEquals(Log.INFO, logs.get(3).type); + assertEquals(4, logs.size()); + } + + @Test + public void warnLoggingTest() { + PermissiveShadowLog.setLevel(Log.WARN); + List logs = ShadowLog.getLogs(); + + Log.wtf("Foo", "Bar"); + Log.e("Foo", "Bar"); + Log.w("Foo", "Bar"); + Log.i("Foo", "Bar"); + Log.d("Foo", "Bar"); + Log.v("Foo", "Bar"); + + assertEquals(Log.ASSERT, logs.get(0).type); + assertEquals(Log.ERROR, logs.get(1).type); + assertEquals(Log.WARN, logs.get(2).type); + assertEquals(3, logs.size()); + } + + @Test + public void errorLoggingTest() { + PermissiveShadowLog.setLevel(Log.ERROR); + List logs = ShadowLog.getLogs(); + + Log.wtf("Foo", "Bar"); + Log.e("Foo", "Bar"); + Log.w("Foo", "Bar"); + Log.i("Foo", "Bar"); + Log.d("Foo", "Bar"); + Log.v("Foo", "Bar"); + + assertEquals(Log.ASSERT, logs.get(0).type); + assertEquals(Log.ERROR, logs.get(1).type); + assertEquals(2, logs.size()); + } + + @Test + public void assertLoggingTest() { + PermissiveShadowLog.setLevel(Log.ASSERT); + List logs = ShadowLog.getLogs(); + + Log.wtf("Foo", "Bar"); + Log.e("Foo", "Bar"); + Log.w("Foo", "Bar"); + Log.i("Foo", "Bar"); + Log.d("Foo", "Bar"); + Log.v("Foo", "Bar"); + + assertEquals(Log.ASSERT, logs.get(0).type); + assertEquals(1, logs.size()); + } + + @Before + public void beforeTest() { + PermissiveShadowLog.reset(); + } + /** Needed to allow debug/verbose logging that is disabled by default. */ @Implements(android.util.Log.class) public static class PermissiveShadowLog extends ShadowLog { + private static int sLevel = Log.VERBOSE; + + /** Sets the log level for all tags. */ + public static void setLevel(int level) { + sLevel = level; + } + @Implementation public static boolean isLoggable(String tag, int level) { - return true; + return level >= sLevel; + } + + public static void reset() { + sLevel = Log.VERBOSE; } } } diff --git a/base/android/library_loader/library_loader_hooks.cc b/base/android/library_loader/library_loader_hooks.cc index 0b59a30429676..2ba78883471c1 100644 --- a/base/android/library_loader/library_loader_hooks.cc +++ b/base/android/library_loader/library_loader_hooks.cc @@ -48,13 +48,19 @@ enum BrowserHistogramCode { RendererHistogramCode g_renderer_histogram_code = NO_PENDING_HISTOGRAM_CODE; +// The amount of time, in milliseconds, that it took to load the shared +// libraries in the renderer. Set in +// RegisterChromiumAndroidLinkerRendererHistogram. +long g_renderer_library_load_time_ms = 0; + } // namespace static void RegisterChromiumAndroidLinkerRendererHistogram( JNIEnv* env, jobject jcaller, jboolean requested_shared_relro, - jboolean load_at_fixed_address_failed) { + jboolean load_at_fixed_address_failed, + jlong library_load_time_ms) { // Note a pending histogram value for later recording. if (requested_shared_relro) { g_renderer_histogram_code = load_at_fixed_address_failed @@ -62,6 +68,8 @@ static void RegisterChromiumAndroidLinkerRendererHistogram( } else { g_renderer_histogram_code = LFA_NOT_ATTEMPTED; } + + g_renderer_library_load_time_ms = library_load_time_ms; } void RecordChromiumAndroidLinkerRendererHistogram() { @@ -72,6 +80,10 @@ void RecordChromiumAndroidLinkerRendererHistogram() { g_renderer_histogram_code, MAX_RENDERER_HISTOGRAM_CODE); g_renderer_histogram_code = NO_PENDING_HISTOGRAM_CODE; + + // Record how long it took to load the shared libraries. + UMA_HISTOGRAM_TIMES("ChromiumAndroidLinker.RendererLoadTime", + base::TimeDelta::FromMilliseconds(g_renderer_library_load_time_ms)); } static void RecordChromiumAndroidLinkerBrowserHistogram( @@ -79,7 +91,8 @@ static void RecordChromiumAndroidLinkerBrowserHistogram( jobject jcaller, jboolean is_using_browser_shared_relros, jboolean load_at_fixed_address_failed, - jint library_load_from_apk_status) { + jint library_load_from_apk_status, + jlong library_load_time_ms) { // For low-memory devices, record whether or not we successfully loaded the // browser at a fixed address. Otherwise just record a normal invocation. BrowserHistogramCode histogram_code; @@ -97,6 +110,10 @@ static void RecordChromiumAndroidLinkerBrowserHistogram( UMA_HISTOGRAM_ENUMERATION("ChromiumAndroidLinker.LibraryLoadFromApkStatus", library_load_from_apk_status, LIBRARY_LOAD_FROM_APK_STATUS_CODES_MAX); + + // Record how long it took to load the shared libraries. + UMA_HISTOGRAM_TIMES("ChromiumAndroidLinker.BrowserLoadTime", + base::TimeDelta::FromMilliseconds(library_load_time_ms)); } void SetLibraryLoadedHook(LibraryLoadedHook* func) { diff --git a/base/android/library_loader/library_prefetcher.cc b/base/android/library_loader/library_prefetcher.cc index 798a283d71b32..9b54843fc8329 100644 --- a/base/android/library_loader/library_prefetcher.cc +++ b/base/android/library_loader/library_prefetcher.cc @@ -36,7 +36,7 @@ bool IsReadableAndPrivate(const base::debug::MappedMemoryRegion& region) { bool PathMatchesSuffix(const std::string& path) { for (size_t i = 0; i < arraysize(kSuffixesToMatch); i++) { - if (EndsWith(path, kSuffixesToMatch[i], true)) { + if (EndsWith(path, kSuffixesToMatch[i], CompareCase::SENSITIVE)) { return true; } } @@ -82,14 +82,14 @@ void NativeLibraryPrefetcher::FilterLibchromeRangesOnlyIfPossible( std::vector* ranges) { bool has_libchrome_region = false; for (const base::debug::MappedMemoryRegion& region : regions) { - if (EndsWith(region.path, kLibchromeSuffix, true)) { + if (EndsWith(region.path, kLibchromeSuffix, CompareCase::SENSITIVE)) { has_libchrome_region = true; break; } } for (const base::debug::MappedMemoryRegion& region : regions) { if (has_libchrome_region && - !EndsWith(region.path, kLibchromeSuffix, true)) { + !EndsWith(region.path, kLibchromeSuffix, CompareCase::SENSITIVE)) { continue; } ranges->push_back(std::make_pair(region.start, region.end)); diff --git a/base/android/linker/BUILD.gn b/base/android/linker/BUILD.gn index 190ea4776d44e..043bfc6b3be9d 100644 --- a/base/android/linker/BUILD.gn +++ b/base/android/linker/BUILD.gn @@ -9,7 +9,7 @@ assert(is_android) # GYP: //base/base.gyp:chromium_android_linker shared_library("chromium_android_linker") { sources = [ - "linker_jni.cc", + "legacy_linker_jni.cc", ] # The NDK contains the crazy_linker here: diff --git a/base/android/linker/linker_jni.cc b/base/android/linker/legacy_linker_jni.cc similarity index 90% rename from base/android/linker/linker_jni.cc rename to base/android/linker/legacy_linker_jni.cc index 2bc480cf776dd..14c260f71c136 100644 --- a/base/android/linker/linker_jni.cc +++ b/base/android/linker/legacy_linker_jni.cc @@ -22,6 +22,13 @@ #include #include +// See commentary in crazy_linker_elf_loader.cpp for the effect of setting +// this. If changing there, change here also. +// +// For more, see: +// https://crbug.com/504410 +#define RESERVE_BREAKPAD_GUARD_REGION 1 + // Set this to 1 to enable debug traces to the Android log. // Note that LOG() from "base/logging.h" cannot be used, since it is // in base/ which hasn't been loaded yet. @@ -626,6 +633,13 @@ jboolean CanUseSharedRelro(JNIEnv* env, jclass clazz) { } jlong GetRandomBaseLoadAddress(JNIEnv* env, jclass clazz, jlong bytes) { +#if RESERVE_BREAKPAD_GUARD_REGION + // Add a Breakpad guard region. 16Mb should be comfortably larger than + // the largest relocation packer saving we expect to encounter. + static const size_t kBreakpadGuardRegionBytes = 16 * 1024 * 1024; + bytes += kBreakpadGuardRegionBytes; +#endif + void* address = mmap(NULL, bytes, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (address == MAP_FAILED) { @@ -633,54 +647,15 @@ jlong GetRandomBaseLoadAddress(JNIEnv* env, jclass clazz, jlong bytes) { return 0; } munmap(address, bytes); - LOG_INFO("%s: Random base load address is %p\n", __FUNCTION__, address); - return static_cast(reinterpret_cast(address)); -} -// Get the full path of a library in the zip file -// (lib//crazy.). -// -// |env| is the current JNI environment handle. -// |clazz| is the static class handle which is not used here. -// |lib_name| is the library base name. -// Returns the full path (or empty string on failure). -jstring GetLibraryFilePathInZipFile(JNIEnv* env, - jclass clazz, - jstring lib_name) { - String lib_name_str(env, lib_name); - const char* lib_name_c_str = lib_name_str.c_str(); - char buffer[kMaxFilePathLengthInZip + 1]; - if (crazy_library_file_path_in_zip_file( - lib_name_c_str, buffer, sizeof(buffer)) == CRAZY_STATUS_FAILURE) { - LOG_ERROR("%s: Failed to get full filename for library '%s'", - __FUNCTION__, lib_name_c_str); - buffer[0] = '\0'; - } - return env->NewStringUTF(buffer); -} +#if RESERVE_BREAKPAD_GUARD_REGION + // Allow for a Breakpad guard region ahead of the returned address. + address = reinterpret_cast( + reinterpret_cast(address) + kBreakpadGuardRegionBytes); +#endif -// Check whether a library is page aligned and uncompressed in the APK file. -// -// |env| is the current JNI environment handle. -// |clazz| is the static class handle which is not used here. -// |apkfile_name| is the filename of the APK. -// |library_name| is the library base name. -// Returns true if page aligned and uncompressed. -jboolean CheckLibraryIsMappableInApk(JNIEnv* env, jclass clazz, - jstring apkfile_name, - jstring library_name) { - String apkfile_name_str(env, apkfile_name); - const char* apkfile_name_c_str = apkfile_name_str.c_str(); - String library_name_str(env, library_name); - const char* library_name_c_str = library_name_str.c_str(); - - LOG_INFO("%s: Checking if %s is page-aligned and uncompressed in %s\n", - __FUNCTION__, library_name_c_str, apkfile_name_c_str); - jboolean mappable = crazy_linker_check_library_is_mappable_in_zip_file( - apkfile_name_c_str, library_name_c_str) == CRAZY_STATUS_SUCCESS; - LOG_INFO("%s: %s\n", __FUNCTION__, mappable ? "Mappable" : "NOT mappable"); - - return mappable; + LOG_INFO("%s: Random base load address is %p\n", __FUNCTION__, address); + return static_cast(reinterpret_cast(address)); } const JNINativeMethod kNativeMethods[] = { @@ -733,19 +708,7 @@ const JNINativeMethod kNativeMethods[] = { ")" "J", reinterpret_cast(&GetRandomBaseLoadAddress)}, - {"nativeGetLibraryFilePathInZipFile", - "(" - "Ljava/lang/String;" - ")" - "Ljava/lang/String;", - reinterpret_cast(&GetLibraryFilePathInZipFile)}, - {"nativeCheckLibraryIsMappableInApk", - "(" - "Ljava/lang/String;" - "Ljava/lang/String;" - ")" - "Z", - reinterpret_cast(&CheckLibraryIsMappableInApk)}, }; +}; } // namespace @@ -769,7 +732,7 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) { // Register native methods. jclass linker_class; if (!InitClassReference(env, - "org/chromium/base/library_loader/Linker", + "org/chromium/base/library_loader/LegacyLinker", &linker_class)) return -1; diff --git a/base/android/path_utils.cc b/base/android/path_utils.cc index c98007cf8b4c3..caad53a36f6a6 100644 --- a/base/android/path_utils.cc +++ b/base/android/path_utils.cc @@ -41,6 +41,16 @@ bool GetCacheDirectory(FilePath* result) { return true; } +bool GetThumbnailCacheDirectory(FilePath* result) { + JNIEnv* env = AttachCurrentThread(); + ScopedJavaLocalRef path = + Java_PathUtils_getThumbnailCacheDirectoryPath(env, + GetApplicationContext()); + FilePath thumbnail_cache_path(ConvertJavaStringToUTF8(path)); + *result = thumbnail_cache_path; + return true; +} + bool GetDownloadsDirectory(FilePath* result) { JNIEnv* env = AttachCurrentThread(); ScopedJavaLocalRef path = diff --git a/base/android/path_utils.h b/base/android/path_utils.h index d3421b3b01aa7..6501f1bdb6804 100644 --- a/base/android/path_utils.h +++ b/base/android/path_utils.h @@ -31,6 +31,10 @@ BASE_EXPORT bool GetDatabaseDirectory(FilePath* result); // cache dir. BASE_EXPORT bool GetCacheDirectory(FilePath* result); +// Retrieves the path to the thumbnail cache directory. The result is placed +// in the FilePath pointed to by 'result'. +BASE_EXPORT bool GetThumbnailCacheDirectory(FilePath* result); + // Retrieves the path to the public downloads directory. The result is placed // in the FilePath pointed to by 'result'. BASE_EXPORT bool GetDownloadsDirectory(FilePath* result); diff --git a/base/android/trace_event_binding.cc b/base/android/trace_event_binding.cc index 791b67fcf23e1..3c5ee17c7abf0 100644 --- a/base/android/trace_event_binding.cc +++ b/base/android/trace_event_binding.cc @@ -8,6 +8,7 @@ #include +#include "base/android/jni_string.h" #include "base/lazy_instance.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event_impl.h" @@ -25,32 +26,28 @@ const char kLooperDispatchMessage[] = "Looper.dispatchMessage"; // Boilerplate for safely converting Java data to TRACE_EVENT data. class TraceEventDataConverter { public: - TraceEventDataConverter(JNIEnv* env, - jstring jname, - jstring jarg) + TraceEventDataConverter(JNIEnv* env, jstring jname, jstring jarg) : env_(env), jname_(jname), jarg_(jarg), - name_(env->GetStringUTFChars(jname, NULL)), - arg_(jarg ? env->GetStringUTFChars(jarg, NULL) : NULL) { - } + name_(ConvertJavaStringToUTF8(env, jname)), + has_arg_(jarg != nullptr), + arg_(jarg ? ConvertJavaStringToUTF8(env, jarg) : "") {} ~TraceEventDataConverter() { - env_->ReleaseStringUTFChars(jname_, name_); - if (jarg_) - env_->ReleaseStringUTFChars(jarg_, arg_); } // Return saves values to pass to TRACE_EVENT macros. - const char* name() { return name_; } - const char* arg_name() { return arg_ ? "arg" : NULL; } - const char* arg() { return arg_; } + const char* name() { return name_.c_str(); } + const char* arg_name() { return has_arg_ ? "arg" : nullptr; } + const char* arg() { return has_arg_ ? arg_.c_str() : nullptr; } private: JNIEnv* env_; jstring jname_; jstring jarg_; - const char* name_; - const char* arg_; + std::string name_; + bool has_arg_; + std::string arg_; DISALLOW_COPY_AND_ASSIGN(TraceEventDataConverter); }; diff --git a/base/atomicops.h b/base/atomicops.h index 6a5371c75c295..f983b455f193d 100644 --- a/base/atomicops.h +++ b/base/atomicops.h @@ -144,33 +144,6 @@ Atomic64 Release_Load(volatile const Atomic64* ptr); } // namespace subtle } // namespace base -// The following x86 CPU features are used in atomicops_internals_x86_gcc.h, but -// this file is duplicated inside of Chrome: protobuf and tcmalloc rely on the -// struct being present at link time. Some parts of Chrome can currently use the -// portable interface whereas others still use GCC one. The include guards are -// the same as in atomicops_internals_x86_gcc.cc. -#if defined(__i386__) || defined(__x86_64__) -// This struct is not part of the public API of this module; clients may not -// use it. (However, it's exported via BASE_EXPORT because clients implicitly -// do use it at link time by inlining these functions.) -// Features of this x86. Values may not be correct before main() is run, -// but are set conservatively. -struct AtomicOps_x86CPUFeatureStruct { - bool has_amd_lock_mb_bug; // Processor has AMD memory-barrier bug; do lfence - // after acquire compare-and-swap. - // The following fields are unused by Chrome's base implementation but are - // still used by copies of the same code in other parts of the code base. This - // causes an ODR violation, and the other code is likely reading invalid - // memory. - // TODO(jfb) Delete these fields once the rest of the Chrome code base doesn't - // depend on them. - bool has_sse2; // Processor has SSE2. - bool has_cmpxchg16b; // Processor supports cmpxchg16b instruction. -}; -BASE_EXPORT extern struct AtomicOps_x86CPUFeatureStruct - AtomicOps_Internalx86CPUFeatures; -#endif - // Try to use a portable implementation based on C++11 atomics. // // Some toolchains support C++11 language features without supporting library @@ -188,17 +161,6 @@ BASE_EXPORT extern struct AtomicOps_x86CPUFeatureStruct # include "base/atomicops_internals_x86_msvc.h" # elif defined(OS_MACOSX) # include "base/atomicops_internals_mac.h" -# elif defined(OS_NACL) -# include "base/atomicops_internals_gcc.h" -# elif defined(COMPILER_GCC) && defined(ARCH_CPU_ARMEL) -# include "base/atomicops_internals_arm_gcc.h" -# elif defined(COMPILER_GCC) && defined(ARCH_CPU_ARM64) -# include "base/atomicops_internals_arm64_gcc.h" -# elif defined(COMPILER_GCC) && defined(ARCH_CPU_X86_FAMILY) -# include "base/atomicops_internals_x86_gcc.h" -# elif (defined(COMPILER_GCC) && \ - (defined(ARCH_CPU_MIPS_FAMILY) || defined(ARCH_CPU_MIPS64_FAMILY))) -# include "base/atomicops_internals_mips_gcc.h" # else # error "Atomic operations are not supported on your platform" # endif diff --git a/base/atomicops_internals_arm64_gcc.h b/base/atomicops_internals_arm64_gcc.h deleted file mode 100644 index ddcfec901f937..0000000000000 --- a/base/atomicops_internals_arm64_gcc.h +++ /dev/null @@ -1,307 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This file is an internal atomic implementation, use base/atomicops.h instead. - -// TODO(rmcilroy): Investigate whether we can use __sync__ intrinsics instead of -// the hand coded assembly without introducing perf regressions. -// TODO(rmcilroy): Investigate whether we can use acquire / release versions of -// exclusive load / store assembly instructions and do away with -// the barriers. - -#ifndef BASE_ATOMICOPS_INTERNALS_ARM64_GCC_H_ -#define BASE_ATOMICOPS_INTERNALS_ARM64_GCC_H_ - -#if defined(OS_QNX) -#include -#endif - -namespace base { -namespace subtle { - -inline void MemoryBarrier() { - __asm__ __volatile__ ("dmb ish" ::: "memory"); // NOLINT -} - -// NoBarrier versions of the operation include "memory" in the clobber list. -// This is not required for direct usage of the NoBarrier versions of the -// operations. However this is required for correctness when they are used as -// part of the Acquire or Release versions, to ensure that nothing from outside -// the call is reordered between the operation and the memory barrier. This does -// not change the code generated, so has no or minimal impact on the -// NoBarrier operations. - -inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - Atomic32 prev; - int32_t temp; - - __asm__ __volatile__ ( // NOLINT - "0: \n\t" - "ldxr %w[prev], %[ptr] \n\t" // Load the previous value. - "cmp %w[prev], %w[old_value] \n\t" - "bne 1f \n\t" - "stxr %w[temp], %w[new_value], %[ptr] \n\t" // Try to store the new value. - "cbnz %w[temp], 0b \n\t" // Retry if it did not work. - "1: \n\t" - : [prev]"=&r" (prev), - [temp]"=&r" (temp), - [ptr]"+Q" (*ptr) - : [old_value]"IJr" (old_value), - [new_value]"r" (new_value) - : "cc", "memory" - ); // NOLINT - - return prev; -} - -inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, - Atomic32 new_value) { - Atomic32 result; - int32_t temp; - - __asm__ __volatile__ ( // NOLINT - "0: \n\t" - "ldxr %w[result], %[ptr] \n\t" // Load the previous value. - "stxr %w[temp], %w[new_value], %[ptr] \n\t" // Try to store the new value. - "cbnz %w[temp], 0b \n\t" // Retry if it did not work. - : [result]"=&r" (result), - [temp]"=&r" (temp), - [ptr]"+Q" (*ptr) - : [new_value]"r" (new_value) - : "memory" - ); // NOLINT - - return result; -} - -inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment) { - Atomic32 result; - int32_t temp; - - __asm__ __volatile__ ( // NOLINT - "0: \n\t" - "ldxr %w[result], %[ptr] \n\t" // Load the previous value. - "add %w[result], %w[result], %w[increment]\n\t" - "stxr %w[temp], %w[result], %[ptr] \n\t" // Try to store the result. - "cbnz %w[temp], 0b \n\t" // Retry on failure. - : [result]"=&r" (result), - [temp]"=&r" (temp), - [ptr]"+Q" (*ptr) - : [increment]"IJr" (increment) - : "memory" - ); // NOLINT - - return result; -} - -inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment) { - MemoryBarrier(); - Atomic32 result = NoBarrier_AtomicIncrement(ptr, increment); - MemoryBarrier(); - - return result; -} - -inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - Atomic32 prev = NoBarrier_CompareAndSwap(ptr, old_value, new_value); - MemoryBarrier(); - - return prev; -} - -inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - MemoryBarrier(); - Atomic32 prev = NoBarrier_CompareAndSwap(ptr, old_value, new_value); - - return prev; -} - -inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { - *ptr = value; -} - -inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { - *ptr = value; - MemoryBarrier(); -} - -inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { - __asm__ __volatile__ ( // NOLINT - "stlr %w[value], %[ptr] \n\t" - : [ptr]"=Q" (*ptr) - : [value]"r" (value) - : "memory" - ); // NOLINT -} - -inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { - return *ptr; -} - -inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { - Atomic32 value; - - __asm__ __volatile__ ( // NOLINT - "ldar %w[value], %[ptr] \n\t" - : [value]"=r" (value) - : [ptr]"Q" (*ptr) - : "memory" - ); // NOLINT - - return value; -} - -inline Atomic32 Release_Load(volatile const Atomic32* ptr) { - MemoryBarrier(); - return *ptr; -} - -// 64-bit versions of the operations. -// See the 32-bit versions for comments. - -inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value) { - Atomic64 prev; - int32_t temp; - - __asm__ __volatile__ ( // NOLINT - "0: \n\t" - "ldxr %[prev], %[ptr] \n\t" - "cmp %[prev], %[old_value] \n\t" - "bne 1f \n\t" - "stxr %w[temp], %[new_value], %[ptr] \n\t" - "cbnz %w[temp], 0b \n\t" - "1: \n\t" - : [prev]"=&r" (prev), - [temp]"=&r" (temp), - [ptr]"+Q" (*ptr) - : [old_value]"IJr" (old_value), - [new_value]"r" (new_value) - : "cc", "memory" - ); // NOLINT - - return prev; -} - -inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, - Atomic64 new_value) { - Atomic64 result; - int32_t temp; - - __asm__ __volatile__ ( // NOLINT - "0: \n\t" - "ldxr %[result], %[ptr] \n\t" - "stxr %w[temp], %[new_value], %[ptr] \n\t" - "cbnz %w[temp], 0b \n\t" - : [result]"=&r" (result), - [temp]"=&r" (temp), - [ptr]"+Q" (*ptr) - : [new_value]"r" (new_value) - : "memory" - ); // NOLINT - - return result; -} - -inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, - Atomic64 increment) { - Atomic64 result; - int32_t temp; - - __asm__ __volatile__ ( // NOLINT - "0: \n\t" - "ldxr %[result], %[ptr] \n\t" - "add %[result], %[result], %[increment] \n\t" - "stxr %w[temp], %[result], %[ptr] \n\t" - "cbnz %w[temp], 0b \n\t" - : [result]"=&r" (result), - [temp]"=&r" (temp), - [ptr]"+Q" (*ptr) - : [increment]"IJr" (increment) - : "memory" - ); // NOLINT - - return result; -} - -inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, - Atomic64 increment) { - MemoryBarrier(); - Atomic64 result = NoBarrier_AtomicIncrement(ptr, increment); - MemoryBarrier(); - - return result; -} - -inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value) { - Atomic64 prev = NoBarrier_CompareAndSwap(ptr, old_value, new_value); - MemoryBarrier(); - - return prev; -} - -inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value) { - MemoryBarrier(); - Atomic64 prev = NoBarrier_CompareAndSwap(ptr, old_value, new_value); - - return prev; -} - -inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { - *ptr = value; -} - -inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) { - *ptr = value; - MemoryBarrier(); -} - -inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) { - __asm__ __volatile__ ( // NOLINT - "stlr %x[value], %[ptr] \n\t" - : [ptr]"=Q" (*ptr) - : [value]"r" (value) - : "memory" - ); // NOLINT -} - -inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { - return *ptr; -} - -inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) { - Atomic64 value; - - __asm__ __volatile__ ( // NOLINT - "ldar %x[value], %[ptr] \n\t" - : [value]"=r" (value) - : [ptr]"Q" (*ptr) - : "memory" - ); // NOLINT - - return value; -} - -inline Atomic64 Release_Load(volatile const Atomic64* ptr) { - MemoryBarrier(); - return *ptr; -} - -} // namespace subtle -} // namespace base - -#endif // BASE_ATOMICOPS_INTERNALS_ARM64_GCC_H_ diff --git a/base/atomicops_internals_arm_gcc.h b/base/atomicops_internals_arm_gcc.h deleted file mode 100644 index 44c91c87a2556..0000000000000 --- a/base/atomicops_internals_arm_gcc.h +++ /dev/null @@ -1,294 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This file is an internal atomic implementation, use base/atomicops.h instead. -// -// LinuxKernelCmpxchg and Barrier_AtomicIncrement are from Google Gears. - -#ifndef BASE_ATOMICOPS_INTERNALS_ARM_GCC_H_ -#define BASE_ATOMICOPS_INTERNALS_ARM_GCC_H_ - -#if defined(OS_QNX) -#include -#endif - -namespace base { -namespace subtle { - -// Memory barriers on ARM are funky, but the kernel is here to help: -// -// * ARMv5 didn't support SMP, there is no memory barrier instruction at -// all on this architecture, or when targeting its machine code. -// -// * Some ARMv6 CPUs support SMP. A full memory barrier can be produced by -// writing a random value to a very specific coprocessor register. -// -// * On ARMv7, the "dmb" instruction is used to perform a full memory -// barrier (though writing to the co-processor will still work). -// However, on single core devices (e.g. Nexus One, or Nexus S), -// this instruction will take up to 200 ns, which is huge, even though -// it's completely un-needed on these devices. -// -// * There is no easy way to determine at runtime if the device is -// single or multi-core. However, the kernel provides a useful helper -// function at a fixed memory address (0xffff0fa0), which will always -// perform a memory barrier in the most efficient way. I.e. on single -// core devices, this is an empty function that exits immediately. -// On multi-core devices, it implements a full memory barrier. -// -// * This source could be compiled to ARMv5 machine code that runs on a -// multi-core ARMv6 or ARMv7 device. In this case, memory barriers -// are needed for correct execution. Always call the kernel helper, even -// when targeting ARMv5TE. -// - -inline void MemoryBarrier() { -#if defined(OS_LINUX) || defined(OS_ANDROID) - // Note: This is a function call, which is also an implicit compiler barrier. - typedef void (*KernelMemoryBarrierFunc)(); - ((KernelMemoryBarrierFunc)0xffff0fa0)(); -#elif defined(OS_QNX) - __cpu_membarrier(); -#else -#error MemoryBarrier() is not implemented on this platform. -#endif -} - -// An ARM toolchain would only define one of these depending on which -// variant of the target architecture is being used. This tests against -// any known ARMv6 or ARMv7 variant, where it is possible to directly -// use ldrex/strex instructions to implement fast atomic operations. -#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || \ - defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || \ - defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || \ - defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || \ - defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) - -inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - Atomic32 prev_value; - int reloop; - do { - // The following is equivalent to: - // - // prev_value = LDREX(ptr) - // reloop = 0 - // if (prev_value != old_value) - // reloop = STREX(ptr, new_value) - __asm__ __volatile__(" ldrex %0, [%3]\n" - " mov %1, #0\n" - " cmp %0, %4\n" -#ifdef __thumb2__ - " it eq\n" -#endif - " strexeq %1, %5, [%3]\n" - : "=&r"(prev_value), "=&r"(reloop), "+m"(*ptr) - : "r"(ptr), "r"(old_value), "r"(new_value) - : "cc", "memory"); - } while (reloop != 0); - return prev_value; -} - -inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - Atomic32 result = NoBarrier_CompareAndSwap(ptr, old_value, new_value); - MemoryBarrier(); - return result; -} - -inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - MemoryBarrier(); - return NoBarrier_CompareAndSwap(ptr, old_value, new_value); -} - -inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment) { - Atomic32 value; - int reloop; - do { - // Equivalent to: - // - // value = LDREX(ptr) - // value += increment - // reloop = STREX(ptr, value) - // - __asm__ __volatile__(" ldrex %0, [%3]\n" - " add %0, %0, %4\n" - " strex %1, %0, [%3]\n" - : "=&r"(value), "=&r"(reloop), "+m"(*ptr) - : "r"(ptr), "r"(increment) - : "cc", "memory"); - } while (reloop); - return value; -} - -inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment) { - // TODO(digit): Investigate if it's possible to implement this with - // a single MemoryBarrier() operation between the LDREX and STREX. - // See http://crbug.com/246514 - MemoryBarrier(); - Atomic32 result = NoBarrier_AtomicIncrement(ptr, increment); - MemoryBarrier(); - return result; -} - -inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, - Atomic32 new_value) { - Atomic32 old_value; - int reloop; - do { - // old_value = LDREX(ptr) - // reloop = STREX(ptr, new_value) - __asm__ __volatile__(" ldrex %0, [%3]\n" - " strex %1, %4, [%3]\n" - : "=&r"(old_value), "=&r"(reloop), "+m"(*ptr) - : "r"(ptr), "r"(new_value) - : "cc", "memory"); - } while (reloop != 0); - return old_value; -} - -// This tests against any known ARMv5 variant. -#elif defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) || \ - defined(__ARM_ARCH_5TE__) || defined(__ARM_ARCH_5TEJ__) - -// The kernel also provides a helper function to perform an atomic -// compare-and-swap operation at the hard-wired address 0xffff0fc0. -// On ARMv5, this is implemented by a special code path that the kernel -// detects and treats specially when thread pre-emption happens. -// On ARMv6 and higher, it uses LDREX/STREX instructions instead. -// -// Note that this always perform a full memory barrier, there is no -// need to add calls MemoryBarrier() before or after it. It also -// returns 0 on success, and 1 on exit. -// -// Available and reliable since Linux 2.6.24. Both Android and ChromeOS -// use newer kernel revisions, so this should not be a concern. -namespace { - -inline int LinuxKernelCmpxchg(Atomic32 old_value, - Atomic32 new_value, - volatile Atomic32* ptr) { - typedef int (*KernelCmpxchgFunc)(Atomic32, Atomic32, volatile Atomic32*); - return ((KernelCmpxchgFunc)0xffff0fc0)(old_value, new_value, ptr); -} - -} // namespace - -inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - Atomic32 prev_value; - for (;;) { - prev_value = *ptr; - if (prev_value != old_value) - return prev_value; - if (!LinuxKernelCmpxchg(old_value, new_value, ptr)) - return old_value; - } -} - -inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, - Atomic32 new_value) { - Atomic32 old_value; - do { - old_value = *ptr; - } while (LinuxKernelCmpxchg(old_value, new_value, ptr)); - return old_value; -} - -inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment) { - return Barrier_AtomicIncrement(ptr, increment); -} - -inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment) { - for (;;) { - // Atomic exchange the old value with an incremented one. - Atomic32 old_value = *ptr; - Atomic32 new_value = old_value + increment; - if (!LinuxKernelCmpxchg(old_value, new_value, ptr)) { - // The exchange took place as expected. - return new_value; - } - // Otherwise, *ptr changed mid-loop and we need to retry. - } -} - -inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - Atomic32 prev_value; - for (;;) { - prev_value = *ptr; - if (prev_value != old_value) { - // Always ensure acquire semantics. - MemoryBarrier(); - return prev_value; - } - if (!LinuxKernelCmpxchg(old_value, new_value, ptr)) - return old_value; - } -} - -inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - // This could be implemented as: - // MemoryBarrier(); - // return NoBarrier_CompareAndSwap(); - // - // But would use 3 barriers per succesful CAS. To save performance, - // use Acquire_CompareAndSwap(). Its implementation guarantees that: - // - A succesful swap uses only 2 barriers (in the kernel helper). - // - An early return due to (prev_value != old_value) performs - // a memory barrier with no store, which is equivalent to the - // generic implementation above. - return Acquire_CompareAndSwap(ptr, old_value, new_value); -} - -#else -# error "Your CPU's ARM architecture is not supported yet" -#endif - -// NOTE: Atomicity of the following load and store operations is only -// guaranteed in case of 32-bit alignement of |ptr| values. - -inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { - *ptr = value; -} - -inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { - *ptr = value; - MemoryBarrier(); -} - -inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { - MemoryBarrier(); - *ptr = value; -} - -inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { return *ptr; } - -inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { - Atomic32 value = *ptr; - MemoryBarrier(); - return value; -} - -inline Atomic32 Release_Load(volatile const Atomic32* ptr) { - MemoryBarrier(); - return *ptr; -} - -} // namespace subtle -} // namespace base - -#endif // BASE_ATOMICOPS_INTERNALS_ARM_GCC_H_ diff --git a/base/atomicops_internals_gcc.h b/base/atomicops_internals_gcc.h deleted file mode 100644 index 35c95fee56db9..0000000000000 --- a/base/atomicops_internals_gcc.h +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This file is an internal atomic implementation, include base/atomicops.h -// instead. This file is for platforms that use GCC intrinsics rather than -// platform-specific assembly code for atomic operations. - -#ifndef BASE_ATOMICOPS_INTERNALS_GCC_H_ -#define BASE_ATOMICOPS_INTERNALS_GCC_H_ - -namespace base { -namespace subtle { - -inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - Atomic32 prev_value; - do { - if (__sync_bool_compare_and_swap(ptr, old_value, new_value)) - return old_value; - prev_value = *ptr; - } while (prev_value == old_value); - return prev_value; -} - -inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, - Atomic32 new_value) { - Atomic32 old_value; - do { - old_value = *ptr; - } while (!__sync_bool_compare_and_swap(ptr, old_value, new_value)); - return old_value; -} - -inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment) { - return Barrier_AtomicIncrement(ptr, increment); -} - -inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment) { - for (;;) { - // Atomic exchange the old value with an incremented one. - Atomic32 old_value = *ptr; - Atomic32 new_value = old_value + increment; - if (__sync_bool_compare_and_swap(ptr, old_value, new_value)) { - // The exchange took place as expected. - return new_value; - } - // Otherwise, *ptr changed mid-loop and we need to retry. - } -} - -inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - // Since NoBarrier_CompareAndSwap uses __sync_bool_compare_and_swap, which - // is a full memory barrier, none is needed here or below in Release. - return NoBarrier_CompareAndSwap(ptr, old_value, new_value); -} - -inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - return NoBarrier_CompareAndSwap(ptr, old_value, new_value); -} - -inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { - *ptr = value; -} - -inline void MemoryBarrier() { - __sync_synchronize(); -} - -inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { - *ptr = value; - MemoryBarrier(); -} - -inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { - MemoryBarrier(); - *ptr = value; -} - -inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { - return *ptr; -} - -inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { - Atomic32 value = *ptr; - MemoryBarrier(); - return value; -} - -inline Atomic32 Release_Load(volatile const Atomic32* ptr) { - MemoryBarrier(); - return *ptr; -} - -} // namespace subtle -} // namespace base - -#endif // BASE_ATOMICOPS_INTERNALS_GCC_H_ - diff --git a/base/atomicops_internals_mips_gcc.h b/base/atomicops_internals_mips_gcc.h deleted file mode 100644 index b4551b8351e59..0000000000000 --- a/base/atomicops_internals_mips_gcc.h +++ /dev/null @@ -1,280 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This file is an internal atomic implementation, use base/atomicops.h instead. -// -// LinuxKernelCmpxchg and Barrier_AtomicIncrement are from Google Gears. - -#ifndef BASE_ATOMICOPS_INTERNALS_MIPS_GCC_H_ -#define BASE_ATOMICOPS_INTERNALS_MIPS_GCC_H_ - -namespace base { -namespace subtle { - -// Atomically execute: -// result = *ptr; -// if (*ptr == old_value) -// *ptr = new_value; -// return result; -// -// I.e., replace "*ptr" with "new_value" if "*ptr" used to be "old_value". -// Always return the old value of "*ptr" -// -// This routine implies no memory barriers. -inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - Atomic32 prev, tmp; - __asm__ __volatile__(".set push\n" - ".set noreorder\n" - "1:\n" - "ll %0, %5\n" // prev = *ptr - "bne %0, %3, 2f\n" // if (prev != old_value) goto 2 - "move %2, %4\n" // tmp = new_value - "sc %2, %1\n" // *ptr = tmp (with atomic check) - "beqz %2, 1b\n" // start again on atomic error - "nop\n" // delay slot nop - "2:\n" - ".set pop\n" - : "=&r" (prev), "=m" (*ptr), "=&r" (tmp) - : "r" (old_value), "r" (new_value), "m" (*ptr) - : "memory"); - return prev; -} - -// Atomically store new_value into *ptr, returning the previous value held in -// *ptr. This routine implies no memory barriers. -inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, - Atomic32 new_value) { - Atomic32 temp, old; - __asm__ __volatile__(".set push\n" - ".set noreorder\n" - "1:\n" - "ll %1, %4\n" // old = *ptr - "move %0, %3\n" // temp = new_value - "sc %0, %2\n" // *ptr = temp (with atomic check) - "beqz %0, 1b\n" // start again on atomic error - "nop\n" // delay slot nop - ".set pop\n" - : "=&r" (temp), "=&r" (old), "=m" (*ptr) - : "r" (new_value), "m" (*ptr) - : "memory"); - - return old; -} - -// Atomically increment *ptr by "increment". Returns the new value of -// *ptr with the increment applied. This routine implies no memory barriers. -inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment) { - Atomic32 temp, temp2; - - __asm__ __volatile__(".set push\n" - ".set noreorder\n" - "1:\n" - "ll %0, %4\n" // temp = *ptr - "addu %1, %0, %3\n" // temp2 = temp + increment - "sc %1, %2\n" // *ptr = temp2 (with atomic check) - "beqz %1, 1b\n" // start again on atomic error - "addu %1, %0, %3\n" // temp2 = temp + increment - ".set pop\n" - : "=&r" (temp), "=&r" (temp2), "=m" (*ptr) - : "Ir" (increment), "m" (*ptr) - : "memory"); - // temp2 now holds the final value. - return temp2; -} - -inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment) { - MemoryBarrier(); - Atomic32 res = NoBarrier_AtomicIncrement(ptr, increment); - MemoryBarrier(); - return res; -} - -// "Acquire" operations -// ensure that no later memory access can be reordered ahead of the operation. -// "Release" operations ensure that no previous memory access can be reordered -// after the operation. "Barrier" operations have both "Acquire" and "Release" -// semantics. A MemoryBarrier() has "Barrier" semantics, but does no memory -// access. -inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - Atomic32 res = NoBarrier_CompareAndSwap(ptr, old_value, new_value); - MemoryBarrier(); - return res; -} - -inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - MemoryBarrier(); - return NoBarrier_CompareAndSwap(ptr, old_value, new_value); -} - -inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { - *ptr = value; -} - -inline void MemoryBarrier() { - __asm__ __volatile__("sync" : : : "memory"); -} - -inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { - *ptr = value; - MemoryBarrier(); -} - -inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { - MemoryBarrier(); - *ptr = value; -} - -inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { - return *ptr; -} - -inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { - Atomic32 value = *ptr; - MemoryBarrier(); - return value; -} - -inline Atomic32 Release_Load(volatile const Atomic32* ptr) { - MemoryBarrier(); - return *ptr; -} - -#if defined(__LP64__) -// 64-bit versions of the atomic ops. - -inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value) { - Atomic64 prev, tmp; - __asm__ __volatile__(".set push\n" - ".set noreorder\n" - "1:\n" - "lld %0, %5\n" // prev = *ptr - "bne %0, %3, 2f\n" // if (prev != old_value) goto 2 - "move %2, %4\n" // tmp = new_value - "scd %2, %1\n" // *ptr = tmp (with atomic check) - "beqz %2, 1b\n" // start again on atomic error - "nop\n" // delay slot nop - "2:\n" - ".set pop\n" - : "=&r" (prev), "=m" (*ptr), "=&r" (tmp) - : "r" (old_value), "r" (new_value), "m" (*ptr) - : "memory"); - return prev; -} - -// Atomically store new_value into *ptr, returning the previous value held in -// *ptr. This routine implies no memory barriers. -inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, - Atomic64 new_value) { - Atomic64 temp, old; - __asm__ __volatile__(".set push\n" - ".set noreorder\n" - "1:\n" - "lld %1, %4\n" // old = *ptr - "move %0, %3\n" // temp = new_value - "scd %0, %2\n" // *ptr = temp (with atomic check) - "beqz %0, 1b\n" // start again on atomic error - "nop\n" // delay slot nop - ".set pop\n" - : "=&r" (temp), "=&r" (old), "=m" (*ptr) - : "r" (new_value), "m" (*ptr) - : "memory"); - - return old; -} - -// Atomically increment *ptr by "increment". Returns the new value of -// *ptr with the increment applied. This routine implies no memory barriers. -inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, - Atomic64 increment) { - Atomic64 temp, temp2; - - __asm__ __volatile__(".set push\n" - ".set noreorder\n" - "1:\n" - "lld %0, %4\n" // temp = *ptr - "daddu %1, %0, %3\n" // temp2 = temp + increment - "scd %1, %2\n" // *ptr = temp2 (with atomic check) - "beqz %1, 1b\n" // start again on atomic error - "daddu %1, %0, %3\n" // temp2 = temp + increment - ".set pop\n" - : "=&r" (temp), "=&r" (temp2), "=m" (*ptr) - : "Ir" (increment), "m" (*ptr) - : "memory"); - // temp2 now holds the final value. - return temp2; -} - -inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, - Atomic64 increment) { - MemoryBarrier(); - Atomic64 res = NoBarrier_AtomicIncrement(ptr, increment); - MemoryBarrier(); - return res; -} - -// "Acquire" operations -// ensure that no later memory access can be reordered ahead of the operation. -// "Release" operations ensure that no previous memory access can be reordered -// after the operation. "Barrier" operations have both "Acquire" and "Release" -// semantics. A MemoryBarrier() has "Barrier" semantics, but does no memory -// access. -inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value) { - Atomic64 res = NoBarrier_CompareAndSwap(ptr, old_value, new_value); - MemoryBarrier(); - return res; -} - -inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value) { - MemoryBarrier(); - return NoBarrier_CompareAndSwap(ptr, old_value, new_value); -} - -inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { - *ptr = value; -} - -inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) { - *ptr = value; - MemoryBarrier(); -} - -inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) { - MemoryBarrier(); - *ptr = value; -} - -inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { - return *ptr; -} - -inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) { - Atomic64 value = *ptr; - MemoryBarrier(); - return value; -} - -inline Atomic64 Release_Load(volatile const Atomic64* ptr) { - MemoryBarrier(); - return *ptr; -} -#endif - -} // namespace subtle -} // namespace base - -#endif // BASE_ATOMICOPS_INTERNALS_MIPS_GCC_H_ diff --git a/base/atomicops_internals_x86_gcc.cc b/base/atomicops_internals_x86_gcc.cc deleted file mode 100644 index c21e96d71db11..0000000000000 --- a/base/atomicops_internals_x86_gcc.cc +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This module gets enough CPU information to optimize the -// atomicops module on x86. - -#include -#include - -#include "base/atomicops.h" - -// Inline cpuid instruction. In PIC compilations, %ebx contains the address -// of the global offset table. To avoid breaking such executables, this code -// must preserve that register's value across cpuid instructions. -// -// The include guards are the same as in atomicops.h. -#if defined(__i386__) -#define cpuid(a, b, c, d, inp) \ - asm("mov %%ebx, %%edi\n" \ - "cpuid\n" \ - "xchg %%edi, %%ebx\n" \ - : "=a" (a), "=D" (b), "=c" (c), "=d" (d) : "a" (inp)) -#elif defined(__x86_64__) -#define cpuid(a, b, c, d, inp) \ - asm("mov %%rbx, %%rdi\n" \ - "cpuid\n" \ - "xchg %%rdi, %%rbx\n" \ - : "=a" (a), "=D" (b), "=c" (c), "=d" (d) : "a" (inp)) -#endif - -#if defined(cpuid) // initialize the struct only on x86 - -// Set the flags so that code will run correctly and conservatively, so even -// if we haven't been initialized yet, we're probably single threaded, and our -// default values should hopefully be pretty safe. -struct AtomicOps_x86CPUFeatureStruct AtomicOps_Internalx86CPUFeatures = { - false, // bug can't exist before process spawns multiple threads - false, // Chrome requires SSE2, but for transition assume not and initialize - // this properly. - false, // cmpxchg16b isn't present on early AMD64 CPUs. -}; - -namespace { - -// Initialize the AtomicOps_Internalx86CPUFeatures struct. -void AtomicOps_Internalx86CPUFeaturesInit() { - uint32_t eax; - uint32_t ebx; - uint32_t ecx; - uint32_t edx; - - // Get vendor string (issue CPUID with eax = 0) - cpuid(eax, ebx, ecx, edx, 0); - char vendor[13]; - memcpy(vendor, &ebx, 4); - memcpy(vendor + 4, &edx, 4); - memcpy(vendor + 8, &ecx, 4); - vendor[12] = 0; - - // get feature flags in ecx/edx, and family/model in eax - cpuid(eax, ebx, ecx, edx, 1); - - int family = (eax >> 8) & 0xf; // family and model fields - int model = (eax >> 4) & 0xf; - if (family == 0xf) { // use extended family and model fields - family += (eax >> 20) & 0xff; - model += ((eax >> 16) & 0xf) << 4; - } - - // Opteron Rev E has a bug in which on very rare occasions a locked - // instruction doesn't act as a read-acquire barrier if followed by a - // non-locked read-modify-write instruction. Rev F has this bug in - // pre-release versions, but not in versions released to customers, - // so we test only for Rev E, which is family 15, model 32..63 inclusive. - if (strcmp(vendor, "AuthenticAMD") == 0 && // AMD - family == 15 && - 32 <= model && model <= 63) { - AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug = true; - } else { - AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug = false; - } - - // edx bit 26 is SSE2 which we use to tell use whether we can use mfence - AtomicOps_Internalx86CPUFeatures.has_sse2 = ((edx >> 26) & 1); - - // ecx bit 13 indicates whether the cmpxchg16b instruction is supported - AtomicOps_Internalx86CPUFeatures.has_cmpxchg16b = ((ecx >> 13) & 1); -} - -class AtomicOpsx86Initializer { - public: - AtomicOpsx86Initializer() { - AtomicOps_Internalx86CPUFeaturesInit(); - } -}; - -// A global to get use initialized on startup via static initialization :/ -AtomicOpsx86Initializer g_initer; - -} // namespace - -#endif // if x86 diff --git a/base/atomicops_internals_x86_gcc.h b/base/atomicops_internals_x86_gcc.h deleted file mode 100644 index f0d224264b9f6..0000000000000 --- a/base/atomicops_internals_x86_gcc.h +++ /dev/null @@ -1,228 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This file is an internal atomic implementation, use base/atomicops.h instead. - -#ifndef BASE_ATOMICOPS_INTERNALS_X86_GCC_H_ -#define BASE_ATOMICOPS_INTERNALS_X86_GCC_H_ - -#define ATOMICOPS_COMPILER_BARRIER() __asm__ __volatile__("" : : : "memory") - -namespace base { -namespace subtle { - -// 32-bit low-level operations on any platform. - -inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - Atomic32 prev; - __asm__ __volatile__("lock; cmpxchgl %1,%2" - : "=a" (prev) - : "q" (new_value), "m" (*ptr), "0" (old_value) - : "memory"); - return prev; -} - -inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, - Atomic32 new_value) { - __asm__ __volatile__("xchgl %1,%0" // The lock prefix is implicit for xchg. - : "=r" (new_value) - : "m" (*ptr), "0" (new_value) - : "memory"); - return new_value; // Now it's the previous value. -} - -inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment) { - Atomic32 temp = increment; - __asm__ __volatile__("lock; xaddl %0,%1" - : "+r" (temp), "+m" (*ptr) - : : "memory"); - // temp now holds the old value of *ptr - return temp + increment; -} - -inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment) { - Atomic32 temp = increment; - __asm__ __volatile__("lock; xaddl %0,%1" - : "+r" (temp), "+m" (*ptr) - : : "memory"); - // temp now holds the old value of *ptr - if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) { - __asm__ __volatile__("lfence" : : : "memory"); - } - return temp + increment; -} - -inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - Atomic32 x = NoBarrier_CompareAndSwap(ptr, old_value, new_value); - if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) { - __asm__ __volatile__("lfence" : : : "memory"); - } - return x; -} - -inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - return NoBarrier_CompareAndSwap(ptr, old_value, new_value); -} - -inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { - *ptr = value; -} - -inline void MemoryBarrier() { - __asm__ __volatile__("mfence" : : : "memory"); -} - -inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { - *ptr = value; - MemoryBarrier(); -} - -inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { - ATOMICOPS_COMPILER_BARRIER(); - *ptr = value; // An x86 store acts as a release barrier. - // See comments in Atomic64 version of Release_Store(), below. -} - -inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { - return *ptr; -} - -inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { - Atomic32 value = *ptr; // An x86 load acts as a acquire barrier. - // See comments in Atomic64 version of Release_Store(), below. - ATOMICOPS_COMPILER_BARRIER(); - return value; -} - -inline Atomic32 Release_Load(volatile const Atomic32* ptr) { - MemoryBarrier(); - return *ptr; -} - -#if defined(__x86_64__) - -// 64-bit low-level operations on 64-bit platform. - -inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value) { - Atomic64 prev; - __asm__ __volatile__("lock; cmpxchgq %1,%2" - : "=a" (prev) - : "q" (new_value), "m" (*ptr), "0" (old_value) - : "memory"); - return prev; -} - -inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, - Atomic64 new_value) { - __asm__ __volatile__("xchgq %1,%0" // The lock prefix is implicit for xchg. - : "=r" (new_value) - : "m" (*ptr), "0" (new_value) - : "memory"); - return new_value; // Now it's the previous value. -} - -inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, - Atomic64 increment) { - Atomic64 temp = increment; - __asm__ __volatile__("lock; xaddq %0,%1" - : "+r" (temp), "+m" (*ptr) - : : "memory"); - // temp now contains the previous value of *ptr - return temp + increment; -} - -inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, - Atomic64 increment) { - Atomic64 temp = increment; - __asm__ __volatile__("lock; xaddq %0,%1" - : "+r" (temp), "+m" (*ptr) - : : "memory"); - // temp now contains the previous value of *ptr - if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) { - __asm__ __volatile__("lfence" : : : "memory"); - } - return temp + increment; -} - -inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { - *ptr = value; -} - -inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) { - *ptr = value; - MemoryBarrier(); -} - -inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) { - ATOMICOPS_COMPILER_BARRIER(); - - *ptr = value; // An x86 store acts as a release barrier - // for current AMD/Intel chips as of Jan 2008. - // See also Acquire_Load(), below. - - // When new chips come out, check: - // IA-32 Intel Architecture Software Developer's Manual, Volume 3: - // System Programming Guide, Chatper 7: Multiple-processor management, - // Section 7.2, Memory Ordering. - // Last seen at: - // http://developer.intel.com/design/pentium4/manuals/index_new.htm - // - // x86 stores/loads fail to act as barriers for a few instructions (clflush - // maskmovdqu maskmovq movntdq movnti movntpd movntps movntq) but these are - // not generated by the compiler, and are rare. Users of these instructions - // need to know about cache behaviour in any case since all of these involve - // either flushing cache lines or non-temporal cache hints. -} - -inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { - return *ptr; -} - -inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) { - Atomic64 value = *ptr; // An x86 load acts as a acquire barrier, - // for current AMD/Intel chips as of Jan 2008. - // See also Release_Store(), above. - ATOMICOPS_COMPILER_BARRIER(); - return value; -} - -inline Atomic64 Release_Load(volatile const Atomic64* ptr) { - MemoryBarrier(); - return *ptr; -} - -inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value) { - Atomic64 x = NoBarrier_CompareAndSwap(ptr, old_value, new_value); - if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) { - __asm__ __volatile__("lfence" : : : "memory"); - } - return x; -} - -inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value) { - return NoBarrier_CompareAndSwap(ptr, old_value, new_value); -} - -#endif // defined(__x86_64__) - -} // namespace subtle -} // namespace base - -#undef ATOMICOPS_COMPILER_BARRIER - -#endif // BASE_ATOMICOPS_INTERNALS_X86_GCC_H_ diff --git a/base/base.gyp b/base/base.gyp index 4d1b892305953..8536727485812 100644 --- a/base/base.gyp +++ b/base/base.gyp @@ -90,18 +90,6 @@ ], }], ['OS == "android" and _toolset == "target"', { - 'conditions': [ - ['target_arch == "ia32" or target_arch == "x64"', { - 'sources/': [ - ['include', '^atomicops_internals_x86_gcc\\.cc$'], - ], - }], - ['target_arch == "mipsel"', { - 'sources/': [ - ['include', '^atomicops_internals_mips_gcc\\.cc$'], - ], - }], - ], 'dependencies': [ 'base_java', 'base_jni_headers', @@ -464,6 +452,7 @@ 'containers/linked_list_unittest.cc', 'containers/mru_cache_unittest.cc', 'containers/scoped_ptr_hash_map_unittest.cc', + 'containers/scoped_ptr_map_unittest.cc', 'containers/small_map_unittest.cc', 'containers/stack_container_unittest.cc', 'cpu_unittest.cc', @@ -513,6 +502,7 @@ 'lazy_instance_unittest.cc', 'logging_unittest.cc', 'mac/bind_objc_block_unittest.mm', + 'mac/call_with_eh_frame_unittest.mm', 'mac/dispatch_source_mach_unittest.cc', 'mac/foundation_util_unittest.mm', 'mac/libdispatch_task_runner_unittest.cc', @@ -537,8 +527,7 @@ 'memory/singleton_unittest.cc', 'memory/weak_ptr_unittest.cc', 'memory/weak_ptr_unittest.nc', - 'message_loop/message_loop_proxy_impl_unittest.cc', - 'message_loop/message_loop_proxy_unittest.cc', + 'message_loop/message_loop_task_runner_unittest.cc', 'message_loop/message_loop_unittest.cc', 'message_loop/message_pump_glib_unittest.cc', 'message_loop/message_pump_io_ios_unittest.cc', @@ -592,6 +581,7 @@ 'sha1_unittest.cc', 'stl_util_unittest.cc', 'strings/nullable_string16_unittest.cc', + 'strings/pattern_unittest.cc', 'strings/safe_sprintf_unittest.cc', 'strings/string16_unittest.cc', 'strings/string_number_conversions_unittest.cc', @@ -699,7 +689,9 @@ }], ['OS == "ios" and _toolset != "host"', { 'sources/': [ - # Only test the iOS-meaningful portion of process_utils. + # Only test the iOS-meaningful portion of memory and process_utils. + ['exclude', '^memory/discardable_shared_memory_unittest\\.cc$'], + ['exclude', '^memory/shared_memory_unittest\\.cc$'], ['exclude', '^process/memory_unittest'], ['exclude', '^process/process_unittest\\.cc$'], ['exclude', '^process/process_util_unittest\\.cc$'], @@ -1545,7 +1537,7 @@ 'target_name': 'chromium_android_linker', 'type': 'shared_library', 'sources': [ - 'android/linker/linker_jni.cc', + 'android/linker/legacy_linker_jni.cc', ], # The crazy linker is never instrumented. 'cflags!': [ diff --git a/base/base.gypi b/base/base.gypi index f086b43c0f644..7ffad5417a084 100644 --- a/base/base.gypi +++ b/base/base.gypi @@ -37,6 +37,7 @@ 'android/content_uri_utils.cc', 'android/content_uri_utils.h', 'android/cpu_features.cc', + 'android/cxa_demangle_stub.cc', 'android/event_log.cc', 'android/event_log.h', 'android/field_trial_list.cc', @@ -90,11 +91,8 @@ 'atomic_ref_count.h', 'atomic_sequence_num.h', 'atomicops.h', - 'atomicops_internals_gcc.h', 'atomicops_internals_mac.h', 'atomicops_internals_portable.h', - 'atomicops_internals_x86_gcc.cc', - 'atomicops_internals_x86_gcc.h', 'atomicops_internals_x86_msvc.h', 'barrier_closure.cc', 'barrier_closure.h', @@ -138,6 +136,7 @@ 'containers/linked_list.h', 'containers/mru_cache.h', 'containers/scoped_ptr_hash_map.h', + 'containers/scoped_ptr_map.h', 'containers/small_map.h', 'containers/stack_container.h', 'cpu.cc', @@ -247,6 +246,8 @@ 'ios/device_util.mm', 'ios/ios_util.h', 'ios/ios_util.mm', + 'ios/ns_error_util.h', + 'ios/ns_error_util.mm', 'ios/scoped_critical_action.h', 'ios/scoped_critical_action.mm', 'ios/weak_nsobject.h', @@ -278,6 +279,9 @@ 'mac/bind_objc_block.h', 'mac/bundle_locations.h', 'mac/bundle_locations.mm', + 'mac/call_with_eh_frame.cc', + 'mac/call_with_eh_frame.h', + 'mac/call_with_eh_frame_asm.S', 'mac/close_nocancel.cc', 'mac/cocoa_protocols.h', 'mac/dispatch_source_mach.cc', @@ -357,6 +361,9 @@ 'memory/scoped_vector.h', 'memory/shared_memory.h', 'memory/shared_memory_android.cc', + 'memory/shared_memory_handle.h', + 'memory/shared_memory_handle_mac.cc', + 'memory/shared_memory_mac.cc', 'memory/shared_memory_nacl.cc', 'memory/shared_memory_posix.cc', 'memory/shared_memory_win.cc', @@ -368,10 +375,8 @@ 'message_loop/incoming_task_queue.h', 'message_loop/message_loop.cc', 'message_loop/message_loop.h', - 'message_loop/message_loop_proxy.cc', - 'message_loop/message_loop_proxy.h', - 'message_loop/message_loop_proxy_impl.cc', - 'message_loop/message_loop_proxy_impl.h', + 'message_loop/message_loop_task_runner.cc', + 'message_loop/message_loop_task_runner.h', 'message_loop/message_pump.cc', 'message_loop/message_pump.h', 'message_loop/message_pump_android.cc', @@ -432,7 +437,6 @@ 'pending_task.h', 'pickle.cc', 'pickle.h', - 'port.h', 'posix/eintr_wrapper.h', 'posix/global_descriptors.cc', 'posix/global_descriptors.h', @@ -543,6 +547,8 @@ 'strings/latin1_string_conversions.h', 'strings/nullable_string16.cc', 'strings/nullable_string16.h', + 'strings/pattern.cc', + 'strings/pattern.h', 'strings/safe_sprintf.cc', 'strings/safe_sprintf.h', 'strings/string16.cc', @@ -762,13 +768,15 @@ 4018, ], 'target_conditions': [ + ['OS == "mac" or OS == "ios"', { + 'sources!': [ + 'memory/shared_memory_posix.cc', + ], + }], ['(<(desktop_linux) == 0 and <(chromeos) == 0) or >(nacl_untrusted_build)==1', { 'sources/': [ ['exclude', '^nix/'], ], - 'sources!': [ - 'atomicops_internals_x86_gcc.cc', - ], }], ['<(use_glib)==0 or >(nacl_untrusted_build)==1', { 'sources!': [ @@ -853,7 +861,6 @@ ], 'sources/': [ # Pull in specific files for host builds. - ['include', '^atomicops_internals_x86_gcc\\.cc$'], ['include', '^threading/platform_thread_linux\\.cc$'], ], }], @@ -871,6 +878,7 @@ ['include', '^files/file_util_mac\\.'], ['include', '^file_version_info_mac\\.'], ['include', '^mac/bundle_locations\\.'], + ['include', '^mac/call_with_eh_frame\\.'], ['include', '^mac/foundation_util\\.'], ['include', '^mac/mac_logging\\.'], ['include', '^mac/mach_logging\\.'], diff --git a/base/base.isolate b/base/base.isolate index c7ba651ac71f0..948c60045ff24 100644 --- a/base/base.isolate +++ b/base/base.isolate @@ -36,7 +36,9 @@ ['OS=="win" and asan==1 and component=="shared_library"', { 'variables': { 'files': [ - '../third_party/llvm-build/Release+Asserts/lib/clang/3.7.0/lib/windows/clang_rt.asan_dynamic-i386.dll', + # We only need x.y.z/lib/windows/clang_rt.asan_dynamic-i386.dll, + # but since the version (x.y.z) changes, just grab the whole dir. + '../third_party/llvm-build/Release+Asserts/lib/clang/', ], }, }], diff --git a/base/base_nacl.gyp b/base/base_nacl.gyp index 7e7d34ff202e1..47cf840550f14 100644 --- a/base/base_nacl.gyp +++ b/base/base_nacl.gyp @@ -96,6 +96,10 @@ # For GetKnownDeadTerminationStatus and GetTerminationStatus. 'process/kill_posix.cc', + # For ForkWithFlags. + 'process/launch.h', + 'process/launch_posix.cc', + # Unlike libbase_nacl, for Non-SFI build, we need to use # rand_util_posix for random implementation, instead of # rand_util_nacl.cc, which is based on IRT. rand_util_nacl.cc is diff --git a/base/base_paths_mac.mm b/base/base_paths_mac.mm index 9864eb3dce9d4..af4bd1a89e3b9 100644 --- a/base/base_paths_mac.mm +++ b/base/base_paths_mac.mm @@ -29,8 +29,9 @@ void GetNSExecutablePath(base::FilePath* path) { _NSGetExecutablePath(NULL, &executable_length); DCHECK_GT(executable_length, 1u); std::string executable_path; - int rv = _NSGetExecutablePath(WriteInto(&executable_path, executable_length), - &executable_length); + int rv = _NSGetExecutablePath( + base::WriteInto(&executable_path, executable_length), + &executable_length); DCHECK_EQ(rv, 0); // _NSGetExecutablePath may return paths containing ./ or ../ which makes diff --git a/base/base_paths_win.cc b/base/base_paths_win.cc index 4ecb59d4dec1f..58f925f7e1f69 100644 --- a/base/base_paths_win.cc +++ b/base/base_paths_win.cc @@ -32,14 +32,16 @@ bool PathProviderWin(int key, FilePath* result) { FilePath cur; switch (key) { case base::FILE_EXE: - GetModuleFileName(NULL, system_buffer, MAX_PATH); + if (GetModuleFileName(NULL, system_buffer, MAX_PATH) == 0) + return false; cur = FilePath(system_buffer); break; case base::FILE_MODULE: { // the resource containing module is assumed to be the one that // this code lives in, whether that's a dll or exe HMODULE this_module = reinterpret_cast(&__ImageBase); - GetModuleFileName(this_module, system_buffer, MAX_PATH); + if (GetModuleFileName(this_module, system_buffer, MAX_PATH) == 0) + return false; cur = FilePath(system_buffer); break; } diff --git a/base/base_switches.cc b/base/base_switches.cc index 30765405de180..7f3be7f516c58 100644 --- a/base/base_switches.cc +++ b/base/base_switches.cc @@ -67,6 +67,11 @@ const char kProfilerTiming[] = "profiler-timing"; // chrome://profiler. const char kProfilerTimingDisabledValue[] = "0"; +#if defined(OS_WIN) +// Disables the USB keyboard detection for blocking the OSK on Win8+. +const char kDisableUsbKeyboardDetect[] = "disable-usb-keyboard-detect"; +#endif + #if defined(OS_POSIX) // Used for turning on Breakpad crash reporting in a debug environment where // crash reporting is typically compiled but disabled. diff --git a/base/base_switches.h b/base/base_switches.h index c579f6a240df8..bbd590bad05da 100644 --- a/base/base_switches.h +++ b/base/base_switches.h @@ -27,6 +27,10 @@ extern const char kV[]; extern const char kVModule[]; extern const char kWaitForDebugger[]; +#if defined(OS_WIN) +extern const char kDisableUsbKeyboardDetect[]; +#endif + #if defined(OS_POSIX) extern const char kEnableCrashReporterForTesting[]; #endif diff --git a/base/basictypes.h b/base/basictypes.h index bf75e6731572b..d71abd9bac71f 100644 --- a/base/basictypes.h +++ b/base/basictypes.h @@ -16,7 +16,7 @@ #include // For intptr_t. #include "base/macros.h" -#include "base/port.h" // Types that only need exist on certain systems. +#include "build/build_config.h" // DEPRECATED: Please use (u)int{8,16,32,64}_t instead (and include ). typedef int8_t int8; diff --git a/base/compiler_specific.h b/base/compiler_specific.h index 63297dcaf00ea..66dc80db3198a 100644 --- a/base/compiler_specific.h +++ b/base/compiler_specific.h @@ -140,7 +140,7 @@ // Annotate a function indicating the caller must examine the return value. // Use like: // int foo() WARN_UNUSED_RESULT; -// To explicitly ignore a result, see |ignore_result()| in . +// To explicitly ignore a result, see |ignore_result()| in base/macros.h. #if defined(COMPILER_GCC) #define WARN_UNUSED_RESULT __attribute__((warn_unused_result)) #else diff --git a/base/containers/scoped_ptr_map.h b/base/containers/scoped_ptr_map.h new file mode 100644 index 0000000000000..a4605e3b68877 --- /dev/null +++ b/base/containers/scoped_ptr_map.h @@ -0,0 +1,144 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_CONTAINERS_SCOPED_PTR_MAP_H_ +#define BASE_CONTAINERS_SCOPED_PTR_MAP_H_ + +#include +#include +#include + +#include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" +#include "base/move.h" +#include "base/stl_util.h" + +namespace base { + +// ScopedPtrMap provides a std::map that supports scoped_ptr values. It ensures +// that the map's values are properly deleted when removed from the map, or when +// the map is destroyed. +// +// |ScopedPtr| must be a type scoped_ptr. This is for compatibility with +// std::map in C++11. +template > +class ScopedPtrMap { + MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(ScopedPtrMap) + + using Container = std::map; + + public: + using allocator_type = typename Container::allocator_type; + using size_type = typename Container::size_type; + using difference_type = typename Container::difference_type; + using reference = typename Container::reference; + using const_reference = typename Container::const_reference; + using key_type = typename Container::key_type; + using mapped_type = ScopedPtr; + using key_compare = typename Container::key_compare; + using const_iterator = typename Container::const_iterator; + using const_reverse_iterator = typename Container::const_reverse_iterator; + + ScopedPtrMap() {} + ~ScopedPtrMap() { clear(); } + ScopedPtrMap(ScopedPtrMap&& other) { swap(other); } + + ScopedPtrMap& operator=(ScopedPtrMap&& rhs) { + swap(rhs); + return *this; + } + + const_iterator find(const Key& k) const { return data_.find(k); } + size_type count(const Key& k) const { return data_.count(k); } + + bool empty() const { return data_.empty(); } + size_t size() const { return data_.size(); } + + const_reverse_iterator rbegin() const { return data_.rbegin(); } + const_reverse_iterator rend() const { return data_.rend(); } + + const_iterator begin() const { return data_.begin(); } + const_iterator end() const { return data_.end(); } + + void swap(ScopedPtrMap& other) { data_.swap(other.data_); } + + void clear() { STLDeleteValues(&data_); } + + // Inserts |val| into the map, associated with |key|. + std::pair insert(const Key& key, ScopedPtr val) { + auto result = data_.insert(std::make_pair(key, val.get())); + if (result.second) + ignore_result(val.release()); + return result; + } + + // Inserts |val| into the map, associated with |key|. Overwrites any existing + // element at |key|. + void set(const Key& key, ScopedPtr val) { + typename ScopedPtr::element_type*& val_ref = data_[key]; + delete val_ref; + val_ref = val.release(); + } + + void erase(const_iterator position) { + DCHECK(position != end()); + delete position->second; + // Key-based lookup (cannot use const_iterator overload in C++03 library). + data_.erase(position->first); + } + + size_type erase(const Key& k) { + typename Container::iterator it = data_.find(k); + if (it == end()) + return 0; + + delete it->second; + data_.erase(it); + return 1; + } + + void erase(const_iterator first, const_iterator last) { + STLDeleteContainerPairSecondPointers(first, last); + // Need non-const iterators as required by the C++03 library. + data_.erase(ConstIteratorToIterator(first), ConstIteratorToIterator(last)); + } + + // Like |erase()|, but returns the element instead of deleting it. + ScopedPtr take_and_erase(const_iterator position) { + DCHECK(position != end()); + if (position == end()) + return ScopedPtr(); + + ScopedPtr ret(position->second); + // Key-based lookup (cannot use const_iterator overload in C++03 library). + data_.erase(position->first); + return ret.Pass(); + } + + // Like |erase()|, but returns the element instead of deleting it. + ScopedPtr take_and_erase(const Key& k) { + typename Container::iterator it = data_.find(k); + if (it == end()) + return ScopedPtr(); + + ScopedPtr ret(it->second); + data_.erase(it); + return ret.Pass(); + } + + private: + Container data_; + + typename Container::iterator ConstIteratorToIterator(const_iterator it) { + // This is the only way to convert a const iterator to a non-const iterator + // in C++03 (get the key and do the lookup again). + if (it == data_.end()) + return data_.end(); + return data_.find(it->first); + }; +}; + +} // namespace base + +#endif // BASE_CONTAINERS_SCOPED_PTR_MAP_H_ diff --git a/base/containers/scoped_ptr_map_unittest.cc b/base/containers/scoped_ptr_map_unittest.cc new file mode 100644 index 0000000000000..46843b3f2529f --- /dev/null +++ b/base/containers/scoped_ptr_map_unittest.cc @@ -0,0 +1,240 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/containers/scoped_ptr_map.h" + +#include +#include +#include + +#include "base/bind.h" +#include "base/callback.h" +#include "base/memory/scoped_ptr.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace base { +namespace { + +// A ScopedDestroyer sets a Boolean to true upon destruction. +class ScopedDestroyer { + public: + ScopedDestroyer(bool* destroyed) : destroyed_(destroyed) { + *destroyed_ = false; + } + + ~ScopedDestroyer() { *destroyed_ = true; } + + private: + bool* destroyed_; +}; + +TEST(ScopedPtrMapTest, Insert) { + bool destroyed1 = false; + bool destroyed2 = false; + { + ScopedPtrMap> scoped_map; + + // Insert to new key. + ScopedDestroyer* elem1 = new ScopedDestroyer(&destroyed1); + EXPECT_FALSE(destroyed1); + EXPECT_TRUE(scoped_map.insert(0, make_scoped_ptr(elem1)).second); + EXPECT_EQ(elem1, scoped_map.find(0)->second); + EXPECT_FALSE(destroyed1); + + // Insert to existing key. + ScopedDestroyer* elem2 = new ScopedDestroyer(&destroyed2); + EXPECT_FALSE(destroyed2); + EXPECT_FALSE(scoped_map.insert(0, make_scoped_ptr(elem2)).second); + EXPECT_EQ(elem1, scoped_map.find(0)->second); + + EXPECT_FALSE(destroyed1); + EXPECT_TRUE(destroyed2); + } + EXPECT_TRUE(destroyed1); +} + +TEST(ScopedPtrMapTest, Set) { + bool destroyed1 = false; + bool destroyed2 = false; + { + ScopedPtrMap> scoped_map; + + // Set a new key. + ScopedDestroyer* elem1 = new ScopedDestroyer(&destroyed1); + EXPECT_FALSE(destroyed1); + scoped_map.set(0, make_scoped_ptr(elem1)); + EXPECT_EQ(elem1, scoped_map.find(0)->second); + EXPECT_FALSE(destroyed1); + + // Set to replace an existing key. + ScopedDestroyer* elem2 = new ScopedDestroyer(&destroyed2); + EXPECT_FALSE(destroyed2); + scoped_map.set(0, make_scoped_ptr(elem2)); + EXPECT_EQ(elem2, scoped_map.find(0)->second); + + EXPECT_TRUE(destroyed1); + EXPECT_FALSE(destroyed2); + } + EXPECT_TRUE(destroyed1); + EXPECT_TRUE(destroyed2); +} + +TEST(ScopedPtrMapTest, EraseIterator) { + bool destroyed = false; + ScopedPtrMap> scoped_map; + scoped_map.insert(0, make_scoped_ptr(new ScopedDestroyer(&destroyed))); + EXPECT_FALSE(destroyed); + scoped_map.erase(scoped_map.find(0)); + EXPECT_TRUE(destroyed); + EXPECT_TRUE(scoped_map.empty()); +} + +TEST(ScopedPtrMapTest, EraseKey) { + bool destroyed = false; + ScopedPtrMap> scoped_map; + scoped_map.insert(0, make_scoped_ptr(new ScopedDestroyer(&destroyed))); + EXPECT_FALSE(destroyed); + EXPECT_EQ(1u, scoped_map.erase(0)); + EXPECT_TRUE(destroyed); + EXPECT_TRUE(scoped_map.empty()); + + // Test erase of a non-existent key. + EXPECT_EQ(0u, scoped_map.erase(7)); +} + +TEST(ScopedPtrMapTest, EraseRange) { + bool destroyed1 = false; + bool destroyed2 = false; + ScopedPtrMap> scoped_map; + + scoped_map.insert(0, make_scoped_ptr(new ScopedDestroyer(&destroyed1))); + EXPECT_FALSE(destroyed1); + + scoped_map.insert(1, make_scoped_ptr(new ScopedDestroyer(&destroyed2))); + EXPECT_FALSE(destroyed2); + + scoped_map.erase(scoped_map.find(0), scoped_map.end()); + EXPECT_TRUE(destroyed1); + EXPECT_TRUE(destroyed2); + EXPECT_TRUE(scoped_map.empty()); +} + +TEST(ScopedPtrMapTest, TakeAndErase) { + bool destroyed = false; + ScopedPtrMap> scoped_map; + ScopedDestroyer* elem = new ScopedDestroyer(&destroyed); + scoped_map.insert(0, make_scoped_ptr(elem)); + EXPECT_EQ(elem, scoped_map.find(0)->second); + EXPECT_FALSE(destroyed); + scoped_ptr object = scoped_map.take_and_erase(0); + EXPECT_EQ(elem, object.get()); + EXPECT_FALSE(destroyed); + EXPECT_TRUE(scoped_map.empty()); + object.reset(); + EXPECT_TRUE(destroyed); +} + +TEST(ScopedPtrMapTest, Clear) { + bool destroyed = false; + ScopedPtrMap> scoped_map; + scoped_map.insert(0, make_scoped_ptr(new ScopedDestroyer(&destroyed))); + EXPECT_FALSE(destroyed); + scoped_map.clear(); + EXPECT_TRUE(destroyed); + EXPECT_TRUE(scoped_map.empty()); +} + +TEST(ScopedPtrMapTest, Compare) { + // Construct a ScopedPtrMap with a custom comparison function. + bool destroyed = false; + ScopedPtrMap, std::greater> scoped_map; + scoped_map.insert(0, make_scoped_ptr(new ScopedDestroyer(&destroyed))); + scoped_map.insert(1, make_scoped_ptr(new ScopedDestroyer(&destroyed))); + + auto it = scoped_map.begin(); + EXPECT_EQ(1, it->first); + ++it; + EXPECT_EQ(0, it->first); +} + +TEST(ScopedPtrMapTest, Scope) { + bool destroyed = false; + { + ScopedPtrMap> scoped_map; + scoped_map.insert(0, make_scoped_ptr(new ScopedDestroyer(&destroyed))); + EXPECT_FALSE(destroyed); + } + EXPECT_TRUE(destroyed); +} + +TEST(ScopedPtrMapTest, MoveConstruct) { + bool destroyed = false; + { + ScopedPtrMap> scoped_map; + ScopedDestroyer* elem = new ScopedDestroyer(&destroyed); + scoped_map.insert(0, make_scoped_ptr(elem)); + EXPECT_EQ(elem, scoped_map.find(0)->second); + EXPECT_FALSE(destroyed); + EXPECT_FALSE(scoped_map.empty()); + + ScopedPtrMap> scoped_map_copy( + scoped_map.Pass()); + EXPECT_TRUE(scoped_map.empty()); + EXPECT_FALSE(scoped_map_copy.empty()); + EXPECT_EQ(elem, scoped_map_copy.find(0)->second); + EXPECT_FALSE(destroyed); + } + EXPECT_TRUE(destroyed); +} + +TEST(ScopedPtrMapTest, MoveAssign) { + bool destroyed = false; + { + ScopedPtrMap> scoped_map; + ScopedDestroyer* elem = new ScopedDestroyer(&destroyed); + scoped_map.insert(0, make_scoped_ptr(elem)); + EXPECT_EQ(elem, scoped_map.find(0)->second); + EXPECT_FALSE(destroyed); + EXPECT_FALSE(scoped_map.empty()); + + ScopedPtrMap> scoped_map_assign; + scoped_map_assign = scoped_map.Pass(); + EXPECT_TRUE(scoped_map.empty()); + EXPECT_FALSE(scoped_map_assign.empty()); + EXPECT_EQ(elem, scoped_map_assign.find(0)->second); + EXPECT_FALSE(destroyed); + } + EXPECT_TRUE(destroyed); +} + +template +ScopedPtrMap PassThru(ScopedPtrMap scoper) { + return scoper; +} + +TEST(ScopedPtrMapTest, Passed) { + bool destroyed = false; + ScopedPtrMap> scoped_map; + ScopedDestroyer* elem = new ScopedDestroyer(&destroyed); + scoped_map.insert(0, make_scoped_ptr(elem)); + EXPECT_EQ(elem, scoped_map.find(0)->second); + EXPECT_FALSE(destroyed); + + base::Callback>(void)> + callback = base::Bind(&PassThru>, + base::Passed(&scoped_map)); + EXPECT_TRUE(scoped_map.empty()); + EXPECT_FALSE(destroyed); + + ScopedPtrMap> result = callback.Run(); + EXPECT_TRUE(scoped_map.empty()); + EXPECT_EQ(elem, result.find(0)->second); + EXPECT_FALSE(destroyed); + + result.clear(); + EXPECT_TRUE(destroyed); +}; + +} // namespace +} // namespace base diff --git a/base/debug/crash_logging.cc b/base/debug/crash_logging.cc index f9b44490d4bd7..058b476800da3 100644 --- a/base/debug/crash_logging.cc +++ b/base/debug/crash_logging.cc @@ -119,7 +119,7 @@ void SetCrashKeyFromAddresses(const base::StringPiece& key, hex_backtrace.push_back(s); } - value = JoinString(hex_backtrace, ' '); + value = base::JoinString(hex_backtrace, " "); // Warn if this exceeds the breakpad limits. DCHECK_LE(value.length(), kBreakpadValueMax); diff --git a/base/debug/profiler.cc b/base/debug/profiler.cc index ed553cdf2939e..924c7693eb52e 100644 --- a/base/debug/profiler.cc +++ b/base/debug/profiler.cc @@ -7,8 +7,8 @@ #include #include "base/process/process_handle.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" -#include "base/strings/stringprintf.h" #if defined(OS_WIN) #include "base/win/pe_image.h" @@ -30,8 +30,8 @@ static int profile_count = 0; void StartProfiling(const std::string& name) { ++profile_count; std::string full_name(name); - std::string pid = StringPrintf("%d", GetCurrentProcId()); - std::string count = StringPrintf("%d", profile_count); + std::string pid = IntToString(GetCurrentProcId()); + std::string count = IntToString(profile_count); ReplaceSubstringsAfterOffset(&full_name, 0, "{pid}", pid); ReplaceSubstringsAfterOffset(&full_name, 0, "{count}", count); ProfilerStart(full_name.c_str()); diff --git a/base/debug/stack_trace_posix.cc b/base/debug/stack_trace_posix.cc index 2eac14e35380d..9593962d3aa83 100644 --- a/base/debug/stack_trace_posix.cc +++ b/base/debug/stack_trace_posix.cc @@ -784,7 +784,8 @@ char *itoa_r(intptr_t i, char *buf, size_t sz, int base, size_t padding) { // Handle negative numbers (only for base 10). if (i < 0 && base == 10) { - j = -i; + // This does "j = -i" while avoiding integer overflow. + j = static_cast(-(i + 1)) + 1; // Make sure we can write the '-' character. if (++n > sz) { diff --git a/base/debug/task_annotator.cc b/base/debug/task_annotator.cc index 19df8cb39e512..b74d390938d75 100644 --- a/base/debug/task_annotator.cc +++ b/base/debug/task_annotator.cc @@ -26,7 +26,6 @@ void TaskAnnotator::DidQueueTask(const char* queue_function, } void TaskAnnotator::RunTask(const char* queue_function, - const char* run_function, const PendingTask& pending_task) { tracked_objects::TaskStopwatch stopwatch; stopwatch.Start(); @@ -39,18 +38,6 @@ void TaskAnnotator::RunTask(const char* queue_function, "queue_duration", queue_duration.InMilliseconds()); - // When tracing memory for posted tasks it's more valuable to attribute the - // memory allocations to the source function than generically to the task - // runner. - TRACE_EVENT_WITH_MEMORY_TAG2( - "toplevel", - run_function, - pending_task.posted_from.function_name(), // Name for memory tracking. - "src_file", - pending_task.posted_from.file_name(), - "src_func", - pending_task.posted_from.function_name()); - // Before running the task, store the program counter where it was posted // and deliberately alias it to ensure it is on the stack if the task // crashes. Be careful not to assume that the variable itself will have the diff --git a/base/debug/task_annotator.h b/base/debug/task_annotator.h index aa5f17b11fee1..74068d920403e 100644 --- a/base/debug/task_annotator.h +++ b/base/debug/task_annotator.h @@ -25,11 +25,8 @@ class BASE_EXPORT TaskAnnotator { const PendingTask& pending_task); // Run a previously queued task. |queue_function| should match what was - // passed into |DidQueueTask| for this task. |run_function| is used as the - // name for the trace event that surrounds the task's execution. - void RunTask(const char* queue_function, - const char* run_function, - const PendingTask& pending_task); + // passed into |DidQueueTask| for this task. + void RunTask(const char* queue_function, const PendingTask& pending_task); private: // Creates a process-wide unique ID to represent this task in trace events. @@ -40,6 +37,13 @@ class BASE_EXPORT TaskAnnotator { DISALLOW_COPY_AND_ASSIGN(TaskAnnotator); }; +#define TRACE_TASK_EXECUTION(run_function, task) \ + TRACE_EVENT_WITH_MEMORY_TAG2( \ + "toplevel", (run_function), \ + (task).posted_from.function_name(), /* Name for memory tracking. */ \ + "src_file", (task).posted_from.file_name(), "src_func", \ + (task).posted_from.function_name()); + } // namespace debug } // namespace base diff --git a/base/debug/task_annotator_unittest.cc b/base/debug/task_annotator_unittest.cc index ddffc21ab028c..9f5c442327e0b 100644 --- a/base/debug/task_annotator_unittest.cc +++ b/base/debug/task_annotator_unittest.cc @@ -24,8 +24,7 @@ TEST(TaskAnnotatorTest, QueueAndRunTask) { TaskAnnotator annotator; annotator.DidQueueTask("TaskAnnotatorTest::Queue", pending_task); EXPECT_EQ(0, result); - annotator.RunTask( - "TaskAnnotatorTest::Queue", "TaskAnnotatorTest::Run", pending_task); + annotator.RunTask("TaskAnnotatorTest::Queue", pending_task); EXPECT_EQ(123, result); } diff --git a/base/file_version_info_unittest.cc b/base/file_version_info_unittest.cc index 9b10d04b97502..c5e9859400316 100644 --- a/base/file_version_info_unittest.cc +++ b/base/file_version_info_unittest.cc @@ -32,53 +32,49 @@ FilePath GetTestDataPath() { #if defined(OS_WIN) TEST(FileVersionInfoTest, HardCodedProperties) { - const wchar_t* kDLLNames[] = { - L"FileVersionInfoTest1.dll" - }; + const wchar_t kDLLName[] = {L"FileVersionInfoTest1.dll"}; - const wchar_t* kExpectedValues[1][15] = { + const wchar_t* const kExpectedValues[15] = { // FileVersionInfoTest.dll - L"Goooooogle", // company_name - L"Google", // company_short_name - L"This is the product name", // product_name - L"This is the product short name", // product_short_name - L"The Internal Name", // internal_name - L"4.3.2.1", // product_version - L"Private build property", // private_build - L"Special build property", // special_build + L"Goooooogle", // company_name + L"Google", // company_short_name + L"This is the product name", // product_name + L"This is the product short name", // product_short_name + L"The Internal Name", // internal_name + L"4.3.2.1", // product_version + L"Private build property", // private_build + L"Special build property", // special_build L"This is a particularly interesting comment", // comments - L"This is the original filename", // original_filename - L"This is my file description", // file_description - L"1.2.3.4", // file_version - L"This is the legal copyright", // legal_copyright - L"This is the legal trademarks", // legal_trademarks - L"This is the last change", // last_change + L"This is the original filename", // original_filename + L"This is my file description", // file_description + L"1.2.3.4", // file_version + L"This is the legal copyright", // legal_copyright + L"This is the legal trademarks", // legal_trademarks + L"This is the last change", // last_change }; - for (int i = 0; i < arraysize(kDLLNames); ++i) { - FilePath dll_path = GetTestDataPath(); - dll_path = dll_path.Append(kDLLNames[i]); + FilePath dll_path = GetTestDataPath(); + dll_path = dll_path.Append(kDLLName); - scoped_ptr version_info( - FileVersionInfo::CreateFileVersionInfo(dll_path)); + scoped_ptr version_info( + FileVersionInfo::CreateFileVersionInfo(dll_path)); - int j = 0; - EXPECT_EQ(kExpectedValues[i][j++], version_info->company_name()); - EXPECT_EQ(kExpectedValues[i][j++], version_info->company_short_name()); - EXPECT_EQ(kExpectedValues[i][j++], version_info->product_name()); - EXPECT_EQ(kExpectedValues[i][j++], version_info->product_short_name()); - EXPECT_EQ(kExpectedValues[i][j++], version_info->internal_name()); - EXPECT_EQ(kExpectedValues[i][j++], version_info->product_version()); - EXPECT_EQ(kExpectedValues[i][j++], version_info->private_build()); - EXPECT_EQ(kExpectedValues[i][j++], version_info->special_build()); - EXPECT_EQ(kExpectedValues[i][j++], version_info->comments()); - EXPECT_EQ(kExpectedValues[i][j++], version_info->original_filename()); - EXPECT_EQ(kExpectedValues[i][j++], version_info->file_description()); - EXPECT_EQ(kExpectedValues[i][j++], version_info->file_version()); - EXPECT_EQ(kExpectedValues[i][j++], version_info->legal_copyright()); - EXPECT_EQ(kExpectedValues[i][j++], version_info->legal_trademarks()); - EXPECT_EQ(kExpectedValues[i][j++], version_info->last_change()); - } + int j = 0; + EXPECT_EQ(kExpectedValues[j++], version_info->company_name()); + EXPECT_EQ(kExpectedValues[j++], version_info->company_short_name()); + EXPECT_EQ(kExpectedValues[j++], version_info->product_name()); + EXPECT_EQ(kExpectedValues[j++], version_info->product_short_name()); + EXPECT_EQ(kExpectedValues[j++], version_info->internal_name()); + EXPECT_EQ(kExpectedValues[j++], version_info->product_version()); + EXPECT_EQ(kExpectedValues[j++], version_info->private_build()); + EXPECT_EQ(kExpectedValues[j++], version_info->special_build()); + EXPECT_EQ(kExpectedValues[j++], version_info->comments()); + EXPECT_EQ(kExpectedValues[j++], version_info->original_filename()); + EXPECT_EQ(kExpectedValues[j++], version_info->file_description()); + EXPECT_EQ(kExpectedValues[j++], version_info->file_version()); + EXPECT_EQ(kExpectedValues[j++], version_info->legal_copyright()); + EXPECT_EQ(kExpectedValues[j++], version_info->legal_trademarks()); + EXPECT_EQ(kExpectedValues[j++], version_info->last_change()); } #endif diff --git a/base/files/file.cc b/base/files/file.cc index 58f80c52322ec..47b9f88f1888d 100644 --- a/base/files/file.cc +++ b/base/files/file.cc @@ -52,7 +52,7 @@ File::File(Error error_details) File::File(RValue other) : file_(other.object->TakePlatformFile()), - path_(other.object->path_), + tracing_path_(other.object->tracing_path_), error_details_(other.object->error_details()), created_(other.object->created()), async_(other.object->async_) { @@ -63,11 +63,20 @@ File::~File() { Close(); } +// static +File File::CreateForAsyncHandle(PlatformFile platform_file) { + File file(platform_file); + // It would be nice if we could validate that |platform_file| was opened with + // FILE_FLAG_OVERLAPPED on Windows but this doesn't appear to be possible. + file.async_ = true; + return file.Pass(); +} + File& File::operator=(RValue other) { if (this != other.object) { Close(); SetPlatformFile(other.object->TakePlatformFile()); - path_ = other.object->path_; + tracing_path_ = other.object->tracing_path_; error_details_ = other.object->error_details(); created_ = other.object->created(); async_ = other.object->async_; @@ -81,9 +90,10 @@ void File::Initialize(const FilePath& path, uint32 flags) { error_details_ = FILE_ERROR_ACCESS_DENIED; return; } - path_ = path; + if (FileTracing::IsCategoryEnabled()) + tracing_path_ = path; SCOPED_FILE_TRACE("Initialize"); - DoInitialize(flags); + DoInitialize(path, flags); } #endif diff --git a/base/files/file.h b/base/files/file.h index b21b15972bce7..cba4353635601 100644 --- a/base/files/file.h +++ b/base/files/file.h @@ -176,6 +176,9 @@ class BASE_EXPORT File { ~File(); + // Takes ownership of |platform_file|. + static File CreateForAsyncHandle(PlatformFile platform_file); + // Move operator= for C++03 move emulation of this type. File& operator=(RValue other); @@ -352,9 +355,9 @@ class BASE_EXPORT File { }; #endif - // Creates or opens the given file. Only called if |path_| has no + // Creates or opens the given file. Only called if |path| has no // traversal ('..') components. - void DoInitialize(uint32 flags); + void DoInitialize(const FilePath& path, uint32 flags); // TODO(tnagel): Reintegrate into Flush() once histogram isn't needed anymore, // cf. issue 473337. @@ -368,8 +371,9 @@ class BASE_EXPORT File { MemoryCheckingScopedFD file_; #endif - // Path that |Initialize()| was called with. Only set if safe (i.e. no '..'). - FilePath path_; + // A path to use for tracing purposes. Set if file tracing is enabled during + // |Initialize()|. + FilePath tracing_path_; // Object tied to the lifetime of |this| that enables/disables tracing. FileTracing::ScopedEnabler trace_enabler_; diff --git a/base/files/file_enumerator_win.cc b/base/files/file_enumerator_win.cc index 931d154981642..ae41a4600d315 100644 --- a/base/files/file_enumerator_win.cc +++ b/base/files/file_enumerator_win.cc @@ -43,10 +43,10 @@ base::Time FileEnumerator::FileInfo::GetLastModifiedTime() const { FileEnumerator::FileEnumerator(const FilePath& root_path, bool recursive, int file_type) - : recursive_(recursive), - file_type_(file_type), - has_find_data_(false), - find_handle_(INVALID_HANDLE_VALUE) { + : has_find_data_(false), + find_handle_(INVALID_HANDLE_VALUE), + recursive_(recursive), + file_type_(file_type) { // INCLUDE_DOT_DOT must not be specified if recursive. DCHECK(!(recursive && (INCLUDE_DOT_DOT & file_type_))); memset(&find_data_, 0, sizeof(find_data_)); @@ -57,11 +57,11 @@ FileEnumerator::FileEnumerator(const FilePath& root_path, bool recursive, int file_type, const FilePath::StringType& pattern) - : recursive_(recursive), + : has_find_data_(false), + find_handle_(INVALID_HANDLE_VALUE), + recursive_(recursive), file_type_(file_type), - has_find_data_(false), - pattern_(pattern), - find_handle_(INVALID_HANDLE_VALUE) { + pattern_(pattern) { // INCLUDE_DOT_DOT must not be specified if recursive. DCHECK(!(recursive && (INCLUDE_DOT_DOT & file_type_))); memset(&find_data_, 0, sizeof(find_data_)); diff --git a/base/files/file_path.cc b/base/files/file_path.cc index de8927ac5b27c..51656d26d3af5 100644 --- a/base/files/file_path.cc +++ b/base/files/file_path.cc @@ -10,9 +10,6 @@ #include "base/basictypes.h" #include "base/logging.h" #include "base/pickle.h" - -// These includes are just for the *Hack functions, and should be removed -// when those functions are removed. #include "base/strings/string_piece.h" #include "base/strings/string_util.h" #include "base/strings/sys_string_conversions.h" @@ -31,7 +28,8 @@ namespace base { -typedef FilePath::StringType StringType; +using StringType = FilePath::StringType; +using StringPieceType = FilePath::StringPieceType; namespace { @@ -45,7 +43,7 @@ const FilePath::CharType kStringTerminator = FILE_PATH_LITERAL('\0'); // otherwise returns npos. This can only be true on Windows, when a pathname // begins with a letter followed by a colon. On other platforms, this always // returns npos. -StringType::size_type FindDriveLetter(const StringType& path) { +StringPieceType::size_type FindDriveLetter(StringPieceType path) { #if defined(FILE_PATH_USES_DRIVE_LETTERS) // This is dependent on an ASCII-based character set, but that's a // reasonable assumption. iswalpha can be too inclusive here. @@ -59,26 +57,25 @@ StringType::size_type FindDriveLetter(const StringType& path) { } #if defined(FILE_PATH_USES_DRIVE_LETTERS) -bool EqualDriveLetterCaseInsensitive(const StringType& a, - const StringType& b) { +bool EqualDriveLetterCaseInsensitive(StringPieceType a, StringPieceType b) { size_t a_letter_pos = FindDriveLetter(a); size_t b_letter_pos = FindDriveLetter(b); if (a_letter_pos == StringType::npos || b_letter_pos == StringType::npos) return a == b; - StringType a_letter(a.substr(0, a_letter_pos + 1)); - StringType b_letter(b.substr(0, b_letter_pos + 1)); - if (!StartsWith(a_letter, b_letter, false)) + StringPieceType a_letter(a.substr(0, a_letter_pos + 1)); + StringPieceType b_letter(b.substr(0, b_letter_pos + 1)); + if (!StartsWith(a_letter, b_letter, CompareCase::INSENSITIVE_ASCII)) return false; - StringType a_rest(a.substr(a_letter_pos + 1)); - StringType b_rest(b.substr(b_letter_pos + 1)); + StringPieceType a_rest(a.substr(a_letter_pos + 1)); + StringPieceType b_rest(b.substr(b_letter_pos + 1)); return a_rest == b_rest; } #endif // defined(FILE_PATH_USES_DRIVE_LETTERS) -bool IsPathAbsolute(const StringType& path) { +bool IsPathAbsolute(StringPieceType path) { #if defined(FILE_PATH_USES_DRIVE_LETTERS) StringType::size_type letter = FindDriveLetter(path); if (letter != StringType::npos) { @@ -177,7 +174,8 @@ FilePath::FilePath() { FilePath::FilePath(const FilePath& that) : path_(that.path_) { } -FilePath::FilePath(const StringType& path) : path_(path) { +FilePath::FilePath(StringPieceType path) { + path.CopyToString(&path_); StringType::size_type nul_pos = path_.find(kStringTerminator); if (nul_pos != StringType::npos) path_.erase(nul_pos, StringType::npos); @@ -279,7 +277,7 @@ bool FilePath::AppendRelativePath(const FilePath& child, // never case sensitive. if ((FindDriveLetter(*parent_comp) != StringType::npos) && (FindDriveLetter(*child_comp) != StringType::npos)) { - if (!StartsWith(*parent_comp, *child_comp, false)) + if (!StartsWith(*parent_comp, *child_comp, CompareCase::INSENSITIVE_ASCII)) return false; ++parent_comp; ++child_comp; @@ -404,7 +402,7 @@ FilePath FilePath::RemoveFinalExtension() const { return FilePath(path_.substr(0, dot)); } -FilePath FilePath::InsertBeforeExtension(const StringType& suffix) const { +FilePath FilePath::InsertBeforeExtension(StringPieceType suffix) const { if (suffix.empty()) return FilePath(path_); @@ -413,27 +411,28 @@ FilePath FilePath::InsertBeforeExtension(const StringType& suffix) const { StringType ext = Extension(); StringType ret = RemoveExtension().value(); - ret.append(suffix); + suffix.AppendToString(&ret); ret.append(ext); return FilePath(ret); } -FilePath FilePath::InsertBeforeExtensionASCII(const StringPiece& suffix) +FilePath FilePath::InsertBeforeExtensionASCII(StringPiece suffix) const { DCHECK(IsStringASCII(suffix)); #if defined(OS_WIN) - return InsertBeforeExtension(ASCIIToUTF16(suffix.as_string())); + return InsertBeforeExtension(ASCIIToUTF16(suffix)); #elif defined(OS_POSIX) - return InsertBeforeExtension(suffix.as_string()); + return InsertBeforeExtension(suffix); #endif } -FilePath FilePath::AddExtension(const StringType& extension) const { +FilePath FilePath::AddExtension(StringPieceType extension) const { if (IsEmptyOrSpecialCase(BaseName().value())) return FilePath(); // If the new extension is "" or ".", then just return the current FilePath. - if (extension.empty() || extension == StringType(1, kExtensionSeparator)) + if (extension.empty() || + (extension.size() == 1 && extension[0] == kExtensionSeparator)) return *this; StringType str = path_; @@ -441,27 +440,28 @@ FilePath FilePath::AddExtension(const StringType& extension) const { *(str.end() - 1) != kExtensionSeparator) { str.append(1, kExtensionSeparator); } - str.append(extension); + extension.AppendToString(&str); return FilePath(str); } -FilePath FilePath::ReplaceExtension(const StringType& extension) const { +FilePath FilePath::ReplaceExtension(StringPieceType extension) const { if (IsEmptyOrSpecialCase(BaseName().value())) return FilePath(); FilePath no_ext = RemoveExtension(); // If the new extension is "" or ".", then just remove the current extension. - if (extension.empty() || extension == StringType(1, kExtensionSeparator)) + if (extension.empty() || + (extension.size() == 1 && extension[0] == kExtensionSeparator)) return no_ext; StringType str = no_ext.value(); if (extension[0] != kExtensionSeparator) str.append(1, kExtensionSeparator); - str.append(extension); + extension.AppendToString(&str); return FilePath(str); } -bool FilePath::MatchesExtension(const StringType& extension) const { +bool FilePath::MatchesExtension(StringPieceType extension) const { DCHECK(extension.empty() || extension[0] == kExtensionSeparator); StringType current_extension = Extension(); @@ -472,17 +472,17 @@ bool FilePath::MatchesExtension(const StringType& extension) const { return FilePath::CompareEqualIgnoreCase(extension, current_extension); } -FilePath FilePath::Append(const StringType& component) const { - const StringType* appended = &component; +FilePath FilePath::Append(StringPieceType component) const { + StringPieceType appended = component; StringType without_nuls; StringType::size_type nul_pos = component.find(kStringTerminator); - if (nul_pos != StringType::npos) { - without_nuls = component.substr(0, nul_pos); - appended = &without_nuls; + if (nul_pos != StringPieceType::npos) { + component.substr(0, nul_pos).CopyToString(&without_nuls); + appended = StringPieceType(without_nuls); } - DCHECK(!IsPathAbsolute(*appended)); + DCHECK(!IsPathAbsolute(appended)); if (path_.compare(kCurrentDirectory) == 0) { // Append normally doesn't do any normalization, but as a special case, @@ -492,7 +492,7 @@ FilePath FilePath::Append(const StringType& component) const { // it's likely in practice to wind up with FilePath objects containing // only kCurrentDirectory when calling DirName on a single relative path // component. - return FilePath(*appended); + return FilePath(appended); } FilePath new_path(path_); @@ -501,7 +501,7 @@ FilePath FilePath::Append(const StringType& component) const { // Don't append a separator if the path is empty (indicating the current // directory) or if the path component is empty (indicating nothing to // append). - if (appended->length() > 0 && new_path.path_.length() > 0) { + if (appended.length() > 0 && new_path.path_.length() > 0) { // Don't append a separator if the path still ends with a trailing // separator after stripping (indicating the root directory). if (!IsSeparator(new_path.path_[new_path.path_.length() - 1])) { @@ -512,7 +512,7 @@ FilePath FilePath::Append(const StringType& component) const { } } - new_path.path_.append(*appended); + appended.AppendToString(&new_path.path_); return new_path; } @@ -520,12 +520,12 @@ FilePath FilePath::Append(const FilePath& component) const { return Append(component.value()); } -FilePath FilePath::AppendASCII(const StringPiece& component) const { +FilePath FilePath::AppendASCII(StringPiece component) const { DCHECK(base::IsStringASCII(component)); #if defined(OS_WIN) - return Append(ASCIIToUTF16(component.as_string())); + return Append(ASCIIToUTF16(component)); #elif defined(OS_POSIX) - return Append(component.as_string()); + return Append(component); #endif } @@ -680,17 +680,17 @@ bool FilePath::ReadFromPickle(PickleIterator* iter) { } #if defined(OS_WIN) -// Windows specific implementation of file string comparisons +// Windows specific implementation of file string comparisons. -int FilePath::CompareIgnoreCase(const StringType& string1, - const StringType& string2) { +int FilePath::CompareIgnoreCase(StringPieceType string1, + StringPieceType string2) { // Perform character-wise upper case comparison rather than using the // fully Unicode-aware CompareString(). For details see: // http://blogs.msdn.com/michkap/archive/2005/10/17/481600.aspx - StringType::const_iterator i1 = string1.begin(); - StringType::const_iterator i2 = string2.begin(); - StringType::const_iterator string1end = string1.end(); - StringType::const_iterator string2end = string2.end(); + StringPieceType::const_iterator i1 = string1.begin(); + StringPieceType::const_iterator i2 = string2.begin(); + StringPieceType::const_iterator string1end = string1.end(); + StringPieceType::const_iterator string2end = string2.end(); for ( ; i1 != string1end && i2 != string2end; ++i1, ++i2) { wchar_t c1 = (wchar_t)LOWORD(::CharUpperW((LPWSTR)(DWORD_PTR)MAKELONG(*i1, 0))); @@ -709,7 +709,7 @@ int FilePath::CompareIgnoreCase(const StringType& string1, } #elif defined(OS_MACOSX) -// Mac OS X specific implementation of file string comparisons +// Mac OS X specific implementation of file string comparisons. // cf. http://developer.apple.com/mac/library/technotes/tn/tn1150.html#UnicodeSubtleties // @@ -1153,23 +1153,23 @@ inline int HFSReadNextNonIgnorableCodepoint(const char* string, return codepoint; } -} // anonymous namespace +} // namespace // Special UTF-8 version of FastUnicodeCompare. Cf: // http://developer.apple.com/mac/library/technotes/tn/tn1150.html#StringComparisonAlgorithm // The input strings must be in the special HFS decomposed form. -int FilePath::HFSFastUnicodeCompare(const StringType& string1, - const StringType& string2) { +int FilePath::HFSFastUnicodeCompare(StringPieceType string1, + StringPieceType string2) { int length1 = string1.length(); int length2 = string2.length(); int index1 = 0; int index2 = 0; for (;;) { - int codepoint1 = HFSReadNextNonIgnorableCodepoint(string1.c_str(), + int codepoint1 = HFSReadNextNonIgnorableCodepoint(string1.data(), length1, &index1); - int codepoint2 = HFSReadNextNonIgnorableCodepoint(string2.c_str(), + int codepoint2 = HFSReadNextNonIgnorableCodepoint(string2.data(), length2, &index2); if (codepoint1 != codepoint2) @@ -1182,11 +1182,11 @@ int FilePath::HFSFastUnicodeCompare(const StringType& string1, } } -StringType FilePath::GetHFSDecomposedForm(const StringType& string) { +StringType FilePath::GetHFSDecomposedForm(StringPieceType string) { ScopedCFTypeRef cfstring( CFStringCreateWithBytesNoCopy( NULL, - reinterpret_cast(string.c_str()), + reinterpret_cast(string.data()), string.length(), kCFStringEncodingUTF8, false, @@ -1215,8 +1215,8 @@ StringType FilePath::GetHFSDecomposedForm(const StringType& string) { return result; } -int FilePath::CompareIgnoreCase(const StringType& string1, - const StringType& string2) { +int FilePath::CompareIgnoreCase(StringPieceType string1, + StringPieceType string2) { // Quick checks for empty strings - these speed things up a bit and make the // following code cleaner. if (string1.empty()) @@ -1233,7 +1233,7 @@ int FilePath::CompareIgnoreCase(const StringType& string1, ScopedCFTypeRef cfstring1( CFStringCreateWithBytesNoCopy( NULL, - reinterpret_cast(string1.c_str()), + reinterpret_cast(string1.data()), string1.length(), kCFStringEncodingUTF8, false, @@ -1241,7 +1241,7 @@ int FilePath::CompareIgnoreCase(const StringType& string1, ScopedCFTypeRef cfstring2( CFStringCreateWithBytesNoCopy( NULL, - reinterpret_cast(string2.c_str()), + reinterpret_cast(string2.data()), string2.length(), kCFStringEncodingUTF8, false, @@ -1256,11 +1256,12 @@ int FilePath::CompareIgnoreCase(const StringType& string1, #else // << WIN. MACOSX | other (POSIX) >> -// Generic (POSIX) implementation of file string comparison. -// TODO(rolandsteiner) check if this is sufficient/correct. -int FilePath::CompareIgnoreCase(const StringType& string1, - const StringType& string2) { - int comparison = strcasecmp(string1.c_str(), string2.c_str()); +// Generic Posix system comparisons. +int FilePath::CompareIgnoreCase(StringPieceType string1, + StringPieceType string2) { + // Specifically need null termianted strings for this API call. + int comparison = strcasecmp(string1.as_string().c_str(), + string2.as_string().c_str()); if (comparison < 0) return -1; if (comparison > 0) diff --git a/base/files/file_path.h b/base/files/file_path.h index 0c84af6c8551d..25b8391c01094 100644 --- a/base/files/file_path.h +++ b/base/files/file_path.h @@ -112,7 +112,7 @@ #include "base/compiler_specific.h" #include "base/containers/hash_tables.h" #include "base/strings/string16.h" -#include "base/strings/string_piece.h" // For implicit conversions. +#include "base/strings/string_piece.h" #include "build/build_config.h" // Windows-style drive letter support and pathname separator characters can be @@ -144,6 +144,7 @@ class BASE_EXPORT FilePath { typedef std::wstring StringType; #endif // OS_WIN + typedef BasicStringPiece StringPieceType; typedef StringType::value_type CharType; // Null-terminated array of separators used to separate components in @@ -166,7 +167,7 @@ class BASE_EXPORT FilePath { FilePath(); FilePath(const FilePath& that); - explicit FilePath(const StringType& path); + explicit FilePath(StringPieceType path); ~FilePath(); FilePath& operator=(const FilePath& that); @@ -268,25 +269,23 @@ class BASE_EXPORT FilePath { // path == "C:\pics\jojo" suffix == " (1)", returns "C:\pics\jojo (1)" // path == "C:\pics.old\jojo" suffix == " (1)", returns "C:\pics.old\jojo (1)" FilePath InsertBeforeExtension( - const StringType& suffix) const WARN_UNUSED_RESULT; + StringPieceType suffix) const WARN_UNUSED_RESULT; FilePath InsertBeforeExtensionASCII( - const base::StringPiece& suffix) const WARN_UNUSED_RESULT; + StringPiece suffix) const WARN_UNUSED_RESULT; // Adds |extension| to |file_name|. Returns the current FilePath if // |extension| is empty. Returns "" if BaseName() == "." or "..". - FilePath AddExtension( - const StringType& extension) const WARN_UNUSED_RESULT; + FilePath AddExtension(StringPieceType extension) const WARN_UNUSED_RESULT; // Replaces the extension of |file_name| with |extension|. If |file_name| // does not have an extension, then |extension| is added. If |extension| is // empty, then the extension is removed from |file_name|. // Returns "" if BaseName() == "." or "..". - FilePath ReplaceExtension( - const StringType& extension) const WARN_UNUSED_RESULT; + FilePath ReplaceExtension(StringPieceType extension) const WARN_UNUSED_RESULT; // Returns true if the file path matches the specified extension. The test is // case insensitive. Don't forget the leading period if appropriate. - bool MatchesExtension(const StringType& extension) const; + bool MatchesExtension(StringPieceType extension) const; // Returns a FilePath by appending a separator and the supplied path // component to this object's path. Append takes care to avoid adding @@ -294,7 +293,7 @@ class BASE_EXPORT FilePath { // If this object's path is kCurrentDirectory, a new FilePath corresponding // only to |component| is returned. |component| must be a relative path; // it is an error to pass an absolute path. - FilePath Append(const StringType& component) const WARN_UNUSED_RESULT; + FilePath Append(StringPieceType component) const WARN_UNUSED_RESULT; FilePath Append(const FilePath& component) const WARN_UNUSED_RESULT; // Although Windows StringType is std::wstring, since the encoding it uses for @@ -303,8 +302,7 @@ class BASE_EXPORT FilePath { // On Linux, although it can use any 8-bit encoding for paths, we assume that // ASCII is a valid subset, regardless of the encoding, since many operating // system paths will always be ASCII. - FilePath AppendASCII(const base::StringPiece& component) - const WARN_UNUSED_RESULT; + FilePath AppendASCII(StringPiece component) const WARN_UNUSED_RESULT; // Returns true if this FilePath contains an absolute path. On Windows, an // absolute path begins with either a drive letter specification followed by @@ -388,14 +386,14 @@ class BASE_EXPORT FilePath { // on parts of a file path, e.g., just the extension. // CompareIgnoreCase() returns -1, 0 or 1 for less-than, equal-to and // greater-than respectively. - static int CompareIgnoreCase(const StringType& string1, - const StringType& string2); - static bool CompareEqualIgnoreCase(const StringType& string1, - const StringType& string2) { + static int CompareIgnoreCase(StringPieceType string1, + StringPieceType string2); + static bool CompareEqualIgnoreCase(StringPieceType string1, + StringPieceType string2) { return CompareIgnoreCase(string1, string2) == 0; } - static bool CompareLessIgnoreCase(const StringType& string1, - const StringType& string2) { + static bool CompareLessIgnoreCase(StringPieceType string1, + StringPieceType string2) { return CompareIgnoreCase(string1, string2) < 0; } @@ -405,14 +403,14 @@ class BASE_EXPORT FilePath { // http://developer.apple.com/mac/library/technotes/tn/tn1150.html#UnicodeSubtleties // for further comments. // Returns the epmty string if the conversion failed. - static StringType GetHFSDecomposedForm(const FilePath::StringType& string); + static StringType GetHFSDecomposedForm(StringPieceType string); // Special UTF-8 version of FastUnicodeCompare. Cf: // http://developer.apple.com/mac/library/technotes/tn/tn1150.html#StringComparisonAlgorithm // IMPORTANT: The input strings must be in the special HFS decomposed form! // (cf. above GetHFSDecomposedForm method) - static int HFSFastUnicodeCompare(const StringType& string1, - const StringType& string2); + static int HFSFastUnicodeCompare(StringPieceType string1, + StringPieceType string2); #endif #if defined(OS_ANDROID) diff --git a/base/files/file_posix.cc b/base/files/file_posix.cc index bb49d2dd730eb..7fb617c3f9daa 100644 --- a/base/files/file_posix.cc +++ b/base/files/file_posix.cc @@ -466,7 +466,7 @@ void File::MemoryCheckingScopedFD::UpdateChecksum() { // NaCl doesn't implement system calls to open files directly. #if !defined(OS_NACL) // TODO(erikkay): does it make sense to support FLAG_EXCLUSIVE_* here? -void File::DoInitialize(uint32 flags) { +void File::DoInitialize(const FilePath& path, uint32 flags) { ThreadRestrictions::AssertIOAllowed(); DCHECK(!IsValid()); @@ -521,7 +521,7 @@ void File::DoInitialize(uint32 flags) { mode |= S_IRGRP | S_IROTH; #endif - int descriptor = HANDLE_EINTR(open(path_.value().c_str(), open_flags, mode)); + int descriptor = HANDLE_EINTR(open(path.value().c_str(), open_flags, mode)); if (flags & FLAG_OPEN_ALWAYS) { if (descriptor < 0) { @@ -529,7 +529,7 @@ void File::DoInitialize(uint32 flags) { if (flags & FLAG_EXCLUSIVE_READ || flags & FLAG_EXCLUSIVE_WRITE) open_flags |= O_EXCL; // together with O_CREAT implies O_NOFOLLOW - descriptor = HANDLE_EINTR(open(path_.value().c_str(), open_flags, mode)); + descriptor = HANDLE_EINTR(open(path.value().c_str(), open_flags, mode)); if (descriptor >= 0) created_ = true; } @@ -544,7 +544,7 @@ void File::DoInitialize(uint32 flags) { created_ = true; if (flags & FLAG_DELETE_ON_CLOSE) - unlink(path_.value().c_str()); + unlink(path.value().c_str()); async_ = ((flags & FLAG_ASYNC) == FLAG_ASYNC); error_details_ = FILE_OK; diff --git a/base/files/file_tracing.cc b/base/files/file_tracing.cc index c25772db8ab5a..92a5780b384cb 100644 --- a/base/files/file_tracing.cc +++ b/base/files/file_tracing.cc @@ -12,6 +12,11 @@ namespace { FileTracing::Provider* g_provider = nullptr; } +// static +bool FileTracing::IsCategoryEnabled() { + return g_provider && g_provider->FileTracingCategoryIsEnabled(); +} + // static void FileTracing::SetProvider(FileTracing::Provider* provider) { g_provider = provider; @@ -34,19 +39,11 @@ FileTracing::ScopedTrace::~ScopedTrace() { g_provider->FileTracingEventEnd(name_, id_); } -bool FileTracing::ScopedTrace::ShouldInitialize() const { - return g_provider && g_provider->FileTracingCategoryIsEnabled(); -} - void FileTracing::ScopedTrace::Initialize( const char* name, File* file, int64 size) { - if (!g_provider) - return; - id_ = &file->trace_enabler_; name_ = name; - - g_provider->FileTracingEventBegin(name_, id_, file->path_, size); + g_provider->FileTracingEventBegin(name_, id_, file->tracing_path_, size); } } // namespace base diff --git a/base/files/file_tracing.h b/base/files/file_tracing.h index 149bd78a9b4a5..d37c21d9ed4eb 100644 --- a/base/files/file_tracing.h +++ b/base/files/file_tracing.h @@ -13,7 +13,7 @@ #define SCOPED_FILE_TRACE_WITH_SIZE(name, size) \ FileTracing::ScopedTrace scoped_file_trace; \ - if (scoped_file_trace.ShouldInitialize()) \ + if (FileTracing::IsCategoryEnabled()) \ scoped_file_trace.Initialize(FILE_TRACING_PREFIX "::" name, this, size) #define SCOPED_FILE_TRACE(name) SCOPED_FILE_TRACE_WITH_SIZE(name, 0) @@ -25,8 +25,13 @@ class FilePath; class BASE_EXPORT FileTracing { public: + // Whether the file tracing category is enabled. + static bool IsCategoryEnabled(); + class Provider { public: + virtual ~Provider() = default; + // Whether the file tracing category is currently enabled. virtual bool FileTracingCategoryIsEnabled() const = 0; @@ -61,9 +66,6 @@ class BASE_EXPORT FileTracing { ScopedTrace(); ~ScopedTrace(); - // Whether this trace should be initialized or not. - bool ShouldInitialize() const; - // Called only if the tracing category is enabled. |name| is the name of the // event to trace (e.g. "Read", "Write") and must have an application // lifetime (e.g. static or literal). |file| is the file being traced; must diff --git a/base/files/file_win.cc b/base/files/file_win.cc index 97928522f106c..ce38d0b0e2af2 100644 --- a/base/files/file_win.cc +++ b/base/files/file_win.cc @@ -308,7 +308,7 @@ File::Error File::OSErrorToFileError(DWORD last_error) { } } -void File::DoInitialize(uint32 flags) { +void File::DoInitialize(const FilePath& path, uint32 flags) { ThreadRestrictions::AssertIOAllowed(); DCHECK(!IsValid()); @@ -376,7 +376,7 @@ void File::DoInitialize(uint32 flags) { if (flags & FLAG_BACKUP_SEMANTICS) create_flags |= FILE_FLAG_BACKUP_SEMANTICS; - file_.Set(CreateFile(path_.value().c_str(), access, sharing, NULL, + file_.Set(CreateFile(path.value().c_str(), access, sharing, NULL, disposition, create_flags, NULL)); if (file_.IsValid()) { diff --git a/base/files/memory_mapped_file.cc b/base/files/memory_mapped_file.cc index bad1792ec3de4..227a41f1cd9e1 100644 --- a/base/files/memory_mapped_file.cc +++ b/base/files/memory_mapped_file.cc @@ -10,18 +10,7 @@ namespace base { -const MemoryMappedFile::Region MemoryMappedFile::Region::kWholeFile( - base::LINKER_INITIALIZED); - -MemoryMappedFile::Region::Region(base::LinkerInitialized) : offset(0), size(0) { -} - -MemoryMappedFile::Region::Region() : offset(-1), size(-1) { -} - -MemoryMappedFile::Region::Region(int64 offset, int64 size) - : offset(offset), size(size) { -} +const MemoryMappedFile::Region MemoryMappedFile::Region::kWholeFile = {0, 0}; bool MemoryMappedFile::Region::operator==( const MemoryMappedFile::Region& other) const { diff --git a/base/files/memory_mapped_file.h b/base/files/memory_mapped_file.h index 96d1d91f9359b..9ff29b9fef11c 100644 --- a/base/files/memory_mapped_file.h +++ b/base/files/memory_mapped_file.h @@ -28,9 +28,6 @@ class BASE_EXPORT MemoryMappedFile { struct BASE_EXPORT Region { static const Region kWholeFile; - Region(); - Region(int64 offset, int64 size); - bool operator==(const Region& other) const; bool operator!=(const Region& other) const; @@ -39,10 +36,6 @@ class BASE_EXPORT MemoryMappedFile { // Length of the region in bytes. int64 size; - - private: - // Used by kWholeFile. - Region(base::LinkerInitialized); }; // Opens an existing file and maps it into memory. Access is restricted to diff --git a/base/files/memory_mapped_file_unittest.cc b/base/files/memory_mapped_file_unittest.cc index d0833b5cc9a24..05b941c308af2 100644 --- a/base/files/memory_mapped_file_unittest.cc +++ b/base/files/memory_mapped_file_unittest.cc @@ -107,7 +107,8 @@ TEST_F(MemoryMappedFileTest, MapPartialRegionAtBeginning) { MemoryMappedFile map; File file(temp_file_path(), File::FLAG_OPEN | File::FLAG_READ); - map.Initialize(file.Pass(), MemoryMappedFile::Region(0, kPartialSize)); + MemoryMappedFile::Region region = {0, kPartialSize}; + map.Initialize(file.Pass(), region); ASSERT_EQ(kPartialSize, map.length()); ASSERT_TRUE(map.data() != NULL); EXPECT_TRUE(map.IsValid()); @@ -122,7 +123,8 @@ TEST_F(MemoryMappedFileTest, MapPartialRegionAtEnd) { MemoryMappedFile map; File file(temp_file_path(), File::FLAG_OPEN | File::FLAG_READ); - map.Initialize(file.Pass(), MemoryMappedFile::Region(kOffset, kPartialSize)); + MemoryMappedFile::Region region = {kOffset, kPartialSize}; + map.Initialize(file.Pass(), region); ASSERT_EQ(kPartialSize, map.length()); ASSERT_TRUE(map.data() != NULL); EXPECT_TRUE(map.IsValid()); @@ -138,7 +140,8 @@ TEST_F(MemoryMappedFileTest, MapSmallPartialRegionInTheMiddle) { MemoryMappedFile map; File file(temp_file_path(), File::FLAG_OPEN | File::FLAG_READ); - map.Initialize(file.Pass(), MemoryMappedFile::Region(kOffset, kPartialSize)); + MemoryMappedFile::Region region = {kOffset, kPartialSize}; + map.Initialize(file.Pass(), region); ASSERT_EQ(kPartialSize, map.length()); ASSERT_TRUE(map.data() != NULL); EXPECT_TRUE(map.IsValid()); @@ -154,7 +157,8 @@ TEST_F(MemoryMappedFileTest, MapLargePartialRegionInTheMiddle) { MemoryMappedFile map; File file(temp_file_path(), File::FLAG_OPEN | File::FLAG_READ); - map.Initialize(file.Pass(), MemoryMappedFile::Region(kOffset, kPartialSize)); + MemoryMappedFile::Region region = {kOffset, kPartialSize}; + map.Initialize(file.Pass(), region); ASSERT_EQ(kPartialSize, map.length()); ASSERT_TRUE(map.data() != NULL); EXPECT_TRUE(map.IsValid()); diff --git a/base/files/memory_mapped_file_win.cc b/base/files/memory_mapped_file_win.cc index 4e7e934e1c858..85859061ef320 100644 --- a/base/files/memory_mapped_file_win.cc +++ b/base/files/memory_mapped_file_win.cc @@ -32,7 +32,7 @@ bool MemoryMappedFile::MapFileRegionToMemory( if (!file_mapping_.IsValid()) return false; - LARGE_INTEGER map_start = {0}; + LARGE_INTEGER map_start = {}; SIZE_T map_size = 0; int32 data_offset = 0; diff --git a/base/i18n/bidi_line_iterator.cc b/base/i18n/bidi_line_iterator.cc index 8c81d85ec62d6..216129e8b88eb 100644 --- a/base/i18n/bidi_line_iterator.cc +++ b/base/i18n/bidi_line_iterator.cc @@ -9,6 +9,25 @@ namespace base { namespace i18n { +namespace { + UBiDiLevel GetParagraphLevelForDirection(TextDirection direction) { + switch (direction) { + case UNKNOWN_DIRECTION: + return UBIDI_DEFAULT_LTR; + break; + case RIGHT_TO_LEFT: + return 1; // Highest RTL level. + break; + case LEFT_TO_RIGHT: + return 0; // Highest LTR level. + break; + default: + NOTREACHED(); + return 0; + } + } +} // namespace + BiDiLineIterator::BiDiLineIterator() : bidi_(NULL) { } @@ -19,15 +38,14 @@ BiDiLineIterator::~BiDiLineIterator() { } } -bool BiDiLineIterator::Open(const string16& text, bool right_to_left) { +bool BiDiLineIterator::Open(const string16& text, TextDirection direction) { DCHECK(!bidi_); UErrorCode error = U_ZERO_ERROR; bidi_ = ubidi_openSized(static_cast(text.length()), 0, &error); if (U_FAILURE(error)) return false; ubidi_setPara(bidi_, text.data(), static_cast(text.length()), - right_to_left ? UBIDI_DEFAULT_RTL : UBIDI_DEFAULT_LTR, - NULL, &error); + GetParagraphLevelForDirection(direction), NULL, &error); return (U_SUCCESS(error) == TRUE); } diff --git a/base/i18n/bidi_line_iterator.h b/base/i18n/bidi_line_iterator.h index 07d9aa261ea27..0bf1ec67ce2a7 100644 --- a/base/i18n/bidi_line_iterator.h +++ b/base/i18n/bidi_line_iterator.h @@ -7,6 +7,7 @@ #include "base/basictypes.h" #include "base/i18n/base_i18n_export.h" +#include "base/i18n/rtl.h" #include "base/strings/string16.h" #include "third_party/icu/source/common/unicode/ubidi.h" @@ -23,7 +24,7 @@ class BASE_I18N_EXPORT BiDiLineIterator { // Initializes the bidirectional iterator with the specified text. Returns // whether initialization succeeded. - bool Open(const string16& text, bool right_to_left); + bool Open(const string16& text, TextDirection direction); // Returns the number of visual runs in the text, or zero on error. int CountRuns(); diff --git a/base/i18n/case_conversion.cc b/base/i18n/case_conversion.cc index 5debc2ec8d662..4b62d16448461 100644 --- a/base/i18n/case_conversion.cc +++ b/base/i18n/case_conversion.cc @@ -4,22 +4,84 @@ #include "base/i18n/case_conversion.h" +#include "base/numerics/safe_conversions.h" #include "base/strings/string16.h" +#include "base/strings/string_util.h" +#include "third_party/icu/source/common/unicode/uchar.h" #include "third_party/icu/source/common/unicode/unistr.h" +#include "third_party/icu/source/common/unicode/ustring.h" namespace base { namespace i18n { -string16 ToLower(const StringPiece16& string) { - icu::UnicodeString unicode_string(string.data(), string.size()); - unicode_string.toLower(); - return string16(unicode_string.getBuffer(), unicode_string.length()); +namespace { + +// Provides a uniform interface for upper/lower/folding which take take +// slightly varying parameters. +typedef int32_t (*CaseMapperFunction)(UChar* dest, int32_t dest_capacity, + const UChar* src, int32_t src_length, + UErrorCode* error); + +int32_t ToUpperMapper(UChar* dest, int32_t dest_capacity, + const UChar* src, int32_t src_length, + UErrorCode* error) { + // Use default locale. + return u_strToUpper(dest, dest_capacity, src, src_length, NULL, error); +} + +int32_t ToLowerMapper(UChar* dest, int32_t dest_capacity, + const UChar* src, int32_t src_length, + UErrorCode* error) { + // Use default locale. + return u_strToLower(dest, dest_capacity, src, src_length, NULL, error); +} + +int32_t FoldCaseMapper(UChar* dest, int32_t dest_capacity, + const UChar* src, int32_t src_length, + UErrorCode* error) { + return u_strFoldCase(dest, dest_capacity, src, src_length, + U_FOLD_CASE_DEFAULT, error); +} + +// Provides similar functionality as UnicodeString::caseMap but on string16. +string16 CaseMap(StringPiece16 string, CaseMapperFunction case_mapper) { + string16 dest; + if (string.empty()) + return dest; + + // Provide an initial guess that the string length won't change. The typical + // strings we use will very rarely change length in this process, so don't + // optimize for that case. + dest.resize(string.size()); + + UErrorCode error; + do { + error = U_ZERO_ERROR; + + // ICU won't terminate the string if there's not enough room for the null + // terminator, but will otherwise. So we don't need to save room for that. + // Don't use WriteInto, which assumes null terminators. + int32_t new_length = case_mapper( + &dest[0], saturated_cast(dest.size()), + string.data(), saturated_cast(string.size()), + &error); + dest.resize(new_length); + } while (error == U_BUFFER_OVERFLOW_ERROR); + return dest; +} + +} // namespace + +string16 ToLower(StringPiece16 string) { + return CaseMap(string, &ToLowerMapper); +} + +string16 ToUpper(StringPiece16 string) { + return CaseMap(string, &ToUpperMapper); } -string16 ToUpper(const StringPiece16& string) { - icu::UnicodeString unicode_string(string.data(), string.size()); - unicode_string.toUpper(); - return string16(unicode_string.getBuffer(), unicode_string.length()); +string16 FoldCase(StringPiece16 string) { + return CaseMap(string, &FoldCaseMapper); } } // namespace i18n diff --git a/base/i18n/case_conversion.h b/base/i18n/case_conversion.h index 5d538ccf1d3e2..0631a800b7176 100644 --- a/base/i18n/case_conversion.h +++ b/base/i18n/case_conversion.h @@ -12,11 +12,35 @@ namespace base { namespace i18n { -// Returns the lower case equivalent of string. Uses ICU's default locale. -BASE_I18N_EXPORT string16 ToLower(const StringPiece16& string); +// UNICODE CASE-HANDLING ADVICE +// +// In English it's always safe to convert to upper-case or lower-case text +// and get a good answer. But some languages have rules specific to those +// locales. One example is the Turkish I: +// http://www.i18nguy.com/unicode/turkish-i18n.html +// +// ToLower/ToUpper use the current ICU locale which will take into account +// the user language preference. Use this when dealing with user typing. +// +// FoldCase canonicalizes to a standardized form independent of the current +// locale. Use this when comparing general Unicode strings that don't +// necessarily belong in the user's current locale (like commands, protocol +// names, other strings from the web) for case-insensitive equality. +// +// Note that case conversions will change the length of the string in some +// not-uncommon cases. Never assume that the output is the same length as +// the input. -// Returns the upper case equivalent of string. Uses ICU's default locale. -BASE_I18N_EXPORT string16 ToUpper(const StringPiece16& string); +// Returns the lower case equivalent of string. Uses ICU's current locale. +BASE_I18N_EXPORT string16 ToLower(StringPiece16 string); + +// Returns the upper case equivalent of string. Uses ICU's current locale. +BASE_I18N_EXPORT string16 ToUpper(StringPiece16 string); + +// Convert the given string to a canonical case, independent of the current +// locale. For ASCII the canonical form is lower case. +// See http://unicode.org/faq/casemap_charprop.html#2 +BASE_I18N_EXPORT string16 FoldCase(StringPiece16 string); } // namespace i18n } // namespace base diff --git a/base/i18n/case_conversion_unittest.cc b/base/i18n/case_conversion_unittest.cc index 75e5ad232533f..dc5bc1fe8b145 100644 --- a/base/i18n/case_conversion_unittest.cc +++ b/base/i18n/case_conversion_unittest.cc @@ -9,39 +9,47 @@ #include "third_party/icu/source/i18n/unicode/usearch.h" namespace base { +namespace i18n { + namespace { +const wchar_t kNonASCIIMixed[] = + L"\xC4\xD6\xE4\xF6\x20\xCF\xEF\x20\xF7\x25" + L"\xA4\x23\x2A\x5E\x60\x40\xA3\x24\x2030\x201A\x7E\x20\x1F07\x1F0F" + L"\x20\x1E00\x1E01"; +const wchar_t kNonASCIILower[] = + L"\xE4\xF6\xE4\xF6\x20\xEF\xEF" + L"\x20\xF7\x25\xA4\x23\x2A\x5E\x60\x40\xA3\x24\x2030\x201A\x7E\x20\x1F07" + L"\x1F07\x20\x1E01\x1E01"; +const wchar_t kNonASCIIUpper[] = + L"\xC4\xD6\xC4\xD6\x20\xCF\xCF" + L"\x20\xF7\x25\xA4\x23\x2A\x5E\x60\x40\xA3\x24\x2030\x201A\x7E\x20\x1F0F" + L"\x1F0F\x20\x1E00\x1E00"; + +} // namespace + // Test upper and lower case string conversion. TEST(CaseConversionTest, UpperLower) { const string16 mixed(ASCIIToUTF16("Text with UPPer & lowER casE.")); const string16 expected_lower(ASCIIToUTF16("text with upper & lower case.")); const string16 expected_upper(ASCIIToUTF16("TEXT WITH UPPER & LOWER CASE.")); - string16 result = base::i18n::ToLower(mixed); + string16 result = ToLower(mixed); EXPECT_EQ(expected_lower, result); - result = base::i18n::ToUpper(mixed); + result = ToUpper(mixed); EXPECT_EQ(expected_upper, result); } TEST(CaseConversionTest, NonASCII) { - const string16 mixed(WideToUTF16( - L"\xC4\xD6\xE4\xF6\x20\xCF\xEF\x20\xF7\x25" - L"\xA4\x23\x2A\x5E\x60\x40\xA3\x24\x2030\x201A\x7E\x20\x1F07\x1F0F" - L"\x20\x1E00\x1E01")); - const string16 expected_lower(WideToUTF16( - L"\xE4\xF6\xE4\xF6\x20\xEF\xEF" - L"\x20\xF7\x25\xA4\x23\x2A\x5E\x60\x40\xA3\x24\x2030\x201A\x7E\x20\x1F07" - L"\x1F07\x20\x1E01\x1E01")); - const string16 expected_upper(WideToUTF16( - L"\xC4\xD6\xC4\xD6\x20\xCF\xCF" - L"\x20\xF7\x25\xA4\x23\x2A\x5E\x60\x40\xA3\x24\x2030\x201A\x7E\x20\x1F0F" - L"\x1F0F\x20\x1E00\x1E00")); - - string16 result = base::i18n::ToLower(mixed); + const string16 mixed(WideToUTF16(kNonASCIIMixed)); + const string16 expected_lower(WideToUTF16(kNonASCIILower)); + const string16 expected_upper(WideToUTF16(kNonASCIIUpper)); + + string16 result = ToLower(mixed); EXPECT_EQ(expected_lower, result); - result = base::i18n::ToUpper(mixed); + result = ToUpper(mixed); EXPECT_EQ(expected_upper, result); } @@ -53,10 +61,10 @@ TEST(CaseConversionTest, TurkishLocaleConversion) { std::string default_locale(uloc_getDefault()); i18n::SetICUDefaultLocale("en_US"); - string16 result = base::i18n::ToLower(mixed); + string16 result = ToLower(mixed); EXPECT_EQ(expected_lower, result); - result = base::i18n::ToUpper(mixed); + result = ToUpper(mixed); EXPECT_EQ(expected_upper, result); i18n::SetICUDefaultLocale("tr"); @@ -64,16 +72,48 @@ TEST(CaseConversionTest, TurkishLocaleConversion) { const string16 expected_lower_turkish(WideToUTF16(L"\x131\x131")); const string16 expected_upper_turkish(WideToUTF16(L"\x49\x49")); - result = base::i18n::ToLower(mixed); + result = ToLower(mixed); EXPECT_EQ(expected_lower_turkish, result); - result = base::i18n::ToUpper(mixed); + result = ToUpper(mixed); EXPECT_EQ(expected_upper_turkish, result); - base::i18n::SetICUDefaultLocale(default_locale.data()); + SetICUDefaultLocale(default_locale.data()); } -} // namespace +TEST(CaseConversionTest, FoldCase) { + // Simple ASCII, should lower-case. + EXPECT_EQ(ASCIIToUTF16("hello, world"), + FoldCase(ASCIIToUTF16("Hello, World"))); + + // Non-ASCII cases from above. They should all fold to the same result. + EXPECT_EQ(FoldCase(WideToUTF16(kNonASCIIMixed)), + FoldCase(WideToUTF16(kNonASCIILower))); + EXPECT_EQ(FoldCase(WideToUTF16(kNonASCIIMixed)), + FoldCase(WideToUTF16(kNonASCIIUpper))); + + // Turkish cases from above. This is the lower-case expected result from the + // US locale. It should be the same even when the current locale is Turkish. + const string16 turkish(WideToUTF16(L"\x49\x131")); + const string16 turkish_expected(WideToUTF16(L"\x69\x131")); + + std::string default_locale(uloc_getDefault()); + i18n::SetICUDefaultLocale("en_US"); + EXPECT_EQ(turkish_expected, FoldCase(turkish)); + + i18n::SetICUDefaultLocale("tr"); + EXPECT_EQ(turkish_expected, FoldCase(turkish)); + + // Test a case that gets bigger when processed. + // U+130 = LATIN CAPITAL LETTER I WITH DOT ABOVE gets folded to a lower case + // "i" followed by U+307 COMBINING DOT ABOVE. + EXPECT_EQ(WideToUTF16(L"i\u0307j"), FoldCase(WideToUTF16(L"\u0130j"))); + + // U+00DF (SHARP S) and U+1E9E (CAPIRAL SHARP S) are both folded to "ss". + EXPECT_EQ(ASCIIToUTF16("ssss"), FoldCase(WideToUTF16(L"\u00DF\u1E9E"))); +} + +} // namespace i18n } // namespace base diff --git a/base/i18n/icu_util.cc b/base/i18n/icu_util.cc index a9f0b129633cd..1dd54cd606d8b 100644 --- a/base/i18n/icu_util.cc +++ b/base/i18n/icu_util.cc @@ -23,6 +23,10 @@ #include "third_party/icu/source/i18n/unicode/timezone.h" #endif +#if defined(OS_ANDROID) +#include "base/android/apk_assets.h" +#endif + #if defined(OS_MACOSX) #include "base/mac/foundation_util.h" #endif @@ -34,11 +38,6 @@ namespace base { namespace i18n { -// Use an unversioned file name to simplify a icu version update down the road. -// No need to change the filename in multiple places (gyp files, windows -// build pkg configurations, etc). 'l' stands for Little Endian. -// This variable is exported through the header file. -const char kIcuDataFileName[] = "icudtl.dat"; #if ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_SHARED #define ICU_UTIL_DATA_SYMBOL "icudt" U_ICU_VERSION_SHORT "_dat" #if defined(OS_WIN) @@ -47,44 +46,140 @@ const char kIcuDataFileName[] = "icudtl.dat"; #endif namespace { - +#if !defined(OS_NACL) #if !defined(NDEBUG) // Assert that we are not called more than once. Even though calling this // function isn't harmful (ICU can handle it), being called twice probably // indicates a programming error. -#if !defined(OS_NACL) +bool g_check_called_once = true; bool g_called_once = false; +#endif // !defined(NDEBUG) + +#if ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_FILE +// Use an unversioned file name to simplify a icu version update down the road. +// No need to change the filename in multiple places (gyp files, windows +// build pkg configurations, etc). 'l' stands for Little Endian. +// This variable is exported through the header file. +const char kIcuDataFileName[] = "icudtl.dat"; +#if defined(OS_ANDROID) +const char kAndroidAssetsIcuDataFileName[] = "assets/icudtl.dat"; #endif -bool g_check_called_once = true; + +// File handle intentionally never closed. Not using File here because its +// Windows implementation guards against two instances owning the same +// PlatformFile (which we allow since we know it is never freed). +const PlatformFile kInvalidPlatformFile = +#if defined(OS_WIN) + INVALID_HANDLE_VALUE; +#else + -1; #endif +PlatformFile g_icudtl_pf = kInvalidPlatformFile; +MemoryMappedFile* g_icudtl_mapped_file = nullptr; +MemoryMappedFile::Region g_icudtl_region; + +void LazyInitIcuDataFile() { + if (g_icudtl_pf != kInvalidPlatformFile) { + return; + } +#if defined(OS_ANDROID) + int fd = base::android::OpenApkAsset(kAndroidAssetsIcuDataFileName, + &g_icudtl_region); + g_icudtl_pf = fd; + if (fd != -1) { + return; + } +// For unit tests, data file is located on disk, so try there as a fallback. +#endif // defined(OS_ANDROID) +#if !defined(OS_MACOSX) + FilePath data_path; +#if defined(OS_WIN) + // The data file will be in the same directory as the current module. + bool path_ok = PathService::Get(DIR_MODULE, &data_path); + wchar_t tmp_buffer[_MAX_PATH] = {0}; + wcscpy_s(tmp_buffer, data_path.value().c_str()); + debug::Alias(tmp_buffer); + CHECK(path_ok); // TODO(scottmg): http://crbug.com/445616 +#elif defined(OS_ANDROID) + bool path_ok = PathService::Get(DIR_ANDROID_APP_DATA, &data_path); +#else + // For now, expect the data file to be alongside the executable. + // This is sufficient while we work on unit tests, but will eventually + // likely live in a data directory. + bool path_ok = PathService::Get(DIR_EXE, &data_path); +#endif + DCHECK(path_ok); + data_path = data_path.AppendASCII(kIcuDataFileName); + +#if defined(OS_WIN) + // TODO(scottmg): http://crbug.com/445616 + wchar_t tmp_buffer2[_MAX_PATH] = {0}; + wcscpy_s(tmp_buffer2, data_path.value().c_str()); + debug::Alias(tmp_buffer2); +#endif + +#else + // Assume it is in the framework bundle's Resources directory. + ScopedCFTypeRef data_file_name( + SysUTF8ToCFStringRef(kIcuDataFileName)); + FilePath data_path = mac::PathForFrameworkBundleResource(data_file_name); + if (data_path.empty()) { + LOG(ERROR) << kIcuDataFileName << " not found in bundle"; + return; + } +#endif // !defined(OS_MACOSX) + File file(data_path, File::FLAG_OPEN | File::FLAG_READ); + if (file.IsValid()) { + g_icudtl_pf = file.TakePlatformFile(); + g_icudtl_region = MemoryMappedFile::Region::kWholeFile; + } } +bool InitializeICUWithFileDescriptorInternal( + PlatformFile data_fd, + const MemoryMappedFile::Region& data_region) { + // This can be called multiple times in tests. + if (g_icudtl_mapped_file) { + return true; + } + if (data_fd == kInvalidPlatformFile) { + return false; + } + + scoped_ptr icudtl_mapped_file(new MemoryMappedFile()); + if (!icudtl_mapped_file->Initialize(File(data_fd), data_region)) { + LOG(ERROR) << "Couldn't mmap icu data file"; + return false; + } + g_icudtl_mapped_file = icudtl_mapped_file.release(); + + UErrorCode err = U_ZERO_ERROR; + udata_setCommonData(const_cast(g_icudtl_mapped_file->data()), &err); + return err == U_ZERO_ERROR; +} +#endif // ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_FILE +#endif // !defined(OS_NACL) + +} // namespace + #if !defined(OS_NACL) +#if ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_FILE bool InitializeICUWithFileDescriptor( PlatformFile data_fd, - MemoryMappedFile::Region data_region) { + const MemoryMappedFile::Region& data_region) { #if !defined(NDEBUG) DCHECK(!g_check_called_once || !g_called_once); g_called_once = true; #endif - -#if (ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_STATIC) - // The ICU data is statically linked. - return true; -#elif (ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_FILE) - CR_DEFINE_STATIC_LOCAL(MemoryMappedFile, mapped_file, ()); - if (!mapped_file.IsValid()) { - if (!mapped_file.Initialize(File(data_fd), data_region)) { - LOG(ERROR) << "Couldn't mmap icu data file"; - return false; - } - } - UErrorCode err = U_ZERO_ERROR; - udata_setCommonData(const_cast(mapped_file.data()), &err); - return err == U_ZERO_ERROR; -#endif // ICU_UTIL_DATA_FILE + return InitializeICUWithFileDescriptorInternal(data_fd, data_region); } +PlatformFile GetIcuDataFileHandle(MemoryMappedFile::Region* out_region) { + CHECK_NE(g_icudtl_pf, kInvalidPlatformFile); + *out_region = g_icudtl_region; + return g_icudtl_pf; +} +#endif // ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_FILE bool InitializeICU() { #if !defined(NDEBUG) @@ -123,60 +218,9 @@ bool InitializeICU() { // it is needed. This can fail if the process is sandboxed at that time. // Instead, we map the file in and hand off the data so the sandbox won't // cause any problems. - - // Chrome doesn't normally shut down ICU, so the mapped data shouldn't ever - // be released. - CR_DEFINE_STATIC_LOCAL(MemoryMappedFile, mapped_file, ()); - if (!mapped_file.IsValid()) { -#if !defined(OS_MACOSX) - FilePath data_path; -#if defined(OS_WIN) - // The data file will be in the same directory as the current module. - bool path_ok = PathService::Get(DIR_MODULE, &data_path); - wchar_t tmp_buffer[_MAX_PATH] = {0}; - wcscpy_s(tmp_buffer, data_path.value().c_str()); - debug::Alias(tmp_buffer); - CHECK(path_ok); // TODO(scottmg): http://crbug.com/445616 -#elif defined(OS_ANDROID) - bool path_ok = PathService::Get(DIR_ANDROID_APP_DATA, &data_path); -#else - // For now, expect the data file to be alongside the executable. - // This is sufficient while we work on unit tests, but will eventually - // likely live in a data directory. - bool path_ok = PathService::Get(DIR_EXE, &data_path); -#endif - DCHECK(path_ok); - data_path = data_path.AppendASCII(kIcuDataFileName); - -#if defined(OS_WIN) - // TODO(scottmg): http://crbug.com/445616 - wchar_t tmp_buffer2[_MAX_PATH] = {0}; - wcscpy_s(tmp_buffer2, data_path.value().c_str()); - debug::Alias(tmp_buffer2); -#endif - -#else - // Assume it is in the framework bundle's Resources directory. - ScopedCFTypeRef data_file_name( - SysUTF8ToCFStringRef(kIcuDataFileName)); - FilePath data_path = - mac::PathForFrameworkBundleResource(data_file_name); - if (data_path.empty()) { - LOG(ERROR) << kIcuDataFileName << " not found in bundle"; - return false; - } -#endif // OS check - if (!mapped_file.Initialize(data_path)) { -#if defined(OS_WIN) - CHECK(false); // TODO(scottmg): http://crbug.com/445616 -#endif - LOG(ERROR) << "Couldn't mmap " << data_path.AsUTF8Unsafe(); - return false; - } - } - UErrorCode err = U_ZERO_ERROR; - udata_setCommonData(const_cast(mapped_file.data()), &err); - result = (err == U_ZERO_ERROR); + LazyInitIcuDataFile(); + result = + InitializeICUWithFileDescriptorInternal(g_icudtl_pf, g_icudtl_region); #if defined(OS_WIN) CHECK(result); // TODO(scottmg): http://crbug.com/445616 #endif @@ -193,10 +237,10 @@ bool InitializeICU() { #endif return result; } -#endif +#endif // !defined(OS_NACL) void AllowMultipleInitializeCallsForTesting() { -#if !defined(NDEBUG) +#if !defined(NDEBUG) && !defined(OS_NACL) g_check_called_once = false; #endif } diff --git a/base/i18n/icu_util.h b/base/i18n/icu_util.h index 65de0ad7e215f..d62f8bac0d946 100644 --- a/base/i18n/icu_util.h +++ b/base/i18n/icu_util.h @@ -12,19 +12,24 @@ namespace base { namespace i18n { -BASE_I18N_EXPORT extern const char kIcuDataFileName[]; - #if !defined(OS_NACL) // Call this function to load ICU's data tables for the current process. This // function should be called before ICU is used. BASE_I18N_EXPORT bool InitializeICU(); +#if ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_FILE +// Returns the PlatformFile and Region that was initialized by InitializeICU(). +// Use with InitializeICUWithFileDescriptor(). +BASE_I18N_EXPORT PlatformFile GetIcuDataFileHandle( + MemoryMappedFile::Region* out_region); + // Android and html_viewer use a file descriptor passed by browser process to // initialize ICU in render processes. BASE_I18N_EXPORT bool InitializeICUWithFileDescriptor( PlatformFile data_fd, - MemoryMappedFile::Region data_region); -#endif + const MemoryMappedFile::Region& data_region); +#endif // ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_FILE +#endif // !defined(OS_NACL) // In a test binary, the call above might occur twice. BASE_I18N_EXPORT void AllowMultipleInitializeCallsForTesting(); diff --git a/base/i18n/time_formatting.cc b/base/i18n/time_formatting.cc index 15b34a31f917f..55121115fa538 100644 --- a/base/i18n/time_formatting.cc +++ b/base/i18n/time_formatting.cc @@ -45,6 +45,26 @@ string16 TimeFormatWithoutAmPm(const icu::DateFormat* formatter, static_cast(time_string.length())); } +icu::SimpleDateFormat CreateSimpleDateFormatter(const char* pattern) { + // Generate a locale-dependent format pattern. The generator will take + // care of locale-dependent formatting issues like which separator to + // use (some locales use '.' instead of ':'), and where to put the am/pm + // marker. + UErrorCode status = U_ZERO_ERROR; + scoped_ptr generator( + icu::DateTimePatternGenerator::createInstance(status)); + DCHECK(U_SUCCESS(status)); + icu::UnicodeString generated_pattern = + generator->getBestPattern(icu::UnicodeString(pattern), status); + DCHECK(U_SUCCESS(status)); + + // Then, format the time using the generated pattern. + icu::SimpleDateFormat formatter(generated_pattern, status); + DCHECK(U_SUCCESS(status)); + + return formatter; +} + } // namespace string16 TimeFormatTimeOfDay(const Time& time) { @@ -55,6 +75,11 @@ string16 TimeFormatTimeOfDay(const Time& time) { return TimeFormat(formatter.get(), time); } +string16 TimeFormatTimeOfDayWithMilliseconds(const Time& time) { + icu::SimpleDateFormat formatter = CreateSimpleDateFormatter("HmsSSS"); + return TimeFormatWithoutAmPm(&formatter, time); +} + string16 TimeFormatTimeOfDayWithHourClockType(const Time& time, HourClockType type, AmPmClockType ampm) { @@ -65,22 +90,9 @@ string16 TimeFormatTimeOfDayWithHourClockType(const Time& time, return TimeFormatTimeOfDay(time); } - // Generate a locale-dependent format pattern. The generator will take - // care of locale-dependent formatting issues like which separator to - // use (some locales use '.' instead of ':'), and where to put the am/pm - // marker. - UErrorCode status = U_ZERO_ERROR; - scoped_ptr generator( - icu::DateTimePatternGenerator::createInstance(status)); - DCHECK(U_SUCCESS(status)); const char* base_pattern = (type == k12HourClock ? "ahm" : "Hm"); - icu::UnicodeString generated_pattern = - generator->getBestPattern(icu::UnicodeString(base_pattern), status); - DCHECK(U_SUCCESS(status)); + icu::SimpleDateFormat formatter = CreateSimpleDateFormatter(base_pattern); - // Then, format the time using the generated pattern. - icu::SimpleDateFormat formatter(generated_pattern, status); - DCHECK(U_SUCCESS(status)); if (ampm == kKeepAmPm) { return TimeFormat(&formatter, time); } else { diff --git a/base/i18n/time_formatting.h b/base/i18n/time_formatting.h index 2053c0b47da12..df91f41beddd2 100644 --- a/base/i18n/time_formatting.h +++ b/base/i18n/time_formatting.h @@ -30,6 +30,10 @@ enum AmPmClockType { // Returns the time of day, e.g., "3:07 PM". BASE_I18N_EXPORT string16 TimeFormatTimeOfDay(const Time& time); +// Returns the time of day in 24-hour clock format with millisecond accuracy, +// e.g., "15:07:30.568" +BASE_I18N_EXPORT string16 TimeFormatTimeOfDayWithMilliseconds(const Time& time); + // Returns the time of day in the specified hour clock type. e.g. // "3:07 PM" (type == k12HourClock, ampm == kKeepAmPm). // "3:07" (type == k12HourClock, ampm == kDropAmPm). diff --git a/base/i18n/time_formatting_unittest.cc b/base/i18n/time_formatting_unittest.cc index df0c1ed5ea1ec..9f152c0b2d90e 100644 --- a/base/i18n/time_formatting_unittest.cc +++ b/base/i18n/time_formatting_unittest.cc @@ -12,6 +12,7 @@ #include "third_party/icu/source/common/unicode/uversion.h" #include "third_party/icu/source/i18n/unicode/calendar.h" #include "third_party/icu/source/i18n/unicode/timezone.h" +#include "third_party/icu/source/i18n/unicode/tzfmt.h" namespace base { namespace { @@ -21,10 +22,19 @@ const Time::Exploded kTestDateTimeExploded = { 15, 42, 7, 0 // 15:42:07.000 }; -base::string16 GetShortTimeZone() { +// Returns difference between the local time and GMT formatted as string. +// This function gets |time| because the difference depends on time, +// see https://en.wikipedia.org/wiki/Daylight_saving_time for details. +base::string16 GetShortTimeZone(const Time& time) { + UErrorCode status = U_ZERO_ERROR; scoped_ptr zone(icu::TimeZone::createDefault()); + scoped_ptr zone_formatter( + icu::TimeZoneFormat::createInstance(icu::Locale::getDefault(), status)); + EXPECT_TRUE(U_SUCCESS(status)); icu::UnicodeString name; - zone->getDisplayName(true, icu::TimeZone::SHORT, name); + zone_formatter->format(UTZFMT_STYLE_SPECIFIC_SHORT, *zone, + static_cast(time.ToDoubleT() * 1000), + name, nullptr); return base::string16(name.getBuffer(), name.length()); } @@ -37,9 +47,11 @@ TEST(TimeFormattingTest, TimeFormatTimeOfDayDefault12h) { string16 clock24h(ASCIIToUTF16("15:42")); string16 clock12h_pm(ASCIIToUTF16("3:42 PM")); string16 clock12h(ASCIIToUTF16("3:42")); + string16 clock24h_millis(ASCIIToUTF16("15:42:07.000")); // The default is 12h clock. EXPECT_EQ(clock12h_pm, TimeFormatTimeOfDay(time)); + EXPECT_EQ(clock24h_millis, TimeFormatTimeOfDayWithMilliseconds(time)); EXPECT_EQ(k12HourClock, GetHourClockType()); // k{Keep,Drop}AmPm should not affect for 24h clock. EXPECT_EQ(clock24h, @@ -70,9 +82,11 @@ TEST(TimeFormattingTest, TimeFormatTimeOfDayDefault24h) { string16 clock24h(ASCIIToUTF16("15:42")); string16 clock12h_pm(ASCIIToUTF16("3:42 pm")); string16 clock12h(ASCIIToUTF16("3:42")); + string16 clock24h_millis(ASCIIToUTF16("15:42:07.000")); // The default is 24h clock. EXPECT_EQ(clock24h, TimeFormatTimeOfDay(time)); + EXPECT_EQ(clock24h_millis, TimeFormatTimeOfDayWithMilliseconds(time)); EXPECT_EQ(k24HourClock, GetHourClockType()); // k{Keep,Drop}AmPm should not affect for 24h clock. EXPECT_EQ(clock24h, @@ -139,7 +153,7 @@ TEST(TimeFormattingTest, TimeFormatDateUS) { EXPECT_EQ(ASCIIToUTF16("4/30/11, 3:42:07 PM"), TimeFormatShortDateAndTime(time)); - EXPECT_EQ(ASCIIToUTF16("4/30/11, 3:42:07 PM ") + GetShortTimeZone(), + EXPECT_EQ(ASCIIToUTF16("4/30/11, 3:42:07 PM ") + GetShortTimeZone(time), TimeFormatShortDateAndTimeWithTimeZone(time)); EXPECT_EQ(ASCIIToUTF16("Saturday, April 30, 2011 at 3:42:07 PM"), @@ -160,7 +174,7 @@ TEST(TimeFormattingTest, TimeFormatDateGB) { EXPECT_EQ(ASCIIToUTF16("30/04/2011"), TimeFormatShortDateNumeric(time)); EXPECT_EQ(ASCIIToUTF16("30/04/2011, 15:42:07"), TimeFormatShortDateAndTime(time)); - EXPECT_EQ(ASCIIToUTF16("30/04/2011, 15:42:07 ") + GetShortTimeZone(), + EXPECT_EQ(ASCIIToUTF16("30/04/2011, 15:42:07 ") + GetShortTimeZone(time), TimeFormatShortDateAndTimeWithTimeZone(time)); EXPECT_EQ(ASCIIToUTF16("Saturday, 30 April 2011 at 15:42:07"), TimeFormatFriendlyDateAndTime(time)); diff --git a/base/ios/crb_protocol_observers_unittest.mm b/base/ios/crb_protocol_observers_unittest.mm index 5f1105122943f..b8cf4231e4d3b 100644 --- a/base/ios/crb_protocol_observers_unittest.mm +++ b/base/ios/crb_protocol_observers_unittest.mm @@ -4,6 +4,7 @@ #import "base/ios/crb_protocol_observers.h" #include "base/ios/weak_nsobject.h" +#include "base/logging.h" #include "base/mac/scoped_nsautorelease_pool.h" #include "base/mac/scoped_nsobject.h" #include "testing/gtest/include/gtest/gtest.h" @@ -36,10 +37,9 @@ @interface TestCompleteObserver : TestPartialObserver @end @interface TestMutateObserver : TestCompleteObserver - - (instancetype)initWithObserver:(CRBProtocolObservers*)observer NS_DESIGNATED_INITIALIZER; - +- (instancetype)init NS_UNAVAILABLE; @end namespace { @@ -266,6 +266,11 @@ - (instancetype)initWithObserver:(CRBProtocolObservers*)observers { return self; } +- (instancetype)init { + NOTREACHED(); + return nil; +} + - (void)mutateByAddingObserver:(id)observer { [_observers addObserver:observer]; } diff --git a/base/ios/device_util.mm b/base/ios/device_util.mm index 1234562944d11..4af8234988fc3 100644 --- a/base/ios/device_util.mm +++ b/base/ios/device_util.mm @@ -59,7 +59,7 @@ std::string platform; size_t size = 0; sysctlbyname("hw.machine", NULL, &size, NULL, 0); - sysctlbyname("hw.machine", WriteInto(&platform, size), &size, NULL, 0); + sysctlbyname("hw.machine", base::WriteInto(&platform, size), &size, NULL, 0); return platform; } diff --git a/base/ios/ios_util.h b/base/ios/ios_util.h index d9d7e193dd55b..688fbf3ba9fae 100644 --- a/base/ios/ios_util.h +++ b/base/ios/ios_util.h @@ -14,6 +14,9 @@ namespace ios { // Returns whether the operating system is iOS 8 or later. BASE_EXPORT bool IsRunningOnIOS8OrLater(); +// Returns whether the operating system is iOS 9 or later. +BASE_EXPORT bool IsRunningOnIOS9OrLater(); + // Returns whether the operating system is at the given version or later. BASE_EXPORT bool IsRunningOnOrLater(int32 major, int32 minor, int32 bug_fix); diff --git a/base/ios/ios_util.mm b/base/ios/ios_util.mm index ca0a24d2a52d0..d9200450950ae 100644 --- a/base/ios/ios_util.mm +++ b/base/ios/ios_util.mm @@ -20,10 +20,15 @@ namespace base { namespace ios { +// When dropping iOS7 support, also address issues listed in crbug.com/502968. bool IsRunningOnIOS8OrLater() { return IsRunningOnOrLater(8, 0, 0); } +bool IsRunningOnIOS9OrLater() { + return IsRunningOnOrLater(9, 0, 0); +} + bool IsRunningOnOrLater(int32 major, int32 minor, int32 bug_fix) { static const int32* current_version = OSVersionAsArray(); int32 version[] = { major, minor, bug_fix }; diff --git a/base/ios/ns_error_util.h b/base/ios/ns_error_util.h new file mode 100644 index 0000000000000..101229208517e --- /dev/null +++ b/base/ios/ns_error_util.h @@ -0,0 +1,25 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_IOS_NS_ERROR_UTIL_H_ +#define BASE_IOS_NS_ERROR_UTIL_H_ + +@class NSError; + +namespace base { +namespace ios { + +// Iterates through |error|'s underlying errors and returns the first error for +// which there is no underlying error. +NSError* GetFinalUnderlyingErrorFromError(NSError* error); + +// Returns a copy of |original_error| with |underlying_error| appended to the +// end of its underlying error chain. +NSError* ErrorWithAppendedUnderlyingError(NSError* original_error, + NSError* underlying_error); + +} // namespace ios +} // namespace base + +#endif // BASE_IOS_NS_ERROR_UTIL_H_ diff --git a/base/ios/ns_error_util.mm b/base/ios/ns_error_util.mm new file mode 100644 index 0000000000000..c44d9ee4135c4 --- /dev/null +++ b/base/ios/ns_error_util.mm @@ -0,0 +1,53 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "base/ios/ns_error_util.h" + +#import + +#include "base/logging.h" +#include "base/mac/scoped_nsobject.h" + +namespace base { +namespace ios { + +namespace { +// Iterates through |error|'s underlying errors and returns them in an array. +NSArray* GetFullErrorChainForError(NSError* error) { + NSMutableArray* error_chain = [NSMutableArray array]; + NSError* current_error = error; + while (current_error) { + DCHECK([current_error isKindOfClass:[NSError class]]); + [error_chain addObject:current_error]; + current_error = current_error.userInfo[NSUnderlyingErrorKey]; + } + return error_chain; +} +} // namespace + +NSError* GetFinalUnderlyingErrorFromError(NSError* error) { + DCHECK(error); + return [GetFullErrorChainForError(error) lastObject]; +} + +NSError* ErrorWithAppendedUnderlyingError(NSError* original_error, + NSError* underlying_error) { + DCHECK(original_error); + DCHECK(underlying_error); + NSArray* error_chain = GetFullErrorChainForError(original_error); + NSError* current_error = underlying_error; + for (NSInteger idx = error_chain.count - 1; idx >= 0; --idx) { + NSError* error = error_chain[idx]; + scoped_nsobject user_info( + [error.userInfo mutableCopy]); + [user_info setObject:current_error forKey:NSUnderlyingErrorKey]; + current_error = [NSError errorWithDomain:error.domain + code:error.code + userInfo:user_info]; + } + return current_error; +} + +} // namespace ios +} // namespace base diff --git a/base/json/json_parser.cc b/base/json/json_parser.cc index 4d79be36194ba..9be690a628700 100644 --- a/base/json/json_parser.cc +++ b/base/json/json_parser.cc @@ -31,7 +31,7 @@ const int32 kExtendedASCIIStart = 0x80; // optimization avoids about 2/3rds of string memory copies. The constructor // takes ownership of the input string. The real root value is Swap()ed into // the new instance. -class DictionaryHiddenRootValue : public base::DictionaryValue { +class DictionaryHiddenRootValue : public DictionaryValue { public: DictionaryHiddenRootValue(std::string* json, Value* root) : json_(json) { DCHECK(root->IsType(Value::TYPE_DICTIONARY)); @@ -43,7 +43,7 @@ class DictionaryHiddenRootValue : public base::DictionaryValue { // First deep copy to convert JSONStringValue to std::string and swap that // copy with |other|, which contains the new contents of |this|. - scoped_ptr copy(DeepCopy()); + scoped_ptr copy(DeepCopy()); copy->Swap(other); // Then erase the contents of the current dictionary and swap in the @@ -81,7 +81,7 @@ class DictionaryHiddenRootValue : public base::DictionaryValue { DISALLOW_COPY_AND_ASSIGN(DictionaryHiddenRootValue); }; -class ListHiddenRootValue : public base::ListValue { +class ListHiddenRootValue : public ListValue { public: ListHiddenRootValue(std::string* json, Value* root) : json_(json) { DCHECK(root->IsType(Value::TYPE_LIST)); @@ -93,7 +93,7 @@ class ListHiddenRootValue : public base::ListValue { // First deep copy to convert JSONStringValue to std::string and swap that // copy with |other|, which contains the new contents of |this|. - scoped_ptr copy(DeepCopy()); + scoped_ptr copy(DeepCopy()); copy->Swap(other); // Then erase the contents of the current list and swap in the new contents, @@ -130,14 +130,14 @@ class ListHiddenRootValue : public base::ListValue { // A variant on StringValue that uses StringPiece instead of copying the string // into the Value. This can only be stored in a child of hidden root (above), // otherwise the referenced string will not be guaranteed to outlive it. -class JSONStringValue : public base::Value { +class JSONStringValue : public Value { public: - explicit JSONStringValue(const base::StringPiece& piece) + explicit JSONStringValue(const StringPiece& piece) : Value(TYPE_STRING), string_piece_(piece) { } - // Overridden from base::Value: + // Overridden from Value: bool GetAsString(std::string* out_value) const override { string_piece_.CopyToString(out_value); return true; @@ -157,7 +157,7 @@ class JSONStringValue : public base::Value { private: // The location in the original input stream. - base::StringPiece string_piece_; + StringPiece string_piece_; DISALLOW_COPY_AND_ASSIGN(JSONStringValue); }; @@ -776,11 +776,17 @@ bool JSONParser::DecodeUTF16(std::string* dest_string) { uint32 code_point = CBU16_GET_SUPPLEMENTARY(code_unit16_high, code_unit16_low); + if (!IsValidCharacter(code_point)) + return false; + offset = 0; CBU8_APPEND_UNSAFE(code_unit8, offset, code_point); } else { // Not a surrogate. DCHECK(CBU16_IS_SINGLE(code_unit16_high)); + if (!IsValidCharacter(code_unit16_high)) + return false; + CBU8_APPEND_UNSAFE(code_unit8, offset, code_unit16_high); } @@ -789,6 +795,8 @@ bool JSONParser::DecodeUTF16(std::string* dest_string) { } void JSONParser::DecodeUTF8(const int32& point, StringBuilder* dest) { + DCHECK(IsValidCharacter(point)); + // Anything outside of the basic ASCII plane will need to be decoded from // int32 to a multi-byte sequence. if (point < kExtendedASCIIStart) { @@ -872,7 +880,7 @@ Value* JSONParser::ConsumeNumber() { return new FundamentalValue(num_int); double num_double; - if (base::StringToDouble(num_string.as_string(), &num_double) && + if (StringToDouble(num_string.as_string(), &num_double) && std::isfinite(num_double)) { return new FundamentalValue(num_double); } diff --git a/base/json/json_parser_unittest.cc b/base/json/json_parser_unittest.cc index f776ddfc2c0a8..d88f9ea795225 100644 --- a/base/json/json_parser_unittest.cc +++ b/base/json/json_parser_unittest.cc @@ -313,5 +313,13 @@ TEST_F(JSONParserTest, Decode4ByteUtf8Char) { EXPECT_TRUE(root.get()) << error_message; } +TEST_F(JSONParserTest, DecodeUnicodeNonCharacter) { + // Tests Unicode code points (encoded as escaped UTF-16) that are not valid + // characters. + EXPECT_FALSE(JSONReader::Read("[\"\\ufdd0\"]")); + EXPECT_FALSE(JSONReader::Read("[\"\\ufffe\"]")); + EXPECT_FALSE(JSONReader::Read("[\"\\ud83f\\udffe\"]")); +} + } // namespace internal } // namespace base diff --git a/base/logging.cc b/base/logging.cc index 71528ad3f4ece..559cb083b6ad3 100644 --- a/base/logging.cc +++ b/base/logging.cc @@ -521,6 +521,12 @@ LogMessage::LogMessage(const char* file, int line, LogSeverity severity) Init(file, line); } +LogMessage::LogMessage(const char* file, int line, const char* condition) + : severity_(LOG_FATAL), file_(file), line_(line) { + Init(file, line); + stream_ << "Check failed: " << condition << ". "; +} + LogMessage::LogMessage(const char* file, int line, std::string* result) : severity_(LOG_FATAL), file_(file), line_(line) { Init(file, line); diff --git a/base/logging.h b/base/logging.h index ea096d19f729c..adc8fb6c21535 100644 --- a/base/logging.h +++ b/base/logging.h @@ -436,7 +436,7 @@ const LogSeverity LOG_0 = LOG_ERROR; #if defined(OFFICIAL_BUILD) && defined(NDEBUG) && !defined(OS_ANDROID) // Make all CHECK functions discard their log strings to reduce code -// bloat for official release builds. +// bloat for official release builds (except Android). // TODO(akalin): This would be more valuable if there were some way to // remove BreakDebugger() from the backtrace, perhaps by turning it @@ -470,9 +470,10 @@ const LogSeverity LOG_0 = LOG_ERROR; #else // _PREFAST_ -#define CHECK(condition) \ - LAZY_STREAM(LOG_STREAM(FATAL), !(condition)) \ - << "Check failed: " #condition ". " +// Do as much work as possible out of line to reduce inline code size. +#define CHECK(condition) \ + LAZY_STREAM(logging::LogMessage(__FILE__, __LINE__, #condition).stream(), \ + !(condition)) #define PCHECK(condition) \ LAZY_STREAM(PLOG_STREAM(FATAL), !(condition)) \ @@ -727,6 +728,9 @@ class BASE_EXPORT LogMessage { // Used for LOG(severity). LogMessage(const char* file, int line, LogSeverity severity); + // Used for CHECK(). Implied severity = LOG_FATAL. + LogMessage(const char* file, int line, const char* condition); + // Used for CHECK_EQ(), etc. Takes ownership of the given string. // Implied severity = LOG_FATAL. LogMessage(const char* file, int line, std::string* result); diff --git a/base/mac/OWNERS b/base/mac/OWNERS index 4aba972a39780..093a9c894741b 100644 --- a/base/mac/OWNERS +++ b/base/mac/OWNERS @@ -2,13 +2,5 @@ mark@chromium.org thakis@chromium.org # sdk_forward_declarations.[h|mm] will likely need to be modified by Cocoa -# developers in general; keep in sync with OWNERS of //chrome/browser/ui/cocoa. -per-file sdk_forward_declarations.*=asvitkine@chromium.org -per-file sdk_forward_declarations.*=avi@chromium.org -per-file sdk_forward_declarations.*=groby@chromium.org -per-file sdk_forward_declarations.*=jeremy@chromium.org -per-file sdk_forward_declarations.*=mark@chromium.org -per-file sdk_forward_declarations.*=rohitrao@chromium.org -per-file sdk_forward_declarations.*=rsesek@chromium.org -per-file sdk_forward_declarations.*=shess@chromium.org -per-file sdk_forward_declarations.*=thakis@chromium.org +# developers in general. +per-file sdk_forward_declarations.*=file://chrome/browser/ui/cocoa/OWNERS diff --git a/base/mac/call_with_eh_frame.cc b/base/mac/call_with_eh_frame.cc new file mode 100644 index 0000000000000..8ea6f75b4bfd8 --- /dev/null +++ b/base/mac/call_with_eh_frame.cc @@ -0,0 +1,37 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/mac/call_with_eh_frame.h" + +#include + +#include "build/build_config.h" + +namespace base { +namespace mac { + +_Unwind_Reason_Code CxxPersonalityRoutine( + int version, + _Unwind_Action actions, + uint64_t exceptionClass, + struct _Unwind_Exception* exceptionObject, + struct _Unwind_Context* context) { + // Tell libunwind that this is the end of the stack. When it encounters the + // CallWithEHFrame, it will stop searching for an exception handler. The + // result is that no exception handler has been found higher on the stack, + // and any that are lower on the stack (e.g. in CFRunLoopRunSpecific), will + // now be skipped. Since this is reporting the end of the stack, and no + // exception handler will have been found, std::terminate() will be called. + return _URC_END_OF_STACK; +} + +#if defined(OS_IOS) +// No iOS assembly implementation exists, so just call the block directly. +void CallWithEHFrame(void (^block)(void)) { + block(); +} +#endif + +} // namespace mac +} // namespace base diff --git a/base/mac/call_with_eh_frame.h b/base/mac/call_with_eh_frame.h new file mode 100644 index 0000000000000..1f7d5e0dec80c --- /dev/null +++ b/base/mac/call_with_eh_frame.h @@ -0,0 +1,26 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_MAC_CALL_WITH_EH_FRAME_H_ +#define BASE_MAC_CALL_WITH_EH_FRAME_H_ + +#include "base/base_export.h" + +namespace base { +namespace mac { + +// Invokes the specified block in a stack frame with a special exception +// handler. This function creates an exception handling stack frame that +// specifies a custom C++ exception personality routine, which terminates the +// search for an exception handler at this frame. +// +// The purpose of this function is to prevent a try/catch statement in system +// libraries, acting as a global exception handler, from handling exceptions +// in such a way that disrupts the generation of useful stack traces. +void BASE_EXPORT CallWithEHFrame(void (^block)(void)); + +} // namespace mac +} // namespace base + +#endif // BASE_MAC_CALL_WITH_EH_FRAME_H_ diff --git a/base/mac/call_with_eh_frame_asm.S b/base/mac/call_with_eh_frame_asm.S new file mode 100644 index 0000000000000..0e399cf2ae0b9 --- /dev/null +++ b/base/mac/call_with_eh_frame_asm.S @@ -0,0 +1,89 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// base::mac::CallWithEHFrame(void () block_pointer) +#define CALL_WITH_EH_FRAME __ZN4base3mac15CallWithEHFrameEU13block_pointerFvvE + + .section __TEXT,__text,regular,pure_instructions +#if !defined(COMPONENT_BUILD) + .private_extern CALL_WITH_EH_FRAME +#endif + .globl CALL_WITH_EH_FRAME + .align 4 +CALL_WITH_EH_FRAME: + + .cfi_startproc + + // Configure the C++ exception handler personality routine. Normally the + // compiler would emit ___gxx_personality_v0 here. The purpose of this + // function is to use a custom personality routine. + .cfi_personality 155, __ZN4base3mac21CxxPersonalityRoutineEi14_Unwind_ActionyP17_Unwind_ExceptionP15_Unwind_Context + .cfi_lsda 16, CallWithEHFrame_exception_table + +Lfunction_start: + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset %rbp, -16 + movq %rsp, %rbp + .cfi_def_cfa_register %rbp + + // Load the function pointer from the block descriptor. + movq 16(%rdi), %rax + + // Execute the block in the context of a C++ try{}. +Ltry_start: + callq *%rax +Ltry_end: + popq %rbp + ret + + // Landing pad for the exception handler. This should never be called, since + // the personality routine will stop the search for an exception handler, + // which will cause the runtime to invoke the default terminate handler. +Lcatch: + movq %rax, %rdi + callq ___cxa_begin_catch // The ABI requires a call to the catch handler. + ud2 // In the event this is called, make it fatal. + +Lfunction_end: + .cfi_endproc + +// The C++ exception table that is used to identify this frame as an +// exception handler. See http://llvm.org/docs/ExceptionHandling.html and +// http://mentorembedded.github.io/cxx-abi/exceptions.pdf. + .section __TEXT,__gcc_except_tab + .align 2 +CallWithEHFrame_exception_table: + .byte 255 // DW_EH_PE_omit + .byte 155 // DW_EH_PE_indirect | DW_EH_PE_pcrel | DW_EH_PE_sdata4 + .asciz "\242\200\200" // LE int128 for the number of bytes in this table. + .byte 3 // DW_EH_PE_udata4 + .byte 26 // Callsite table length. + +// First callsite. +CS1_begin = Ltry_start - Lfunction_start + .long CS1_begin +CS1_end = Ltry_end - Ltry_start + .long CS1_end + +// First landing pad. +LP1 = Lcatch - Lfunction_start + .long LP1 + .byte 1 // Action record. + +// Second callsite. +CS2_begin = Ltry_end - Lfunction_start + .long CS2_begin +CS2_end = Lfunction_end - Ltry_end + .long CS2_end + +// Second landing pad (none). + .long 0 + .byte 0 // No action. + +// Action table. + .byte 1 // Action record 1. + .byte 0 // No further action to take. + .long 0 // No type filter for this catch(){} clause. + .align 2 diff --git a/base/mac/call_with_eh_frame_unittest.mm b/base/mac/call_with_eh_frame_unittest.mm new file mode 100644 index 0000000000000..46bf285c2cd95 --- /dev/null +++ b/base/mac/call_with_eh_frame_unittest.mm @@ -0,0 +1,53 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/mac/call_with_eh_frame.h" + +#import + +#include "testing/gtest/include/gtest/gtest.h" + +namespace base { +namespace mac { +namespace { + +class CallWithEHFrameTest : public testing::Test { + protected: + void ThrowException() { + [NSArray arrayWithObject:nil]; + } +}; + +// Catching from within the EHFrame is allowed. +TEST_F(CallWithEHFrameTest, CatchExceptionHigher) { + bool __block saw_exception = false; + base::mac::CallWithEHFrame(^{ + @try { + ThrowException(); + } @catch (NSException* exception) { + saw_exception = true; + } + }); + EXPECT_TRUE(saw_exception); +} + +// Trying to catch an exception outside the EHFrame is blocked. +TEST_F(CallWithEHFrameTest, CatchExceptionLower) { + auto catch_exception_lower = ^{ + bool saw_exception = false; + @try { + base::mac::CallWithEHFrame(^{ + ThrowException(); + }); + } @catch (NSException* exception) { + saw_exception = true; + } + ASSERT_FALSE(saw_exception); + }; + EXPECT_DEATH(catch_exception_lower(), ""); +} + +} // namespace +} // namespace mac +} // namespace base diff --git a/base/mac/mac_util.h b/base/mac/mac_util.h index f8ffa97545dec..060f35b6c0c64 100644 --- a/base/mac/mac_util.h +++ b/base/mac/mac_util.h @@ -147,6 +147,10 @@ BASE_EXPORT bool IsOSMavericksOrLater(); BASE_EXPORT bool IsOSYosemite(); BASE_EXPORT bool IsOSYosemiteOrLater(); +// El Capitan is Mac OS X 10.11, Darwin 15. +BASE_EXPORT bool IsOSElCapitan(); +BASE_EXPORT bool IsOSElCapitanOrLater(); + // This should be infrequently used. It only makes sense to use this to avoid // codepaths that are very likely to break on future (unreleased, untested, // unborn) OS releases, or to log when the OS is newer than any known version. @@ -157,6 +161,7 @@ BASE_EXPORT bool IsOSLaterThanYosemite_DontCallThis(); inline bool IsOSLionOrEarlier() { return !IsOSMountainLionOrLater(); } inline bool IsOSMountainLionOrEarlier() { return !IsOSMavericksOrLater(); } inline bool IsOSMavericksOrEarlier() { return !IsOSYosemiteOrLater(); } +inline bool IsOSYosemiteOrEarlier() { return !IsOSElCapitanOrLater(); } // When the deployment target is set, the code produced cannot run on earlier // OS releases. That enables some of the IsOS* family to be implemented as @@ -213,6 +218,18 @@ inline bool IsOSYosemite() { return false; } inline bool IsOSLaterThanYosemite_DontCallThis() { return true; } #endif +#if defined(MAC_OS_X_VERSION_10_11) && \ + MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_11 +#define BASE_MAC_MAC_UTIL_H_INLINED_GE_10_11 +inline bool IsOSElCapitanOrLater() { return true; } +#endif + +#if defined(MAC_OS_X_VERSION_10_11) && \ + MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_11 +#define BASE_MAC_MAC_UTIL_H_INLINED_GT_10_11 +inline bool IsOSElCapitan() { return false; } +#endif + // Retrieve the system's model identifier string from the IOKit registry: // for example, "MacPro4,1", "MacBookPro6,1". Returns empty string upon // failure. diff --git a/base/mac/mac_util.mm b/base/mac/mac_util.mm index bdf45deb5bd20..e1e15dc538271 100644 --- a/base/mac/mac_util.mm +++ b/base/mac/mac_util.mm @@ -483,6 +483,7 @@ int MacOSXMinorVersion() { MOUNTAIN_LION_MINOR_VERSION = 8, MAVERICKS_MINOR_VERSION = 9, YOSEMITE_MINOR_VERSION = 10, + EL_CAPITAN_MINOR_VERSION = 11, }; } // namespace @@ -547,6 +548,18 @@ bool IsOSLaterThanYosemite_DontCallThis() { } #endif +#if !defined(BASE_MAC_MAC_UTIL_H_INLINED_GT_10_11) +bool IsOSElCapitan() { + return MacOSXMinorVersion() == EL_CAPITAN_MINOR_VERSION; +} +#endif + +#if !defined(BASE_MAC_MAC_UTIL_H_INLINED_GE_10_11) +bool IsOSElCapitanOrLater() { + return MacOSXMinorVersion() >= EL_CAPITAN_MINOR_VERSION; +} +#endif + std::string GetModelIdentifier() { std::string return_string; ScopedIOObject platform_expert( diff --git a/base/macros.h b/base/macros.h index 0325e7416510f..53b3926cd2424 100644 --- a/base/macros.h +++ b/base/macros.h @@ -41,7 +41,7 @@ // that wants to prevent anyone from instantiating it. This is // especially useful for classes containing only static methods. #define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \ - TypeName(); \ + TypeName() = delete; \ DISALLOW_COPY_AND_ASSIGN(TypeName) // The arraysize(arr) macro returns the # of elements in an array arr. diff --git a/base/memory/BUILD.gn b/base/memory/BUILD.gn index c3442794d8c77..79d99ebba70ef 100644 --- a/base/memory/BUILD.gn +++ b/base/memory/BUILD.gn @@ -35,6 +35,9 @@ source_set("memory") { "scoped_vector.h", "shared_memory.h", "shared_memory_android.cc", + "shared_memory_handle.h", + "shared_memory_handle_mac.cc", + "shared_memory_mac.cc", "shared_memory_nacl.cc", "shared_memory_posix.cc", "shared_memory_win.cc", @@ -58,6 +61,10 @@ source_set("memory") { sources -= [ "shared_memory_nacl.cc" ] } + if (is_mac) { + sources -= [ "shared_memory_posix.cc" ] + } + if (is_android) { deps = [ "//third_party/ashmem", diff --git a/base/memory/ref_counted_delete_on_message_loop.h b/base/memory/ref_counted_delete_on_message_loop.h index 6a109e81e00e6..d278a445d513c 100644 --- a/base/memory/ref_counted_delete_on_message_loop.h +++ b/base/memory/ref_counted_delete_on_message_loop.h @@ -8,8 +8,6 @@ #include "base/location.h" #include "base/logging.h" #include "base/memory/ref_counted.h" -// TODO(ricea): Remove the following include once all callers have been fixed. -#include "base/message_loop/message_loop_proxy.h" #include "base/single_thread_task_runner.h" namespace base { diff --git a/base/memory/scoped_vector.h b/base/memory/scoped_vector.h index 173ea5a1d63d1..e1e5c722a4fbe 100644 --- a/base/memory/scoped_vector.h +++ b/base/memory/scoped_vector.h @@ -106,6 +106,10 @@ class ScopedVector { return v_.insert(position, x); } + iterator insert(iterator position, scoped_ptr x) { + return v_.insert(position, x.release()); + } + // Lets the ScopedVector take ownership of elements in [first,last). template void insert(iterator position, InputIterator first, InputIterator last) { diff --git a/base/memory/shared_memory.h b/base/memory/shared_memory.h index 008bb0106688c..4326758177aac 100644 --- a/base/memory/shared_memory.h +++ b/base/memory/shared_memory.h @@ -17,6 +17,7 @@ #include "base/base_export.h" #include "base/basictypes.h" +#include "base/memory/shared_memory_handle.h" #include "base/process/process_handle.h" #if defined(OS_POSIX) @@ -29,14 +30,6 @@ namespace base { class FilePath; -// SharedMemoryHandle is a platform specific type which represents -// the underlying OS handle to a shared memory segment. -#if defined(OS_WIN) -typedef HANDLE SharedMemoryHandle; -#elif defined(OS_POSIX) -typedef FileDescriptor SharedMemoryHandle; -#endif - // Options for creating a shared memory object. struct SharedMemoryCreateOptions { SharedMemoryCreateOptions() @@ -89,12 +82,13 @@ class BASE_EXPORT SharedMemory { // only affects how the SharedMemory will be mmapped. Use // ShareReadOnlyToProcess to drop permissions. TODO(jln,jyasskin): DCHECK // that |read_only| matches the permissions of the handle. - SharedMemory(SharedMemoryHandle handle, bool read_only); + SharedMemory(const SharedMemoryHandle& handle, bool read_only); // Create a new SharedMemory object from an existing, open // shared memory file that was created by a remote process and not shared // to the current process. - SharedMemory(SharedMemoryHandle handle, bool read_only, + SharedMemory(const SharedMemoryHandle& handle, + bool read_only, ProcessHandle process); // Closes any open files. @@ -257,27 +251,11 @@ class BASE_EXPORT SharedMemory { return ShareToProcessCommon(process, new_handle, true, SHARE_CURRENT_MODE); } - // DEPRECATED (crbug.com/345734): - // Locks the shared memory. - // - // WARNING: on POSIX the memory locking primitive only works across - // processes, not across threads. The LockDeprecated method is not currently - // used in inner loops, so we protect against multiple threads in a - // critical section using a class global lock. - void LockDeprecated(); - - // DEPRECATED (crbug.com/345734): - // Releases the shared memory lock. - void UnlockDeprecated(); - private: -#if defined(OS_POSIX) && !defined(OS_NACL) -#if !defined(OS_ANDROID) +#if defined(OS_POSIX) && !defined(OS_NACL) && !defined(OS_ANDROID) bool PrepareMapFile(ScopedFILE fp, ScopedFD readonly); bool FilePathForMemoryName(const std::string& mem_name, FilePath* path); -#endif - void LockOrUnlockCommon(int function); -#endif // defined(OS_POSIX) && !defined(OS_NACL) +#endif // defined(OS_POSIX) && !defined(OS_NACL) && !defined(OS_ANDROID) enum ShareMode { SHARE_READONLY, SHARE_CURRENT_MODE, @@ -298,32 +276,9 @@ class BASE_EXPORT SharedMemory { void* memory_; bool read_only_; size_t requested_size_; -#if !defined(OS_POSIX) - HANDLE lock_; -#endif DISALLOW_COPY_AND_ASSIGN(SharedMemory); }; - -// DEPRECATED (crbug.com/345734): -// A helper class that acquires the shared memory lock while -// the SharedMemoryAutoLockDeprecated is in scope. -class SharedMemoryAutoLockDeprecated { - public: - explicit SharedMemoryAutoLockDeprecated(SharedMemory* shared_memory) - : shared_memory_(shared_memory) { - shared_memory_->LockDeprecated(); - } - - ~SharedMemoryAutoLockDeprecated() { - shared_memory_->UnlockDeprecated(); - } - - private: - SharedMemory* shared_memory_; - DISALLOW_COPY_AND_ASSIGN(SharedMemoryAutoLockDeprecated); -}; - } // namespace base #endif // BASE_MEMORY_SHARED_MEMORY_H_ diff --git a/base/memory/shared_memory_handle.h b/base/memory/shared_memory_handle.h new file mode 100644 index 0000000000000..7af8729976dab --- /dev/null +++ b/base/memory/shared_memory_handle.h @@ -0,0 +1,97 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_MEMORY_SHARED_MEMORY_HANDLE_H_ +#define BASE_MEMORY_SHARED_MEMORY_HANDLE_H_ + +#include "build/build_config.h" + +#if defined(OS_WIN) +#include +#elif defined(OS_MACOSX) && !defined(OS_IOS) +#include +#include "base/base_export.h" +#include "base/file_descriptor_posix.h" +#include "base/macros.h" +#elif defined(OS_POSIX) +#include +#include "base/file_descriptor_posix.h" +#endif + +namespace base { + +class Pickle; + +// SharedMemoryHandle is a platform specific type which represents +// the underlying OS handle to a shared memory segment. +#if defined(OS_WIN) +typedef HANDLE SharedMemoryHandle; +#elif defined(OS_POSIX) && !(defined(OS_MACOSX) && !defined(OS_IOS)) +typedef FileDescriptor SharedMemoryHandle; +#else +class BASE_EXPORT SharedMemoryHandle { + public: + enum Type { + // Indicates that the SharedMemoryHandle is backed by a POSIX fd. + POSIX, + // Indicates that the SharedMemoryHandle is backed by the Mach primitive + // "memory object". + MACH, + }; + + // The format that should be used to transmit |Type| over the wire. + typedef int TypeWireFormat; + + // The default constructor returns an invalid SharedMemoryHandle. + SharedMemoryHandle(); + + // Constructs a SharedMemoryHandle backed by the components of a + // FileDescriptor. The newly created instance has the same ownership semantics + // as base::FileDescriptor. This typically means that the SharedMemoryHandle + // takes ownership of the |fd| if |auto_close| is true. Unfortunately, it's + // common for existing code to make shallow copies of SharedMemoryHandle, and + // the one that is finally passed into a base::SharedMemory is the one that + // "consumes" the fd. + explicit SharedMemoryHandle(const base::FileDescriptor& file_descriptor); + SharedMemoryHandle(int fd, bool auto_close); + + // Standard copy constructor. The new instance shares the underlying OS + // primitives. + SharedMemoryHandle(const SharedMemoryHandle& handle); + + // Standard assignment operator. The updated instance shares the underlying + // OS primitives. + SharedMemoryHandle& operator=(const SharedMemoryHandle& handle); + + // Duplicates the underlying OS resources. + SharedMemoryHandle Duplicate() const; + + // Comparison operators. + bool operator==(const SharedMemoryHandle& handle) const; + bool operator!=(const SharedMemoryHandle& handle) const; + + // Returns the type. + Type GetType() const; + + // Whether the underlying OS primitive is valid. + bool IsValid() const; + + // Sets the POSIX fd backing the SharedMemoryHandle. Requires that the + // SharedMemoryHandle be backed by a POSIX fd. + void SetFileHandle(int fd, bool auto_close); + + // This method assumes that the SharedMemoryHandle is backed by a POSIX fd. + // This is eventually no longer going to be true, so please avoid adding new + // uses of this method. + const FileDescriptor GetFileDescriptor() const; + + private: + Type type_; + FileDescriptor file_descriptor_; +}; +#endif + +} // namespace base + +#endif // BASE_MEMORY_SHARED_MEMORY_HANDLE_H_ diff --git a/base/memory/shared_memory_handle_mac.cc b/base/memory/shared_memory_handle_mac.cc new file mode 100644 index 0000000000000..eb4f4654a938f --- /dev/null +++ b/base/memory/shared_memory_handle_mac.cc @@ -0,0 +1,90 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/memory/shared_memory_handle.h" + +#include + +#include "base/posix/eintr_wrapper.h" + +#if defined(OS_MACOSX) && !defined(OS_IOS) +namespace base { + +static_assert(sizeof(SharedMemoryHandle::Type) <= + sizeof(SharedMemoryHandle::TypeWireFormat), + "Size of enum SharedMemoryHandle::Type exceeds size of type " + "transmitted over wire."); + +SharedMemoryHandle::SharedMemoryHandle() : type_(POSIX), file_descriptor_() { +} + +SharedMemoryHandle::SharedMemoryHandle( + const base::FileDescriptor& file_descriptor) + : type_(POSIX), file_descriptor_(file_descriptor) { +} + +SharedMemoryHandle::SharedMemoryHandle(int fd, bool auto_close) + : type_(POSIX), file_descriptor_(fd, auto_close) { +} + +SharedMemoryHandle::SharedMemoryHandle(const SharedMemoryHandle& handle) + : type_(handle.type_), file_descriptor_(handle.file_descriptor_) { +} + +SharedMemoryHandle& SharedMemoryHandle::operator=( + const SharedMemoryHandle& handle) { + if (this == &handle) + return *this; + + type_ = handle.type_; + file_descriptor_ = handle.file_descriptor_; + return *this; +} + +bool SharedMemoryHandle::operator==(const SharedMemoryHandle& handle) const { + // Invalid handles are always equal, even if they have different types. + if (!IsValid() && !handle.IsValid()) + return true; + + return type_ == handle.type_ && file_descriptor_ == handle.file_descriptor_; +} + +bool SharedMemoryHandle::operator!=(const SharedMemoryHandle& handle) const { + return !(*this == handle); +} + +SharedMemoryHandle::Type SharedMemoryHandle::GetType() const { + return type_; +} + +bool SharedMemoryHandle::IsValid() const { + switch (type_) { + case POSIX: + return file_descriptor_.fd >= 0; + case MACH: + return false; + } +} + +void SharedMemoryHandle::SetFileHandle(int fd, bool auto_close) { + DCHECK_EQ(type_, POSIX); + file_descriptor_.fd = fd; + file_descriptor_.auto_close = auto_close; +} + +const FileDescriptor SharedMemoryHandle::GetFileDescriptor() const { + DCHECK_EQ(type_, POSIX); + return file_descriptor_; +} + +SharedMemoryHandle SharedMemoryHandle::Duplicate() const { + DCHECK_EQ(type_, POSIX); + int duped_handle = HANDLE_EINTR(dup(file_descriptor_.fd)); + if (duped_handle < 0) + return SharedMemoryHandle(); + return SharedMemoryHandle(duped_handle, true); +} + +} // namespace base +#endif // defined(OS_MACOSX) && !defined(OS_IOS) diff --git a/base/memory/shared_memory_mac.cc b/base/memory/shared_memory_mac.cc new file mode 100644 index 0000000000000..0ec8b8544fa5c --- /dev/null +++ b/base/memory/shared_memory_mac.cc @@ -0,0 +1,464 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/memory/shared_memory.h" + +#include +#include +#include +#include + +#include "base/files/file_util.h" +#include "base/files/scoped_file.h" +#include "base/logging.h" +#include "base/posix/eintr_wrapper.h" +#include "base/posix/safe_strerror.h" +#include "base/process/process_metrics.h" +#include "base/profiler/scoped_tracker.h" +#include "base/scoped_generic.h" +#include "base/strings/utf_string_conversions.h" + +#if defined(OS_MACOSX) +#include "base/mac/foundation_util.h" +#endif // OS_MACOSX + +namespace base { + +namespace { + +struct ScopedPathUnlinkerTraits { + static FilePath* InvalidValue() { return nullptr; } + + static void Free(FilePath* path) { + // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/466437 + // is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "466437 SharedMemory::Create::Unlink")); + if (unlink(path->value().c_str())) + PLOG(WARNING) << "unlink"; + } +}; + +// Unlinks the FilePath when the object is destroyed. +typedef ScopedGeneric ScopedPathUnlinker; + +// Makes a temporary file, fdopens it, and then unlinks it. |fp| is populated +// with the fdopened FILE. |readonly_fd| is populated with the opened fd if +// options.share_read_only is true. |path| is populated with the location of +// the file before it was unlinked. +// Returns false if there's an unhandled failure. +bool CreateAnonymousSharedMemory(const SharedMemoryCreateOptions& options, + ScopedFILE* fp, + ScopedFD* readonly_fd, + FilePath* path) { + // It doesn't make sense to have a open-existing private piece of shmem + DCHECK(!options.open_existing_deprecated); + // Q: Why not use the shm_open() etc. APIs? + // A: Because they're limited to 4mb on OS X. FFFFFFFUUUUUUUUUUU + FilePath directory; + ScopedPathUnlinker path_unlinker; + if (GetShmemTempDir(options.executable, &directory)) { + // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/466437 + // is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "466437 SharedMemory::Create::OpenTemporaryFile")); + fp->reset(base::CreateAndOpenTemporaryFileInDir(directory, path)); + + // Deleting the file prevents anyone else from mapping it in (making it + // private), and prevents the need for cleanup (once the last fd is + // closed, it is truly freed). + if (*fp) + path_unlinker.reset(path); + } + + if (*fp) { + if (options.share_read_only) { + // TODO(erikchen): Remove ScopedTracker below once + // http://crbug.com/466437 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "466437 SharedMemory::Create::OpenReadonly")); + // Also open as readonly so that we can ShareReadOnlyToProcess. + readonly_fd->reset(HANDLE_EINTR(open(path->value().c_str(), O_RDONLY))); + if (!readonly_fd->is_valid()) { + DPLOG(ERROR) << "open(\"" << path->value() << "\", O_RDONLY) failed"; + fp->reset(); + return false; + } + } + } + return true; +} +} + +SharedMemory::SharedMemory() + : mapped_file_(-1), + readonly_mapped_file_(-1), + mapped_size_(0), + memory_(NULL), + read_only_(false), + requested_size_(0) { +} + +SharedMemory::SharedMemory(const SharedMemoryHandle& handle, bool read_only) + : mapped_file_(GetFdFromSharedMemoryHandle(handle)), + readonly_mapped_file_(-1), + mapped_size_(0), + memory_(NULL), + read_only_(read_only), + requested_size_(0) { +} + +SharedMemory::SharedMemory(const SharedMemoryHandle& handle, + bool read_only, + ProcessHandle process) + : mapped_file_(GetFdFromSharedMemoryHandle(handle)), + readonly_mapped_file_(-1), + mapped_size_(0), + memory_(NULL), + read_only_(read_only), + requested_size_(0) { + // We don't handle this case yet (note the ignored parameter); let's die if + // someone comes calling. + NOTREACHED(); +} + +SharedMemory::~SharedMemory() { + Unmap(); + Close(); +} + +// static +bool SharedMemory::IsHandleValid(const SharedMemoryHandle& handle) { + return handle.IsValid(); +} + +// static +SharedMemoryHandle SharedMemory::NULLHandle() { + return SharedMemoryHandle(); +} + +// static +void SharedMemory::CloseHandle(const SharedMemoryHandle& handle) { + DCHECK_GE(GetFdFromSharedMemoryHandle(handle), 0); + if (close(GetFdFromSharedMemoryHandle(handle)) < 0) + DPLOG(ERROR) << "close"; +} + +// static +size_t SharedMemory::GetHandleLimit() { + return base::GetMaxFds(); +} + +// static +SharedMemoryHandle SharedMemory::DuplicateHandle( + const SharedMemoryHandle& handle) { + return handle.Duplicate(); +} + +// static +int SharedMemory::GetFdFromSharedMemoryHandle( + const SharedMemoryHandle& handle) { + return handle.GetFileDescriptor().fd; +} + +bool SharedMemory::CreateAndMapAnonymous(size_t size) { + return CreateAnonymous(size) && Map(size); +} + +// static +int SharedMemory::GetSizeFromSharedMemoryHandle( + const SharedMemoryHandle& handle) { + struct stat st; + if (fstat(GetFdFromSharedMemoryHandle(handle), &st) != 0) + return -1; + return st.st_size; +} + +// Chromium mostly only uses the unique/private shmem as specified by +// "name == L"". The exception is in the StatsTable. +// TODO(jrg): there is no way to "clean up" all unused named shmem if +// we restart from a crash. (That isn't a new problem, but it is a problem.) +// In case we want to delete it later, it may be useful to save the value +// of mem_filename after FilePathForMemoryName(). +bool SharedMemory::Create(const SharedMemoryCreateOptions& options) { + // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/466437 + // is fixed. + tracked_objects::ScopedTracker tracking_profile1( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "466437 SharedMemory::Create::Start")); + DCHECK_EQ(-1, mapped_file_); + if (options.size == 0) return false; + + if (options.size > static_cast(std::numeric_limits::max())) + return false; + + // This function theoretically can block on the disk, but realistically + // the temporary files we create will just go into the buffer cache + // and be deleted before they ever make it out to disk. + base::ThreadRestrictions::ScopedAllowIO allow_io; + + ScopedFILE fp; + bool fix_size = true; + ScopedFD readonly_fd; + + FilePath path; + if (options.name_deprecated == NULL || options.name_deprecated->empty()) { + bool result = + CreateAnonymousSharedMemory(options, &fp, &readonly_fd, &path); + if (!result) + return false; + } else { + if (!FilePathForMemoryName(*options.name_deprecated, &path)) + return false; + + // Make sure that the file is opened without any permission + // to other users on the system. + const mode_t kOwnerOnly = S_IRUSR | S_IWUSR; + + // First, try to create the file. + int fd = HANDLE_EINTR( + open(path.value().c_str(), O_RDWR | O_CREAT | O_EXCL, kOwnerOnly)); + if (fd == -1 && options.open_existing_deprecated) { + // If this doesn't work, try and open an existing file in append mode. + // Opening an existing file in a world writable directory has two main + // security implications: + // - Attackers could plant a file under their control, so ownership of + // the file is checked below. + // - Attackers could plant a symbolic link so that an unexpected file + // is opened, so O_NOFOLLOW is passed to open(). + fd = HANDLE_EINTR( + open(path.value().c_str(), O_RDWR | O_APPEND | O_NOFOLLOW)); + + // Check that the current user owns the file. + // If uid != euid, then a more complex permission model is used and this + // API is not appropriate. + const uid_t real_uid = getuid(); + const uid_t effective_uid = geteuid(); + struct stat sb; + if (fd >= 0 && + (fstat(fd, &sb) != 0 || sb.st_uid != real_uid || + sb.st_uid != effective_uid)) { + LOG(ERROR) << + "Invalid owner when opening existing shared memory file."; + close(fd); + return false; + } + + // An existing file was opened, so its size should not be fixed. + fix_size = false; + } + + if (options.share_read_only) { + // Also open as readonly so that we can ShareReadOnlyToProcess. + readonly_fd.reset(HANDLE_EINTR(open(path.value().c_str(), O_RDONLY))); + if (!readonly_fd.is_valid()) { + DPLOG(ERROR) << "open(\"" << path.value() << "\", O_RDONLY) failed"; + close(fd); + fd = -1; + return false; + } + } + if (fd >= 0) { + // "a+" is always appropriate: if it's a new file, a+ is similar to w+. + fp.reset(fdopen(fd, "a+")); + } + } + if (fp && fix_size) { + // Get current size. + struct stat stat; + if (fstat(fileno(fp.get()), &stat) != 0) + return false; + const size_t current_size = stat.st_size; + if (current_size != options.size) { + if (HANDLE_EINTR(ftruncate(fileno(fp.get()), options.size)) != 0) + return false; + } + requested_size_ = options.size; + } + if (fp == NULL) { + PLOG(ERROR) << "Creating shared memory in " << path.value() << " failed"; + return false; + } + + return PrepareMapFile(fp.Pass(), readonly_fd.Pass()); +} + +// Our current implementation of shmem is with mmap()ing of files. +// These files need to be deleted explicitly. +// In practice this call is only needed for unit tests. +bool SharedMemory::Delete(const std::string& name) { + FilePath path; + if (!FilePathForMemoryName(name, &path)) + return false; + + if (PathExists(path)) + return base::DeleteFile(path, false); + + // Doesn't exist, so success. + return true; +} + +bool SharedMemory::Open(const std::string& name, bool read_only) { + FilePath path; + if (!FilePathForMemoryName(name, &path)) + return false; + + read_only_ = read_only; + + const char *mode = read_only ? "r" : "r+"; + ScopedFILE fp(base::OpenFile(path, mode)); + ScopedFD readonly_fd(HANDLE_EINTR(open(path.value().c_str(), O_RDONLY))); + if (!readonly_fd.is_valid()) { + DPLOG(ERROR) << "open(\"" << path.value() << "\", O_RDONLY) failed"; + return false; + } + return PrepareMapFile(fp.Pass(), readonly_fd.Pass()); +} + +bool SharedMemory::MapAt(off_t offset, size_t bytes) { + if (mapped_file_ == -1) + return false; + + if (bytes > static_cast(std::numeric_limits::max())) + return false; + + if (memory_) + return false; + + memory_ = mmap(NULL, bytes, PROT_READ | (read_only_ ? 0 : PROT_WRITE), + MAP_SHARED, mapped_file_, offset); + + bool mmap_succeeded = memory_ != (void*)-1 && memory_ != NULL; + if (mmap_succeeded) { + mapped_size_ = bytes; + DCHECK_EQ(0U, reinterpret_cast(memory_) & + (SharedMemory::MAP_MINIMUM_ALIGNMENT - 1)); + } else { + memory_ = NULL; + } + + return mmap_succeeded; +} + +bool SharedMemory::Unmap() { + if (memory_ == NULL) + return false; + + munmap(memory_, mapped_size_); + memory_ = NULL; + mapped_size_ = 0; + return true; +} + +SharedMemoryHandle SharedMemory::handle() const { + return SharedMemoryHandle(mapped_file_, false); +} + +void SharedMemory::Close() { + if (mapped_file_ > 0) { + if (close(mapped_file_) < 0) + PLOG(ERROR) << "close"; + mapped_file_ = -1; + } + if (readonly_mapped_file_ > 0) { + if (close(readonly_mapped_file_) < 0) + PLOG(ERROR) << "close"; + readonly_mapped_file_ = -1; + } +} + +bool SharedMemory::PrepareMapFile(ScopedFILE fp, ScopedFD readonly_fd) { + DCHECK_EQ(-1, mapped_file_); + DCHECK_EQ(-1, readonly_mapped_file_); + if (fp == NULL) + return false; + + // This function theoretically can block on the disk, but realistically + // the temporary files we create will just go into the buffer cache + // and be deleted before they ever make it out to disk. + base::ThreadRestrictions::ScopedAllowIO allow_io; + + struct stat st = {}; + if (fstat(fileno(fp.get()), &st)) + NOTREACHED(); + if (readonly_fd.is_valid()) { + struct stat readonly_st = {}; + if (fstat(readonly_fd.get(), &readonly_st)) + NOTREACHED(); + if (st.st_dev != readonly_st.st_dev || st.st_ino != readonly_st.st_ino) { + LOG(ERROR) << "writable and read-only inodes don't match; bailing"; + return false; + } + } + + mapped_file_ = HANDLE_EINTR(dup(fileno(fp.get()))); + if (mapped_file_ == -1) { + if (errno == EMFILE) { + LOG(WARNING) << "Shared memory creation failed; out of file descriptors"; + return false; + } else { + NOTREACHED() << "Call to dup failed, errno=" << errno; + } + } + readonly_mapped_file_ = readonly_fd.release(); + + return true; +} + +// For the given shmem named |mem_name|, return a filename to mmap() +// (and possibly create). Modifies |filename|. Return false on +// error, or true of we are happy. +bool SharedMemory::FilePathForMemoryName(const std::string& mem_name, + FilePath* path) { + // mem_name will be used for a filename; make sure it doesn't + // contain anything which will confuse us. + DCHECK_EQ(std::string::npos, mem_name.find('/')); + DCHECK_EQ(std::string::npos, mem_name.find('\0')); + + FilePath temp_dir; + if (!GetShmemTempDir(false, &temp_dir)) + return false; + + std::string name_base = std::string(base::mac::BaseBundleID()); + *path = temp_dir.AppendASCII(name_base + ".shmem." + mem_name); + return true; +} + +bool SharedMemory::ShareToProcessCommon(ProcessHandle process, + SharedMemoryHandle* new_handle, + bool close_self, + ShareMode share_mode) { + int handle_to_dup = -1; + switch(share_mode) { + case SHARE_CURRENT_MODE: + handle_to_dup = mapped_file_; + break; + case SHARE_READONLY: + // We could imagine re-opening the file from /dev/fd, but that can't make + // it readonly on Mac: https://codereview.chromium.org/27265002/#msg10 + CHECK_GE(readonly_mapped_file_, 0); + handle_to_dup = readonly_mapped_file_; + break; + } + + const int new_fd = HANDLE_EINTR(dup(handle_to_dup)); + if (new_fd < 0) { + DPLOG(ERROR) << "dup() failed."; + return false; + } + + new_handle->SetFileHandle(new_fd, true); + + if (close_self) { + Unmap(); + Close(); + } + + return true; +} + +} // namespace base diff --git a/base/memory/shared_memory_nacl.cc b/base/memory/shared_memory_nacl.cc index 26dd4a380d6b0..41416a1d7f830 100644 --- a/base/memory/shared_memory_nacl.cc +++ b/base/memory/shared_memory_nacl.cc @@ -24,7 +24,7 @@ SharedMemory::SharedMemory() requested_size_(0) { } -SharedMemory::SharedMemory(SharedMemoryHandle handle, bool read_only) +SharedMemory::SharedMemory(const SharedMemoryHandle& handle, bool read_only) : mapped_file_(handle.fd), mapped_size_(0), memory_(NULL), @@ -32,7 +32,8 @@ SharedMemory::SharedMemory(SharedMemoryHandle handle, bool read_only) requested_size_(0) { } -SharedMemory::SharedMemory(SharedMemoryHandle handle, bool read_only, +SharedMemory::SharedMemory(const SharedMemoryHandle& handle, + bool read_only, ProcessHandle process) : mapped_file_(handle.fd), mapped_size_(0), @@ -139,14 +140,6 @@ void SharedMemory::Close() { } } -void SharedMemory::LockDeprecated() { - NOTIMPLEMENTED(); -} - -void SharedMemory::UnlockDeprecated() { - NOTIMPLEMENTED(); -} - bool SharedMemory::ShareToProcessCommon(ProcessHandle process, SharedMemoryHandle *new_handle, bool close_self, diff --git a/base/memory/shared_memory_posix.cc b/base/memory/shared_memory_posix.cc index 35d746e5394e0..2e66b34cfcd7b 100644 --- a/base/memory/shared_memory_posix.cc +++ b/base/memory/shared_memory_posix.cc @@ -4,16 +4,13 @@ #include "base/memory/shared_memory.h" -#include #include #include #include -#include #include #include "base/files/file_util.h" #include "base/files/scoped_file.h" -#include "base/lazy_instance.h" #include "base/logging.h" #include "base/posix/eintr_wrapper.h" #include "base/posix/safe_strerror.h" @@ -21,13 +18,6 @@ #include "base/profiler/scoped_tracker.h" #include "base/scoped_generic.h" #include "base/strings/utf_string_conversions.h" -#include "base/synchronization/lock.h" -#include "base/threading/platform_thread.h" -#include "base/threading/thread_restrictions.h" - -#if defined(OS_MACOSX) -#include "base/mac/foundation_util.h" -#endif // OS_MACOSX #if defined(OS_ANDROID) #include "base/os_compat_android.h" @@ -38,8 +28,6 @@ namespace base { namespace { -LazyInstance::Leaky g_thread_lock_ = LAZY_INSTANCE_INITIALIZER; - struct ScopedPathUnlinkerTraits { static FilePath* InvalidValue() { return nullptr; } @@ -118,7 +106,7 @@ SharedMemory::SharedMemory() requested_size_(0) { } -SharedMemory::SharedMemory(SharedMemoryHandle handle, bool read_only) +SharedMemory::SharedMemory(const SharedMemoryHandle& handle, bool read_only) : mapped_file_(handle.fd), readonly_mapped_file_(-1), mapped_size_(0), @@ -127,7 +115,8 @@ SharedMemory::SharedMemory(SharedMemoryHandle handle, bool read_only) requested_size_(0) { } -SharedMemory::SharedMemory(SharedMemoryHandle handle, bool read_only, +SharedMemory::SharedMemory(const SharedMemoryHandle& handle, + bool read_only, ProcessHandle process) : mapped_file_(handle.fd), readonly_mapped_file_(-1), @@ -298,7 +287,6 @@ bool SharedMemory::Create(const SharedMemoryCreateOptions& options) { requested_size_ = options.size; } if (fp == NULL) { -#if !defined(OS_MACOSX) PLOG(ERROR) << "Creating shared memory in " << path.value() << " failed"; FilePath dir = path.DirName(); if (access(dir.value().c_str(), W_OK | X_OK) < 0) { @@ -308,9 +296,6 @@ bool SharedMemory::Create(const SharedMemoryCreateOptions& options) { << "/dev/shm. Try 'sudo chmod 1777 /dev/shm' to fix."; } } -#else - PLOG(ERROR) << "Creating shared memory in " << path.value() << " failed"; -#endif return false; } @@ -414,16 +399,6 @@ void SharedMemory::Close() { } } -void SharedMemory::LockDeprecated() { - g_thread_lock_.Get().Acquire(); - LockOrUnlockCommon(F_LOCK); -} - -void SharedMemory::UnlockDeprecated() { - LockOrUnlockCommon(F_ULOCK); - g_thread_lock_.Get().Release(); -} - #if !defined(OS_ANDROID) bool SharedMemory::PrepareMapFile(ScopedFILE fp, ScopedFD readonly_fd) { DCHECK_EQ(-1, mapped_file_); @@ -477,39 +452,16 @@ bool SharedMemory::FilePathForMemoryName(const std::string& mem_name, if (!GetShmemTempDir(false, &temp_dir)) return false; -#if !defined(OS_MACOSX) #if defined(GOOGLE_CHROME_BUILD) std::string name_base = std::string("com.google.Chrome"); #else std::string name_base = std::string("org.chromium.Chromium"); #endif -#else // OS_MACOSX - std::string name_base = std::string(base::mac::BaseBundleID()); -#endif // OS_MACOSX *path = temp_dir.AppendASCII(name_base + ".shmem." + mem_name); return true; } #endif // !defined(OS_ANDROID) -void SharedMemory::LockOrUnlockCommon(int function) { - DCHECK_GE(mapped_file_, 0); - while (lockf(mapped_file_, function, 0) < 0) { - if (errno == EINTR) { - continue; - } else if (errno == ENOLCK) { - // temporary kernel resource exaustion - base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(500)); - continue; - } else { - NOTREACHED() << "lockf() failed." - << " function:" << function - << " fd:" << mapped_file_ - << " errno:" << errno - << " msg:" << base::safe_strerror(errno); - } - } -} - bool SharedMemory::ShareToProcessCommon(ProcessHandle process, SharedMemoryHandle* new_handle, bool close_self, diff --git a/base/memory/shared_memory_unittest.cc b/base/memory/shared_memory_unittest.cc index 6fe57060e6fcd..c129e18d4c304 100644 --- a/base/memory/shared_memory_unittest.cc +++ b/base/memory/shared_memory_unittest.cc @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/atomicops.h" #include "base/basictypes.h" #include "base/memory/scoped_ptr.h" #include "base/memory/shared_memory.h" @@ -33,7 +34,7 @@ #endif static const int kNumThreads = 5; -#if !defined(OS_IOS) // iOS does not allow multiple processes. +#if !defined(OS_IOS) && !defined(OS_ANDROID) static const int kNumTasks = 5; #endif @@ -90,56 +91,6 @@ class MultipleThreadMain : public PlatformThread::Delegate { const char* const MultipleThreadMain::s_test_name_ = "SharedMemoryOpenThreadTest"; -// TODO(port): -// This test requires the ability to pass file descriptors between processes. -// We haven't done that yet in Chrome for POSIX. -#if defined(OS_WIN) -// Each thread will open the shared memory. Each thread will take the memory, -// and keep changing it while trying to lock it, with some small pauses in -// between. Verify that each thread's value in the shared memory is always -// correct. -class MultipleLockThread : public PlatformThread::Delegate { - public: - explicit MultipleLockThread(int id) : id_(id) {} - ~MultipleLockThread() override {} - - // PlatformThread::Delegate interface. - void ThreadMain() override { - const uint32 kDataSize = sizeof(int); - SharedMemoryHandle handle = NULL; - { - SharedMemory memory1; - EXPECT_TRUE(memory1.CreateNamedDeprecated( - "SharedMemoryMultipleLockThreadTest", true, kDataSize)); - EXPECT_TRUE(memory1.ShareToProcess(GetCurrentProcess(), &handle)); - // TODO(paulg): Implement this once we have a posix version of - // SharedMemory::ShareToProcess. - EXPECT_TRUE(true); - } - - SharedMemory memory2(handle, false); - EXPECT_TRUE(memory2.Map(kDataSize)); - volatile int* const ptr = static_cast(memory2.memory()); - - for (int idx = 0; idx < 20; idx++) { - memory2.LockDeprecated(); - int i = (id_ << 16) + idx; - *ptr = i; - PlatformThread::Sleep(TimeDelta::FromMilliseconds(1)); - EXPECT_EQ(*ptr, i); - memory2.UnlockDeprecated(); - } - - memory2.Close(); - } - - private: - int id_; - - DISALLOW_COPY_AND_ASSIGN(MultipleLockThread); -}; -#endif - } // namespace // Android doesn't support SharedMemory::Open/Delete/ @@ -320,34 +271,6 @@ TEST(SharedMemoryTest, MultipleThreads) { MultipleThreadMain::CleanUp(); } -// TODO(port): this test requires the MultipleLockThread class -// (defined above), which requires the ability to pass file -// descriptors between processes. We haven't done that yet in Chrome -// for POSIX. -#if defined(OS_WIN) -// Create a set of threads to each open a shared memory segment and write to it -// with the lock held. Verify that they are always reading/writing consistent -// data. -TEST(SharedMemoryTest, Lock) { - PlatformThreadHandle thread_handles[kNumThreads]; - MultipleLockThread* thread_delegates[kNumThreads]; - - // Spawn the threads. - for (int index = 0; index < kNumThreads; ++index) { - PlatformThreadHandle pth; - thread_delegates[index] = new MultipleLockThread(index); - EXPECT_TRUE(PlatformThread::Create(0, thread_delegates[index], &pth)); - thread_handles[index] = pth; - } - - // Wait for the threads to finish. - for (int index = 0; index < kNumThreads; ++index) { - PlatformThread::Join(thread_handles[index]); - delete thread_delegates[index]; - } -} -#endif - // Allocate private (unique) shared memory with an empty string for a // name. Make sure several of them don't point to the same thing as // we might expect if the names are equal. @@ -437,12 +360,13 @@ TEST(SharedMemoryTest, ShareReadOnly) { // http://crbug.com/320865 (void)handle; #elif defined(OS_POSIX) - EXPECT_EQ(O_RDONLY, fcntl(handle.fd, F_GETFL) & O_ACCMODE) + int handle_fd = SharedMemory::GetFdFromSharedMemoryHandle(handle); + EXPECT_EQ(O_RDONLY, fcntl(handle_fd, F_GETFL) & O_ACCMODE) << "The descriptor itself should be read-only."; errno = 0; - void* writable = mmap( - NULL, contents.size(), PROT_READ | PROT_WRITE, MAP_SHARED, handle.fd, 0); + void* writable = mmap(NULL, contents.size(), PROT_READ | PROT_WRITE, + MAP_SHARED, handle_fd, 0); int mmap_errno = errno; EXPECT_EQ(MAP_FAILED, writable) << "It shouldn't be possible to re-mmap the descriptor writable."; @@ -596,7 +520,8 @@ TEST(SharedMemoryTest, FilePermissionsAnonymous) { EXPECT_TRUE(shared_memory.Create(options)); - int shm_fd = shared_memory.handle().fd; + int shm_fd = + SharedMemory::GetFdFromSharedMemoryHandle(shared_memory.handle()); struct stat shm_stat; EXPECT_EQ(0, fstat(shm_fd, &shm_stat)); // Neither the group, nor others should be able to read the shared memory @@ -622,7 +547,8 @@ TEST(SharedMemoryTest, FilePermissionsNamed) { // Clean-up the backing file name immediately, we don't need it. EXPECT_TRUE(shared_memory.Delete(shared_mem_name)); - int shm_fd = shared_memory.handle().fd; + int shm_fd = + SharedMemory::GetFdFromSharedMemoryHandle(shared_memory.handle()); struct stat shm_stat; EXPECT_EQ(0, fstat(shm_fd, &shm_stat)); // Neither the group, nor others should have been able to open the shared @@ -647,7 +573,9 @@ TEST(SharedMemoryTest, MapMinimumAlignment) { shared_memory.Close(); } -#if !defined(OS_IOS) // iOS does not allow multiple processes. +// iOS does not allow multiple processes. +// Android ashmem doesn't support named shared memory. +#if !defined(OS_IOS) && !defined(OS_ANDROID) // On POSIX it is especially important we test shmem across processes, // not just across threads. But the test is enabled on all platforms. @@ -664,53 +592,61 @@ class SharedMemoryProcessTest : public MultiProcessTest { #if defined(OS_MACOSX) mac::ScopedNSAutoreleasePool pool; #endif - const uint32 kDataSize = 1024; SharedMemory memory; - bool rv = memory.CreateNamedDeprecated(s_test_name_, true, kDataSize); + bool rv = memory.CreateNamedDeprecated(s_test_name_, true, s_data_size_); EXPECT_TRUE(rv); if (rv != true) errors++; - rv = memory.Map(kDataSize); + rv = memory.Map(s_data_size_); EXPECT_TRUE(rv); if (rv != true) errors++; int *ptr = static_cast(memory.memory()); - for (int idx = 0; idx < 20; idx++) { - memory.LockDeprecated(); - int i = (1 << 16) + idx; - *ptr = i; - PlatformThread::Sleep(TimeDelta::FromMilliseconds(10)); - if (*ptr != i) - errors++; - memory.UnlockDeprecated(); - } - + // This runs concurrently in multiple processes. Writes need to be atomic. + base::subtle::Barrier_AtomicIncrement(ptr, 1); memory.Close(); return errors; } - private: static const char* const s_test_name_; + static const uint32 s_data_size_; }; const char* const SharedMemoryProcessTest::s_test_name_ = "MPMem"; +const uint32 SharedMemoryProcessTest::s_data_size_ = 1024; -TEST_F(SharedMemoryProcessTest, Tasks) { +TEST_F(SharedMemoryProcessTest, SharedMemoryAcrossProcesses) { SharedMemoryProcessTest::CleanUp(); + // Create a shared memory region. Set the first word to 0. + SharedMemory memory; + bool rv = memory.CreateNamedDeprecated(s_test_name_, true, s_data_size_); + ASSERT_TRUE(rv); + rv = memory.Map(s_data_size_); + ASSERT_TRUE(rv); + int* ptr = static_cast(memory.memory()); + *ptr = 0; + + // Start |kNumTasks| processes, each of which atomically increments the first + // word by 1. Process processes[kNumTasks]; for (int index = 0; index < kNumTasks; ++index) { processes[index] = SpawnChild("SharedMemoryTestMain"); ASSERT_TRUE(processes[index].IsValid()); } + // Check that each process exited correctly. int exit_code = 0; for (int index = 0; index < kNumTasks; ++index) { EXPECT_TRUE(processes[index].WaitForExit(&exit_code)); EXPECT_EQ(0, exit_code); } + // Check that the shared memory region reflects |kNumTasks| increments. + ASSERT_EQ(kNumTasks, *ptr); + + memory.Close(); SharedMemoryProcessTest::CleanUp(); } @@ -718,6 +654,6 @@ MULTIPROCESS_TEST_MAIN(SharedMemoryTestMain) { return SharedMemoryProcessTest::TaskTestMain(); } -#endif // !OS_IOS +#endif // !defined(OS_IOS) && !defined(OS_ANDROID) } // namespace base diff --git a/base/memory/shared_memory_win.cc b/base/memory/shared_memory_win.cc index eacf0d6ccefcd..5f706fe648598 100644 --- a/base/memory/shared_memory_win.cc +++ b/base/memory/shared_memory_win.cc @@ -29,40 +29,37 @@ namespace base { SharedMemory::SharedMemory() : mapped_file_(NULL), + mapped_size_(0), memory_(NULL), read_only_(false), - mapped_size_(0), - requested_size_(0), - lock_(NULL) { + requested_size_(0) { } SharedMemory::SharedMemory(const std::wstring& name) - : mapped_file_(NULL), + : name_(name), + mapped_file_(NULL), + mapped_size_(0), memory_(NULL), read_only_(false), - requested_size_(0), - mapped_size_(0), - lock_(NULL), - name_(name) { + requested_size_(0) { } -SharedMemory::SharedMemory(SharedMemoryHandle handle, bool read_only) +SharedMemory::SharedMemory(const SharedMemoryHandle& handle, bool read_only) : mapped_file_(handle), + mapped_size_(0), memory_(NULL), read_only_(read_only), - requested_size_(0), - mapped_size_(0), - lock_(NULL) { + requested_size_(0) { } -SharedMemory::SharedMemory(SharedMemoryHandle handle, bool read_only, +SharedMemory::SharedMemory(const SharedMemoryHandle& handle, + bool read_only, ProcessHandle process) : mapped_file_(NULL), + mapped_size_(0), memory_(NULL), read_only_(read_only), - requested_size_(0), - mapped_size_(0), - lock_(NULL) { + requested_size_(0) { ::DuplicateHandle(process, handle, GetCurrentProcess(), &mapped_file_, read_only_ ? FILE_MAP_READ : FILE_MAP_READ | @@ -73,8 +70,6 @@ SharedMemory::SharedMemory(SharedMemoryHandle handle, bool read_only, SharedMemory::~SharedMemory() { Unmap(); Close(); - if (lock_ != NULL) - CloseHandle(lock_); } // static @@ -270,26 +265,6 @@ void SharedMemory::Close() { } } -void SharedMemory::LockDeprecated() { - if (lock_ == NULL) { - std::wstring name = name_; - name.append(L"lock"); - lock_ = CreateMutex(NULL, FALSE, name.c_str()); - if (lock_ == NULL) { - DPLOG(ERROR) << "Could not create mutex."; - NOTREACHED(); - return; // There is nothing good we can do here. - } - } - DWORD result = WaitForSingleObject(lock_, INFINITE); - DCHECK_EQ(result, WAIT_OBJECT_0); -} - -void SharedMemory::UnlockDeprecated() { - DCHECK(lock_ != NULL); - ReleaseMutex(lock_); -} - SharedMemoryHandle SharedMemory::handle() const { return mapped_file_; } diff --git a/base/message_loop/message_loop.cc b/base/message_loop/message_loop.cc index 4222c774dd58b..6bd6730cde347 100644 --- a/base/message_loop/message_loop.cc +++ b/base/message_loop/message_loop.cc @@ -19,6 +19,7 @@ #include "base/thread_task_runner_handle.h" #include "base/threading/thread_local.h" #include "base/time/time.h" +#include "base/trace_event/trace_event.h" #include "base/tracked_objects.h" #if defined(OS_MACOSX) @@ -170,7 +171,8 @@ MessageLoop::~MessageLoop() { // Tell the incoming queue that we are dying. incoming_task_queue_->WillDestroyCurrentMessageLoop(); incoming_task_queue_ = NULL; - message_loop_proxy_ = NULL; + unbound_task_runner_ = NULL; + task_runner_ = NULL; // OK, now make it so that no one can find us. lazy_tls_ptr.Pointer()->Set(NULL); @@ -257,27 +259,27 @@ void MessageLoop::RemoveDestructionObserver( void MessageLoop::PostTask( const tracked_objects::Location& from_here, const Closure& task) { - message_loop_proxy_->PostTask(from_here, task); + task_runner_->PostTask(from_here, task); } void MessageLoop::PostDelayedTask( const tracked_objects::Location& from_here, const Closure& task, TimeDelta delay) { - message_loop_proxy_->PostDelayedTask(from_here, task, delay); + task_runner_->PostDelayedTask(from_here, task, delay); } void MessageLoop::PostNonNestableTask( const tracked_objects::Location& from_here, const Closure& task) { - message_loop_proxy_->PostNonNestableTask(from_here, task); + task_runner_->PostNonNestableTask(from_here, task); } void MessageLoop::PostNonNestableDelayedTask( const tracked_objects::Location& from_here, const Closure& task, TimeDelta delay) { - message_loop_proxy_->PostNonNestableDelayedTask(from_here, task, delay); + task_runner_->PostNonNestableDelayedTask(from_here, task, delay); } void MessageLoop::Run() { @@ -367,6 +369,7 @@ bool MessageLoop::IsIdleForTesting() { //------------------------------------------------------------------------------ +// static scoped_ptr MessageLoop::CreateUnbound( Type type, MessagePumpFactoryCallback pump_factory) { return make_scoped_ptr(new MessageLoop(type, pump_factory)); @@ -386,8 +389,9 @@ MessageLoop::MessageLoop(Type type, MessagePumpFactoryCallback pump_factory) message_histogram_(NULL), run_loop_(NULL), incoming_task_queue_(new internal::IncomingTaskQueue(this)), - message_loop_proxy_( - new internal::MessageLoopProxyImpl(incoming_task_queue_)) { + unbound_task_runner_( + new internal::MessageLoopTaskRunner(incoming_task_queue_)), + task_runner_(unbound_task_runner_) { // If type is TYPE_CUSTOM non-null pump_factory must be given. DCHECK_EQ(type_ == TYPE_CUSTOM, !pump_factory_.is_null()); } @@ -403,9 +407,26 @@ void MessageLoop::BindToCurrentThread() { lazy_tls_ptr.Pointer()->Set(this); incoming_task_queue_->StartScheduling(); - message_loop_proxy_->BindToCurrentThread(); - thread_task_runner_handle_.reset( - new ThreadTaskRunnerHandle(message_loop_proxy_)); + unbound_task_runner_->BindToCurrentThread(); + unbound_task_runner_ = nullptr; + SetThreadTaskRunnerHandle(); +} + +void MessageLoop::SetTaskRunner( + scoped_refptr task_runner) { + DCHECK_EQ(this, current()); + DCHECK(task_runner->BelongsToCurrentThread()); + DCHECK(!unbound_task_runner_); + task_runner_ = task_runner.Pass(); + SetThreadTaskRunnerHandle(); +} + +void MessageLoop::SetThreadTaskRunnerHandle() { + DCHECK_EQ(this, current()); + // Clear the previous thread task runner first because only one can exist at + // a time. + thread_task_runner_handle_.reset(); + thread_task_runner_handle_.reset(new ThreadTaskRunnerHandle(task_runner_)); } void MessageLoop::RunHandler() { @@ -453,10 +474,11 @@ void MessageLoop::RunTask(const PendingTask& pending_task) { HistogramEvent(kTaskRunEvent); + TRACE_TASK_EXECUTION("toplevel", pending_task); + FOR_EACH_OBSERVER(TaskObserver, task_observers_, WillProcessTask(pending_task)); - task_annotator_.RunTask( - "MessageLoop::PostTask", "MessageLoop::RunTask", pending_task); + task_annotator_.RunTask("MessageLoop::PostTask", pending_task); FOR_EACH_OBSERVER(TaskObserver, task_observers_, DidProcessTask(pending_task)); diff --git a/base/message_loop/message_loop.h b/base/message_loop/message_loop.h index f2f89d0574dc0..fbb8309c20327 100644 --- a/base/message_loop/message_loop.h +++ b/base/message_loop/message_loop.h @@ -16,8 +16,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/message_loop/incoming_task_queue.h" -#include "base/message_loop/message_loop_proxy.h" -#include "base/message_loop/message_loop_proxy_impl.h" +#include "base/message_loop/message_loop_task_runner.h" #include "base/message_loop/message_pump.h" #include "base/message_loop/timer_slack.h" #include "base/observer_list.h" @@ -296,20 +295,18 @@ class BASE_EXPORT MessageLoop : public MessagePump::Delegate { } const std::string& thread_name() const { return thread_name_; } - // Gets the message loop proxy associated with this message loop. - // - // NOTE: Deprecated; prefer task_runner() and the TaskRunner interfaces - scoped_refptr message_loop_proxy() { - return message_loop_proxy_; - } - // Gets the TaskRunner associated with this message loop. - // TODO(skyostil): Change this to return a const reference to a refptr - // once the internal type matches what is being returned (crbug.com/465354). - scoped_refptr task_runner() { - return message_loop_proxy_; + const scoped_refptr& task_runner() { + return task_runner_; } + // Sets a new TaskRunner for this message loop. The message loop must already + // have been bound to a thread prior to this call, and the task runner must + // belong to that thread. Note that changing the task runner will also affect + // the ThreadTaskRunnerHandle for the target thread. Must be called on the + // thread to which the message loop is bound. + void SetTaskRunner(scoped_refptr task_runner); + // Enables or disables the recursive task processing. This happens in the case // of recursive message loops. Some unwanted message loop may occurs when // using common controls or printer functions. By default, recursive task @@ -425,7 +422,7 @@ class BASE_EXPORT MessageLoop : public MessagePump::Delegate { // thread the message loop runs on, before calling Run(). // Before BindToCurrentThread() is called only Post*Task() functions can // be called on the message loop. - scoped_ptr CreateUnbound( + static scoped_ptr CreateUnbound( Type type, MessagePumpFactoryCallback pump_factory); @@ -436,6 +433,10 @@ class BASE_EXPORT MessageLoop : public MessagePump::Delegate { // Configure various members and bind this message loop to the current thread. void BindToCurrentThread(); + // Sets the ThreadTaskRunnerHandle for the current thread to point to the + // task runner for this message loop. + void SetThreadTaskRunnerHandle(); + // Invokes the actual run loop using the message pump. void RunHandler(); @@ -531,8 +532,11 @@ class BASE_EXPORT MessageLoop : public MessagePump::Delegate { scoped_refptr incoming_task_queue_; - // The message loop proxy associated with this message loop. - scoped_refptr message_loop_proxy_; + // A task runner which we haven't bound to a thread yet. + scoped_refptr unbound_task_runner_; + + // The task runner associated with this message loop. + scoped_refptr task_runner_; scoped_ptr thread_task_runner_handle_; template friend class base::subtle::DeleteHelperInternal; diff --git a/base/message_loop/message_loop_proxy.cc b/base/message_loop/message_loop_proxy.cc deleted file mode 100644 index e5f0142633f07..0000000000000 --- a/base/message_loop/message_loop_proxy.cc +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/message_loop/message_loop_proxy.h" - -#include "base/bind.h" - -namespace base { - -MessageLoopProxy::MessageLoopProxy() { -} - -MessageLoopProxy::~MessageLoopProxy() { -} - -} // namespace base diff --git a/base/message_loop/message_loop_proxy.h b/base/message_loop/message_loop_proxy.h deleted file mode 100644 index d5ecc041b6fc4..0000000000000 --- a/base/message_loop/message_loop_proxy.h +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_MESSAGE_LOOP_MESSAGE_LOOP_PROXY_H_ -#define BASE_MESSAGE_LOOP_MESSAGE_LOOP_PROXY_H_ - -#include "base/base_export.h" -#include "base/compiler_specific.h" -#include "base/memory/ref_counted.h" -#include "base/single_thread_task_runner.h" - -// MessageLoopProxy is deprecated. Code should prefer to depend on TaskRunner -// (or the various specializations) for passing task runners around, and should -// use ThreadTaskRunnerHandle::Get() to get the thread's associated task runner. -// -// See http://crbug.com/391045 for more details. -// Example for these changes: -// -// base::MessageLoopProxy::current() -> base::ThreadTaskRunnerHandle::Get() -// scoped_refptr -> -// scoped_refptr -// base::MessageLoopProxy -> base::SingleThreadTaskRunner - -namespace base { - -// This class provides a thread-safe refcounted interface to the Post* methods -// of a message loop. This class can outlive the target message loop. -// MessageLoopProxy objects are constructed automatically for all MessageLoops. -// So, to access them, you can use any of the following: -// Thread::message_loop_proxy() -// MessageLoop::current()->message_loop_proxy() -// MessageLoopProxy::current() -// -// TODO(akalin): Now that we have the *TaskRunner interfaces, we can -// merge this with MessageLoopProxyImpl. -class BASE_EXPORT MessageLoopProxy : public SingleThreadTaskRunner { - public: - // Gets the MessageLoopProxy for the current message loop, creating one if - // needed. - static scoped_refptr current(); - - protected: - MessageLoopProxy(); - ~MessageLoopProxy() override; -}; - -} // namespace base - -#endif // BASE_MESSAGE_LOOP_MESSAGE_LOOP_PROXY_H_ diff --git a/base/message_loop/message_loop_proxy_impl_unittest.cc b/base/message_loop/message_loop_proxy_impl_unittest.cc deleted file mode 100644 index fa253717654e7..0000000000000 --- a/base/message_loop/message_loop_proxy_impl_unittest.cc +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/message_loop/message_loop_proxy_impl.h" - -#include "base/bind.h" -#include "base/memory/scoped_ptr.h" -#include "base/message_loop/message_loop.h" -#include "base/message_loop/message_loop_proxy.h" -#include "base/threading/thread.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "testing/platform_test.h" - -namespace base { - -class MessageLoopProxyImplTest : public testing::Test { - public: - void Release() const { - AssertOnIOThread(); - Quit(); - } - - void Quit() const { - loop_.PostTask(FROM_HERE, MessageLoop::QuitWhenIdleClosure()); - } - - void AssertOnIOThread() const { - ASSERT_TRUE(io_thread_->message_loop_proxy()->BelongsToCurrentThread()); - ASSERT_EQ(io_thread_->message_loop_proxy(), - MessageLoopProxy::current()); - } - - void AssertOnFileThread() const { - ASSERT_TRUE(file_thread_->message_loop_proxy()->BelongsToCurrentThread()); - ASSERT_EQ(file_thread_->message_loop_proxy(), - MessageLoopProxy::current()); - } - - protected: - void SetUp() override { - io_thread_.reset(new Thread("MessageLoopProxyImplTest_IO")); - file_thread_.reset(new Thread("MessageLoopProxyImplTest_File")); - io_thread_->Start(); - file_thread_->Start(); - } - - void TearDown() override { - io_thread_->Stop(); - file_thread_->Stop(); - } - - static void BasicFunction(MessageLoopProxyImplTest* test) { - test->AssertOnFileThread(); - test->Quit(); - } - - static void AssertNotRun() { - FAIL() << "Callback Should not get executed."; - } - - class DeletedOnFile { - public: - explicit DeletedOnFile(MessageLoopProxyImplTest* test) : test_(test) {} - - ~DeletedOnFile() { - test_->AssertOnFileThread(); - test_->Quit(); - } - - private: - MessageLoopProxyImplTest* test_; - }; - - scoped_ptr io_thread_; - scoped_ptr file_thread_; - - private: - mutable MessageLoop loop_; -}; - -TEST_F(MessageLoopProxyImplTest, Release) { - EXPECT_TRUE(io_thread_->message_loop_proxy()->ReleaseSoon(FROM_HERE, this)); - MessageLoop::current()->Run(); -} - -TEST_F(MessageLoopProxyImplTest, Delete) { - DeletedOnFile* deleted_on_file = new DeletedOnFile(this); - EXPECT_TRUE(file_thread_->message_loop_proxy()->DeleteSoon( - FROM_HERE, deleted_on_file)); - MessageLoop::current()->Run(); -} - -TEST_F(MessageLoopProxyImplTest, PostTask) { - EXPECT_TRUE(file_thread_->message_loop_proxy()->PostTask( - FROM_HERE, Bind(&MessageLoopProxyImplTest::BasicFunction, - Unretained(this)))); - MessageLoop::current()->Run(); -} - -TEST_F(MessageLoopProxyImplTest, PostTaskAfterThreadExits) { - scoped_ptr test_thread( - new Thread("MessageLoopProxyImplTest_Dummy")); - test_thread->Start(); - scoped_refptr message_loop_proxy = - test_thread->message_loop_proxy(); - test_thread->Stop(); - - bool ret = message_loop_proxy->PostTask( - FROM_HERE, - Bind(&MessageLoopProxyImplTest::AssertNotRun)); - EXPECT_FALSE(ret); -} - -TEST_F(MessageLoopProxyImplTest, PostTaskAfterThreadIsDeleted) { - scoped_refptr message_loop_proxy; - { - scoped_ptr test_thread( - new Thread("MessageLoopProxyImplTest_Dummy")); - test_thread->Start(); - message_loop_proxy = test_thread->message_loop_proxy(); - } - bool ret = message_loop_proxy->PostTask( - FROM_HERE, - Bind(&MessageLoopProxyImplTest::AssertNotRun)); - EXPECT_FALSE(ret); -} - -} // namespace base diff --git a/base/message_loop/message_loop_proxy_impl.cc b/base/message_loop/message_loop_task_runner.cc similarity index 62% rename from base/message_loop/message_loop_proxy_impl.cc rename to base/message_loop/message_loop_task_runner.cc index 580620d6bd5bf..c9b5ffe3f739d 100644 --- a/base/message_loop/message_loop_proxy_impl.cc +++ b/base/message_loop/message_loop_task_runner.cc @@ -2,29 +2,27 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/message_loop/message_loop_proxy_impl.h" +#include "base/message_loop/message_loop_task_runner.h" #include "base/location.h" #include "base/logging.h" #include "base/message_loop/incoming_task_queue.h" -#include "base/message_loop/message_loop.h" namespace base { namespace internal { -MessageLoopProxyImpl::MessageLoopProxyImpl( +MessageLoopTaskRunner::MessageLoopTaskRunner( scoped_refptr incoming_queue) - : incoming_queue_(incoming_queue), - valid_thread_id_(kInvalidThreadId) { + : incoming_queue_(incoming_queue), valid_thread_id_(kInvalidThreadId) { } -void MessageLoopProxyImpl::BindToCurrentThread() { +void MessageLoopTaskRunner::BindToCurrentThread() { AutoLock lock(valid_thread_id_lock_); DCHECK_EQ(kInvalidThreadId, valid_thread_id_); valid_thread_id_ = PlatformThread::CurrentId(); } -bool MessageLoopProxyImpl::PostDelayedTask( +bool MessageLoopTaskRunner::PostDelayedTask( const tracked_objects::Location& from_here, const base::Closure& task, base::TimeDelta delay) { @@ -32,7 +30,7 @@ bool MessageLoopProxyImpl::PostDelayedTask( return incoming_queue_->AddToIncomingQueue(from_here, task, delay, true); } -bool MessageLoopProxyImpl::PostNonNestableDelayedTask( +bool MessageLoopTaskRunner::PostNonNestableDelayedTask( const tracked_objects::Location& from_here, const base::Closure& task, base::TimeDelta delay) { @@ -40,22 +38,14 @@ bool MessageLoopProxyImpl::PostNonNestableDelayedTask( return incoming_queue_->AddToIncomingQueue(from_here, task, delay, false); } -bool MessageLoopProxyImpl::RunsTasksOnCurrentThread() const { +bool MessageLoopTaskRunner::RunsTasksOnCurrentThread() const { AutoLock lock(valid_thread_id_lock_); return valid_thread_id_ == PlatformThread::CurrentId(); } -MessageLoopProxyImpl::~MessageLoopProxyImpl() { +MessageLoopTaskRunner::~MessageLoopTaskRunner() { } } // namespace internal -scoped_refptr -MessageLoopProxy::current() { - MessageLoop* cur_loop = MessageLoop::current(); - if (!cur_loop) - return NULL; - return cur_loop->message_loop_proxy(); -} - } // namespace base diff --git a/base/message_loop/message_loop_proxy_impl.h b/base/message_loop/message_loop_task_runner.h similarity index 60% rename from base/message_loop/message_loop_proxy_impl.h rename to base/message_loop/message_loop_task_runner.h index fa611c2908534..dc2947df26c61 100644 --- a/base/message_loop/message_loop_proxy_impl.h +++ b/base/message_loop/message_loop_task_runner.h @@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_MESSAGE_LOOP_MESSAGE_LOOP_PROXY_IMPL_H_ -#define BASE_MESSAGE_LOOP_MESSAGE_LOOP_PROXY_IMPL_H_ +#ifndef BASE_MESSAGE_LOOP_MESSAGE_LOOP_TASK_RUNNER_H_ +#define BASE_MESSAGE_LOOP_MESSAGE_LOOP_TASK_RUNNER_H_ #include "base/base_export.h" #include "base/memory/ref_counted.h" -#include "base/message_loop/message_loop_proxy.h" #include "base/pending_task.h" +#include "base/single_thread_task_runner.h" #include "base/synchronization/lock.h" #include "base/threading/platform_thread.h" @@ -17,18 +17,18 @@ namespace internal { class IncomingTaskQueue; -// A stock implementation of MessageLoopProxy that is created and managed by a -// MessageLoop. For now a MessageLoopProxyImpl can only be created as part of a -// MessageLoop. -class BASE_EXPORT MessageLoopProxyImpl : public MessageLoopProxy { +// A stock implementation of SingleThreadTaskRunner that is created and managed +// by a MessageLoop. For now a MessageLoopTaskRunner can only be created as +// part of a MessageLoop. +class BASE_EXPORT MessageLoopTaskRunner : public SingleThreadTaskRunner { public: - explicit MessageLoopProxyImpl( + explicit MessageLoopTaskRunner( scoped_refptr incoming_queue); - // Initialize this message loop proxy on the current thread. + // Initialize this message loop task runner on the current thread. void BindToCurrentThread(); - // MessageLoopProxy implementation + // SingleThreadTaskRunner implementation bool PostDelayedTask(const tracked_objects::Location& from_here, const base::Closure& task, base::TimeDelta delay) override; @@ -38,10 +38,10 @@ class BASE_EXPORT MessageLoopProxyImpl : public MessageLoopProxy { bool RunsTasksOnCurrentThread() const override; private: - friend class RefCountedThreadSafe; - ~MessageLoopProxyImpl() override; + friend class RefCountedThreadSafe; + ~MessageLoopTaskRunner() override; - // THe incoming queue receiving all posted tasks. + // The incoming queue receiving all posted tasks. scoped_refptr incoming_queue_; // ID of the thread |this| was created on. Could be accessed on multiple @@ -49,10 +49,10 @@ class BASE_EXPORT MessageLoopProxyImpl : public MessageLoopProxy { PlatformThreadId valid_thread_id_; mutable Lock valid_thread_id_lock_; - DISALLOW_COPY_AND_ASSIGN(MessageLoopProxyImpl); + DISALLOW_COPY_AND_ASSIGN(MessageLoopTaskRunner); }; } // namespace internal } // namespace base -#endif // BASE_MESSAGE_LOOP_MESSAGE_LOOP_PROXY_IMPL_H_ +#endif // BASE_MESSAGE_LOOP_MESSAGE_LOOP_TASK_RUNNER_H_ diff --git a/base/message_loop/message_loop_proxy_unittest.cc b/base/message_loop/message_loop_task_runner_unittest.cc similarity index 58% rename from base/message_loop/message_loop_proxy_unittest.cc rename to base/message_loop/message_loop_task_runner_unittest.cc index 0b0d9f8ad0071..caf88afadd020 100644 --- a/base/message_loop/message_loop_proxy_unittest.cc +++ b/base/message_loop/message_loop_task_runner_unittest.cc @@ -2,33 +2,30 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/message_loop/message_loop_proxy.h" +#include "base/message_loop/message_loop_task_runner.h" #include "base/atomic_sequence_num.h" #include "base/bind.h" #include "base/debug/leak_annotations.h" -#include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" +#include "base/message_loop/message_loop_task_runner.h" #include "base/synchronization/waitable_event.h" +#include "base/thread_task_runner_handle.h" #include "base/threading/thread.h" #include "testing/gtest/include/gtest/gtest.h" +#include "testing/platform_test.h" namespace base { -namespace { - -class MessageLoopProxyTest : public testing::Test { +class MessageLoopTaskRunnerTest : public testing::Test { public: - MessageLoopProxyTest() + MessageLoopTaskRunnerTest() : current_loop_(new MessageLoop()), task_thread_("task_thread"), - thread_sync_(true, false) { - } + thread_sync_(true, false) {} - void DeleteCurrentMessageLoop() { - current_loop_.reset(); - } + void DeleteCurrentMessageLoop() { current_loop_.reset(); } protected: void SetUp() override { @@ -38,8 +35,8 @@ class MessageLoopProxyTest : public testing::Test { // Allow us to pause the |task_thread_|'s MessageLoop. task_thread_.message_loop()->PostTask( - FROM_HERE, - Bind(&MessageLoopProxyTest::BlockTaskThreadHelper, Unretained(this))); + FROM_HERE, Bind(&MessageLoopTaskRunnerTest::BlockTaskThreadHelper, + Unretained(this))); } void TearDown() override { @@ -55,16 +52,14 @@ class MessageLoopProxyTest : public testing::Test { // threading mistake sneaks into the PostTaskAndReplyRelay implementation. class LoopRecorder : public RefCountedThreadSafe { public: - LoopRecorder(MessageLoop** run_on, MessageLoop** deleted_on, + LoopRecorder(MessageLoop** run_on, + MessageLoop** deleted_on, int* destruct_order) : run_on_(run_on), deleted_on_(deleted_on), - destruct_order_(destruct_order) { - } + destruct_order_(destruct_order) {} - void RecordRun() { - *run_on_ = MessageLoop::current(); - } + void RecordRun() { *run_on_ = MessageLoop::current(); } private: friend class RefCountedThreadSafe; @@ -87,13 +82,9 @@ class MessageLoopProxyTest : public testing::Test { MessageLoop::current()->QuitWhenIdle(); } - void UnblockTaskThread() { - thread_sync_.Signal(); - } + void UnblockTaskThread() { thread_sync_.Signal(); } - void BlockTaskThreadHelper() { - thread_sync_.Wait(); - } + void BlockTaskThreadHelper() { thread_sync_.Wait(); } static StaticAtomicSequenceNumber g_order; @@ -104,9 +95,9 @@ class MessageLoopProxyTest : public testing::Test { base::WaitableEvent thread_sync_; }; -StaticAtomicSequenceNumber MessageLoopProxyTest::g_order; +StaticAtomicSequenceNumber MessageLoopTaskRunnerTest::g_order; -TEST_F(MessageLoopProxyTest, PostTaskAndReply_Basic) { +TEST_F(MessageLoopTaskRunnerTest, PostTaskAndReply_Basic) { MessageLoop* task_run_on = NULL; MessageLoop* task_deleted_on = NULL; int task_delete_order = -1; @@ -119,9 +110,8 @@ TEST_F(MessageLoopProxyTest, PostTaskAndReply_Basic) { scoped_refptr reply_recoder = new LoopRecorder(&reply_run_on, &reply_deleted_on, &reply_delete_order); - ASSERT_TRUE(task_thread_.message_loop_proxy()->PostTaskAndReply( - FROM_HERE, - Bind(&RecordLoop, task_recoder), + ASSERT_TRUE(task_thread_.task_runner()->PostTaskAndReply( + FROM_HERE, Bind(&RecordLoop, task_recoder), Bind(&RecordLoopAndQuit, reply_recoder))); // Die if base::Bind doesn't retain a reference to the recorders. @@ -140,7 +130,7 @@ TEST_F(MessageLoopProxyTest, PostTaskAndReply_Basic) { EXPECT_LT(task_delete_order, reply_delete_order); } -TEST_F(MessageLoopProxyTest, PostTaskAndReplyOnDeletedThreadDoesNotLeak) { +TEST_F(MessageLoopTaskRunnerTest, PostTaskAndReplyOnDeletedThreadDoesNotLeak) { MessageLoop* task_run_on = NULL; MessageLoop* task_deleted_on = NULL; int task_delete_order = -1; @@ -153,16 +143,15 @@ TEST_F(MessageLoopProxyTest, PostTaskAndReplyOnDeletedThreadDoesNotLeak) { scoped_refptr reply_recoder = new LoopRecorder(&reply_run_on, &reply_deleted_on, &reply_delete_order); - // Grab a MessageLoopProxy to a dead MessageLoop. - scoped_refptr task_loop_proxy = - task_thread_.message_loop_proxy(); + // Grab a task runner to a dead MessageLoop. + scoped_refptr task_runner = + task_thread_.task_runner(); UnblockTaskThread(); task_thread_.Stop(); - ASSERT_FALSE(task_loop_proxy->PostTaskAndReply( - FROM_HERE, - Bind(&RecordLoop, task_recoder), - Bind(&RecordLoopAndQuit, reply_recoder))); + ASSERT_FALSE( + task_runner->PostTaskAndReply(FROM_HERE, Bind(&RecordLoop, task_recoder), + Bind(&RecordLoopAndQuit, reply_recoder))); // The relay should have properly deleted its resources leaving us as the only // reference. @@ -175,7 +164,7 @@ TEST_F(MessageLoopProxyTest, PostTaskAndReplyOnDeletedThreadDoesNotLeak) { EXPECT_FALSE(reply_run_on); } -TEST_F(MessageLoopProxyTest, PostTaskAndReply_SameLoop) { +TEST_F(MessageLoopTaskRunnerTest, PostTaskAndReply_SameLoop) { MessageLoop* task_run_on = NULL; MessageLoop* task_deleted_on = NULL; int task_delete_order = -1; @@ -189,9 +178,8 @@ TEST_F(MessageLoopProxyTest, PostTaskAndReply_SameLoop) { new LoopRecorder(&reply_run_on, &reply_deleted_on, &reply_delete_order); // Enqueue the relay. - ASSERT_TRUE(current_loop_->message_loop_proxy()->PostTaskAndReply( - FROM_HERE, - Bind(&RecordLoop, task_recoder), + ASSERT_TRUE(current_loop_->task_runner()->PostTaskAndReply( + FROM_HERE, Bind(&RecordLoop, task_recoder), Bind(&RecordLoopAndQuit, reply_recoder))); // Die if base::Bind doesn't retain a reference to the recorders. @@ -209,7 +197,7 @@ TEST_F(MessageLoopProxyTest, PostTaskAndReply_SameLoop) { EXPECT_LT(task_delete_order, reply_delete_order); } -TEST_F(MessageLoopProxyTest, PostTaskAndReply_DeadReplyLoopDoesNotDelete) { +TEST_F(MessageLoopTaskRunnerTest, PostTaskAndReply_DeadReplyLoopDoesNotDelete) { // Annotate the scope as having memory leaks to suppress heapchecker reports. ANNOTATE_SCOPED_MEMORY_LEAK; MessageLoop* task_run_on = NULL; @@ -225,9 +213,8 @@ TEST_F(MessageLoopProxyTest, PostTaskAndReply_DeadReplyLoopDoesNotDelete) { new LoopRecorder(&reply_run_on, &reply_deleted_on, &reply_delete_order); // Enqueue the relay. - task_thread_.message_loop_proxy()->PostTaskAndReply( - FROM_HERE, - Bind(&RecordLoop, task_recoder), + task_thread_.task_runner()->PostTaskAndReply( + FROM_HERE, Bind(&RecordLoop, task_recoder), Bind(&RecordLoopAndQuit, reply_recoder)); // Die if base::Bind doesn't retain a reference to the recorders. @@ -261,6 +248,111 @@ TEST_F(MessageLoopProxyTest, PostTaskAndReply_DeadReplyLoopDoesNotDelete) { // http://crbug.com/86301. } -} // namespace +class MessageLoopTaskRunnerThreadingTest : public testing::Test { + public: + void Release() const { + AssertOnIOThread(); + Quit(); + } + + void Quit() const { + loop_.PostTask(FROM_HERE, MessageLoop::QuitWhenIdleClosure()); + } + + void AssertOnIOThread() const { + ASSERT_TRUE(io_thread_->task_runner()->BelongsToCurrentThread()); + ASSERT_EQ(io_thread_->task_runner(), ThreadTaskRunnerHandle::Get()); + } + + void AssertOnFileThread() const { + ASSERT_TRUE(file_thread_->task_runner()->BelongsToCurrentThread()); + ASSERT_EQ(file_thread_->task_runner(), ThreadTaskRunnerHandle::Get()); + } + + protected: + void SetUp() override { + io_thread_.reset(new Thread("MessageLoopTaskRunnerThreadingTest_IO")); + file_thread_.reset(new Thread("MessageLoopTaskRunnerThreadingTest_File")); + io_thread_->Start(); + file_thread_->Start(); + } + + void TearDown() override { + io_thread_->Stop(); + file_thread_->Stop(); + } + + static void BasicFunction(MessageLoopTaskRunnerThreadingTest* test) { + test->AssertOnFileThread(); + test->Quit(); + } + + static void AssertNotRun() { FAIL() << "Callback Should not get executed."; } + + class DeletedOnFile { + public: + explicit DeletedOnFile(MessageLoopTaskRunnerThreadingTest* test) + : test_(test) {} + + ~DeletedOnFile() { + test_->AssertOnFileThread(); + test_->Quit(); + } + + private: + MessageLoopTaskRunnerThreadingTest* test_; + }; + + scoped_ptr io_thread_; + scoped_ptr file_thread_; + + private: + mutable MessageLoop loop_; +}; + +TEST_F(MessageLoopTaskRunnerThreadingTest, Release) { + EXPECT_TRUE(io_thread_->task_runner()->ReleaseSoon(FROM_HERE, this)); + MessageLoop::current()->Run(); +} + +TEST_F(MessageLoopTaskRunnerThreadingTest, Delete) { + DeletedOnFile* deleted_on_file = new DeletedOnFile(this); + EXPECT_TRUE( + file_thread_->task_runner()->DeleteSoon(FROM_HERE, deleted_on_file)); + MessageLoop::current()->Run(); +} + +TEST_F(MessageLoopTaskRunnerThreadingTest, PostTask) { + EXPECT_TRUE(file_thread_->task_runner()->PostTask( + FROM_HERE, Bind(&MessageLoopTaskRunnerThreadingTest::BasicFunction, + Unretained(this)))); + MessageLoop::current()->Run(); +} + +TEST_F(MessageLoopTaskRunnerThreadingTest, PostTaskAfterThreadExits) { + scoped_ptr test_thread( + new Thread("MessageLoopTaskRunnerThreadingTest_Dummy")); + test_thread->Start(); + scoped_refptr task_runner = + test_thread->task_runner(); + test_thread->Stop(); + + bool ret = task_runner->PostTask( + FROM_HERE, Bind(&MessageLoopTaskRunnerThreadingTest::AssertNotRun)); + EXPECT_FALSE(ret); +} + +TEST_F(MessageLoopTaskRunnerThreadingTest, PostTaskAfterThreadIsDeleted) { + scoped_refptr task_runner; + { + scoped_ptr test_thread( + new Thread("MessageLoopTaskRunnerThreadingTest_Dummy")); + test_thread->Start(); + task_runner = test_thread->task_runner(); + } + bool ret = task_runner->PostTask( + FROM_HERE, Bind(&MessageLoopTaskRunnerThreadingTest::AssertNotRun)); + EXPECT_FALSE(ret); +} } // namespace base diff --git a/base/message_loop/message_loop_unittest.cc b/base/message_loop/message_loop_unittest.cc index ddde6bb170d93..9c1701756882f 100644 --- a/base/message_loop/message_loop_unittest.cc +++ b/base/message_loop/message_loop_unittest.cc @@ -10,12 +10,12 @@ #include "base/logging.h" #include "base/memory/ref_counted.h" #include "base/message_loop/message_loop.h" -#include "base/message_loop/message_loop_proxy_impl.h" #include "base/message_loop/message_loop_test.h" #include "base/pending_task.h" #include "base/posix/eintr_wrapper.h" #include "base/run_loop.h" #include "base/synchronization/waitable_event.h" +#include "base/test/test_simple_task_runner.h" #include "base/thread_task_runner_handle.h" #include "base/threading/platform_thread.h" #include "base/threading/thread.h" @@ -1012,4 +1012,26 @@ TEST(MessageLoopTest, AlwaysHaveUserMessageWhenNesting) { } #endif // defined(OS_WIN) +TEST(MessageLoopTest, SetTaskRunner) { + MessageLoop loop; + scoped_refptr new_runner(new TestSimpleTaskRunner()); + + loop.SetTaskRunner(new_runner); + EXPECT_EQ(new_runner, loop.task_runner()); + EXPECT_EQ(new_runner, ThreadTaskRunnerHandle::Get()); +} + +TEST(MessageLoopTest, OriginalRunnerWorks) { + MessageLoop loop; + scoped_refptr new_runner(new TestSimpleTaskRunner()); + scoped_refptr original_runner(loop.task_runner()); + loop.SetTaskRunner(new_runner); + + scoped_refptr foo(new Foo()); + original_runner->PostTask(FROM_HERE, + Bind(&Foo::Test1ConstRef, foo.get(), "a")); + loop.RunUntilIdle(); + EXPECT_EQ(1, foo->test_count()); +} + } // namespace base diff --git a/base/message_loop/message_pump_libevent_unittest.cc b/base/message_loop/message_pump_libevent_unittest.cc index 7d796dff8763c..e911905abd7b4 100644 --- a/base/message_loop/message_pump_libevent_unittest.cc +++ b/base/message_loop/message_pump_libevent_unittest.cc @@ -77,8 +77,8 @@ class StupidWatcher : public MessagePumpLibevent::Watcher { // Test to make sure that we catch calling WatchFileDescriptor off of the // wrong thread. -#if defined(OS_CHROMEOS) -// Flaky on Chrome OS: crbug.com/138845. +#if defined(OS_CHROMEOS) || defined(OS_LINUX) +// Flaky on Chrome OS and Linux: crbug.com/138845. #define MAYBE_TestWatchingFromBadThread DISABLED_TestWatchingFromBadThread #else #define MAYBE_TestWatchingFromBadThread TestWatchingFromBadThread @@ -246,7 +246,7 @@ TEST_F(MessagePumpLibeventTest, QuitWatcher) { MessagePumpLibevent::FileDescriptorWatcher controller; QuitWatcher delegate(&controller, &run_loop); WaitableEvent event(false /* manual_reset */, false /* initially_signaled */); - WaitableEventWatcher watcher; + scoped_ptr watcher(new WaitableEventWatcher); // Tell the pump to watch the pipe. pump->WatchFileDescriptor(pipefds_[0], false, MessagePumpLibevent::WATCH_READ, @@ -258,13 +258,17 @@ TEST_F(MessagePumpLibeventTest, QuitWatcher) { Bind(&WriteFDWrapper, pipefds_[1], &buf, 1); io_loop()->PostTask(FROM_HERE, Bind(IgnoreResult(&WaitableEventWatcher::StartWatching), - Unretained(&watcher), &event, write_fd_task)); + Unretained(watcher.get()), &event, write_fd_task)); // Queue |event| to signal on |loop|. loop.PostTask(FROM_HERE, Bind(&WaitableEvent::Signal, Unretained(&event))); // Now run the MessageLoop. run_loop.Run(); + + // StartWatching can move |watcher| to IO thread. Release on IO thread. + io_loop()->PostTask(FROM_HERE, Bind(&WaitableEventWatcher::StopWatching, + Owned(watcher.release()))); } } // namespace diff --git a/base/message_loop/message_pump_mac.mm b/base/message_loop/message_pump_mac.mm index 914977b13d593..53e3363da572c 100644 --- a/base/message_loop/message_pump_mac.mm +++ b/base/message_loop/message_pump_mac.mm @@ -10,6 +10,7 @@ #include #include "base/logging.h" +#include "base/mac/call_with_eh_frame.h" #include "base/mac/scoped_cftyperef.h" #include "base/message_loop/timer_slack.h" #include "base/run_loop.h" @@ -300,7 +301,9 @@ explicit MessagePumpScopedAutoreleasePool(MessagePumpCFRunLoopBase* pump) : // static void MessagePumpCFRunLoopBase::RunWorkSource(void* info) { MessagePumpCFRunLoopBase* self = static_cast(info); - self->RunWork(); + base::mac::CallWithEHFrame(^{ + self->RunWork(); + }); } // Called by MessagePumpCFRunLoopBase::RunWorkSource. @@ -359,7 +362,9 @@ explicit MessagePumpScopedAutoreleasePool(MessagePumpCFRunLoopBase* pump) : // static void MessagePumpCFRunLoopBase::RunIdleWorkSource(void* info) { MessagePumpCFRunLoopBase* self = static_cast(info); - self->RunIdleWork(); + base::mac::CallWithEHFrame(^{ + self->RunIdleWork(); + }); } // Called by MessagePumpCFRunLoopBase::RunIdleWorkSource. @@ -393,7 +398,9 @@ explicit MessagePumpScopedAutoreleasePool(MessagePumpCFRunLoopBase* pump) : // static void MessagePumpCFRunLoopBase::RunNestingDeferredWorkSource(void* info) { MessagePumpCFRunLoopBase* self = static_cast(info); - self->RunNestingDeferredWork(); + base::mac::CallWithEHFrame(^{ + self->RunNestingDeferredWork(); + }); } // Called by MessagePumpCFRunLoopBase::RunNestingDeferredWorkSource. @@ -440,15 +447,16 @@ explicit MessagePumpScopedAutoreleasePool(MessagePumpCFRunLoopBase* pump) : CFRunLoopActivity activity, void* info) { MessagePumpCFRunLoopBase* self = static_cast(info); - - // Attempt to do some idle work before going to sleep. - self->RunIdleWork(); - - // The run loop is about to go to sleep. If any of the work done since it - // started or woke up resulted in a nested run loop running, - // nesting-deferred work may have accumulated. Schedule it for processing - // if appropriate. - self->MaybeScheduleNestingDeferredWork(); + base::mac::CallWithEHFrame(^{ + // Attempt to do some idle work before going to sleep. + self->RunIdleWork(); + + // The run loop is about to go to sleep. If any of the work done since it + // started or woke up resulted in a nested run loop running, + // nesting-deferred work may have accumulated. Schedule it for processing + // if appropriate. + self->MaybeScheduleNestingDeferredWork(); + }); } // Called from the run loop. @@ -463,7 +471,9 @@ explicit MessagePumpScopedAutoreleasePool(MessagePumpCFRunLoopBase* pump) : // level did not sleep or exit, nesting-deferred work may have accumulated // if a nested loop ran. Schedule nesting-deferred work for processing if // appropriate. - self->MaybeScheduleNestingDeferredWork(); + base::mac::CallWithEHFrame(^{ + self->MaybeScheduleNestingDeferredWork(); + }); } // Called from the run loop. @@ -498,7 +508,9 @@ explicit MessagePumpScopedAutoreleasePool(MessagePumpCFRunLoopBase* pump) : // to sleep or exiting. It must be called before decrementing the // value so that the value still corresponds to the level of the exiting // loop. - self->MaybeScheduleNestingDeferredWork(); + base::mac::CallWithEHFrame(^{ + self->MaybeScheduleNestingDeferredWork(); + }); --self->nesting_level_; break; @@ -506,7 +518,9 @@ explicit MessagePumpScopedAutoreleasePool(MessagePumpCFRunLoopBase* pump) : break; } - self->EnterExitRunLoop(activity); + base::mac::CallWithEHFrame(^{ + self->EnterExitRunLoop(activity); + }); } // Called by MessagePumpCFRunLoopBase::EnterExitRunLoop. The default diff --git a/base/metrics/field_trial_unittest.cc b/base/metrics/field_trial_unittest.cc index f1a1042585254..ed84d865d5ef0 100644 --- a/base/metrics/field_trial_unittest.cc +++ b/base/metrics/field_trial_unittest.cc @@ -1021,9 +1021,9 @@ TEST_F(FieldTrialTest, FloatBoundariesGiveEqualGroupSizes) { scoped_refptr trial( new base::FieldTrial("test", kBucketCount, "default", entropy)); for (int j = 0; j < kBucketCount; ++j) - trial->AppendGroup(base::StringPrintf("%d", j), 1); + trial->AppendGroup(base::IntToString(j), 1); - EXPECT_EQ(base::StringPrintf("%d", i), trial->group_name()); + EXPECT_EQ(base::IntToString(i), trial->group_name()); } } diff --git a/base/metrics/histogram.cc b/base/metrics/histogram.cc index 15504205e87e8..7ff1b16184f10 100644 --- a/base/metrics/histogram.cc +++ b/base/metrics/histogram.cc @@ -17,6 +17,7 @@ #include "base/compiler_specific.h" #include "base/debug/alias.h" #include "base/logging.h" +#include "base/metrics/histogram_macros.h" #include "base/metrics/sample_vector.h" #include "base/metrics/statistics_recorder.h" #include "base/pickle.h" @@ -130,6 +131,23 @@ HistogramBase* Histogram::FactoryTimeGet(const std::string& name, flags); } +HistogramBase* Histogram::FactoryGet(const char* name, + Sample minimum, + Sample maximum, + size_t bucket_count, + int32 flags) { + return FactoryGet(std::string(name), minimum, maximum, bucket_count, flags); +} + +HistogramBase* Histogram::FactoryTimeGet(const char* name, + TimeDelta minimum, + TimeDelta maximum, + size_t bucket_count, + int32 flags) { + return FactoryTimeGet(std::string(name), minimum, maximum, bucket_count, + flags); +} + // Calculate what range of values are held in each bucket. // We have to be careful that we don't pick a ratio between starting points in // consecutive buckets that is sooo small, that the integer bounds are the same @@ -262,6 +280,8 @@ void Histogram::Add(int value) { if (value < 0) value = 0; samples_->Accumulate(value, 1); + + FindAndRunCallback(value); } scoped_ptr Histogram::SnapshotSamples() const { @@ -531,6 +551,23 @@ HistogramBase* LinearHistogram::FactoryTimeGet(const std::string& name, flags); } +HistogramBase* LinearHistogram::FactoryGet(const char* name, + Sample minimum, + Sample maximum, + size_t bucket_count, + int32 flags) { + return FactoryGet(std::string(name), minimum, maximum, bucket_count, flags); +} + +HistogramBase* LinearHistogram::FactoryTimeGet(const char* name, + TimeDelta minimum, + TimeDelta maximum, + size_t bucket_count, + int32 flags) { + return FactoryTimeGet(std::string(name), minimum, maximum, bucket_count, + flags); +} + HistogramBase* LinearHistogram::FactoryGetWithRangeDescription( const std::string& name, Sample minimum, @@ -676,6 +713,10 @@ HistogramBase* BooleanHistogram::FactoryGet(const std::string& name, return histogram; } +HistogramBase* BooleanHistogram::FactoryGet(const char* name, int32 flags) { + return FactoryGet(std::string(name), flags); +} + HistogramType BooleanHistogram::GetHistogramType() const { return BOOLEAN_HISTOGRAM; } @@ -736,6 +777,13 @@ HistogramBase* CustomHistogram::FactoryGet( return histogram; } +HistogramBase* CustomHistogram::FactoryGet( + const char* name, + const std::vector& custom_ranges, + int32 flags) { + return FactoryGet(std::string(name), custom_ranges, flags); +} + HistogramType CustomHistogram::GetHistogramType() const { return CUSTOM_HISTOGRAM; } diff --git a/base/metrics/histogram.h b/base/metrics/histogram.h index c13f05e17904c..58bc0297aba45 100644 --- a/base/metrics/histogram.h +++ b/base/metrics/histogram.h @@ -121,6 +121,20 @@ class BASE_EXPORT Histogram : public HistogramBase { size_t bucket_count, int32 flags); + // Overloads of the above two functions that take a const char* |name| param, + // to avoid code bloat from the std::string constructor being inlined into + // call sites. + static HistogramBase* FactoryGet(const char* name, + Sample minimum, + Sample maximum, + size_t bucket_count, + int32 flags); + static HistogramBase* FactoryTimeGet(const char* name, + base::TimeDelta minimum, + base::TimeDelta maximum, + size_t bucket_count, + int32 flags); + static void InitializeBucketRanges(Sample minimum, Sample maximum, BucketRanges* ranges); @@ -277,6 +291,20 @@ class BASE_EXPORT LinearHistogram : public Histogram { size_t bucket_count, int32 flags); + // Overloads of the above two functions that take a const char* |name| param, + // to avoid code bloat from the std::string constructor being inlined into + // call sites. + static HistogramBase* FactoryGet(const char* name, + Sample minimum, + Sample maximum, + size_t bucket_count, + int32 flags); + static HistogramBase* FactoryTimeGet(const char* name, + TimeDelta minimum, + TimeDelta maximum, + size_t bucket_count, + int32 flags); + struct DescriptionPair { Sample sample; const char* description; // Null means end of a list of pairs. @@ -339,6 +367,11 @@ class BASE_EXPORT BooleanHistogram : public LinearHistogram { public: static HistogramBase* FactoryGet(const std::string& name, int32 flags); + // Overload of the above function that takes a const char* |name| param, + // to avoid code bloat from the std::string constructor being inlined into + // call sites. + static HistogramBase* FactoryGet(const char* name, int32 flags); + HistogramType GetHistogramType() const override; private: @@ -364,6 +397,13 @@ class BASE_EXPORT CustomHistogram : public Histogram { const std::vector& custom_ranges, int32 flags); + // Overload of the above function that takes a const char* |name| param, + // to avoid code bloat from the std::string constructor being inlined into + // call sites. + static HistogramBase* FactoryGet(const char* name, + const std::vector& custom_ranges, + int32 flags); + // Overridden from Histogram: HistogramType GetHistogramType() const override; diff --git a/base/metrics/histogram_base.cc b/base/metrics/histogram_base.cc index de34c79d4b4bf..6b3f69c2c047a 100644 --- a/base/metrics/histogram_base.cc +++ b/base/metrics/histogram_base.cc @@ -12,6 +12,7 @@ #include "base/metrics/histogram.h" #include "base/metrics/histogram_samples.h" #include "base/metrics/sparse_histogram.h" +#include "base/metrics/statistics_recorder.h" #include "base/pickle.h" #include "base/process/process_handle.h" #include "base/strings/stringprintf.h" @@ -117,6 +118,16 @@ void HistogramBase::WriteJSON(std::string* output) const { serializer.Serialize(root); } +void HistogramBase::FindAndRunCallback(HistogramBase::Sample sample) const { + if ((flags_ & kCallbackExists) == 0) + return; + + StatisticsRecorder::OnSampleCallback cb = + StatisticsRecorder::FindCallback(histogram_name()); + if (!cb.is_null()) + cb.Run(sample); +} + void HistogramBase::WriteAsciiBucketGraph(double current_size, double max_size, std::string* output) const { diff --git a/base/metrics/histogram_base.h b/base/metrics/histogram_base.h index 006395b1f2939..1bc1f6eb6fe78 100644 --- a/base/metrics/histogram_base.h +++ b/base/metrics/histogram_base.h @@ -31,7 +31,7 @@ class PickleIterator; // processes into the browser. If you create another class that inherits from // HistogramBase, add new histogram types and names below. -enum BASE_EXPORT HistogramType { +enum HistogramType { HISTOGRAM, LINEAR_HISTOGRAM, BOOLEAN_HISTOGRAM, @@ -74,6 +74,12 @@ class BASE_EXPORT HistogramBase { // the source histogram!). kIPCSerializationSourceFlag = 0x10, + // Indicates that a callback exists for when a new sample is recorded on + // this histogram. We store this as a flag with the histogram since + // histograms can be in performance critical code, and this allows us + // to shortcut looking up the callback if it doesn't exist. + kCallbackExists = 0x20, + // Only for Histogram and its sub classes: fancy bucket-naming support. kHexRangePrintingFlag = 0x8000, }; @@ -92,7 +98,7 @@ class BASE_EXPORT HistogramBase { explicit HistogramBase(const std::string& name); virtual ~HistogramBase(); - std::string histogram_name() const { return histogram_name_; } + const std::string& histogram_name() const { return histogram_name_; } // Comapres |name| to the histogram name and triggers a DCHECK if they do not // match. This is a helper function used by histogram macros, which results in @@ -172,6 +178,10 @@ class BASE_EXPORT HistogramBase { double scaled_sum, std::string* output) const; + // Retrieves the callback for this histogram, if one exists, and runs it + // passing |sample| as the parameter. + void FindAndRunCallback(Sample sample) const; + private: const std::string histogram_name_; int32_t flags_; diff --git a/base/metrics/histogram_macros.h b/base/metrics/histogram_macros.h index 2aee1a5de440c..988e942caf697 100644 --- a/base/metrics/histogram_macros.h +++ b/base/metrics/histogram_macros.h @@ -189,6 +189,9 @@ #define UMA_HISTOGRAM_COUNTS_100(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \ name, sample, 1, 100, 50) +#define UMA_HISTOGRAM_COUNTS_1000(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \ + name, sample, 1, 1000, 50) + #define UMA_HISTOGRAM_COUNTS_10000(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \ name, sample, 1, 10000, 50) diff --git a/base/metrics/histogram_snapshot_manager_unittest.cc b/base/metrics/histogram_snapshot_manager_unittest.cc index 3a1fd4044b229..e9e7398bca9fa 100644 --- a/base/metrics/histogram_snapshot_manager_unittest.cc +++ b/base/metrics/histogram_snapshot_manager_unittest.cc @@ -7,8 +7,8 @@ #include #include -#include "base/metrics/histogram.h" #include "base/metrics/histogram_delta_serialization.h" +#include "base/metrics/histogram_macros.h" #include "base/metrics/statistics_recorder.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/base/metrics/histogram_unittest.cc b/base/metrics/histogram_unittest.cc index 2e3a1ee013d60..f189267f3587a 100644 --- a/base/metrics/histogram_unittest.cc +++ b/base/metrics/histogram_unittest.cc @@ -11,6 +11,7 @@ #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "base/metrics/bucket_ranges.h" +#include "base/metrics/histogram_macros.h" #include "base/metrics/sample_vector.h" #include "base/metrics/statistics_recorder.h" #include "base/pickle.h" diff --git a/base/metrics/sparse_histogram.cc b/base/metrics/sparse_histogram.cc index e5cdb43c04fea..a853dce3505f4 100644 --- a/base/metrics/sparse_histogram.cc +++ b/base/metrics/sparse_histogram.cc @@ -46,8 +46,12 @@ bool SparseHistogram::HasConstructionArguments( } void SparseHistogram::Add(Sample value) { - base::AutoLock auto_lock(lock_); - samples_.Accumulate(value, 1); + { + base::AutoLock auto_lock(lock_); + samples_.Accumulate(value, 1); + } + + FindAndRunCallback(value); } scoped_ptr SparseHistogram::SnapshotSamples() const { diff --git a/base/metrics/statistics_recorder.cc b/base/metrics/statistics_recorder.cc index 85408e1fa496d..87ffa3dbcd04e 100644 --- a/base/metrics/statistics_recorder.cc +++ b/base/metrics/statistics_recorder.cc @@ -10,6 +10,7 @@ #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "base/metrics/histogram.h" +#include "base/stl_util.h" #include "base/strings/stringprintf.h" #include "base/synchronization/lock.h" #include "base/values.h" @@ -57,10 +58,19 @@ HistogramBase* StatisticsRecorder::RegisterOrDeleteDuplicate( histogram_to_return = histogram; } else { const std::string& name = histogram->histogram_name(); - HistogramMap::iterator it = histograms_->find(name); + HistogramMap::iterator it = histograms_->find(HistogramNameRef(name)); if (histograms_->end() == it) { - (*histograms_)[name] = histogram; + (*histograms_)[HistogramNameRef(name)] = histogram; ANNOTATE_LEAKING_OBJECT_PTR(histogram); // see crbug.com/79322 + // If there are callbacks for this histogram, we set the kCallbackExists + // flag. + auto callback_iterator = callbacks_->find(name); + if (callback_iterator != callbacks_->end()) { + if (!callback_iterator->second.is_null()) + histogram->SetFlags(HistogramBase::kCallbackExists); + else + histogram->ClearFlags(HistogramBase::kCallbackExists); + } histogram_to_return = histogram; } else if (histogram == it->second) { // The histogram was registered before. @@ -190,7 +200,7 @@ void StatisticsRecorder::GetHistograms(Histograms* output) { return; for (const auto& entry : *histograms_) { - DCHECK_EQ(entry.first, entry.second->histogram_name()); + DCHECK_EQ(entry.first.name_, entry.second->histogram_name()); output->push_back(entry.second); } } @@ -219,12 +229,64 @@ HistogramBase* StatisticsRecorder::FindHistogram(const std::string& name) { if (histograms_ == NULL) return NULL; - HistogramMap::iterator it = histograms_->find(name); + HistogramMap::iterator it = histograms_->find(HistogramNameRef(name)); if (histograms_->end() == it) return NULL; return it->second; } +// static +bool StatisticsRecorder::SetCallback( + const std::string& name, + const StatisticsRecorder::OnSampleCallback& cb) { + DCHECK(!cb.is_null()); + if (lock_ == NULL) + return false; + base::AutoLock auto_lock(*lock_); + if (histograms_ == NULL) + return false; + + if (ContainsKey(*callbacks_, name)) + return false; + callbacks_->insert(std::make_pair(name, cb)); + + auto histogram_iterator = histograms_->find(HistogramNameRef(name)); + if (histogram_iterator != histograms_->end()) + histogram_iterator->second->SetFlags(HistogramBase::kCallbackExists); + + return true; +} + +// static +void StatisticsRecorder::ClearCallback(const std::string& name) { + if (lock_ == NULL) + return; + base::AutoLock auto_lock(*lock_); + if (histograms_ == NULL) + return; + + callbacks_->erase(name); + + // We also clear the flag from the histogram (if it exists). + auto histogram_iterator = histograms_->find(HistogramNameRef(name)); + if (histogram_iterator != histograms_->end()) + histogram_iterator->second->ClearFlags(HistogramBase::kCallbackExists); +} + +// static +StatisticsRecorder::OnSampleCallback StatisticsRecorder::FindCallback( + const std::string& name) { + if (lock_ == NULL) + return OnSampleCallback(); + base::AutoLock auto_lock(*lock_); + if (histograms_ == NULL) + return OnSampleCallback(); + + auto callback_iterator = callbacks_->find(name); + return callback_iterator != callbacks_->end() ? callback_iterator->second + : OnSampleCallback(); +} + // private static void StatisticsRecorder::GetSnapshot(const std::string& query, Histograms* snapshot) { @@ -235,7 +297,7 @@ void StatisticsRecorder::GetSnapshot(const std::string& query, return; for (const auto& entry : *histograms_) { - if (entry.first.find(query) != std::string::npos) + if (entry.first.name_.find(query) != std::string::npos) snapshot->push_back(entry.second); } } @@ -256,6 +318,7 @@ StatisticsRecorder::StatisticsRecorder() { } base::AutoLock auto_lock(*lock_); histograms_ = new HistogramMap; + callbacks_ = new CallbackMap; ranges_ = new RangesMap; if (VLOG_IS_ON(1)) @@ -274,14 +337,17 @@ StatisticsRecorder::~StatisticsRecorder() { // Clean up. scoped_ptr histograms_deleter; + scoped_ptr callbacks_deleter; scoped_ptr ranges_deleter; // We don't delete lock_ on purpose to avoid having to properly protect // against it going away after we checked for NULL in the static methods. { base::AutoLock auto_lock(*lock_); histograms_deleter.reset(histograms_); + callbacks_deleter.reset(callbacks_); ranges_deleter.reset(ranges_); histograms_ = NULL; + callbacks_ = NULL; ranges_ = NULL; } // We are going to leak the histograms and the ranges. @@ -291,6 +357,8 @@ StatisticsRecorder::~StatisticsRecorder() { // static StatisticsRecorder::HistogramMap* StatisticsRecorder::histograms_ = NULL; // static +StatisticsRecorder::CallbackMap* StatisticsRecorder::callbacks_ = NULL; +// static StatisticsRecorder::RangesMap* StatisticsRecorder::ranges_ = NULL; // static base::Lock* StatisticsRecorder::lock_ = NULL; diff --git a/base/metrics/statistics_recorder.h b/base/metrics/statistics_recorder.h index b5230575963e0..0e5168f413700 100644 --- a/base/metrics/statistics_recorder.h +++ b/base/metrics/statistics_recorder.h @@ -17,13 +17,14 @@ #include "base/base_export.h" #include "base/basictypes.h" +#include "base/callback.h" #include "base/gtest_prod_util.h" #include "base/lazy_instance.h" +#include "base/metrics/histogram_base.h" namespace base { class BucketRanges; -class HistogramBase; class Lock; class BASE_EXPORT StatisticsRecorder { @@ -75,9 +76,47 @@ class BASE_EXPORT StatisticsRecorder { // histograms). static void GetSnapshot(const std::string& query, Histograms* snapshot); + typedef base::Callback OnSampleCallback; + + // SetCallback sets the callback to notify when a new sample is recorded on + // the histogram referred to by |histogram_name|. The call to this method can + // be be done before or after the histogram is created. This method is thread + // safe. The return value is whether or not the callback was successfully set. + static bool SetCallback(const std::string& histogram_name, + const OnSampleCallback& callback); + + // ClearCallback clears any callback set on the histogram referred to by + // |histogram_name|. This method is thread safe. + static void ClearCallback(const std::string& histogram_name); + + // FindCallback retrieves the callback for the histogram referred to by + // |histogram_name|, or a null callback if no callback exists for this + // histogram. This method is thread safe. + static OnSampleCallback FindCallback(const std::string& histogram_name); + private: + // HistogramNameRef holds a weak const ref to the name field of the associated + // Histogram object, allowing re-use of the underlying string storage for the + // map keys. The wrapper is required as using "const std::string&" as the key + // results in compile errors. + struct HistogramNameRef { + explicit HistogramNameRef(const std::string& name) : name_(name) {}; + + // Operator < is necessary to use this type as a std::map key. + bool operator<(const HistogramNameRef& other) const { + return name_ < other.name_; + } + + // Weak, owned by the associated Histogram object. + const std::string& name_; + }; + // We keep all registered histograms in a map, from name to histogram. - typedef std::map HistogramMap; + typedef std::map HistogramMap; + + // We keep a map of callbacks to histograms, so that as histograms are + // created, we can set the callback properly. + typedef std::map CallbackMap; // We keep all |bucket_ranges_| in a map, from checksum to a list of // |bucket_ranges_|. Checksum is calculated from the |ranges_| in @@ -103,6 +142,7 @@ class BASE_EXPORT StatisticsRecorder { static void DumpHistogramsToVlog(void* instance); static HistogramMap* histograms_; + static CallbackMap* callbacks_; static RangesMap* ranges_; // Lock protects access to above maps. diff --git a/base/metrics/statistics_recorder_unittest.cc b/base/metrics/statistics_recorder_unittest.cc index d26df6901bad5..b18c580389386 100644 --- a/base/metrics/statistics_recorder_unittest.cc +++ b/base/metrics/statistics_recorder_unittest.cc @@ -4,9 +4,11 @@ #include +#include "base/bind.h" #include "base/json/json_reader.h" #include "base/memory/scoped_ptr.h" -#include "base/metrics/histogram.h" +#include "base/metrics/histogram_macros.h" +#include "base/metrics/sparse_histogram.h" #include "base/metrics/statistics_recorder.h" #include "base/values.h" #include "testing/gtest/include/gtest/gtest.h" @@ -312,4 +314,178 @@ TEST_F(StatisticsRecorderTest, ToJSON) { EXPECT_TRUE(json.empty()); } +namespace { + +// CallbackCheckWrapper is simply a convenient way to check and store that +// a callback was actually run. +struct CallbackCheckWrapper { + CallbackCheckWrapper() : called(false), last_histogram_value(0) {} + + void OnHistogramChanged(base::HistogramBase::Sample histogram_value) { + called = true; + last_histogram_value = histogram_value; + } + + bool called; + base::HistogramBase::Sample last_histogram_value; +}; + +} // namespace + +// Check that you can't overwrite the callback with another. +TEST_F(StatisticsRecorderTest, SetCallbackFailsWithoutHistogramTest) { + CallbackCheckWrapper callback_wrapper; + + bool result = base::StatisticsRecorder::SetCallback( + "TestHistogram", base::Bind(&CallbackCheckWrapper::OnHistogramChanged, + base::Unretained(&callback_wrapper))); + EXPECT_TRUE(result); + + result = base::StatisticsRecorder::SetCallback( + "TestHistogram", base::Bind(&CallbackCheckWrapper::OnHistogramChanged, + base::Unretained(&callback_wrapper))); + EXPECT_FALSE(result); +} + +// Check that you can't overwrite the callback with another. +TEST_F(StatisticsRecorderTest, SetCallbackFailsWithHistogramTest) { + HistogramBase* histogram = Histogram::FactoryGet("TestHistogram", 1, 1000, 10, + HistogramBase::kNoFlags); + EXPECT_TRUE(histogram); + + CallbackCheckWrapper callback_wrapper; + + bool result = base::StatisticsRecorder::SetCallback( + "TestHistogram", base::Bind(&CallbackCheckWrapper::OnHistogramChanged, + base::Unretained(&callback_wrapper))); + EXPECT_TRUE(result); + EXPECT_EQ(histogram->flags() & base::HistogramBase::kCallbackExists, + base::HistogramBase::kCallbackExists); + + result = base::StatisticsRecorder::SetCallback( + "TestHistogram", base::Bind(&CallbackCheckWrapper::OnHistogramChanged, + base::Unretained(&callback_wrapper))); + EXPECT_FALSE(result); + EXPECT_EQ(histogram->flags() & base::HistogramBase::kCallbackExists, + base::HistogramBase::kCallbackExists); + + histogram->Add(1); + + EXPECT_TRUE(callback_wrapper.called); +} + +// Check that you can't overwrite the callback with another. +TEST_F(StatisticsRecorderTest, ClearCallbackSuceedsWithHistogramTest) { + HistogramBase* histogram = Histogram::FactoryGet("TestHistogram", 1, 1000, 10, + HistogramBase::kNoFlags); + EXPECT_TRUE(histogram); + + CallbackCheckWrapper callback_wrapper; + + bool result = base::StatisticsRecorder::SetCallback( + "TestHistogram", base::Bind(&CallbackCheckWrapper::OnHistogramChanged, + base::Unretained(&callback_wrapper))); + EXPECT_TRUE(result); + EXPECT_EQ(histogram->flags() & base::HistogramBase::kCallbackExists, + base::HistogramBase::kCallbackExists); + + base::StatisticsRecorder::ClearCallback("TestHistogram"); + EXPECT_EQ(histogram->flags() & base::HistogramBase::kCallbackExists, 0); + + histogram->Add(1); + + EXPECT_FALSE(callback_wrapper.called); +} + +// Check that callback is used. +TEST_F(StatisticsRecorderTest, CallbackUsedTest) { + { + HistogramBase* histogram = Histogram::FactoryGet( + "TestHistogram", 1, 1000, 10, HistogramBase::kNoFlags); + EXPECT_TRUE(histogram); + + CallbackCheckWrapper callback_wrapper; + + base::StatisticsRecorder::SetCallback( + "TestHistogram", base::Bind(&CallbackCheckWrapper::OnHistogramChanged, + base::Unretained(&callback_wrapper))); + + histogram->Add(1); + + EXPECT_TRUE(callback_wrapper.called); + EXPECT_EQ(callback_wrapper.last_histogram_value, 1); + } + + { + HistogramBase* linear_histogram = LinearHistogram::FactoryGet( + "TestLinearHistogram", 1, 1000, 10, HistogramBase::kNoFlags); + + CallbackCheckWrapper callback_wrapper; + + base::StatisticsRecorder::SetCallback( + "TestLinearHistogram", + base::Bind(&CallbackCheckWrapper::OnHistogramChanged, + base::Unretained(&callback_wrapper))); + + linear_histogram->Add(1); + + EXPECT_TRUE(callback_wrapper.called); + EXPECT_EQ(callback_wrapper.last_histogram_value, 1); + } + + { + std::vector custom_ranges; + custom_ranges.push_back(1); + custom_ranges.push_back(5); + HistogramBase* custom_histogram = CustomHistogram::FactoryGet( + "TestCustomHistogram", custom_ranges, HistogramBase::kNoFlags); + + CallbackCheckWrapper callback_wrapper; + + base::StatisticsRecorder::SetCallback( + "TestCustomHistogram", + base::Bind(&CallbackCheckWrapper::OnHistogramChanged, + base::Unretained(&callback_wrapper))); + + custom_histogram->Add(1); + + EXPECT_TRUE(callback_wrapper.called); + EXPECT_EQ(callback_wrapper.last_histogram_value, 1); + } + + { + HistogramBase* custom_histogram = SparseHistogram::FactoryGet( + "TestSparseHistogram", HistogramBase::kNoFlags); + + CallbackCheckWrapper callback_wrapper; + + base::StatisticsRecorder::SetCallback( + "TestSparseHistogram", + base::Bind(&CallbackCheckWrapper::OnHistogramChanged, + base::Unretained(&callback_wrapper))); + + custom_histogram->Add(1); + + EXPECT_TRUE(callback_wrapper.called); + EXPECT_EQ(callback_wrapper.last_histogram_value, 1); + } +} + +// Check that setting a callback before the histogram exists works. +TEST_F(StatisticsRecorderTest, CallbackUsedBeforeHistogramCreatedTest) { + CallbackCheckWrapper callback_wrapper; + + base::StatisticsRecorder::SetCallback( + "TestHistogram", base::Bind(&CallbackCheckWrapper::OnHistogramChanged, + base::Unretained(&callback_wrapper))); + + HistogramBase* histogram = Histogram::FactoryGet("TestHistogram", 1, 1000, 10, + HistogramBase::kNoFlags); + EXPECT_TRUE(histogram); + histogram->Add(1); + + EXPECT_TRUE(callback_wrapper.called); + EXPECT_EQ(callback_wrapper.last_histogram_value, 1); +} + } // namespace base diff --git a/base/pickle.cc b/base/pickle.cc index 09d42c9deb016..cf4a865d35c33 100644 --- a/base/pickle.cc +++ b/base/pickle.cc @@ -317,13 +317,17 @@ void Pickle::Reserve(size_t length) { } void Pickle::Resize(size_t new_capacity) { - new_capacity = AlignInt(new_capacity, kPayloadUnit); - CHECK_NE(capacity_after_header_, kCapacityReadOnly); - void* p = realloc(header_, header_size_ + new_capacity); + capacity_after_header_ = AlignInt(new_capacity, kPayloadUnit); + void* p = realloc(header_, GetTotalAllocatedSize()); CHECK(p); header_ = reinterpret_cast(p); - capacity_after_header_ = new_capacity; +} + +size_t Pickle::GetTotalAllocatedSize() const { + if (capacity_after_header_ == kCapacityReadOnly) + return 0; + return header_size_ + capacity_after_header_; } // static diff --git a/base/pickle.h b/base/pickle.h index 7a6b0c86fb4f8..c9fef715a7b6e 100644 --- a/base/pickle.h +++ b/base/pickle.h @@ -153,12 +153,18 @@ class BASE_EXPORT Pickle { // Performs a deep copy. Pickle& operator=(const Pickle& other); - // Returns the size of the Pickle's data. + // Returns the number of bytes written in the Pickle, including the header. size_t size() const { return header_size_ + header_->payload_size; } // Returns the data for this Pickle. const void* data() const { return header_; } + // Returns the effective memory capacity of this Pickle, that is, the total + // number of bytes currently dynamically allocated or 0 in the case of a + // read-only Pickle. This should be used only for diagnostic / profiling + // purposes. + size_t GetTotalAllocatedSize() const; + // Methods for adding to the payload of the Pickle. These values are // appended to the end of the Pickle's payload. When reading values from a // Pickle, it is important to read them in the order in which they were added diff --git a/base/port.h b/base/port.h deleted file mode 100644 index 56c4d4e109f23..0000000000000 --- a/base/port.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_PORT_H_ -#define BASE_PORT_H_ - -#include -#include "build/build_config.h" - -// DEPRECATED: Use ...LL and ...ULL suffixes. -// TODO(viettrungluu): Delete these. These are only here until |GG_(U)INT64_C| -// are deleted (some other header files (re)define |GG_(U)INT64_C|, so our -// definitions of them must exactly match theirs). -#ifdef COMPILER_MSVC -#define GG_LONGLONG(x) x##I64 -#define GG_ULONGLONG(x) x##UI64 -#else -#define GG_LONGLONG(x) x##LL -#define GG_ULONGLONG(x) x##ULL -#endif - -// DEPRECATED: In Chromium, we force-define __STDC_CONSTANT_MACROS, so you can -// just use the regular (U)INTn_C macros from . -// TODO(viettrungluu): Remove the remaining GG_(U)INTn_C macros. -#define GG_INT64_C(x) GG_LONGLONG(x) -#define GG_UINT64_C(x) GG_ULONGLONG(x) - -// Define an OS-neutral wrapper for shared library entry points -#if defined(OS_WIN) -#define API_CALL __stdcall -#else -#define API_CALL -#endif - -#endif // BASE_PORT_H_ diff --git a/base/prefs/default_pref_store.cc b/base/prefs/default_pref_store.cc index 92abba14c5ae3..efb4a754f4599 100644 --- a/base/prefs/default_pref_store.cc +++ b/base/prefs/default_pref_store.cc @@ -29,7 +29,7 @@ bool DefaultPrefStore::HasObservers() const { void DefaultPrefStore::SetDefaultValue(const std::string& key, scoped_ptr value) { DCHECK(!GetValue(key, NULL)); - prefs_.SetValue(key, value.release()); + prefs_.SetValue(key, value.Pass()); } void DefaultPrefStore::ReplaceDefaultValue(const std::string& key, @@ -37,7 +37,7 @@ void DefaultPrefStore::ReplaceDefaultValue(const std::string& key, const Value* old_value = NULL; GetValue(key, &old_value); bool notify = !old_value->Equals(value.get()); - prefs_.SetValue(key, value.release()); + prefs_.SetValue(key, value.Pass()); if (notify) FOR_EACH_OBSERVER(Observer, observers_, OnPrefValueChanged(key)); } diff --git a/base/prefs/json_pref_store.cc b/base/prefs/json_pref_store.cc index c2ff42593fad0..354fd948681b9 100644 --- a/base/prefs/json_pref_store.cc +++ b/base/prefs/json_pref_store.cc @@ -221,31 +221,29 @@ bool JsonPrefStore::GetMutableValue(const std::string& key, } void JsonPrefStore::SetValue(const std::string& key, - base::Value* value, + scoped_ptr value, uint32 flags) { DCHECK(CalledOnValidThread()); DCHECK(value); - scoped_ptr new_value(value); base::Value* old_value = NULL; prefs_->Get(key, &old_value); if (!old_value || !value->Equals(old_value)) { - prefs_->Set(key, new_value.Pass()); + prefs_->Set(key, value.Pass()); ReportValueChanged(key, flags); } } void JsonPrefStore::SetValueSilently(const std::string& key, - base::Value* value, + scoped_ptr value, uint32 flags) { DCHECK(CalledOnValidThread()); DCHECK(value); - scoped_ptr new_value(value); base::Value* old_value = NULL; prefs_->Get(key, &old_value); if (!old_value || !value->Equals(old_value)) { - prefs_->Set(key, new_value.Pass()); + prefs_->Set(key, value.Pass()); ScheduleWrite(flags); } } diff --git a/base/prefs/json_pref_store.h b/base/prefs/json_pref_store.h index d6943e09c64b8..0be7702481ed2 100644 --- a/base/prefs/json_pref_store.h +++ b/base/prefs/json_pref_store.h @@ -84,10 +84,10 @@ class BASE_PREFS_EXPORT JsonPrefStore // PersistentPrefStore overrides: bool GetMutableValue(const std::string& key, base::Value** result) override; void SetValue(const std::string& key, - base::Value* value, + scoped_ptr value, uint32 flags) override; void SetValueSilently(const std::string& key, - base::Value* value, + scoped_ptr value, uint32 flags) override; void RemoveValue(const std::string& key, uint32 flags) override; bool ReadOnly() const override; diff --git a/base/prefs/json_pref_store_unittest.cc b/base/prefs/json_pref_store_unittest.cc index 4c7bc1ff4603c..5195a18c436d8 100644 --- a/base/prefs/json_pref_store_unittest.cc +++ b/base/prefs/json_pref_store_unittest.cc @@ -192,7 +192,8 @@ void RunBasicJsonPrefStoreTest(JsonPrefStore* pref_store, EXPECT_EQ(base::FilePath::StringType(FILE_PATH_LITERAL("/usr/local/")), path); base::FilePath some_path(FILE_PATH_LITERAL("/usr/sbin/")); - pref_store->SetValue(kSomeDirectory, new StringValue(some_path.value()), + pref_store->SetValue(kSomeDirectory, + make_scoped_ptr(new StringValue(some_path.value())), WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); EXPECT_TRUE(pref_store->GetValue(kSomeDirectory, &actual)); EXPECT_TRUE(actual->GetAsString(&path)); @@ -204,7 +205,8 @@ void RunBasicJsonPrefStoreTest(JsonPrefStore* pref_store, EXPECT_TRUE(actual->GetAsBoolean(&boolean)); EXPECT_TRUE(boolean); - pref_store->SetValue(kNewWindowsInTabs, new FundamentalValue(false), + pref_store->SetValue(kNewWindowsInTabs, + make_scoped_ptr(new FundamentalValue(false)), WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); EXPECT_TRUE(pref_store->GetValue(kNewWindowsInTabs, &actual)); EXPECT_TRUE(actual->GetAsBoolean(&boolean)); @@ -214,15 +216,16 @@ void RunBasicJsonPrefStoreTest(JsonPrefStore* pref_store, int integer = 0; EXPECT_TRUE(actual->GetAsInteger(&integer)); EXPECT_EQ(20, integer); - pref_store->SetValue(kMaxTabs, new FundamentalValue(10), + pref_store->SetValue(kMaxTabs, make_scoped_ptr(new FundamentalValue(10)), WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); EXPECT_TRUE(pref_store->GetValue(kMaxTabs, &actual)); EXPECT_TRUE(actual->GetAsInteger(&integer)); EXPECT_EQ(10, integer); - pref_store->SetValue(kLongIntPref, - new StringValue(base::Int64ToString(214748364842LL)), - WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); + pref_store->SetValue( + kLongIntPref, + make_scoped_ptr(new StringValue(base::Int64ToString(214748364842LL))), + WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); EXPECT_TRUE(pref_store->GetValue(kLongIntPref, &actual)); EXPECT_TRUE(actual->GetAsString(&string_value)); int64 value; @@ -312,9 +315,9 @@ TEST_F(JsonPrefStoreTest, PreserveEmptyValues) { pref_file, message_loop_.task_runner(), scoped_ptr()); // Set some keys with empty values. - pref_store->SetValue("list", new base::ListValue, + pref_store->SetValue("list", make_scoped_ptr(new base::ListValue), WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); - pref_store->SetValue("dict", new base::DictionaryValue, + pref_store->SetValue("dict", make_scoped_ptr(new base::DictionaryValue), WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); // Write to file. @@ -343,9 +346,9 @@ TEST_F(JsonPrefStoreTest, RemoveClearsEmptyParent) { scoped_refptr pref_store = new JsonPrefStore( pref_file, message_loop_.task_runner(), scoped_ptr()); - base::DictionaryValue* dict = new base::DictionaryValue; + scoped_ptr dict(new base::DictionaryValue); dict->SetString("key", "value"); - pref_store->SetValue("dict", dict, + pref_store->SetValue("dict", dict.Pass(), WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); pref_store->RemoveValue("dict.key", @@ -845,7 +848,8 @@ TEST_F(JsonPrefStoreLossyWriteTest, LossyWriteBasic) { // Set a normal pref and check that it gets scheduled to be written. ASSERT_FALSE(file_writer->HasPendingWrite()); - pref_store->SetValue("normal", new base::StringValue("normal"), + pref_store->SetValue("normal", + make_scoped_ptr(new base::StringValue("normal")), WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); ASSERT_TRUE(file_writer->HasPendingWrite()); file_writer->DoScheduledWrite(); @@ -854,14 +858,15 @@ TEST_F(JsonPrefStoreLossyWriteTest, LossyWriteBasic) { // Set a lossy pref and check that it is not scheduled to be written. // SetValue/RemoveValue. - pref_store->SetValue("lossy", new base::StringValue("lossy"), + pref_store->SetValue("lossy", make_scoped_ptr(new base::StringValue("lossy")), WriteablePrefStore::LOSSY_PREF_WRITE_FLAG); ASSERT_FALSE(file_writer->HasPendingWrite()); pref_store->RemoveValue("lossy", WriteablePrefStore::LOSSY_PREF_WRITE_FLAG); ASSERT_FALSE(file_writer->HasPendingWrite()); // SetValueSilently/RemoveValueSilently. - pref_store->SetValueSilently("lossy", new base::StringValue("lossy"), + pref_store->SetValueSilently("lossy", + make_scoped_ptr(new base::StringValue("lossy")), WriteablePrefStore::LOSSY_PREF_WRITE_FLAG); ASSERT_FALSE(file_writer->HasPendingWrite()); pref_store->RemoveValueSilently("lossy", @@ -869,7 +874,7 @@ TEST_F(JsonPrefStoreLossyWriteTest, LossyWriteBasic) { ASSERT_FALSE(file_writer->HasPendingWrite()); // ReportValueChanged. - pref_store->SetValue("lossy", new base::StringValue("lossy"), + pref_store->SetValue("lossy", make_scoped_ptr(new base::StringValue("lossy")), WriteablePrefStore::LOSSY_PREF_WRITE_FLAG); ASSERT_FALSE(file_writer->HasPendingWrite()); pref_store->ReportValueChanged("lossy", @@ -890,12 +895,13 @@ TEST_F(JsonPrefStoreLossyWriteTest, LossyWriteMixedLossyFirst) { // Set a lossy pref and check that it is not scheduled to be written. ASSERT_FALSE(file_writer->HasPendingWrite()); - pref_store->SetValue("lossy", new base::StringValue("lossy"), + pref_store->SetValue("lossy", make_scoped_ptr(new base::StringValue("lossy")), WriteablePrefStore::LOSSY_PREF_WRITE_FLAG); ASSERT_FALSE(file_writer->HasPendingWrite()); // Set a normal pref and check that it is scheduled to be written. - pref_store->SetValue("normal", new base::StringValue("normal"), + pref_store->SetValue("normal", + make_scoped_ptr(new base::StringValue("normal")), WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); ASSERT_TRUE(file_writer->HasPendingWrite()); @@ -912,12 +918,13 @@ TEST_F(JsonPrefStoreLossyWriteTest, LossyWriteMixedLossySecond) { // Set a normal pref and check that it is scheduled to be written. ASSERT_FALSE(file_writer->HasPendingWrite()); - pref_store->SetValue("normal", new base::StringValue("normal"), + pref_store->SetValue("normal", + make_scoped_ptr(new base::StringValue("normal")), WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); ASSERT_TRUE(file_writer->HasPendingWrite()); // Set a lossy pref and check that the write is still scheduled. - pref_store->SetValue("lossy", new base::StringValue("lossy"), + pref_store->SetValue("lossy", make_scoped_ptr(new base::StringValue("lossy")), WriteablePrefStore::LOSSY_PREF_WRITE_FLAG); ASSERT_TRUE(file_writer->HasPendingWrite()); @@ -933,7 +940,7 @@ TEST_F(JsonPrefStoreLossyWriteTest, ScheduleLossyWrite) { ImportantFileWriter* file_writer = GetImportantFileWriter(pref_store); // Set a lossy pref and check that it is not scheduled to be written. - pref_store->SetValue("lossy", new base::StringValue("lossy"), + pref_store->SetValue("lossy", make_scoped_ptr(new base::StringValue("lossy")), WriteablePrefStore::LOSSY_PREF_WRITE_FLAG); ASSERT_FALSE(file_writer->HasPendingWrite()); diff --git a/base/prefs/overlay_user_pref_store.cc b/base/prefs/overlay_user_pref_store.cc index 4c236f10dd0da..d76b537ce6224 100644 --- a/base/prefs/overlay_user_pref_store.cc +++ b/base/prefs/overlay_user_pref_store.cc @@ -58,31 +58,31 @@ bool OverlayUserPrefStore::GetMutableValue(const std::string& key, return false; *result = underlay_value->DeepCopy(); - overlay_.SetValue(key, *result); + overlay_.SetValue(key, make_scoped_ptr(*result)); return true; } void OverlayUserPrefStore::SetValue(const std::string& key, - base::Value* value, + scoped_ptr value, uint32 flags) { if (!ShallBeStoredInOverlay(key)) { - underlay_->SetValue(GetUnderlayKey(key), value, flags); + underlay_->SetValue(GetUnderlayKey(key), value.Pass(), flags); return; } - if (overlay_.SetValue(key, value)) + if (overlay_.SetValue(key, value.Pass())) ReportValueChanged(key, flags); } void OverlayUserPrefStore::SetValueSilently(const std::string& key, - base::Value* value, + scoped_ptr value, uint32 flags) { if (!ShallBeStoredInOverlay(key)) { - underlay_->SetValueSilently(GetUnderlayKey(key), value, flags); + underlay_->SetValueSilently(GetUnderlayKey(key), value.Pass(), flags); return; } - overlay_.SetValue(key, value); + overlay_.SetValue(key, value.Pass()); } void OverlayUserPrefStore::RemoveValue(const std::string& key, uint32 flags) { diff --git a/base/prefs/overlay_user_pref_store.h b/base/prefs/overlay_user_pref_store.h index 885da0813e7db..737b4262f3e10 100644 --- a/base/prefs/overlay_user_pref_store.h +++ b/base/prefs/overlay_user_pref_store.h @@ -40,10 +40,10 @@ class BASE_PREFS_EXPORT OverlayUserPrefStore : public PersistentPrefStore, // Methods of PersistentPrefStore. bool GetMutableValue(const std::string& key, base::Value** result) override; void SetValue(const std::string& key, - base::Value* value, + scoped_ptr value, uint32 flags) override; void SetValueSilently(const std::string& key, - base::Value* value, + scoped_ptr value, uint32 flags) override; void RemoveValue(const std::string& key, uint32 flags) override; bool ReadOnly() const override; diff --git a/base/prefs/overlay_user_pref_store_unittest.cc b/base/prefs/overlay_user_pref_store_unittest.cc index 06b4ec989a690..bf5e6a59c4fe7 100644 --- a/base/prefs/overlay_user_pref_store_unittest.cc +++ b/base/prefs/overlay_user_pref_store_unittest.cc @@ -48,22 +48,22 @@ TEST_F(OverlayUserPrefStoreTest, Observer) { overlay_->AddObserver(&obs); // Check that underlay first value is reported. - underlay_->SetValue(overlay_key, new FundamentalValue(42), + underlay_->SetValue(overlay_key, make_scoped_ptr(new FundamentalValue(42)), WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); obs.VerifyAndResetChangedKey(overlay_key); // Check that underlay overwriting is reported. - underlay_->SetValue(overlay_key, new FundamentalValue(43), + underlay_->SetValue(overlay_key, make_scoped_ptr(new FundamentalValue(43)), WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); obs.VerifyAndResetChangedKey(overlay_key); // Check that overwriting change in overlay is reported. - overlay_->SetValue(overlay_key, new FundamentalValue(44), + overlay_->SetValue(overlay_key, make_scoped_ptr(new FundamentalValue(44)), WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); obs.VerifyAndResetChangedKey(overlay_key); // Check that hidden underlay change is not reported. - underlay_->SetValue(overlay_key, new FundamentalValue(45), + underlay_->SetValue(overlay_key, make_scoped_ptr(new FundamentalValue(45)), WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); EXPECT_TRUE(obs.changed_keys.empty()); @@ -78,16 +78,17 @@ TEST_F(OverlayUserPrefStoreTest, Observer) { obs.VerifyAndResetChangedKey(overlay_key); // Check respecting of silence. - overlay_->SetValueSilently(overlay_key, new FundamentalValue(46), + overlay_->SetValueSilently(overlay_key, + make_scoped_ptr(new FundamentalValue(46)), WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); EXPECT_TRUE(obs.changed_keys.empty()); overlay_->RemoveObserver(&obs); // Check successful unsubscription. - underlay_->SetValue(overlay_key, new FundamentalValue(47), + underlay_->SetValue(overlay_key, make_scoped_ptr(new FundamentalValue(47)), WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); - overlay_->SetValue(overlay_key, new FundamentalValue(48), + overlay_->SetValue(overlay_key, make_scoped_ptr(new FundamentalValue(48)), WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); EXPECT_TRUE(obs.changed_keys.empty()); } @@ -97,7 +98,7 @@ TEST_F(OverlayUserPrefStoreTest, GetAndSet) { EXPECT_FALSE(overlay_->GetValue(overlay_key, &value)); EXPECT_FALSE(underlay_->GetValue(overlay_key, &value)); - underlay_->SetValue(overlay_key, new FundamentalValue(42), + underlay_->SetValue(overlay_key, make_scoped_ptr(new FundamentalValue(42)), WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); // Value shines through: @@ -107,7 +108,7 @@ TEST_F(OverlayUserPrefStoreTest, GetAndSet) { EXPECT_TRUE(underlay_->GetValue(overlay_key, &value)); EXPECT_TRUE(base::FundamentalValue(42).Equals(value)); - overlay_->SetValue(overlay_key, new FundamentalValue(43), + overlay_->SetValue(overlay_key, make_scoped_ptr(new FundamentalValue(43)), WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); EXPECT_TRUE(overlay_->GetValue(overlay_key, &value)); @@ -129,7 +130,7 @@ TEST_F(OverlayUserPrefStoreTest, GetAndSet) { // Check that GetMutableValue does not return the dictionary of the underlay. TEST_F(OverlayUserPrefStoreTest, ModifyDictionaries) { - underlay_->SetValue(overlay_key, new DictionaryValue, + underlay_->SetValue(overlay_key, make_scoped_ptr(new DictionaryValue), WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); Value* modify = NULL; @@ -159,12 +160,12 @@ TEST_F(OverlayUserPrefStoreTest, GlobalPref) { const Value* value = NULL; // Check that underlay first value is reported. - underlay_->SetValue(regular_key, new FundamentalValue(42), + underlay_->SetValue(regular_key, make_scoped_ptr(new FundamentalValue(42)), WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); obs.VerifyAndResetChangedKey(regular_key); // Check that underlay overwriting is reported. - underlay_->SetValue(regular_key, new FundamentalValue(43), + underlay_->SetValue(regular_key, make_scoped_ptr(new FundamentalValue(43)), WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); obs.VerifyAndResetChangedKey(regular_key); @@ -173,7 +174,7 @@ TEST_F(OverlayUserPrefStoreTest, GlobalPref) { EXPECT_TRUE(base::FundamentalValue(43).Equals(value)); // Check that overwriting change in overlay is reported. - overlay_->SetValue(regular_key, new FundamentalValue(44), + overlay_->SetValue(regular_key, make_scoped_ptr(new FundamentalValue(44)), WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); obs.VerifyAndResetChangedKey(regular_key); @@ -193,16 +194,17 @@ TEST_F(OverlayUserPrefStoreTest, GlobalPref) { EXPECT_FALSE(underlay_->GetValue(regular_key, &value)); // Check respecting of silence. - overlay_->SetValueSilently(regular_key, new FundamentalValue(46), + overlay_->SetValueSilently(regular_key, + make_scoped_ptr(new FundamentalValue(46)), WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); EXPECT_TRUE(obs.changed_keys.empty()); overlay_->RemoveObserver(&obs); // Check successful unsubscription. - underlay_->SetValue(regular_key, new FundamentalValue(47), + underlay_->SetValue(regular_key, make_scoped_ptr(new FundamentalValue(47)), WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); - overlay_->SetValue(regular_key, new FundamentalValue(48), + overlay_->SetValue(regular_key, make_scoped_ptr(new FundamentalValue(48)), WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); EXPECT_TRUE(obs.changed_keys.empty()); } @@ -216,12 +218,14 @@ TEST_F(OverlayUserPrefStoreTest, NamesMapping) { // Check that if there is no override in the overlay, changing underlay value // is reported as changing an overlay value. - underlay_->SetValue(mapped_underlay_key, new FundamentalValue(42), + underlay_->SetValue(mapped_underlay_key, + make_scoped_ptr(new FundamentalValue(42)), WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); obs.VerifyAndResetChangedKey(mapped_overlay_key); // Check that underlay overwriting is reported. - underlay_->SetValue(mapped_underlay_key, new FundamentalValue(43), + underlay_->SetValue(mapped_underlay_key, + make_scoped_ptr(new FundamentalValue(43)), WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); obs.VerifyAndResetChangedKey(mapped_overlay_key); @@ -233,7 +237,8 @@ TEST_F(OverlayUserPrefStoreTest, NamesMapping) { EXPECT_TRUE(base::FundamentalValue(43).Equals(value)); // Check that overwriting change in overlay is reported. - overlay_->SetValue(mapped_overlay_key, new FundamentalValue(44), + overlay_->SetValue(mapped_overlay_key, + make_scoped_ptr(new FundamentalValue(44)), WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); obs.VerifyAndResetChangedKey(mapped_overlay_key); @@ -247,7 +252,8 @@ TEST_F(OverlayUserPrefStoreTest, NamesMapping) { EXPECT_TRUE(base::FundamentalValue(43).Equals(value)); // Check that hidden underlay change is not reported. - underlay_->SetValue(mapped_underlay_key, new FundamentalValue(45), + underlay_->SetValue(mapped_underlay_key, + make_scoped_ptr(new FundamentalValue(45)), WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); EXPECT_TRUE(obs.changed_keys.empty()); @@ -266,16 +272,19 @@ TEST_F(OverlayUserPrefStoreTest, NamesMapping) { EXPECT_FALSE(overlay_->GetValue(mapped_underlay_key, &value)); // Check respecting of silence. - overlay_->SetValueSilently(mapped_overlay_key, new FundamentalValue(46), + overlay_->SetValueSilently(mapped_overlay_key, + make_scoped_ptr(new FundamentalValue(46)), WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); EXPECT_TRUE(obs.changed_keys.empty()); overlay_->RemoveObserver(&obs); // Check successful unsubscription. - underlay_->SetValue(mapped_underlay_key, new FundamentalValue(47), + underlay_->SetValue(mapped_underlay_key, + make_scoped_ptr(new FundamentalValue(47)), WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); - overlay_->SetValue(mapped_overlay_key, new FundamentalValue(48), + overlay_->SetValue(mapped_overlay_key, + make_scoped_ptr(new FundamentalValue(48)), WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); EXPECT_TRUE(obs.changed_keys.empty()); } diff --git a/base/prefs/pref_service.cc b/base/prefs/pref_service.cc index a9749b2ba836f..c53b8966b347c 100644 --- a/base/prefs/pref_service.cc +++ b/base/prefs/pref_service.cc @@ -471,7 +471,8 @@ base::Value* PrefService::GetMutableUserPref(const std::string& path, } else { NOTREACHED(); } - user_pref_store_->SetValueSilently(path, value, GetWriteFlags(pref)); + user_pref_store_->SetValueSilently(path, make_scoped_ptr(value), + GetWriteFlags(pref)); } return value; } @@ -498,7 +499,7 @@ void PrefService::SetUserPrefValue(const std::string& path, return; } - user_pref_store_->SetValue(path, owned_value.release(), GetWriteFlags(pref)); + user_pref_store_->SetValue(path, owned_value.Pass(), GetWriteFlags(pref)); } void PrefService::UpdateCommandLinePrefStore(PrefStore* command_line_store) { diff --git a/base/prefs/pref_service_unittest.cc b/base/prefs/pref_service_unittest.cc index 262d7e9de9dae..2506b1d3f5722 100644 --- a/base/prefs/pref_service_unittest.cc +++ b/base/prefs/pref_service_unittest.cc @@ -239,17 +239,15 @@ class WriteFlagChecker : public TestingPrefStore { } void SetValue(const std::string& key, - base::Value* value, + scoped_ptr value, uint32 flags) override { SetLastWriteFlags(flags); - delete value; } void SetValueSilently(const std::string& key, - base::Value* value, + scoped_ptr value, uint32 flags) override { SetLastWriteFlags(flags); - delete value; } void RemoveValue(const std::string& key, uint32 flags) override { diff --git a/base/prefs/pref_value_map.cc b/base/prefs/pref_value_map.cc index 5f2dc506b69c0..93eadb72db469 100644 --- a/base/prefs/pref_value_map.cc +++ b/base/prefs/pref_value_map.cc @@ -13,60 +13,43 @@ PrefValueMap::PrefValueMap() {} -PrefValueMap::~PrefValueMap() { - Clear(); -} +PrefValueMap::~PrefValueMap() {} bool PrefValueMap::GetValue(const std::string& key, const base::Value** value) const { - const Map::const_iterator entry = prefs_.find(key); - if (entry == prefs_.end()) - return false; + const base::Value* got_value = prefs_.get(key); + if (value && got_value) + *value = got_value; - if (value) - *value = entry->second; - return true; + return !!got_value; } bool PrefValueMap::GetValue(const std::string& key, base::Value** value) { - const Map::const_iterator entry = prefs_.find(key); - if (entry == prefs_.end()) - return false; + base::Value* got_value = prefs_.get(key); + if (value && got_value) + *value = got_value; - if (value) - *value = entry->second; - return true; + return !!got_value; } -bool PrefValueMap::SetValue(const std::string& key, base::Value* value) { +bool PrefValueMap::SetValue(const std::string& key, + scoped_ptr value) { DCHECK(value); - auto result = prefs_.insert(std::make_pair(key, value)); - if (result.second) - return true; - scoped_ptr value_ptr(value); - const Map::iterator& entry = result.first; - if (base::Value::Equals(entry->second, value)) + base::Value* old_value = prefs_.get(key); + if (old_value && value->Equals(old_value)) return false; - delete entry->second; - entry->second = value_ptr.release(); - + prefs_.set(key, value.Pass()); return true; } bool PrefValueMap::RemoveValue(const std::string& key) { - const Map::iterator entry = prefs_.find(key); - if (entry == prefs_.end()) - return false; - - delete entry->second; - prefs_.erase(entry); - return true; + return prefs_.erase(key) != 0; } void PrefValueMap::Clear() { - STLDeleteValues(&prefs_); + prefs_.clear(); } void PrefValueMap::Swap(PrefValueMap* other) { @@ -96,7 +79,7 @@ bool PrefValueMap::GetBoolean(const std::string& key, } void PrefValueMap::SetBoolean(const std::string& key, bool value) { - SetValue(key, new base::FundamentalValue(value)); + SetValue(key, make_scoped_ptr(new base::FundamentalValue(value))); } bool PrefValueMap::GetString(const std::string& key, @@ -107,7 +90,7 @@ bool PrefValueMap::GetString(const std::string& key, void PrefValueMap::SetString(const std::string& key, const std::string& value) { - SetValue(key, new base::StringValue(value)); + SetValue(key, make_scoped_ptr(new base::StringValue(value))); } bool PrefValueMap::GetInteger(const std::string& key, int* value) const { @@ -116,11 +99,11 @@ bool PrefValueMap::GetInteger(const std::string& key, int* value) const { } void PrefValueMap::SetInteger(const std::string& key, const int value) { - SetValue(key, new base::FundamentalValue(value)); + SetValue(key, make_scoped_ptr(new base::FundamentalValue(value))); } void PrefValueMap::SetDouble(const std::string& key, const double value) { - SetValue(key, new base::FundamentalValue(value)); + SetValue(key, make_scoped_ptr(new base::FundamentalValue(value))); } void PrefValueMap::GetDifferingKeys( diff --git a/base/prefs/pref_value_map.h b/base/prefs/pref_value_map.h index 12b30c6973948..7d43f2b96ca1c 100644 --- a/base/prefs/pref_value_map.h +++ b/base/prefs/pref_value_map.h @@ -9,7 +9,8 @@ #include #include "base/basictypes.h" -#include "base/containers/hash_tables.h" +#include "base/containers/scoped_ptr_hash_map.h" +#include "base/memory/scoped_ptr.h" #include "base/prefs/base_prefs_export.h" namespace base { @@ -19,7 +20,7 @@ class Value; // A generic string to value map used by the PrefStore implementations. class BASE_PREFS_EXPORT PrefValueMap { public: - using Map = base::hash_map; + using Map = base::ScopedPtrHashMap>; using iterator = Map::iterator; using const_iterator = Map::const_iterator; @@ -32,9 +33,9 @@ class BASE_PREFS_EXPORT PrefValueMap { bool GetValue(const std::string& key, const base::Value** value) const; bool GetValue(const std::string& key, base::Value** value); - // Sets a new |value| for |key|. Takes ownership of |value|, which must be - // non-NULL. Returns true if the value changed. - bool SetValue(const std::string& key, base::Value* value); + // Sets a new |value| for |key|. |value| must be non-null. Returns true if the + // value changed. + bool SetValue(const std::string& key, scoped_ptr value); // Removes the value for |key| from the map. Returns true if a value was // removed. diff --git a/base/prefs/pref_value_map_unittest.cc b/base/prefs/pref_value_map_unittest.cc index 82499daf9c37b..f78c999916316 100644 --- a/base/prefs/pref_value_map_unittest.cc +++ b/base/prefs/pref_value_map_unittest.cc @@ -16,9 +16,9 @@ TEST(PrefValueMapTest, SetValue) { EXPECT_FALSE(map.GetValue("key", &result)); EXPECT_FALSE(result); - EXPECT_TRUE(map.SetValue("key", new StringValue("test"))); - EXPECT_FALSE(map.SetValue("key", new StringValue("test"))); - EXPECT_TRUE(map.SetValue("key", new StringValue("hi mom!"))); + EXPECT_TRUE(map.SetValue("key", make_scoped_ptr(new StringValue("test")))); + EXPECT_FALSE(map.SetValue("key", make_scoped_ptr(new StringValue("test")))); + EXPECT_TRUE(map.SetValue("key", make_scoped_ptr(new StringValue("hi mom!")))); EXPECT_TRUE(map.GetValue("key", &result)); EXPECT_TRUE(StringValue("hi mom!").Equals(result)); @@ -26,7 +26,7 @@ TEST(PrefValueMapTest, SetValue) { TEST(PrefValueMapTest, GetAndSetIntegerValue) { PrefValueMap map; - ASSERT_TRUE(map.SetValue("key", new FundamentalValue(5))); + ASSERT_TRUE(map.SetValue("key", make_scoped_ptr(new FundamentalValue(5)))); int int_value = 0; EXPECT_TRUE(map.GetInteger("key", &int_value)); @@ -39,7 +39,7 @@ TEST(PrefValueMapTest, GetAndSetIntegerValue) { TEST(PrefValueMapTest, SetDoubleValue) { PrefValueMap map; - ASSERT_TRUE(map.SetValue("key", new FundamentalValue(5.5))); + ASSERT_TRUE(map.SetValue("key", make_scoped_ptr(new FundamentalValue(5.5)))); const Value* result = NULL; ASSERT_TRUE(map.GetValue("key", &result)); @@ -52,7 +52,7 @@ TEST(PrefValueMapTest, RemoveValue) { PrefValueMap map; EXPECT_FALSE(map.RemoveValue("key")); - EXPECT_TRUE(map.SetValue("key", new StringValue("test"))); + EXPECT_TRUE(map.SetValue("key", make_scoped_ptr(new StringValue("test")))); EXPECT_TRUE(map.GetValue("key", NULL)); EXPECT_TRUE(map.RemoveValue("key")); @@ -63,7 +63,7 @@ TEST(PrefValueMapTest, RemoveValue) { TEST(PrefValueMapTest, Clear) { PrefValueMap map; - EXPECT_TRUE(map.SetValue("key", new StringValue("test"))); + EXPECT_TRUE(map.SetValue("key", make_scoped_ptr(new StringValue("test")))); EXPECT_TRUE(map.GetValue("key", NULL)); map.Clear(); @@ -73,9 +73,12 @@ TEST(PrefValueMapTest, Clear) { TEST(PrefValueMapTest, GetDifferingKeys) { PrefValueMap reference; - EXPECT_TRUE(reference.SetValue("b", new StringValue("test"))); - EXPECT_TRUE(reference.SetValue("c", new StringValue("test"))); - EXPECT_TRUE(reference.SetValue("e", new StringValue("test"))); + EXPECT_TRUE( + reference.SetValue("b", make_scoped_ptr(new StringValue("test")))); + EXPECT_TRUE( + reference.SetValue("c", make_scoped_ptr(new StringValue("test")))); + EXPECT_TRUE( + reference.SetValue("e", make_scoped_ptr(new StringValue("test")))); PrefValueMap check; std::vector differing_paths; @@ -87,9 +90,9 @@ TEST(PrefValueMapTest, GetDifferingKeys) { expected_differing_paths.push_back("e"); EXPECT_EQ(expected_differing_paths, differing_paths); - EXPECT_TRUE(check.SetValue("a", new StringValue("test"))); - EXPECT_TRUE(check.SetValue("c", new StringValue("test"))); - EXPECT_TRUE(check.SetValue("d", new StringValue("test"))); + EXPECT_TRUE(check.SetValue("a", make_scoped_ptr(new StringValue("test")))); + EXPECT_TRUE(check.SetValue("c", make_scoped_ptr(new StringValue("test")))); + EXPECT_TRUE(check.SetValue("d", make_scoped_ptr(new StringValue("test")))); reference.GetDifferingKeys(&check, &differing_paths); expected_differing_paths.clear(); @@ -102,14 +105,20 @@ TEST(PrefValueMapTest, GetDifferingKeys) { TEST(PrefValueMapTest, SwapTwoMaps) { PrefValueMap first_map; - EXPECT_TRUE(first_map.SetValue("a", new StringValue("test"))); - EXPECT_TRUE(first_map.SetValue("b", new StringValue("test"))); - EXPECT_TRUE(first_map.SetValue("c", new StringValue("test"))); + EXPECT_TRUE( + first_map.SetValue("a", make_scoped_ptr(new StringValue("test")))); + EXPECT_TRUE( + first_map.SetValue("b", make_scoped_ptr(new StringValue("test")))); + EXPECT_TRUE( + first_map.SetValue("c", make_scoped_ptr(new StringValue("test")))); PrefValueMap second_map; - EXPECT_TRUE(second_map.SetValue("d", new StringValue("test"))); - EXPECT_TRUE(second_map.SetValue("e", new StringValue("test"))); - EXPECT_TRUE(second_map.SetValue("f", new StringValue("test"))); + EXPECT_TRUE( + second_map.SetValue("d", make_scoped_ptr(new StringValue("test")))); + EXPECT_TRUE( + second_map.SetValue("e", make_scoped_ptr(new StringValue("test")))); + EXPECT_TRUE( + second_map.SetValue("f", make_scoped_ptr(new StringValue("test")))); first_map.Swap(&second_map); diff --git a/base/prefs/testing_pref_service.h b/base/prefs/testing_pref_service.h index 75873836b4112..cbc978dd4efbc 100644 --- a/base/prefs/testing_pref_service.h +++ b/base/prefs/testing_pref_service.h @@ -182,7 +182,7 @@ void TestingPrefServiceBase:: SetPref(TestingPrefStore* pref_store, const std::string& path, base::Value* value) { - pref_store->SetValue(path, value, + pref_store->SetValue(path, make_scoped_ptr(value), WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); } diff --git a/base/prefs/testing_pref_store.cc b/base/prefs/testing_pref_store.cc index 1a1e6bcd0f5b1..2322f4e476846 100644 --- a/base/prefs/testing_pref_store.cc +++ b/base/prefs/testing_pref_store.cc @@ -43,18 +43,18 @@ bool TestingPrefStore::IsInitializationComplete() const { } void TestingPrefStore::SetValue(const std::string& key, - base::Value* value, + scoped_ptr value, uint32 flags) { - if (prefs_.SetValue(key, value)) { + if (prefs_.SetValue(key, value.Pass())) { committed_ = false; NotifyPrefValueChanged(key); } } void TestingPrefStore::SetValueSilently(const std::string& key, - base::Value* value, + scoped_ptr value, uint32 flags) { - if (prefs_.SetValue(key, value)) + if (prefs_.SetValue(key, value.Pass())) committed_ = false; } @@ -115,15 +115,18 @@ void TestingPrefStore::ReportValueChanged(const std::string& key, void TestingPrefStore::SetString(const std::string& key, const std::string& value) { - SetValue(key, new base::StringValue(value), DEFAULT_PREF_WRITE_FLAGS); + SetValue(key, make_scoped_ptr(new base::StringValue(value)), + DEFAULT_PREF_WRITE_FLAGS); } void TestingPrefStore::SetInteger(const std::string& key, int value) { - SetValue(key, new base::FundamentalValue(value), DEFAULT_PREF_WRITE_FLAGS); + SetValue(key, make_scoped_ptr(new base::FundamentalValue(value)), + DEFAULT_PREF_WRITE_FLAGS); } void TestingPrefStore::SetBoolean(const std::string& key, bool value) { - SetValue(key, new base::FundamentalValue(value), DEFAULT_PREF_WRITE_FLAGS); + SetValue(key, make_scoped_ptr(new base::FundamentalValue(value)), + DEFAULT_PREF_WRITE_FLAGS); } bool TestingPrefStore::GetString(const std::string& key, diff --git a/base/prefs/testing_pref_store.h b/base/prefs/testing_pref_store.h index f43a0309240f3..72e61b3030d54 100644 --- a/base/prefs/testing_pref_store.h +++ b/base/prefs/testing_pref_store.h @@ -32,10 +32,10 @@ class TestingPrefStore : public PersistentPrefStore { bool GetMutableValue(const std::string& key, base::Value** result) override; void ReportValueChanged(const std::string& key, uint32 flags) override; void SetValue(const std::string& key, - base::Value* value, + scoped_ptr value, uint32 flags) override; void SetValueSilently(const std::string& key, - base::Value* value, + scoped_ptr value, uint32 flags) override; void RemoveValue(const std::string& key, uint32 flags) override; bool ReadOnly() const override; diff --git a/base/prefs/value_map_pref_store.cc b/base/prefs/value_map_pref_store.cc index d8501501f0406..f22f93aed6946 100644 --- a/base/prefs/value_map_pref_store.cc +++ b/base/prefs/value_map_pref_store.cc @@ -29,9 +29,9 @@ bool ValueMapPrefStore::HasObservers() const { } void ValueMapPrefStore::SetValue(const std::string& key, - base::Value* value, + scoped_ptr value, uint32 flags) { - if (prefs_.SetValue(key, value)) + if (prefs_.SetValue(key, value.Pass())) FOR_EACH_OBSERVER(Observer, observers_, OnPrefValueChanged(key)); } @@ -51,9 +51,9 @@ void ValueMapPrefStore::ReportValueChanged(const std::string& key, } void ValueMapPrefStore::SetValueSilently(const std::string& key, - base::Value* value, + scoped_ptr value, uint32 flags) { - prefs_.SetValue(key, value); + prefs_.SetValue(key, value.Pass()); } ValueMapPrefStore::~ValueMapPrefStore() {} diff --git a/base/prefs/value_map_pref_store.h b/base/prefs/value_map_pref_store.h index 9d8fa3ef2272c..badfef783e1f8 100644 --- a/base/prefs/value_map_pref_store.h +++ b/base/prefs/value_map_pref_store.h @@ -29,13 +29,13 @@ class BASE_PREFS_EXPORT ValueMapPrefStore : public WriteablePrefStore { // WriteablePrefStore overrides: void SetValue(const std::string& key, - base::Value* value, + scoped_ptr value, uint32 flags) override; void RemoveValue(const std::string& key, uint32 flags) override; bool GetMutableValue(const std::string& key, base::Value** value) override; void ReportValueChanged(const std::string& key, uint32 flags) override; void SetValueSilently(const std::string& key, - base::Value* value, + scoped_ptr value, uint32 flags) override; protected: diff --git a/base/prefs/writeable_pref_store.h b/base/prefs/writeable_pref_store.h index d85b4c8d4272a..cde3c84d0f11f 100644 --- a/base/prefs/writeable_pref_store.h +++ b/base/prefs/writeable_pref_store.h @@ -8,6 +8,7 @@ #include #include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" #include "base/prefs/pref_store.h" namespace base { @@ -30,10 +31,10 @@ class BASE_PREFS_EXPORT WriteablePrefStore : public PrefStore { WriteablePrefStore() {} - // Sets a |value| for |key| in the store. Assumes ownership of |value|, which - // must be non-NULL. |flags| is a bitmask of PrefWriteFlags. + // Sets a |value| for |key| in the store. |value| must be non-NULL. |flags| is + // a bitmask of PrefWriteFlags. virtual void SetValue(const std::string& key, - base::Value* value, + scoped_ptr value, uint32 flags) = 0; // Removes the value for |key|. @@ -56,7 +57,7 @@ class BASE_PREFS_EXPORT WriteablePrefStore : public PrefStore { // tests rely on the number of notifications generated. |flags| is a bitmask // of PrefWriteFlags. virtual void SetValueSilently(const std::string& key, - base::Value* value, + scoped_ptr value, uint32 flags) = 0; protected: diff --git a/base/process/BUILD.gn b/base/process/BUILD.gn index 814459b13e038..3978b2e58cf88 100644 --- a/base/process/BUILD.gn +++ b/base/process/BUILD.gn @@ -77,7 +77,7 @@ source_set("process") { set_sources_assignment_filter(sources_assignment_filter) } - if (is_nacl) { + if (is_nacl || is_ios) { sources -= [ "kill.cc", "kill.h", @@ -95,6 +95,10 @@ source_set("process") { ] } + if (is_ios) { + sources += [ "process_metrics.cc" ] + } + configs += [ "//base:base_implementation" ] deps = [ diff --git a/base/process/internal_linux.cc b/base/process/internal_linux.cc index d2e9ec52e5345..4f3fcaccbfb65 100644 --- a/base/process/internal_linux.cc +++ b/base/process/internal_linux.cc @@ -25,8 +25,8 @@ const char kProcDir[] = "/proc"; const char kStatFile[] = "stat"; -base::FilePath GetProcPidDir(pid_t pid) { - return base::FilePath(kProcDir).Append(IntToString(pid)); +FilePath GetProcPidDir(pid_t pid) { + return FilePath(kProcDir).Append(IntToString(pid)); } pid_t ProcDirSlotToPid(const char* d_name) { @@ -106,7 +106,7 @@ bool ParseProcStats(const std::string& stats_data, typedef std::map ProcStatMap; void ParseProcStat(const std::string& contents, ProcStatMap* output) { - base::StringPairs key_value_pairs; + StringPairs key_value_pairs; SplitStringIntoKeyValuePairs(contents, ' ', '\n', &key_value_pairs); for (size_t i = 0; i < key_value_pairs.size(); ++i) { output->insert(key_value_pairs[i]); diff --git a/base/process/launch.h b/base/process/launch.h index 56f27a8210989..0e42cd006ff0c 100644 --- a/base/process/launch.h +++ b/base/process/launch.h @@ -297,7 +297,7 @@ void ReplaceBootstrapPort(const std::string& replacement_bootstrap_name); // binary. This should not be called in production/released code. BASE_EXPORT LaunchOptions LaunchOptionsForTest(); -#if defined(OS_LINUX) +#if defined(OS_LINUX) || defined(OS_NACL_NONSFI) // A wrapper for clone with fork-like behavior, meaning that it returns the // child's pid in the parent and 0 in the child. |flags|, |ptid|, and |ctid| are // as in the clone system call (the CLONE_VM flag is not supported). diff --git a/base/process/launch_posix.cc b/base/process/launch_posix.cc index 77edc1283191c..99d8e3aa64da8 100644 --- a/base/process/launch_posix.cc +++ b/base/process/launch_posix.cc @@ -65,6 +65,8 @@ extern char** environ; namespace base { +#if !defined(OS_NACL_NONSFI) + namespace { // Get the process's "environment" (i.e. the thing that setenv/getenv @@ -188,55 +190,6 @@ void ResetChildSignalHandlersToDefaults(void) { } #endif // !defined(OS_LINUX) || // (!defined(__i386__) && !defined(__x86_64__) && !defined(__arm__)) - -#if defined(OS_LINUX) -bool IsRunningOnValgrind() { - return RUNNING_ON_VALGRIND; -} - -// This function runs on the stack specified on the clone call. It uses longjmp -// to switch back to the original stack so the child can return from sys_clone. -int CloneHelper(void* arg) { - jmp_buf* env_ptr = reinterpret_cast(arg); - longjmp(*env_ptr, 1); - - // Should not be reached. - RAW_CHECK(false); - return 1; -} - -// This function is noinline to ensure that stack_buf is below the stack pointer -// that is saved when setjmp is called below. This is needed because when -// compiled with FORTIFY_SOURCE, glibc's longjmp checks that the stack is moved -// upwards. See crbug.com/442912 for more details. -#if defined(ADDRESS_SANITIZER) -// Disable AddressSanitizer instrumentation for this function to make sure -// |stack_buf| is allocated on thread stack instead of ASan's fake stack. -// Under ASan longjmp() will attempt to clean up the area between the old and -// new stack pointers and print a warning that may confuse the user. -__attribute__((no_sanitize_address)) -#endif -NOINLINE pid_t CloneAndLongjmpInChild(unsigned long flags, - pid_t* ptid, - pid_t* ctid, - jmp_buf* env) { - // We use the libc clone wrapper instead of making the syscall - // directly because making the syscall may fail to update the libc's - // internal pid cache. The libc interface unfortunately requires - // specifying a new stack, so we use setjmp/longjmp to emulate - // fork-like behavior. - char stack_buf[PTHREAD_STACK_MIN]; -#if defined(ARCH_CPU_X86_FAMILY) || defined(ARCH_CPU_ARM_FAMILY) || \ - defined(ARCH_CPU_MIPS64_FAMILY) || defined(ARCH_CPU_MIPS_FAMILY) - // The stack grows downward. - void* stack = stack_buf + sizeof(stack_buf); -#else -#error "Unsupported architecture" -#endif - return clone(&CloneHelper, stack, flags, env, ptid, nullptr, ctid); -} -#endif // defined(OS_LINUX) - } // anonymous namespace // Functor for |ScopedDIR| (below). @@ -741,7 +694,59 @@ bool GetAppOutputWithExitCode(const CommandLine& cl, return result == EXECUTE_SUCCESS; } -#if defined(OS_LINUX) +#endif // !defined(OS_NACL_NONSFI) + +#if defined(OS_LINUX) || defined(OS_NACL_NONSFI) +namespace { + +bool IsRunningOnValgrind() { + return RUNNING_ON_VALGRIND; +} + +// This function runs on the stack specified on the clone call. It uses longjmp +// to switch back to the original stack so the child can return from sys_clone. +int CloneHelper(void* arg) { + jmp_buf* env_ptr = reinterpret_cast(arg); + longjmp(*env_ptr, 1); + + // Should not be reached. + RAW_CHECK(false); + return 1; +} + +// This function is noinline to ensure that stack_buf is below the stack pointer +// that is saved when setjmp is called below. This is needed because when +// compiled with FORTIFY_SOURCE, glibc's longjmp checks that the stack is moved +// upwards. See crbug.com/442912 for more details. +#if defined(ADDRESS_SANITIZER) +// Disable AddressSanitizer instrumentation for this function to make sure +// |stack_buf| is allocated on thread stack instead of ASan's fake stack. +// Under ASan longjmp() will attempt to clean up the area between the old and +// new stack pointers and print a warning that may confuse the user. +__attribute__((no_sanitize_address)) +#endif +NOINLINE pid_t CloneAndLongjmpInChild(unsigned long flags, + pid_t* ptid, + pid_t* ctid, + jmp_buf* env) { + // We use the libc clone wrapper instead of making the syscall + // directly because making the syscall may fail to update the libc's + // internal pid cache. The libc interface unfortunately requires + // specifying a new stack, so we use setjmp/longjmp to emulate + // fork-like behavior. + char stack_buf[PTHREAD_STACK_MIN]; +#if defined(ARCH_CPU_X86_FAMILY) || defined(ARCH_CPU_ARM_FAMILY) || \ + defined(ARCH_CPU_MIPS64_FAMILY) || defined(ARCH_CPU_MIPS_FAMILY) + // The stack grows downward. + void* stack = stack_buf + sizeof(stack_buf); +#else +#error "Unsupported architecture" +#endif + return clone(&CloneHelper, stack, flags, env, ptid, nullptr, ctid); +} + +} // anonymous namespace + pid_t ForkWithFlags(unsigned long flags, pid_t* ptid, pid_t* ctid) { const bool clone_tls_used = flags & CLONE_SETTLS; const bool invalid_ctid = @@ -780,6 +785,6 @@ pid_t ForkWithFlags(unsigned long flags, pid_t* ptid, pid_t* ctid) { return 0; } -#endif // defined(OS_LINUX) +#endif // defined(OS_LINUX) || defined(OS_NACL_NONSFI) } // namespace base diff --git a/base/process/launch_win.cc b/base/process/launch_win.cc index ebc19b8313093..fa59f1ae90744 100644 --- a/base/process/launch_win.cc +++ b/base/process/launch_win.cc @@ -238,7 +238,7 @@ Process LaunchElevatedProcess(const CommandLine& cmdline, const string16 file = cmdline.GetProgram().value(); const string16 arguments = cmdline.GetArgumentsString(); - SHELLEXECUTEINFO shex_info = {0}; + SHELLEXECUTEINFO shex_info = {}; shex_info.cbSize = sizeof(shex_info); shex_info.fMask = SEE_MASK_NOCLOSEPROCESS; shex_info.hwnd = GetActiveWindow(); @@ -261,7 +261,7 @@ Process LaunchElevatedProcess(const CommandLine& cmdline, } bool SetJobObjectLimitFlags(HANDLE job_object, DWORD limit_flags) { - JOBOBJECT_EXTENDED_LIMIT_INFORMATION limit_info = {0}; + JOBOBJECT_EXTENDED_LIMIT_INFORMATION limit_info = {}; limit_info.BasicLimitInformation.LimitFlags = limit_flags; return 0 != SetInformationJobObject( job_object, diff --git a/base/process/process_iterator_freebsd.cc b/base/process/process_iterator_freebsd.cc index 5b1e2ab09dbf7..22087fdd30977 100644 --- a/base/process/process_iterator_freebsd.cc +++ b/base/process/process_iterator_freebsd.cc @@ -9,6 +9,7 @@ #include #include "base/logging.h" +#include "base/strings/string_split.h" #include "base/strings/string_util.h" namespace base { @@ -88,7 +89,8 @@ bool ProcessIterator::CheckForNextProcess() { std::string delimiters; delimiters.push_back('\0'); - Tokenize(data, delimiters, &entry_.cmd_line_args_); + entry_.cmd_line_args_ = SplitString(data, delimiters, + KEEP_WHITESPACE, SPLIT_WANT_NONEMPTY); size_t exec_name_end = data.find('\0'); if (exec_name_end == std::string::npos) { diff --git a/base/process/process_iterator_linux.cc b/base/process/process_iterator_linux.cc index 3319552f38de1..a9d044c53824f 100644 --- a/base/process/process_iterator_linux.cc +++ b/base/process/process_iterator_linux.cc @@ -7,6 +7,7 @@ #include "base/files/file_util.h" #include "base/logging.h" #include "base/process/internal_linux.h" +#include "base/strings/string_split.h" #include "base/strings/string_util.h" #include "base/threading/thread_restrictions.h" @@ -48,7 +49,8 @@ bool GetProcCmdline(pid_t pid, std::vector* proc_cmd_line_args) { return false; std::string delimiters; delimiters.push_back('\0'); - Tokenize(cmd_line, delimiters, proc_cmd_line_args); + *proc_cmd_line_args = SplitString(cmd_line, delimiters, KEEP_WHITESPACE, + SPLIT_WANT_NONEMPTY); return true; } diff --git a/base/process/process_iterator_mac.cc b/base/process/process_iterator_mac.cc index e35c2ae19ba23..9b33a0a8e4036 100644 --- a/base/process/process_iterator_mac.cc +++ b/base/process/process_iterator_mac.cc @@ -10,6 +10,7 @@ #include #include "base/logging.h" +#include "base/strings/string_split.h" #include "base/strings/string_util.h" namespace base { @@ -99,7 +100,8 @@ bool ProcessIterator::CheckForNextProcess() { // |entry_.cmd_line_args_|. std::string delimiters; delimiters.push_back('\0'); - Tokenize(data, delimiters, &entry_.cmd_line_args_); + entry_.cmd_line_args_ = SplitString(data, delimiters, + KEEP_WHITESPACE, SPLIT_WANT_NONEMPTY); // |data| starts with the full executable path followed by a null character. // We search for the first instance of '\0' and extract everything before it diff --git a/base/process/process_iterator_openbsd.cc b/base/process/process_iterator_openbsd.cc index 7c44eb118c00e..f864f58da4f88 100644 --- a/base/process/process_iterator_openbsd.cc +++ b/base/process/process_iterator_openbsd.cc @@ -8,6 +8,7 @@ #include #include "base/logging.h" +#include "base/strings/string_split.h" #include "base/strings/string_util.h" namespace base { @@ -92,7 +93,8 @@ bool ProcessIterator::CheckForNextProcess() { // |entry_.cmd_line_args_|. std::string delimiters; delimiters.push_back('\0'); - Tokenize(data, delimiters, &entry_.cmd_line_args_); + entry_.cmd_line_args_ = SplitString(data, delimiters, KEEP_WHITESPACE, + SPLIT_WANT_NONEMPTY); // |data| starts with the full executable path followed by a null character. // We search for the first instance of '\0' and extract everything before it diff --git a/base/process/process_linux.cc b/base/process/process_linux.cc index 88a310eccdb9c..6e10dd2301fb6 100644 --- a/base/process/process_linux.cc +++ b/base/process/process_linux.cc @@ -10,6 +10,7 @@ #include "base/files/file_util.h" #include "base/lazy_instance.h" #include "base/logging.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" #include "base/strings/stringprintf.h" #include "base/synchronization/lock.h" @@ -119,7 +120,7 @@ bool Process::SetProcessBackgrounded(bool background) { #if defined(OS_CHROMEOS) if (cgroups.Get().enabled) { - std::string pid = StringPrintf("%d", process_); + std::string pid = IntToString(process_); const base::FilePath file = background ? cgroups.Get().background_file : cgroups.Get().foreground_file; diff --git a/base/process/process_metrics.h b/base/process/process_metrics.h index 5916b94148cb2..8b4ec86693ac9 100644 --- a/base/process/process_metrics.h +++ b/base/process/process_metrics.h @@ -140,7 +140,8 @@ class BASE_EXPORT ProcessMetrics { // memory usage as per definition of CommittedBytes. void GetCommittedKBytes(CommittedKBytes* usage) const; // Fills a WorkingSetKBytes containing resident private and shared memory - // usage in bytes, as per definition of WorkingSetBytes. + // usage in bytes, as per definition of WorkingSetBytes. Note that this + // function is somewhat expensive on Windows (a few ms per process). bool GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const; #if defined(OS_MACOSX) diff --git a/base/process/process_metrics_linux.cc b/base/process/process_metrics_linux.cc index c564a6798baa6..47a79e51e5eb1 100644 --- a/base/process/process_metrics_linux.cc +++ b/base/process/process_metrics_linux.cc @@ -563,17 +563,15 @@ bool ParseProcMeminfo(const std::string& meminfo_data, // MemTotal value meminfo->total = 0; - std::vector meminfo_lines; - Tokenize(meminfo_data, "\n", &meminfo_lines); - for (std::vector::iterator it = meminfo_lines.begin(); - it != meminfo_lines.end(); ++it) { - std::vector tokens; - SplitStringAlongWhitespace(*it, &tokens); + for (const StringPiece& line : SplitStringPiece( + meminfo_data, "\n", KEEP_WHITESPACE, SPLIT_WANT_NONEMPTY)) { + std::vector tokens = SplitStringPiece( + line, kWhitespaceASCII, TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY); // HugePages_* only has a number and no suffix so we can't rely on // there being exactly 3 tokens. if (tokens.size() <= 1) { DLOG(WARNING) << "meminfo: tokens: " << tokens.size() - << " malformed line: " << *it; + << " malformed line: " << line.as_string(); continue; } @@ -630,12 +628,10 @@ bool ParseProcVmstat(const std::string& vmstat_data, // We iterate through the whole file because the position of the // fields are dependent on the kernel version and configuration. - std::vector vmstat_lines; - Tokenize(vmstat_data, "\n", &vmstat_lines); - for (std::vector::iterator it = vmstat_lines.begin(); - it != vmstat_lines.end(); ++it) { - std::vector tokens; - SplitString(*it, ' ', &tokens); + for (const StringPiece& line : SplitStringPiece( + vmstat_data, "\n", KEEP_WHITESPACE, SPLIT_WANT_NONEMPTY)) { + std::vector tokens = SplitStringPiece( + line, " ", KEEP_WHITESPACE, SPLIT_WANT_NONEMPTY); if (tokens.size() != 2) continue; @@ -792,9 +788,9 @@ bool GetSystemDiskInfo(SystemDiskInfo* diskinfo) { return false; } - std::vector diskinfo_lines; - size_t line_count = Tokenize(diskinfo_data, "\n", &diskinfo_lines); - if (line_count == 0) { + std::vector diskinfo_lines = SplitStringPiece( + diskinfo_data, "\n", KEEP_WHITESPACE, SPLIT_WANT_NONEMPTY); + if (diskinfo_lines.size() == 0) { DLOG(WARNING) << "No lines found"; return false; } @@ -823,12 +819,12 @@ bool GetSystemDiskInfo(SystemDiskInfo* diskinfo) { uint64 io_time = 0; uint64 weighted_io_time = 0; - for (size_t i = 0; i < line_count; i++) { - std::vector disk_fields; - SplitStringAlongWhitespace(diskinfo_lines[i], &disk_fields); + for (const StringPiece& line : diskinfo_lines) { + std::vector disk_fields = SplitStringPiece( + line, kWhitespaceASCII, TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY); // Fields may have overflowed and reset to zero. - if (IsValidDiskName(disk_fields[kDiskDriveName])) { + if (IsValidDiskName(disk_fields[kDiskDriveName].as_string())) { StringToUint64(disk_fields[kDiskReads], &reads); StringToUint64(disk_fields[kDiskReadsMerged], &reads_merged); StringToUint64(disk_fields[kDiskSectorsRead], §ors_read); diff --git a/base/process/process_metrics_win.cc b/base/process/process_metrics_win.cc index 6c424e3cacf24..170f6dcaab8af 100644 --- a/base/process/process_metrics_win.cc +++ b/base/process/process_metrics_win.cc @@ -260,7 +260,7 @@ static BOOL InternalGetPerformanceInfo( GetProcAddress(psapi_dll, "GetPerformanceInfo")); if (!GetPerformanceInfo_func) { - // The function could be loaded! + // The function could not be loaded! memset(pPerformanceInformation, 0, cb); return FALSE; } diff --git a/base/process/process_posix.cc b/base/process/process_posix.cc index 47b0d5b11fb29..b6f22c1edcf7e 100644 --- a/base/process/process_posix.cc +++ b/base/process/process_posix.cc @@ -295,9 +295,10 @@ void Process::Close() { #if !defined(OS_NACL_NONSFI) bool Process::Terminate(int exit_code, bool wait) const { - // result_code isn't supportable. + // exit_code isn't supportable. DCHECK(IsValid()); - DCHECK_GT(process_, 1); + CHECK_GT(process_, 0); + bool result = kill(process_, SIGTERM) == 0; if (result && wait) { int tries = 60; diff --git a/base/process/process_util_unittest.cc b/base/process/process_util_unittest.cc index 1f7f1b2c776ed..6c1a3f1d7619d 100644 --- a/base/process/process_util_unittest.cc +++ b/base/process/process_util_unittest.cc @@ -64,6 +64,12 @@ using base::FilePath; namespace { +const char kSignalFileSlow[] = "SlowChildProcess.die"; +const char kSignalFileKill[] = "KilledChildProcess.die"; + +#if defined(OS_POSIX) +const char kSignalFileTerm[] = "TerminatedChildProcess.die"; + #if defined(OS_ANDROID) const char kShellPath[] = "/system/bin/sh"; const char kPosixShell[] = "sh"; @@ -71,13 +77,7 @@ const char kPosixShell[] = "sh"; const char kShellPath[] = "/bin/sh"; const char kPosixShell[] = "bash"; #endif - -const char kSignalFileSlow[] = "SlowChildProcess.die"; -const char kSignalFileKill[] = "KilledChildProcess.die"; - -#if defined(OS_POSIX) -const char kSignalFileTerm[] = "TerminatedChildProcess.die"; -#endif +#endif // defined(OS_POSIX) #if defined(OS_WIN) const int kExpectedStillRunningExitCode = 0x102; @@ -1025,6 +1025,7 @@ MULTIPROCESS_TEST_MAIN(CheckPidProcess) { return kSuccess; } +#if defined(CLONE_NEWUSER) && defined(CLONE_NEWPID) TEST_F(ProcessUtilTest, CloneFlags) { if (RunningOnValgrind() || !base::PathExists(FilePath("/proc/self/ns/user")) || @@ -1043,6 +1044,7 @@ TEST_F(ProcessUtilTest, CloneFlags) { EXPECT_TRUE(process.WaitForExit(&exit_code)); EXPECT_EQ(kSuccess, exit_code); } +#endif TEST(ForkWithFlagsTest, UpdatesPidCache) { // The libc clone function, which allows ForkWithFlags to keep the pid cache diff --git a/base/process/process_win.cc b/base/process/process_win.cc index 2ad72c706b054..30cd9dc737268 100644 --- a/base/process/process_win.cc +++ b/base/process/process_win.cc @@ -9,6 +9,7 @@ #include "base/metrics/field_trial.h" #include "base/numerics/safe_conversions.h" #include "base/process/kill.h" +#include "base/strings/string_util.h" #include "base/win/windows_version.h" namespace { @@ -189,8 +190,10 @@ bool Process::SetProcessBackgrounded(bool value) { DWORD background_priority = IDLE_PRIORITY_CLASS; base::FieldTrial* trial = base::FieldTrialList::Find("BackgroundRendererProcesses"); - if (trial && trial->group_name() == "AllowBelowNormalFromBrowser") + if (trial && StartsWith(trial->group_name(), "AllowBelowNormalFromBrowser", + CompareCase::SENSITIVE)) { background_priority = BELOW_NORMAL_PRIORITY_CLASS; + } priority = value ? background_priority : NORMAL_PRIORITY_CLASS; } diff --git a/base/profiler/stack_sampling_profiler_win.cc b/base/profiler/stack_sampling_profiler_win.cc index 1ccd13412a644..73b8e11ce4125 100644 --- a/base/profiler/stack_sampling_profiler_win.cc +++ b/base/profiler/stack_sampling_profiler_win.cc @@ -40,7 +40,7 @@ int RecordStack(CONTEXT* context, instruction_pointers[i] = reinterpret_cast(context->Rip); if (runtime_function) { - KNONVOLATILE_CONTEXT_POINTERS nvcontext = {0}; + KNONVOLATILE_CONTEXT_POINTERS nvcontext = {}; void* handler_data; ULONG64 establisher_frame; RtlVirtualUnwind(0, image_base, context->Rip, runtime_function, context, diff --git a/base/strings/pattern.cc b/base/strings/pattern.cc new file mode 100644 index 0000000000000..af30aab86da39 --- /dev/null +++ b/base/strings/pattern.cc @@ -0,0 +1,169 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/strings/pattern.h" + +#include "base/third_party/icu/icu_utf.h" + +namespace base { + +namespace { + +static bool IsWildcard(base_icu::UChar32 character) { + return character == '*' || character == '?'; +} + +// Move the strings pointers to the point where they start to differ. +template +static void EatSameChars(const CHAR** pattern, const CHAR* pattern_end, + const CHAR** string, const CHAR* string_end, + NEXT next) { + const CHAR* escape = NULL; + while (*pattern != pattern_end && *string != string_end) { + if (!escape && IsWildcard(**pattern)) { + // We don't want to match wildcard here, except if it's escaped. + return; + } + + // Check if the escapement char is found. If so, skip it and move to the + // next character. + if (!escape && **pattern == '\\') { + escape = *pattern; + next(pattern, pattern_end); + continue; + } + + // Check if the chars match, if so, increment the ptrs. + const CHAR* pattern_next = *pattern; + const CHAR* string_next = *string; + base_icu::UChar32 pattern_char = next(&pattern_next, pattern_end); + if (pattern_char == next(&string_next, string_end) && + pattern_char != CBU_SENTINEL) { + *pattern = pattern_next; + *string = string_next; + } else { + // Uh oh, it did not match, we are done. If the last char was an + // escapement, that means that it was an error to advance the ptr here, + // let's put it back where it was. This also mean that the MatchPattern + // function will return false because if we can't match an escape char + // here, then no one will. + if (escape) { + *pattern = escape; + } + return; + } + + escape = NULL; + } +} + +template +static void EatWildcard(const CHAR** pattern, const CHAR* end, NEXT next) { + while (*pattern != end) { + if (!IsWildcard(**pattern)) + return; + next(pattern, end); + } +} + +template +static bool MatchPatternT(const CHAR* eval, const CHAR* eval_end, + const CHAR* pattern, const CHAR* pattern_end, + int depth, + NEXT next) { + const int kMaxDepth = 16; + if (depth > kMaxDepth) + return false; + + // Eat all the matching chars. + EatSameChars(&pattern, pattern_end, &eval, eval_end, next); + + // If the string is empty, then the pattern must be empty too, or contains + // only wildcards. + if (eval == eval_end) { + EatWildcard(&pattern, pattern_end, next); + return pattern == pattern_end; + } + + // Pattern is empty but not string, this is not a match. + if (pattern == pattern_end) + return false; + + // If this is a question mark, then we need to compare the rest with + // the current string or the string with one character eaten. + const CHAR* next_pattern = pattern; + next(&next_pattern, pattern_end); + if (pattern[0] == '?') { + if (MatchPatternT(eval, eval_end, next_pattern, pattern_end, + depth + 1, next)) + return true; + const CHAR* next_eval = eval; + next(&next_eval, eval_end); + if (MatchPatternT(next_eval, eval_end, next_pattern, pattern_end, + depth + 1, next)) + return true; + } + + // This is a *, try to match all the possible substrings with the remainder + // of the pattern. + if (pattern[0] == '*') { + // Collapse duplicate wild cards (********** into *) so that the + // method does not recurse unnecessarily. http://crbug.com/52839 + EatWildcard(&next_pattern, pattern_end, next); + + while (eval != eval_end) { + if (MatchPatternT(eval, eval_end, next_pattern, pattern_end, + depth + 1, next)) + return true; + eval++; + } + + // We reached the end of the string, let see if the pattern contains only + // wildcards. + if (eval == eval_end) { + EatWildcard(&pattern, pattern_end, next); + if (pattern != pattern_end) + return false; + return true; + } + } + + return false; +} + +struct NextCharUTF8 { + base_icu::UChar32 operator()(const char** p, const char* end) { + base_icu::UChar32 c; + int offset = 0; + CBU8_NEXT(*p, offset, end - *p, c); + *p += offset; + return c; + } +}; + +struct NextCharUTF16 { + base_icu::UChar32 operator()(const char16** p, const char16* end) { + base_icu::UChar32 c; + int offset = 0; + CBU16_NEXT(*p, offset, end - *p, c); + *p += offset; + return c; + } +}; + +} // namespace + +bool MatchPattern(const StringPiece& eval, const StringPiece& pattern) { + return MatchPatternT(eval.data(), eval.data() + eval.size(), + pattern.data(), pattern.data() + pattern.size(), + 0, NextCharUTF8()); +} + +bool MatchPattern(const StringPiece16& eval, const StringPiece16& pattern) { + return MatchPatternT(eval.data(), eval.data() + eval.size(), + pattern.data(), pattern.data() + pattern.size(), + 0, NextCharUTF16()); +} + +} // namespace base diff --git a/base/strings/pattern.h b/base/strings/pattern.h new file mode 100644 index 0000000000000..b698207b9d652 --- /dev/null +++ b/base/strings/pattern.h @@ -0,0 +1,26 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_STRINGS_PATTERN_H_ +#define BASE_STRINGS_PATTERN_H_ + +#include "base/base_export.h" +#include "base/strings/string_piece.h" + +namespace base { + +// Returns true if the string passed in matches the pattern. The pattern +// string can contain wildcards like * and ? +// +// The backslash character (\) is an escape character for * and ? +// We limit the patterns to having a max of 16 * or ? characters. +// ? matches 0 or 1 character, while * matches 0 or more characters. +BASE_EXPORT bool MatchPattern(const StringPiece& string, + const StringPiece& pattern); +BASE_EXPORT bool MatchPattern(const StringPiece16& string, + const StringPiece16& pattern); + +} // namespace base + +#endif // BASE_STRINGS_PATTERN_H_ diff --git a/base/strings/pattern_unittest.cc b/base/strings/pattern_unittest.cc new file mode 100644 index 0000000000000..9e82b3cba1122 --- /dev/null +++ b/base/strings/pattern_unittest.cc @@ -0,0 +1,50 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/strings/pattern.h" +#include "base/strings/utf_string_conversions.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace base { + +TEST(StringUtilTest, MatchPatternTest) { + EXPECT_TRUE(MatchPattern("www.google.com", "*.com")); + EXPECT_TRUE(MatchPattern("www.google.com", "*")); + EXPECT_FALSE(MatchPattern("www.google.com", "www*.g*.org")); + EXPECT_TRUE(MatchPattern("Hello", "H?l?o")); + EXPECT_FALSE(MatchPattern("www.google.com", "http://*)")); + EXPECT_FALSE(MatchPattern("www.msn.com", "*.COM")); + EXPECT_TRUE(MatchPattern("Hello*1234", "He??o\\*1*")); + EXPECT_FALSE(MatchPattern("", "*.*")); + EXPECT_TRUE(MatchPattern("", "*")); + EXPECT_TRUE(MatchPattern("", "?")); + EXPECT_TRUE(MatchPattern("", "")); + EXPECT_FALSE(MatchPattern("Hello", "")); + EXPECT_TRUE(MatchPattern("Hello*", "Hello*")); + // Stop after a certain recursion depth. + EXPECT_FALSE(MatchPattern("123456789012345678", "?????????????????*")); + + // Test UTF8 matching. + EXPECT_TRUE(MatchPattern("heart: \xe2\x99\xa0", "*\xe2\x99\xa0")); + EXPECT_TRUE(MatchPattern("heart: \xe2\x99\xa0.", "heart: ?.")); + EXPECT_TRUE(MatchPattern("hearts: \xe2\x99\xa0\xe2\x99\xa0", "*")); + // Invalid sequences should be handled as a single invalid character. + EXPECT_TRUE(MatchPattern("invalid: \xef\xbf\xbe", "invalid: ?")); + // If the pattern has invalid characters, it shouldn't match anything. + EXPECT_FALSE(MatchPattern("\xf4\x90\x80\x80", "\xf4\x90\x80\x80")); + + // Test UTF16 character matching. + EXPECT_TRUE(MatchPattern(UTF8ToUTF16("www.google.com"), + UTF8ToUTF16("*.com"))); + EXPECT_TRUE(MatchPattern(UTF8ToUTF16("Hello*1234"), + UTF8ToUTF16("He??o\\*1*"))); + + // This test verifies that consecutive wild cards are collapsed into 1 + // wildcard (when this doesn't occur, MatchPattern reaches it's maximum + // recursion depth). + EXPECT_TRUE(MatchPattern(UTF8ToUTF16("Hello"), + UTF8ToUTF16("He********************************o"))); +} + +} // namespace base diff --git a/base/strings/string_number_conversions.cc b/base/strings/string_number_conversions.cc index 642d24e9ada11..b6b65d2a3bf8c 100644 --- a/base/strings/string_number_conversions.cc +++ b/base/strings/string_number_conversions.cc @@ -42,7 +42,12 @@ struct IntToStringT { template struct ToUnsignedT { static UINT2 ToUnsigned(INT2 value) { - return static_cast(value < 0 ? -value : value); + if (value >= 0) { + return value; + } else { + // Avoid integer overflow when negating INT_MIN. + return static_cast(-(value + 1)) + 1; + } } }; @@ -131,10 +136,10 @@ template bool CharToDigit(CHAR c, uint8* digit) { return BaseCharToDigit::Convert(c, digit); } -// There is an IsWhitespace for wchars defined in string_util.h, but it is -// locale independent, whereas the functions we are replacing were -// locale-dependent. TBD what is desired, but for the moment let's not introduce -// a change in behaviour. +// There is an IsUnicodeWhitespace for wchars defined in string_util.h, but it +// is locale independent, whereas the functions we are replacing were +// locale-dependent. TBD what is desired, but for the moment let's not +// introduce a change in behaviour. template class WhitespaceHelper { }; diff --git a/base/strings/string_piece.h b/base/strings/string_piece.h index 349018b9d0a25..a83b7d8f66162 100644 --- a/base/strings/string_piece.h +++ b/base/strings/string_piece.h @@ -18,12 +18,6 @@ // Both of these have the same lifetime semantics. Passing by value // generates slightly smaller code. For more discussion, Googlers can see // the thread go/stringpiecebyvalue on c-users. -// -// StringPiece16 is similar to StringPiece but for base::string16 instead of -// std::string. We do not define as large of a subset of the STL functions -// from basic_string as in StringPiece, but this can be changed if these -// functions (find, find_first_of, etc.) are found to be useful in this context. -// #ifndef BASE_STRINGS_STRING_PIECE_H_ #define BASE_STRINGS_STRING_PIECE_H_ diff --git a/base/strings/string_split.cc b/base/strings/string_split.cc index 88a623664fcc1..cc62a6f4b47a1 100644 --- a/base/strings/string_split.cc +++ b/base/strings/string_split.cc @@ -12,26 +12,91 @@ namespace base { namespace { -template -void SplitStringT(const STR& str, - const typename STR::value_type s, - bool trim_whitespace, - std::vector* r) { - r->clear(); - size_t last = 0; - size_t c = str.size(); - for (size_t i = 0; i <= c; ++i) { - if (i == c || str[i] == s) { - STR tmp(str, last, i - last); - if (trim_whitespace) - TrimWhitespace(tmp, TRIM_ALL, &tmp); - // Avoid converting an empty or all-whitespace source string into a vector - // of one empty string. - if (i != c || !r->empty() || !tmp.empty()) - r->push_back(tmp); - last = i + 1; +// PieceToOutputType converts a StringPiece as needed to a given output type, +// which is either the same type of StringPiece (a NOP) or the corresponding +// non-piece string type. +// +// The default converter is a NOP, it works when the OutputType is the +// correct StringPiece. +template +OutputType PieceToOutputType(BasicStringPiece piece) { + return piece; +} +template<> // Convert StringPiece to std::string +std::string PieceToOutputType(StringPiece piece) { + return piece.as_string(); +} +template<> // Convert StringPiece16 to string16. +string16 PieceToOutputType(StringPiece16 piece) { + return piece.as_string(); +} + +// Returns either the ASCII or UTF-16 whitespace. +template BasicStringPiece WhitespaceForType(); +template<> StringPiece16 WhitespaceForType() { + return kWhitespaceUTF16; +} +template<> StringPiece WhitespaceForType() { + return kWhitespaceASCII; +} + +// Optimize the single-character case to call find() on the string instead, +// since this is the common case and can be made faster. This could have been +// done with template specialization too, but would have been less clear. +// +// There is no corresponding FindFirstNotOf because StringPiece already +// implements these different versions that do the optimized searching. +size_t FindFirstOf(StringPiece piece, char c, size_t pos) { + return piece.find(c, pos); +} +size_t FindFirstOf(StringPiece16 piece, char16 c, size_t pos) { + return piece.find(c, pos); +} +size_t FindFirstOf(StringPiece piece, StringPiece one_of, size_t pos) { + return piece.find_first_of(one_of, pos); +} +size_t FindFirstOf(StringPiece16 piece, StringPiece16 one_of, size_t pos) { + return piece.find_first_of(one_of, pos); +} + +// General string splitter template. Can take 8- or 16-bit input, can produce +// the corresponding string or StringPiece output, and can take single- or +// multiple-character delimiters. +// +// DelimiterType is either a character (Str::value_type) or a string piece of +// multiple characters (BasicStringPiece). StringPiece has a version of +// find for both of these cases, and the single-character version is the most +// common and can be implemented faster, which is why this is a template. +template +static std::vector SplitStringT( + BasicStringPiece str, + DelimiterType delimiter, + WhitespaceHandling whitespace, + SplitResult result_type) { + std::vector result; + if (str.empty()) + return result; + + size_t start = 0; + while (start != Str::npos) { + size_t end = FindFirstOf(str, delimiter, start); + + BasicStringPiece piece; + if (end == Str::npos) { + piece = str.substr(start); + start = Str::npos; + } else { + piece = str.substr(start, end - start); + start = end + 1; } + + if (whitespace == TRIM_WHITESPACE) + piece = TrimString(piece, WhitespaceForType(), TRIM_ALL); + + if (result_type == SPLIT_WANT_ALL || !piece.empty()) + result.push_back(PieceToOutputType(piece)); } + return result; } bool SplitStringIntoKeyValue(const std::string& line, @@ -62,8 +127,8 @@ bool SplitStringIntoKeyValue(const std::string& line, template void SplitStringUsingSubstrT(const STR& str, - const STR& s, - std::vector* r) { + const STR& s, + std::vector* r) { r->clear(); typename STR::size_type begin_index = 0; while (true) { @@ -83,64 +148,88 @@ void SplitStringUsingSubstrT(const STR& str, } } -template -void SplitStringAlongWhitespaceT(const STR& str, std::vector* result) { - result->clear(); - const size_t length = str.length(); - if (!length) - return; - - bool last_was_ws = false; - size_t last_non_ws_start = 0; - for (size_t i = 0; i < length; ++i) { - switch (str[i]) { - // HTML 5 defines whitespace as: space, tab, LF, line tab, FF, or CR. - case L' ': - case L'\t': - case L'\xA': - case L'\xB': - case L'\xC': - case L'\xD': - if (!last_was_ws) { - if (i > 0) { - result->push_back( - str.substr(last_non_ws_start, i - last_non_ws_start)); - } - last_was_ws = true; - } - break; - - default: // Not a space character. - if (last_was_ws) { - last_was_ws = false; - last_non_ws_start = i; - } - break; - } +} // namespace + +std::vector SplitString(StringPiece input, + StringPiece separators, + WhitespaceHandling whitespace, + SplitResult result_type) { + if (separators.size() == 1) { + return SplitStringT( + input, separators[0], whitespace, result_type); } - if (!last_was_ws) { - result->push_back( - str.substr(last_non_ws_start, length - last_non_ws_start)); + return SplitStringT( + input, separators, whitespace, result_type); +} + +std::vector SplitString(StringPiece16 input, + StringPiece16 separators, + WhitespaceHandling whitespace, + SplitResult result_type) { + if (separators.size() == 1) { + return SplitStringT( + input, separators[0], whitespace, result_type); } + return SplitStringT( + input, separators, whitespace, result_type); } -} // namespace +std::vector SplitStringPiece(StringPiece input, + StringPiece separators, + WhitespaceHandling whitespace, + SplitResult result_type) { + if (separators.size() == 1) { + return SplitStringT( + input, separators[0], whitespace, result_type); + } + return SplitStringT( + input, separators, whitespace, result_type); +} + +std::vector SplitStringPiece(StringPiece16 input, + StringPiece16 separators, + WhitespaceHandling whitespace, + SplitResult result_type) { + if (separators.size() == 1) { + return SplitStringT( + input, separators[0], whitespace, result_type); + } + return SplitStringT( + input, separators, whitespace, result_type); +} void SplitString(const string16& str, char16 c, - std::vector* r) { + std::vector* result) { DCHECK(CBU16_IS_SINGLE(c)); - SplitStringT(str, c, true, r); + *result = SplitStringT( + str, c, TRIM_WHITESPACE, SPLIT_WANT_ALL); + + // Backward-compat hack: The old SplitString implementation would keep + // empty substrings, for example: + // "a,,b" -> ["a", "", "b"] + // "a, ,b" -> ["a", "", "b"] + // which the current code also does. But the old one would discard them when + // the only result was that empty string: + // " " -> [] + // In the latter case, our new code will give [""] + if (result->size() == 1 && (*result)[0].empty()) + result->clear(); } void SplitString(const std::string& str, char c, - std::vector* r) { + std::vector* result) { #if CHAR_MIN < 0 DCHECK_GE(c, 0); #endif DCHECK_LT(c, 0x7F); - SplitStringT(str, c, true, r); + *result = SplitStringT( + str, c, TRIM_WHITESPACE, SPLIT_WANT_ALL); + + // Backward-compat hack, see above. + if (result->size() == 1 && (*result)[0].empty()) + result->clear(); } bool SplitStringIntoKeyValuePairs(const std::string& line, @@ -182,31 +271,37 @@ void SplitStringUsingSubstr(const std::string& str, SplitStringUsingSubstrT(str, s, r); } -void SplitStringDontTrim(const string16& str, +void SplitStringDontTrim(StringPiece16 str, char16 c, - std::vector* r) { + std::vector* result) { DCHECK(CBU16_IS_SINGLE(c)); - SplitStringT(str, c, false, r); + *result = SplitStringT( + str, c, KEEP_WHITESPACE, SPLIT_WANT_ALL); } -void SplitStringDontTrim(const std::string& str, +void SplitStringDontTrim(StringPiece str, char c, - std::vector* r) { + std::vector* result) { #if CHAR_MIN < 0 DCHECK_GE(c, 0); #endif DCHECK_LT(c, 0x7F); - SplitStringT(str, c, false, r); + *result = SplitStringT( + str, c, KEEP_WHITESPACE, SPLIT_WANT_ALL); } void SplitStringAlongWhitespace(const string16& str, std::vector* result) { - SplitStringAlongWhitespaceT(str, result); + *result = SplitStringT( + str, StringPiece16(kWhitespaceASCIIAs16), + TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY); } void SplitStringAlongWhitespace(const std::string& str, std::vector* result) { - SplitStringAlongWhitespaceT(str, result); + *result = SplitStringT( + str, StringPiece(kWhitespaceASCII), + TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY); } } // namespace base diff --git a/base/strings/string_split.h b/base/strings/string_split.h index 55d8cb377edfa..dc4108d327ff2 100644 --- a/base/strings/string_split.h +++ b/base/strings/string_split.h @@ -11,28 +11,73 @@ #include "base/base_export.h" #include "base/strings/string16.h" +#include "base/strings/string_piece.h" namespace base { -// Splits |str| into a vector of strings delimited by |c|, placing the results -// in |r|. If several instances of |c| are contiguous, or if |str| begins with -// or ends with |c|, then an empty string is inserted. +enum WhitespaceHandling { + KEEP_WHITESPACE, + TRIM_WHITESPACE, +}; + +enum SplitResult { + // Strictly return all results. + // + // If the input is ",," and the separator is ',' this will return a + // vector of three empty strings. + SPLIT_WANT_ALL, + + // Only nonempty results will be added to the results. Multiple separators + // will be coalesced. Separators at the beginning and end of the input will + // be ignored. With TRIM_WHITESPACE, whitespace-only results will be dropped. + // + // If the input is ",," and the separator is ',', this will return an empty + // vector. + SPLIT_WANT_NONEMPTY, +}; + +// Split the given string on ANY of the given separators, returning copies of +// the result. // -// Every substring is trimmed of any leading or trailing white space. -// NOTE: |c| must be in BMP (Basic Multilingual Plane) -BASE_EXPORT void SplitString(const string16& str, - char16 c, - std::vector* r); +// To split on either commas or semicolons, keeping all whitespace: +// +// std::vector tokens = base::SplitString( +// input, ",;", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); +BASE_EXPORT std::vector SplitString( + StringPiece input, + StringPiece separators, + WhitespaceHandling whitespace, + SplitResult result_type); +BASE_EXPORT std::vector SplitString( + StringPiece16 input, + StringPiece16 separators, + WhitespaceHandling whitespace, + SplitResult result_type); -// |str| should not be in a multi-byte encoding like Shift-JIS or GBK in which -// the trailing byte of a multi-byte character can be in the ASCII range. -// UTF-8, and other single/multi-byte ASCII-compatible encodings are OK. -// Note: |c| must be in the ASCII range. -BASE_EXPORT void SplitString(const std::string& str, - char c, - std::vector* r); +// Like SplitString above except it returns a vector of StringPieces which +// reference the original buffer without copying. Although you have to be +// careful to keep the original string unmodified, this provides an efficient +// way to iterate through tokens in a string. +// +// To iterate through all whitespace-separated tokens in an input string: +// +// for (const auto& cur : +// base::SplitStringPiece(input, base::kWhitespaceASCII, +// base::KEEP_WHITESPACE, +// base::SPLIT_WANT_NONEMPTY)) { +// ... +BASE_EXPORT std::vector SplitStringPiece( + StringPiece input, + StringPiece separators, + WhitespaceHandling whitespace, + SplitResult result_type); +BASE_EXPORT std::vector SplitStringPiece( + StringPiece16 input, + StringPiece16 separators, + WhitespaceHandling whitespace, + SplitResult result_type); -typedef std::vector > StringPairs; +using StringPairs = std::vector>; // Splits |line| into key value pairs according to the given delimiters and // removes whitespace leading each key and trailing each value. Returns true @@ -43,7 +88,12 @@ BASE_EXPORT bool SplitStringIntoKeyValuePairs(const std::string& line, char key_value_pair_delimiter, StringPairs* key_value_pairs); -// The same as SplitString, but use a substring delimiter instead of a char. +// Similar to SplitString, but use a substring delimiter instead of a list of +// characters that are all possible delimiters. +// +// TODO(brettw) this should probably be changed and expanded to provide a +// mirror of the SplitString[Piece] API above, just with the different +// delimiter handling. BASE_EXPORT void SplitStringUsingSubstr(const string16& str, const string16& s, std::vector* r); @@ -51,27 +101,53 @@ BASE_EXPORT void SplitStringUsingSubstr(const std::string& str, const std::string& s, std::vector* r); +// ----------------------------------------------------------------------------- +// Backwards-compat wrappers +// +// New code should use one of the more general variants above. +// TODO(brettw) remove these and convert to the versions above. + +// Splits |str| into a vector of strings delimited by |c|, placing the results +// in |r|. If several instances of |c| are contiguous, or if |str| begins with +// or ends with |c|, then an empty string is inserted. +// +// Every substring is trimmed of any leading or trailing white space. +// NOTE: |c| must be in BMP (Basic Multilingual Plane) +BASE_EXPORT void SplitString(const string16& str, + char16 c, + std::vector* r); + +// |str| should not be in a multi-byte encoding like Shift-JIS or GBK in which +// the trailing byte of a multi-byte character can be in the ASCII range. +// UTF-8, and other single/multi-byte ASCII-compatible encodings are OK. +// Note: |c| must be in the ASCII range. +BASE_EXPORT void SplitString(const std::string& str, + char c, + std::vector* r); + // The same as SplitString, but don't trim white space. // NOTE: |c| must be in BMP (Basic Multilingual Plane) -BASE_EXPORT void SplitStringDontTrim(const string16& str, +BASE_EXPORT void SplitStringDontTrim(StringPiece16 str, char16 c, std::vector* r); // |str| should not be in a multi-byte encoding like Shift-JIS or GBK in which // the trailing byte of a multi-byte character can be in the ASCII range. // UTF-8, and other single/multi-byte ASCII-compatible encodings are OK. // Note: |c| must be in the ASCII range. -BASE_EXPORT void SplitStringDontTrim(const std::string& str, +BASE_EXPORT void SplitStringDontTrim(StringPiece str, char c, - std::vector* r); + std::vector* result); -// WARNING: this uses whitespace as defined by the HTML5 spec. If you need -// a function similar to this but want to trim all types of whitespace, then -// factor this out into a function that takes a string containing the characters -// that are treated as whitespace. +// WARNING: this uses whitespace as defined by the HTML5 spec (ASCII whitespace +// only). +// +// The difference between this and calling SplitString with the whitespace +// characters as separators is the treatment of the first element when the +// string starts with whitespace. // -// Splits the string along whitespace (where whitespace is the five space -// characters defined by HTML 5). Each contiguous block of non-whitespace -// characters is added to result. +// Input SplitString SplitStringAlongWhitespace +// -------------------------------------------------------- +// " a " "", "a" "a" BASE_EXPORT void SplitStringAlongWhitespace(const string16& str, std::vector* result); BASE_EXPORT void SplitStringAlongWhitespace(const std::string& str, diff --git a/base/strings/string_split_unittest.cc b/base/strings/string_split_unittest.cc index 32bbe28b65f2f..c745ab58f08e9 100644 --- a/base/strings/string_split_unittest.cc +++ b/base/strings/string_split_unittest.cc @@ -169,7 +169,81 @@ TEST(SplitStringUsingSubstrTest, EmptyString) { EXPECT_THAT(results, ElementsAre("")); } -TEST(StringUtilTest, SplitString) { +TEST(StringUtilTest, SplitString_Basics) { + std::vector r; + + r = SplitString(std::string(), ",:;", KEEP_WHITESPACE, SPLIT_WANT_ALL); + EXPECT_TRUE(r.empty()); + + // Empty separator list + r = SplitString("hello, world", "", KEEP_WHITESPACE, SPLIT_WANT_ALL); + ASSERT_EQ(1u, r.size()); + EXPECT_EQ("hello, world", r[0]); + + // Should split on any of the separators. + r = SplitString("::,,;;", ",:;", KEEP_WHITESPACE, SPLIT_WANT_ALL); + ASSERT_EQ(7u, r.size()); + for (auto str : r) + ASSERT_TRUE(str.empty()); + + r = SplitString("red, green; blue:", ",:;", TRIM_WHITESPACE, + SPLIT_WANT_NONEMPTY); + ASSERT_EQ(3u, r.size()); + EXPECT_EQ("red", r[0]); + EXPECT_EQ("green", r[1]); + EXPECT_EQ("blue", r[2]); + + // Want to split a string along whitespace sequences. + r = SplitString(" red green \tblue\n", " \t\n", TRIM_WHITESPACE, + SPLIT_WANT_NONEMPTY); + ASSERT_EQ(3u, r.size()); + EXPECT_EQ("red", r[0]); + EXPECT_EQ("green", r[1]); + EXPECT_EQ("blue", r[2]); + + // Weird case of splitting on spaces but not trimming. + r = SplitString(" red ", " ", TRIM_WHITESPACE, SPLIT_WANT_ALL); + ASSERT_EQ(3u, r.size()); + EXPECT_EQ("", r[0]); // Before the first space. + EXPECT_EQ("red", r[1]); + EXPECT_EQ("", r[2]); // After the last space. +} + +TEST(StringUtilTest, SplitString_WhitespaceAndResultType) { + std::vector r; + + // Empty input handling. + r = SplitString(std::string(), ",", KEEP_WHITESPACE, SPLIT_WANT_ALL); + EXPECT_TRUE(r.empty()); + r = SplitString(std::string(), ",", KEEP_WHITESPACE, SPLIT_WANT_NONEMPTY); + EXPECT_TRUE(r.empty()); + + // Input string is space and we're trimming. + r = SplitString(" ", ",", TRIM_WHITESPACE, SPLIT_WANT_ALL); + ASSERT_EQ(1u, r.size()); + EXPECT_EQ("", r[0]); + r = SplitString(" ", ",", TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY); + EXPECT_TRUE(r.empty()); + + // Test all 4 combinations of flags on ", ,". + r = SplitString(", ,", ",", KEEP_WHITESPACE, SPLIT_WANT_ALL); + ASSERT_EQ(3u, r.size()); + EXPECT_EQ("", r[0]); + EXPECT_EQ(" ", r[1]); + EXPECT_EQ("", r[2]); + r = SplitString(", ,", ",", KEEP_WHITESPACE, SPLIT_WANT_NONEMPTY); + ASSERT_EQ(1u, r.size()); + ASSERT_EQ(" ", r[0]); + r = SplitString(", ,", ",", TRIM_WHITESPACE, SPLIT_WANT_ALL); + ASSERT_EQ(3u, r.size()); + EXPECT_EQ("", r[0]); + EXPECT_EQ("", r[1]); + EXPECT_EQ("", r[2]); + r = SplitString(", ,", ",", TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY); + ASSERT_TRUE(r.empty()); +} + +TEST(StringUtilTest, SplitString_Legacy) { std::vector r; SplitString(std::wstring(), L',', &r); @@ -197,6 +271,13 @@ TEST(StringUtilTest, SplitString) { EXPECT_EQ(r[2], L"c"); r.clear(); + SplitString(L"a, ,c", L',', &r); + ASSERT_EQ(3U, r.size()); + EXPECT_EQ(r[0], L"a"); + EXPECT_EQ(r[1], L""); + EXPECT_EQ(r[2], L"c"); + r.clear(); + SplitString(L" ", L'*', &r); EXPECT_EQ(0U, r.size()); r.clear(); diff --git a/base/strings/string_util.cc b/base/strings/string_util.cc index cc7769343b5a5..b6fad2916bc68 100644 --- a/base/strings/string_util.cc +++ b/base/strings/string_util.cc @@ -21,14 +21,13 @@ #include "base/basictypes.h" #include "base/logging.h" #include "base/memory/singleton.h" +#include "base/strings/string_split.h" #include "base/strings/utf_string_conversion_utils.h" #include "base/strings/utf_string_conversions.h" #include "base/third_party/icu/icu_utf.h" #include "build/build_config.h" -// Remove when this entire file is in the base namespace. -using base::char16; -using base::string16; +namespace base { namespace { @@ -79,13 +78,13 @@ template inline T* AlignToMachineWord(T* pointer) { } template struct NonASCIIMask; -template<> struct NonASCIIMask<4, base::char16> { +template<> struct NonASCIIMask<4, char16> { static inline uint32_t value() { return 0xFF80FF80U; } }; template<> struct NonASCIIMask<4, char> { static inline uint32_t value() { return 0x80808080U; } }; -template<> struct NonASCIIMask<8, base::char16> { +template<> struct NonASCIIMask<8, char16> { static inline uint64_t value() { return 0xFF80FF80FF80FF80ULL; } }; template<> struct NonASCIIMask<8, char> { @@ -100,9 +99,19 @@ template<> struct NonASCIIMask<8, wchar_t> { }; #endif // WCHAR_T_IS_UTF32 -} // namespace +// DO NOT USE. http://crbug.com/24917 +// +// tolower() will given incorrect results for non-ASCII characters. Use the +// ASCII version, base::i18n::ToLower, or base::i18n::FoldCase. This is here +// for backwards-compat for StartsWith until such calls can be updated. +struct CaseInsensitiveCompareDeprecated { + public: + bool operator()(char16 x, char16 y) const { + return tolower(x) == tolower(y); + } +}; -namespace base { +} // namespace bool IsWprintfFormatPortable(const wchar_t* format) { for (const wchar_t* position = format; *position != '\0'; ++position) { @@ -139,6 +148,53 @@ bool IsWprintfFormatPortable(const wchar_t* format) { return true; } +template +int CompareCaseInsensitiveASCIIT(BasicStringPiece a, + BasicStringPiece b) { + // Find the first characters that aren't equal and compare them. If the end + // of one of the strings is found before a nonequal character, the lengths + // of the strings are compared. + size_t i = 0; + while (i < a.length() && i < b.length()) { + typename StringType::value_type lower_a = ToLowerASCII(a[i]); + typename StringType::value_type lower_b = ToLowerASCII(b[i]); + if (lower_a < lower_b) + return -1; + if (lower_a > lower_b) + return 1; + i++; + } + + // End of one string hit before finding a different character. Expect the + // common case to be "strings equal" at this point so check that first. + if (a.length() == b.length()) + return 0; + + if (a.length() < b.length()) + return -1; + return 1; +} + +int CompareCaseInsensitiveASCII(StringPiece a, StringPiece b) { + return CompareCaseInsensitiveASCIIT(a, b); +} + +int CompareCaseInsensitiveASCII(StringPiece16 a, StringPiece16 b) { + return CompareCaseInsensitiveASCIIT(a, b); +} + +bool EqualsCaseInsensitiveASCII(StringPiece a, StringPiece b) { + if (a.length() != b.length()) + return false; + return CompareCaseInsensitiveASCIIT(a, b) == 0; +} + +bool EqualsCaseInsensitiveASCII(StringPiece16 a, StringPiece16 b) { + if (a.length() != b.length()) + return false; + return CompareCaseInsensitiveASCIIT(a, b) == 0; +} + const std::string& EmptyString() { return EmptyStrings::GetInstance()->s; } @@ -168,54 +224,58 @@ bool ReplaceCharsT(const STR& input, } bool ReplaceChars(const string16& input, - const base::StringPiece16& replace_chars, + const StringPiece16& replace_chars, const string16& replace_with, string16* output) { return ReplaceCharsT(input, replace_chars.as_string(), replace_with, output); } bool ReplaceChars(const std::string& input, - const base::StringPiece& replace_chars, + const StringPiece& replace_chars, const std::string& replace_with, std::string* output) { return ReplaceCharsT(input, replace_chars.as_string(), replace_with, output); } bool RemoveChars(const string16& input, - const base::StringPiece16& remove_chars, + const StringPiece16& remove_chars, string16* output) { return ReplaceChars(input, remove_chars.as_string(), string16(), output); } bool RemoveChars(const std::string& input, - const base::StringPiece& remove_chars, + const StringPiece& remove_chars, std::string* output) { return ReplaceChars(input, remove_chars.as_string(), std::string(), output); } -template -TrimPositions TrimStringT(const STR& input, - const STR& trim_chars, +template +TrimPositions TrimStringT(const Str& input, + BasicStringPiece trim_chars, TrimPositions positions, - STR* output) { - // Find the edges of leading/trailing whitespace as desired. + Str* output) { + // Find the edges of leading/trailing whitespace as desired. Need to use + // a StringPiece version of input to be able to call find* on it with the + // StringPiece version of trim_chars (normally the trim_chars will be a + // constant so avoid making a copy). + BasicStringPiece input_piece(input); const size_t last_char = input.length() - 1; const size_t first_good_char = (positions & TRIM_LEADING) ? - input.find_first_not_of(trim_chars) : 0; + input_piece.find_first_not_of(trim_chars) : 0; const size_t last_good_char = (positions & TRIM_TRAILING) ? - input.find_last_not_of(trim_chars) : last_char; + input_piece.find_last_not_of(trim_chars) : last_char; - // When the string was all whitespace, report that we stripped off whitespace - // from whichever position the caller was interested in. For empty input, we - // stripped no whitespace, but we still need to clear |output|. + // When the string was all trimmed, report that we stripped off characters + // from whichever position the caller was interested in. For empty input, we + // stripped no characters, but we still need to clear |output|. if (input.empty() || - (first_good_char == STR::npos) || (last_good_char == STR::npos)) { + (first_good_char == Str::npos) || (last_good_char == Str::npos)) { bool input_was_empty = input.empty(); // in case output == &input output->clear(); return input_was_empty ? TRIM_NONE : positions; } - // Trim the whitespace. + // Trim. *output = input.substr(first_good_char, last_good_char - first_good_char + 1); @@ -226,17 +286,38 @@ TrimPositions TrimStringT(const STR& input, } bool TrimString(const string16& input, - const base::StringPiece16& trim_chars, + StringPiece16 trim_chars, string16* output) { - return TrimStringT(input, trim_chars.as_string(), TRIM_ALL, output) != - TRIM_NONE; + return TrimStringT(input, trim_chars, TRIM_ALL, output) != TRIM_NONE; } bool TrimString(const std::string& input, - const base::StringPiece& trim_chars, + StringPiece trim_chars, std::string* output) { - return TrimStringT(input, trim_chars.as_string(), TRIM_ALL, output) != - TRIM_NONE; + return TrimStringT(input, trim_chars, TRIM_ALL, output) != TRIM_NONE; +} + +template +BasicStringPiece TrimStringPieceT(BasicStringPiece input, + BasicStringPiece trim_chars, + TrimPositions positions) { + size_t begin = (positions & TRIM_LEADING) ? + input.find_first_not_of(trim_chars) : 0; + size_t end = (positions & TRIM_TRAILING) ? + input.find_last_not_of(trim_chars) + 1 : input.size(); + return input.substr(begin, end - begin); +} + +StringPiece16 TrimString(StringPiece16 input, + const StringPiece16& trim_chars, + TrimPositions positions) { + return TrimStringPieceT(input, trim_chars, positions); +} + +StringPiece TrimString(StringPiece input, + const StringPiece& trim_chars, + TrimPositions positions) { + return TrimStringPieceT(input, trim_chars, positions); } void TruncateUTF8ToByteSize(const std::string& input, @@ -278,14 +359,22 @@ void TruncateUTF8ToByteSize(const std::string& input, TrimPositions TrimWhitespace(const string16& input, TrimPositions positions, string16* output) { - return TrimStringT(input, base::string16(kWhitespaceUTF16), positions, - output); + return TrimStringT(input, StringPiece16(kWhitespaceUTF16), positions, output); +} + +StringPiece16 TrimWhitespaceASCII(StringPiece16 input, + TrimPositions positions) { + return TrimStringPieceT(input, StringPiece16(kWhitespaceUTF16), positions); } TrimPositions TrimWhitespaceASCII(const std::string& input, TrimPositions positions, std::string* output) { - return TrimStringT(input, std::string(kWhitespaceASCII), positions, output); + return TrimStringT(input, StringPiece(kWhitespaceASCII), positions, output); +} + +StringPiece TrimWhitespaceASCII(StringPiece input, TrimPositions positions) { + return TrimStringPieceT(input, StringPiece(kWhitespaceASCII), positions); } // This function is only for backward-compatibility. @@ -309,7 +398,7 @@ STR CollapseWhitespaceT(const STR& text, int chars_written = 0; for (typename STR::const_iterator i(text.begin()); i != text.end(); ++i) { - if (IsWhitespace(*i)) { + if (IsUnicodeWhitespace(*i)) { if (!in_whitespace) { // Reduce all whitespace sequences to a single space. in_whitespace = true; @@ -482,55 +571,125 @@ bool EqualsASCII(const string16& a, const StringPiece& b) { return std::equal(b.begin(), b.end(), a.begin()); } -} // namespace base +template +bool StartsWithT(BasicStringPiece str, + BasicStringPiece search_for, + CompareCase case_sensitivity) { + if (search_for.size() > str.size()) + return false; -bool StartsWithASCII(const std::string& str, - const std::string& search, - bool case_sensitive) { - if (case_sensitive) - return str.compare(0, search.length(), search) == 0; - else - return base::strncasecmp(str.c_str(), search.c_str(), search.length()) == 0; + BasicStringPiece source = str.substr(0, search_for.size()); + + switch (case_sensitivity) { + case CompareCase::SENSITIVE: + return source == search_for; + + case CompareCase::INSENSITIVE_ASCII: + return std::equal( + search_for.begin(), search_for.end(), + source.begin(), + CaseInsensitiveCompareASCII()); + + default: + NOTREACHED(); + return false; + } } -template -bool StartsWithT(const STR& str, const STR& search, bool case_sensitive) { - if (case_sensitive) { - return str.compare(0, search.length(), search) == 0; - } else { +bool StartsWith(StringPiece str, + StringPiece search_for, + CompareCase case_sensitivity) { + return StartsWithT(str, search_for, case_sensitivity); +} + +bool StartsWith(StringPiece16 str, + StringPiece16 search_for, + CompareCase case_sensitivity) { + return StartsWithT(str, search_for, case_sensitivity); +} + +bool StartsWith(const string16& str, + const string16& search, + bool case_sensitive) { + if (!case_sensitive) { + // This function was originally written using the current locale functions + // for case-insensitive comparisons. Emulate this behavior until callers + // can be converted either to use the case-insensitive ASCII one (most + // callers) or ICU functions in base_i18n. if (search.size() > str.size()) return false; return std::equal(search.begin(), search.end(), str.begin(), - base::CaseInsensitiveCompare()); + CaseInsensitiveCompareDeprecated()); } + return StartsWith(StringPiece16(str), StringPiece16(search), + CompareCase::SENSITIVE); } -bool StartsWith(const string16& str, const string16& search, - bool case_sensitive) { - return StartsWithT(str, search, case_sensitive); +template +bool EndsWithT(BasicStringPiece str, + BasicStringPiece search_for, + CompareCase case_sensitivity) { + if (search_for.size() > str.size()) + return false; + + BasicStringPiece source = str.substr(str.size() - search_for.size(), + search_for.size()); + + switch (case_sensitivity) { + case CompareCase::SENSITIVE: + return source == search_for; + + case CompareCase::INSENSITIVE_ASCII: + return std::equal( + source.begin(), source.end(), + search_for.begin(), + CaseInsensitiveCompareASCII()); + + default: + NOTREACHED(); + return false; + } } -template -bool EndsWithT(const STR& str, const STR& search, bool case_sensitive) { - size_t str_length = str.length(); - size_t search_length = search.length(); - if (search_length > str_length) - return false; - if (case_sensitive) - return str.compare(str_length - search_length, search_length, search) == 0; - return std::equal(search.begin(), search.end(), - str.begin() + (str_length - search_length), - base::CaseInsensitiveCompare()); +bool EndsWith(StringPiece str, + StringPiece search_for, + CompareCase case_sensitivity) { + return EndsWithT(str, search_for, case_sensitivity); } -bool EndsWith(const std::string& str, const std::string& search, - bool case_sensitive) { - return EndsWithT(str, search, case_sensitive); +bool EndsWith(StringPiece16 str, + StringPiece16 search_for, + CompareCase case_sensitivity) { + return EndsWithT(str, search_for, case_sensitivity); } -bool EndsWith(const string16& str, const string16& search, +bool EndsWith(const string16& str, + const string16& search, bool case_sensitive) { - return EndsWithT(str, search, case_sensitive); + if (!case_sensitive) { + // This function was originally written using the current locale functions + // for case-insensitive comparisons. Emulate this behavior until callers + // can be converted either to use the case-insensitive ASCII one (most + // callers) or ICU functions in base_i18n. + if (search.size() > str.size()) + return false; + return std::equal(search.begin(), search.end(), + str.begin() + (str.size() - search.size()), + CaseInsensitiveCompareDeprecated()); + } + return EndsWith(StringPiece16(str), StringPiece16(search), + CompareCase::SENSITIVE); +} + +char HexDigitToInt(wchar_t c) { + DCHECK(IsHexDigit(c)); + if (c >= '0' && c <= '9') + return static_cast(c - '0'); + if (c >= 'A' && c <= 'F') + return static_cast(c - 'A' + 10); + if (c >= 'a' && c <= 'f') + return static_cast(c - 'a' + 10); + return 0; } static const char* const kByteStringsUnlocalized[] = { @@ -561,20 +720,20 @@ string16 FormatBytesUnlocalized(int64 bytes) { kByteStringsUnlocalized[dimension]); } - return base::ASCIIToUTF16(buf); + return ASCIIToUTF16(buf); } // Runs in O(n) time in the length of |str|. template void DoReplaceSubstringsAfterOffset(StringType* str, size_t offset, - const StringType& find_this, - const StringType& replace_with, + BasicStringPiece find_this, + BasicStringPiece replace_with, bool replace_all) { DCHECK(!find_this.empty()); // If the find string doesn't appear, there's nothing to do. - offset = str->find(find_this, offset); + offset = str->find(find_this.data(), offset, find_this.size()); if (offset == StringType::npos) return; @@ -582,7 +741,7 @@ void DoReplaceSubstringsAfterOffset(StringType* str, // complicated. size_t find_length = find_this.length(); if (!replace_all) { - str->replace(offset, find_length, replace_with); + str->replace(offset, find_length, replace_with.data(), replace_with.size()); return; } @@ -591,8 +750,10 @@ void DoReplaceSubstringsAfterOffset(StringType* str, size_t replace_length = replace_with.length(); if (find_length == replace_length) { do { - str->replace(offset, find_length, replace_with); - offset = str->find(find_this, offset + replace_length); + str->replace(offset, find_length, + replace_with.data(), replace_with.size()); + offset = str->find(find_this.data(), offset + replace_length, + find_this.size()); } while (offset != StringType::npos); return; } @@ -609,11 +770,14 @@ void DoReplaceSubstringsAfterOffset(StringType* str, size_t write_offset = offset; do { if (replace_length) { - str->replace(write_offset, replace_length, replace_with); + str->replace(write_offset, replace_length, + replace_with.data(), replace_with.size()); write_offset += replace_length; } size_t read_offset = offset + find_length; - offset = std::min(str->find(find_this, read_offset), str_length); + offset = std::min( + str->find(find_this.data(), read_offset, find_this.size()), + str_length); size_t length = offset - read_offset; if (length) { memmove(&(*str)[write_offset], &(*str)[read_offset], @@ -642,13 +806,15 @@ void DoReplaceSubstringsAfterOffset(StringType* str, // exit from the loop, |current_match| will point at the last instance of // the find string, and we won't need to find() it again immediately. current_match = offset; - offset = str->find(find_this, offset + find_length); + offset = str->find(find_this.data(), offset + find_length, + find_this.size()); } while (offset != StringType::npos); str->resize(final_length); // Now do the replacement loop, working backwards through the string. for (size_t prev_match = str_length, write_offset = final_length; ; - current_match = str->rfind(find_this, current_match - 1)) { + current_match = str->rfind(find_this.data(), current_match - 1, + find_this.size())) { size_t read_offset = current_match + find_length; size_t length = prev_match - read_offset; if (length) { @@ -657,7 +823,8 @@ void DoReplaceSubstringsAfterOffset(StringType* str, length * sizeof(typename StringType::value_type)); } write_offset -= replace_length; - str->replace(write_offset, replace_length, replace_with); + str->replace(write_offset, replace_length, + replace_with.data(), replace_with.size()); if (current_match == first_match) return; prev_match = current_match; @@ -666,128 +833,97 @@ void DoReplaceSubstringsAfterOffset(StringType* str, void ReplaceFirstSubstringAfterOffset(string16* str, size_t start_offset, - const string16& find_this, - const string16& replace_with) { - DoReplaceSubstringsAfterOffset(str, start_offset, find_this, replace_with, - false); // replace first instance + StringPiece16 find_this, + StringPiece16 replace_with) { + DoReplaceSubstringsAfterOffset( + str, start_offset, find_this, replace_with, false); // Replace first. } void ReplaceFirstSubstringAfterOffset(std::string* str, size_t start_offset, - const std::string& find_this, - const std::string& replace_with) { - DoReplaceSubstringsAfterOffset(str, start_offset, find_this, replace_with, - false); // replace first instance + StringPiece find_this, + StringPiece replace_with) { + DoReplaceSubstringsAfterOffset( + str, start_offset, find_this, replace_with, false); // Replace first. } void ReplaceSubstringsAfterOffset(string16* str, size_t start_offset, - const string16& find_this, - const string16& replace_with) { - DoReplaceSubstringsAfterOffset(str, start_offset, find_this, replace_with, - true); // replace all instances + StringPiece16 find_this, + StringPiece16 replace_with) { + DoReplaceSubstringsAfterOffset( + str, start_offset, find_this, replace_with, true); // Replace all. } void ReplaceSubstringsAfterOffset(std::string* str, size_t start_offset, - const std::string& find_this, - const std::string& replace_with) { - DoReplaceSubstringsAfterOffset(str, start_offset, find_this, replace_with, - true); // replace all instances -} - - -template -static size_t TokenizeT(const STR& str, - const STR& delimiters, - std::vector* tokens) { - tokens->clear(); - - size_t start = str.find_first_not_of(delimiters); - while (start != STR::npos) { - size_t end = str.find_first_of(delimiters, start + 1); - if (end == STR::npos) { - tokens->push_back(str.substr(start)); - break; - } else { - tokens->push_back(str.substr(start, end - start)); - start = str.find_first_not_of(delimiters, end + 1); - } - } - - return tokens->size(); + StringPiece find_this, + StringPiece replace_with) { + DoReplaceSubstringsAfterOffset( + str, start_offset, find_this, replace_with, true); // Replace all. } -size_t Tokenize(const string16& str, - const string16& delimiters, - std::vector* tokens) { - return TokenizeT(str, delimiters, tokens); +template +inline typename string_type::value_type* WriteIntoT(string_type* str, + size_t length_with_null) { + DCHECK_GT(length_with_null, 1u); + str->reserve(length_with_null); + str->resize(length_with_null - 1); + return &((*str)[0]); } -size_t Tokenize(const std::string& str, - const std::string& delimiters, - std::vector* tokens) { - return TokenizeT(str, delimiters, tokens); +char* WriteInto(std::string* str, size_t length_with_null) { + return WriteIntoT(str, length_with_null); } -size_t Tokenize(const base::StringPiece& str, - const base::StringPiece& delimiters, - std::vector* tokens) { - return TokenizeT(str, delimiters, tokens); +char16* WriteInto(string16* str, size_t length_with_null) { + return WriteIntoT(str, length_with_null); } template -static STR JoinStringT(const std::vector& parts, const STR& sep) { +static STR JoinStringT(const std::vector& parts, + BasicStringPiece sep) { if (parts.empty()) return STR(); STR result(parts[0]); - typename std::vector::const_iterator iter = parts.begin(); + auto iter = parts.begin(); ++iter; for (; iter != parts.end(); ++iter) { - result += sep; + sep.AppendToString(&result); result += *iter; } return result; } -std::string JoinString(const std::vector& parts, char sep) { - return JoinStringT(parts, std::string(1, sep)); -} - -string16 JoinString(const std::vector& parts, char16 sep) { - return JoinStringT(parts, string16(1, sep)); -} - std::string JoinString(const std::vector& parts, - const std::string& separator) { + StringPiece separator) { return JoinStringT(parts, separator); } string16 JoinString(const std::vector& parts, - const string16& separator) { + StringPiece16 separator) { return JoinStringT(parts, separator); } template -OutStringType DoReplaceStringPlaceholders(const FormatStringType& format_string, - const std::vector& subst, std::vector* offsets) { +OutStringType DoReplaceStringPlaceholders( + const FormatStringType& format_string, + const std::vector& subst, + std::vector* offsets) { size_t substitutions = subst.size(); size_t sub_length = 0; - for (typename std::vector::const_iterator iter = subst.begin(); - iter != subst.end(); ++iter) { - sub_length += iter->length(); - } + for (const auto& cur : subst) + sub_length += cur.length(); OutStringType formatted; formatted.reserve(format_string.length() + sub_length); std::vector r_offsets; - for (typename FormatStringType::const_iterator i = format_string.begin(); - i != format_string.end(); ++i) { + for (auto i = format_string.begin(); i != format_string.end(); ++i) { if ('$' == *i) { if (i + 1 != format_string.end()) { ++i; @@ -825,10 +961,8 @@ OutStringType DoReplaceStringPlaceholders(const FormatStringType& format_string, } } if (offsets) { - for (std::vector::const_iterator i = r_offsets.begin(); - i != r_offsets.end(); ++i) { - offsets->push_back(i->offset); - } + for (const auto& cur : r_offsets) + offsets->push_back(cur.offset); } return formatted; } @@ -839,7 +973,7 @@ string16 ReplaceStringPlaceholders(const string16& format_string, return DoReplaceStringPlaceholders(format_string, subst, offsets); } -std::string ReplaceStringPlaceholders(const base::StringPiece& format_string, +std::string ReplaceStringPlaceholders(const StringPiece& format_string, const std::vector& subst, std::vector* offsets) { return DoReplaceStringPlaceholders(format_string, subst, offsets); @@ -859,161 +993,6 @@ string16 ReplaceStringPlaceholders(const string16& format_string, return result; } -static bool IsWildcard(base_icu::UChar32 character) { - return character == '*' || character == '?'; -} - -// Move the strings pointers to the point where they start to differ. -template -static void EatSameChars(const CHAR** pattern, const CHAR* pattern_end, - const CHAR** string, const CHAR* string_end, - NEXT next) { - const CHAR* escape = NULL; - while (*pattern != pattern_end && *string != string_end) { - if (!escape && IsWildcard(**pattern)) { - // We don't want to match wildcard here, except if it's escaped. - return; - } - - // Check if the escapement char is found. If so, skip it and move to the - // next character. - if (!escape && **pattern == '\\') { - escape = *pattern; - next(pattern, pattern_end); - continue; - } - - // Check if the chars match, if so, increment the ptrs. - const CHAR* pattern_next = *pattern; - const CHAR* string_next = *string; - base_icu::UChar32 pattern_char = next(&pattern_next, pattern_end); - if (pattern_char == next(&string_next, string_end) && - pattern_char != CBU_SENTINEL) { - *pattern = pattern_next; - *string = string_next; - } else { - // Uh oh, it did not match, we are done. If the last char was an - // escapement, that means that it was an error to advance the ptr here, - // let's put it back where it was. This also mean that the MatchPattern - // function will return false because if we can't match an escape char - // here, then no one will. - if (escape) { - *pattern = escape; - } - return; - } - - escape = NULL; - } -} - -template -static void EatWildcard(const CHAR** pattern, const CHAR* end, NEXT next) { - while (*pattern != end) { - if (!IsWildcard(**pattern)) - return; - next(pattern, end); - } -} - -template -static bool MatchPatternT(const CHAR* eval, const CHAR* eval_end, - const CHAR* pattern, const CHAR* pattern_end, - int depth, - NEXT next) { - const int kMaxDepth = 16; - if (depth > kMaxDepth) - return false; - - // Eat all the matching chars. - EatSameChars(&pattern, pattern_end, &eval, eval_end, next); - - // If the string is empty, then the pattern must be empty too, or contains - // only wildcards. - if (eval == eval_end) { - EatWildcard(&pattern, pattern_end, next); - return pattern == pattern_end; - } - - // Pattern is empty but not string, this is not a match. - if (pattern == pattern_end) - return false; - - // If this is a question mark, then we need to compare the rest with - // the current string or the string with one character eaten. - const CHAR* next_pattern = pattern; - next(&next_pattern, pattern_end); - if (pattern[0] == '?') { - if (MatchPatternT(eval, eval_end, next_pattern, pattern_end, - depth + 1, next)) - return true; - const CHAR* next_eval = eval; - next(&next_eval, eval_end); - if (MatchPatternT(next_eval, eval_end, next_pattern, pattern_end, - depth + 1, next)) - return true; - } - - // This is a *, try to match all the possible substrings with the remainder - // of the pattern. - if (pattern[0] == '*') { - // Collapse duplicate wild cards (********** into *) so that the - // method does not recurse unnecessarily. http://crbug.com/52839 - EatWildcard(&next_pattern, pattern_end, next); - - while (eval != eval_end) { - if (MatchPatternT(eval, eval_end, next_pattern, pattern_end, - depth + 1, next)) - return true; - eval++; - } - - // We reached the end of the string, let see if the pattern contains only - // wildcards. - if (eval == eval_end) { - EatWildcard(&pattern, pattern_end, next); - if (pattern != pattern_end) - return false; - return true; - } - } - - return false; -} - -struct NextCharUTF8 { - base_icu::UChar32 operator()(const char** p, const char* end) { - base_icu::UChar32 c; - int offset = 0; - CBU8_NEXT(*p, offset, end - *p, c); - *p += offset; - return c; - } -}; - -struct NextCharUTF16 { - base_icu::UChar32 operator()(const char16** p, const char16* end) { - base_icu::UChar32 c; - int offset = 0; - CBU16_NEXT(*p, offset, end - *p, c); - *p += offset; - return c; - } -}; - -bool MatchPattern(const base::StringPiece& eval, - const base::StringPiece& pattern) { - return MatchPatternT(eval.data(), eval.data() + eval.size(), - pattern.data(), pattern.data() + pattern.size(), - 0, NextCharUTF8()); -} - -bool MatchPattern(const string16& eval, const string16& pattern) { - return MatchPatternT(eval.c_str(), eval.c_str() + eval.size(), - pattern.c_str(), pattern.c_str() + pattern.size(), - 0, NextCharUTF16()); -} - // The following code is compatible with the OpenBSD lcpy interface. See: // http://www.gratisoft.us/todd/papers/strlcpy.html // ftp://ftp.openbsd.org/pub/OpenBSD/src/lib/libc/string/{wcs,str}lcpy.c @@ -1038,9 +1017,11 @@ size_t lcpyT(CHAR* dst, const CHAR* src, size_t dst_size) { } // namespace -size_t base::strlcpy(char* dst, const char* src, size_t dst_size) { +size_t strlcpy(char* dst, const char* src, size_t dst_size) { return lcpyT(dst, src, dst_size); } -size_t base::wcslcpy(wchar_t* dst, const wchar_t* src, size_t dst_size) { +size_t wcslcpy(wchar_t* dst, const wchar_t* src, size_t dst_size) { return lcpyT(dst, src, dst_size); } + +} // namespace base diff --git a/base/strings/string_util.h b/base/strings/string_util.h index bea44ae8fddba..755215c0850da 100644 --- a/base/strings/string_util.h +++ b/base/strings/string_util.h @@ -21,23 +21,10 @@ namespace base { -// C standard-library functions like "strncasecmp" and "snprintf" that aren't -// cross-platform are provided as "base::strncasecmp", and their prototypes -// are listed below. These functions are then implemented as inline calls -// to the platform-specific equivalents in the platform-specific headers. - -// Compares the two strings s1 and s2 without regard to case using -// the current locale; returns 0 if they are equal, 1 if s1 > s2, and -1 if -// s2 > s1 according to a lexicographic comparison. -int strcasecmp(const char* s1, const char* s2); - -// Compares up to count characters of s1 and s2 without regard to case using -// the current locale; returns 0 if they are equal, 1 if s1 > s2, and -1 if -// s2 > s1 according to a lexicographic comparison. -int strncasecmp(const char* s1, const char* s2, size_t count); - -// Same as strncmp but for char16 strings. -int strncmp16(const char16* s1, const char16* s2, size_t count); +// C standard-library functions that aren't cross-platform are provided as +// "base::...", and their prototypes are listed below. These functions are +// then implemented as inline calls to the platform-specific equivalents in the +// platform-specific headers. // Wrapper for vsnprintf that always null-terminates and always returns the // number of characters that would be in an untruncated formatted @@ -59,6 +46,19 @@ inline int snprintf(char* buffer, size_t size, const char* format, ...) { return result; } +// TODO(mark) http://crbug.com/472900 crashpad shouldn't use base while +// being DEPSed in. This backwards-compat hack is provided until crashpad is +// updated. +#if defined(OS_WIN) +inline int strcasecmp(const char* s1, const char* s2) { + return _stricmp(s1, s2); +} +#else // Posix +inline int strcasecmp(const char* string1, const char* string2) { + return ::strcasecmp(string1, string2); +} +#endif + // BSD-style safe and consistent string copy functions. // Copies |src| to |dst|, where |dst_size| is the total allocated size of |dst|. // Copies at most |dst_size|-1 characters, and always NULL terminates |dst|, as @@ -103,17 +103,14 @@ template inline Char ToUpperASCII(Char c) { return (c >= 'a' && c <= 'z') ? (c + ('A' - 'a')) : c; } -// Function objects to aid in comparing/searching strings. - -template struct CaseInsensitiveCompare { - public: - bool operator()(Char x, Char y) const { - // TODO(darin): Do we really want to do locale sensitive comparisons here? - // See http://crbug.com/24917 - return tolower(x) == tolower(y); - } -}; - +// Functor for case-insensitive ASCII comparisons for STL algorithms like +// std::search. +// +// Note that a full Unicode version of this functor is not possible to write +// because case mappings might change the number of characters, depend on +// context (combining accents), and require handling UTF-16. If you need +// proper Unicode support, use base::i18n::ToLower/FoldCase and then just +// use a normal operator== on the result. template struct CaseInsensitiveCompareASCII { public: bool operator()(Char x, Char y) const { @@ -121,6 +118,22 @@ template struct CaseInsensitiveCompareASCII { } }; +// Like strcasecmp for case-insensitive ASCII characters only. Returns: +// -1 (a < b) +// 0 (a == b) +// 1 (a > b) +// (unlike strcasecmp which can return values greater or less than 1/-1). For +// full Unicode support, use base::i18n::ToLower or base::i18h::FoldCase +// and then just call the normal string operators on the result. +BASE_EXPORT int CompareCaseInsensitiveASCII(StringPiece a, StringPiece b); +BASE_EXPORT int CompareCaseInsensitiveASCII(StringPiece16 a, StringPiece16 b); + +// Equality for ASCII case-insensitive comparisons. For full Unicode support, +// use base::i18n::ToLower or base::i18h::FoldCase and then compare with either +// == or !=. +BASE_EXPORT bool EqualsCaseInsensitiveASCII(StringPiece a, StringPiece b); +BASE_EXPORT bool EqualsCaseInsensitiveASCII(StringPiece16 a, StringPiece16 b); + // These threadsafe functions return references to globally unique empty // strings. // @@ -138,10 +151,12 @@ BASE_EXPORT const std::string& EmptyString(); BASE_EXPORT const string16& EmptyString16(); // Contains the set of characters representing whitespace in the corresponding -// encoding. Null-terminated. -BASE_EXPORT extern const wchar_t kWhitespaceWide[]; -BASE_EXPORT extern const char16 kWhitespaceUTF16[]; +// encoding. Null-terminated. The ASCII versions are the whitespaces as defined +// by HTML5, and don't include control characters. +BASE_EXPORT extern const wchar_t kWhitespaceWide[]; // Includes Unicode. +BASE_EXPORT extern const char16 kWhitespaceUTF16[]; // Includes Unicode. BASE_EXPORT extern const char kWhitespaceASCII[]; +BASE_EXPORT extern const char16 kWhitespaceASCIIAs16[]; // No unicode. // Null-terminated string representing the UTF-8 byte order mark. BASE_EXPORT extern const char kUtf8ByteOrderMark[]; @@ -150,10 +165,10 @@ BASE_EXPORT extern const char kUtf8ByteOrderMark[]; // if any characters were removed. |remove_chars| must be null-terminated. // NOTE: Safe to use the same variable for both |input| and |output|. BASE_EXPORT bool RemoveChars(const string16& input, - const base::StringPiece16& remove_chars, + const StringPiece16& remove_chars, string16* output); BASE_EXPORT bool RemoveChars(const std::string& input, - const base::StringPiece& remove_chars, + const StringPiece& remove_chars, std::string* output); // Replaces characters in |replace_chars| from anywhere in |input| with @@ -162,49 +177,65 @@ BASE_EXPORT bool RemoveChars(const std::string& input, // |replace_chars| must be null-terminated. // NOTE: Safe to use the same variable for both |input| and |output|. BASE_EXPORT bool ReplaceChars(const string16& input, - const base::StringPiece16& replace_chars, + const StringPiece16& replace_chars, const string16& replace_with, string16* output); BASE_EXPORT bool ReplaceChars(const std::string& input, - const base::StringPiece& replace_chars, + const StringPiece& replace_chars, const std::string& replace_with, std::string* output); +enum TrimPositions { + TRIM_NONE = 0, + TRIM_LEADING = 1 << 0, + TRIM_TRAILING = 1 << 1, + TRIM_ALL = TRIM_LEADING | TRIM_TRAILING, +}; + // Removes characters in |trim_chars| from the beginning and end of |input|. -// |trim_chars| must be null-terminated. -// NOTE: Safe to use the same variable for both |input| and |output|. +// The 8-bit version only works on 8-bit characters, not UTF-8. +// +// It is safe to use the same variable for both |input| and |output| (this is +// the normal usage to trim in-place). BASE_EXPORT bool TrimString(const string16& input, - const base::StringPiece16& trim_chars, + StringPiece16 trim_chars, string16* output); BASE_EXPORT bool TrimString(const std::string& input, - const base::StringPiece& trim_chars, + StringPiece trim_chars, std::string* output); +// StringPiece versions of the above. The returned pieces refer to the original +// buffer. +BASE_EXPORT StringPiece16 TrimString(StringPiece16 input, + const StringPiece16& trim_chars, + TrimPositions positions); +BASE_EXPORT StringPiece TrimString(StringPiece input, + const StringPiece& trim_chars, + TrimPositions positions); + // Truncates a string to the nearest UTF-8 character that will leave // the string less than or equal to the specified byte size. BASE_EXPORT void TruncateUTF8ToByteSize(const std::string& input, const size_t byte_size, std::string* output); -// Trims any whitespace from either end of the input string. Returns where -// whitespace was found. -// The non-wide version has two functions: -// * TrimWhitespaceASCII() -// This function is for ASCII strings and only looks for ASCII whitespace; -// Please choose the best one according to your usage. +// Trims any whitespace from either end of the input string. +// +// The StringPiece versions return a substring referencing the input buffer. +// The ASCII versions look only for ASCII whitespace. +// +// The std::string versions return where whitespace was found. // NOTE: Safe to use the same variable for both input and output. -enum TrimPositions { - TRIM_NONE = 0, - TRIM_LEADING = 1 << 0, - TRIM_TRAILING = 1 << 1, - TRIM_ALL = TRIM_LEADING | TRIM_TRAILING, -}; BASE_EXPORT TrimPositions TrimWhitespace(const string16& input, TrimPositions positions, - base::string16* output); + string16* output); +BASE_EXPORT StringPiece16 TrimWhitespace(StringPiece16 input, + TrimPositions positions); BASE_EXPORT TrimPositions TrimWhitespaceASCII(const std::string& input, TrimPositions positions, std::string* output); +BASE_EXPORT StringPiece TrimWhitespaceASCII(StringPiece input, + TrimPositions positions); // Deprecated. This function is only for backward compatibility and calls // TrimWhitespaceASCII(). @@ -315,32 +346,41 @@ BASE_EXPORT bool LowerCaseEqualsASCII(const char16* a_begin, // strings are not ASCII. BASE_EXPORT bool EqualsASCII(const string16& a, const StringPiece& b); -} // namespace base - -#if defined(OS_WIN) -#include "base/strings/string_util_win.h" -#elif defined(OS_POSIX) -#include "base/strings/string_util_posix.h" -#else -#error Define string operations appropriately for your platform -#endif - -// Returns true if str starts with search, or false otherwise. -BASE_EXPORT bool StartsWithASCII(const std::string& str, - const std::string& search, - bool case_sensitive); -BASE_EXPORT bool StartsWith(const base::string16& str, - const base::string16& search, - bool case_sensitive); - -// Returns true if str ends with search, or false otherwise. -BASE_EXPORT bool EndsWith(const std::string& str, - const std::string& search, - bool case_sensitive); -BASE_EXPORT bool EndsWith(const base::string16& str, - const base::string16& search, - bool case_sensitive); +// Indicates case sensitivity of comparisons. Only ASCII case insensitivity +// is supported. Full Unicode case-insensitive conversions would need to go in +// base/i18n so it can use ICU. +// +// If you need to do Unicode-aware case-insensitive StartsWith/EndsWith, it's +// best to call base::i18n::ToLower() or base::i18n::FoldCase() (see +// base/i18n/case_conversion.h for usage advice) on the arguments, and then use +// the results to a case-sensitive comparison. +enum class CompareCase { + SENSITIVE, + INSENSITIVE_ASCII, +}; +BASE_EXPORT bool StartsWith(StringPiece str, + StringPiece search_for, + CompareCase case_sensitivity); +BASE_EXPORT bool StartsWith(StringPiece16 str, + StringPiece16 search_for, + CompareCase case_sensitivity); +BASE_EXPORT bool EndsWith(StringPiece str, + StringPiece search_for, + CompareCase case_sensitivity); +BASE_EXPORT bool EndsWith(StringPiece16 str, + StringPiece16 search_for, + CompareCase case_sensitivity); + +// DEPRECATED. Returns true if str starts/ends with search, or false otherwise. +// TODO(brettw) remove in favor of the "enum" versions above. +inline bool StartsWithASCII(const std::string& str, + const std::string& search, + bool case_sensitive) { + return StartsWith(StringPiece(str), StringPiece(search), + case_sensitive ? CompareCase::SENSITIVE + : CompareCase::INSENSITIVE_ASCII); +} // Determines the type of ASCII character, independent of locale (the C // library versions will change based on locale). @@ -364,20 +404,15 @@ inline bool IsHexDigit(Char c) { (c >= 'a' && c <= 'f'); } -template -inline char HexDigitToInt(Char c) { - DCHECK(IsHexDigit(c)); - if (c >= '0' && c <= '9') - return static_cast(c - '0'); - if (c >= 'A' && c <= 'F') - return static_cast(c - 'A' + 10); - if (c >= 'a' && c <= 'f') - return static_cast(c - 'a' + 10); - return 0; -} +// Returns the integer corresponding to the given hex character. For example: +// '4' -> 4 +// 'a' -> 10 +// 'B' -> 11 +// Assumes the input is a valid hex character. DCHECKs in debug builds if not. +BASE_EXPORT char HexDigitToInt(wchar_t c); -// Returns true if it's a whitespace character. -inline bool IsWhitespace(wchar_t c) { +// Returns true if it's a Unicode whitespace character. +inline bool IsUnicodeWhitespace(wchar_t c) { return wcschr(base::kWhitespaceWide, c) != NULL; } @@ -385,20 +420,20 @@ inline bool IsWhitespace(wchar_t c) { // appropriate for use in any UI; use of FormatBytes and friends in ui/base is // highly recommended instead. TODO(avi): Figure out how to get callers to use // FormatBytes instead; remove this. -BASE_EXPORT base::string16 FormatBytesUnlocalized(int64 bytes); +BASE_EXPORT string16 FormatBytesUnlocalized(int64 bytes); // Starting at |start_offset| (usually 0), replace the first instance of // |find_this| with |replace_with|. BASE_EXPORT void ReplaceFirstSubstringAfterOffset( base::string16* str, size_t start_offset, - const base::string16& find_this, - const base::string16& replace_with); + StringPiece16 find_this, + StringPiece16 replace_with); BASE_EXPORT void ReplaceFirstSubstringAfterOffset( std::string* str, size_t start_offset, - const std::string& find_this, - const std::string& replace_with); + StringPiece find_this, + StringPiece replace_with); // Starting at |start_offset| (usually 0), look through |str| and replace all // instances of |find_this| with |replace_with|. @@ -407,14 +442,15 @@ BASE_EXPORT void ReplaceFirstSubstringAfterOffset( // characters, for example: // std::replace(str.begin(), str.end(), 'a', 'b'); BASE_EXPORT void ReplaceSubstringsAfterOffset( - base::string16* str, + string16* str, size_t start_offset, - const base::string16& find_this, - const base::string16& replace_with); -BASE_EXPORT void ReplaceSubstringsAfterOffset(std::string* str, - size_t start_offset, - const std::string& find_this, - const std::string& replace_with); + StringPiece16 find_this, + StringPiece16 replace_with); +BASE_EXPORT void ReplaceSubstringsAfterOffset( + std::string* str, + size_t start_offset, + StringPiece find_this, + StringPiece replace_with); // Reserves enough memory in |str| to accommodate |length_with_null| characters, // sets the size of |str| to |length_with_null - 1| characters, and returns a @@ -436,72 +472,45 @@ BASE_EXPORT void ReplaceSubstringsAfterOffset(std::string* str, // of the string, and not doing that will mean people who access |str| rather // than str.c_str() will get back a string of whatever size |str| had on entry // to this function (probably 0). -template -inline typename string_type::value_type* WriteInto(string_type* str, - size_t length_with_null) { - DCHECK_GT(length_with_null, 1u); - str->reserve(length_with_null); - str->resize(length_with_null - 1); - return &((*str)[0]); -} - -//----------------------------------------------------------------------------- - -// Splits a string into its fields delimited by any of the characters in -// |delimiters|. Each field is added to the |tokens| vector. Returns the -// number of tokens found. -BASE_EXPORT size_t Tokenize(const base::string16& str, - const base::string16& delimiters, - std::vector* tokens); -BASE_EXPORT size_t Tokenize(const std::string& str, - const std::string& delimiters, - std::vector* tokens); -BASE_EXPORT size_t Tokenize(const base::StringPiece& str, - const base::StringPiece& delimiters, - std::vector* tokens); +BASE_EXPORT char* WriteInto(std::string* str, size_t length_with_null); +BASE_EXPORT char16* WriteInto(string16* str, size_t length_with_null); +#ifndef OS_WIN +BASE_EXPORT wchar_t* WriteInto(std::wstring* str, size_t length_with_null); +#endif // Does the opposite of SplitString(). -BASE_EXPORT base::string16 JoinString(const std::vector& parts, - base::char16 s); -BASE_EXPORT std::string JoinString( - const std::vector& parts, char s); - -// Join |parts| using |separator|. -BASE_EXPORT std::string JoinString( - const std::vector& parts, - const std::string& separator); -BASE_EXPORT base::string16 JoinString( - const std::vector& parts, - const base::string16& separator); +BASE_EXPORT std::string JoinString(const std::vector& parts, + StringPiece separator); +BASE_EXPORT string16 JoinString(const std::vector& parts, + StringPiece16 separator); // Replace $1-$2-$3..$9 in the format string with |a|-|b|-|c|..|i| respectively. // Additionally, any number of consecutive '$' characters is replaced by that // number less one. Eg $$->$, $$$->$$, etc. The offsets parameter here can be // NULL. This only allows you to use up to nine replacements. -BASE_EXPORT base::string16 ReplaceStringPlaceholders( - const base::string16& format_string, - const std::vector& subst, +BASE_EXPORT string16 ReplaceStringPlaceholders( + const string16& format_string, + const std::vector& subst, std::vector* offsets); BASE_EXPORT std::string ReplaceStringPlaceholders( - const base::StringPiece& format_string, + const StringPiece& format_string, const std::vector& subst, std::vector* offsets); // Single-string shortcut for ReplaceStringHolders. |offset| may be NULL. -BASE_EXPORT base::string16 ReplaceStringPlaceholders( - const base::string16& format_string, - const base::string16& a, - size_t* offset); - -// Returns true if the string passed in matches the pattern. The pattern -// string can contain wildcards like * and ? -// The backslash character (\) is an escape character for * and ? -// We limit the patterns to having a max of 16 * or ? characters. -// ? matches 0 or 1 character, while * matches 0 or more characters. -BASE_EXPORT bool MatchPattern(const base::StringPiece& string, - const base::StringPiece& pattern); -BASE_EXPORT bool MatchPattern(const base::string16& string, - const base::string16& pattern); +BASE_EXPORT string16 ReplaceStringPlaceholders(const string16& format_string, + const string16& a, + size_t* offset); + +} // namespace base + +#if defined(OS_WIN) +#include "base/strings/string_util_win.h" +#elif defined(OS_POSIX) +#include "base/strings/string_util_posix.h" +#else +#error Define string operations appropriately for your platform +#endif #endif // BASE_STRINGS_STRING_UTIL_H_ diff --git a/base/strings/string_util_constants.cc b/base/strings/string_util_constants.cc index 146e5fd535563..aba1b12b88f0a 100644 --- a/base/strings/string_util_constants.cc +++ b/base/strings/string_util_constants.cc @@ -52,6 +52,16 @@ const char kWhitespaceASCII[] = { 0 }; +const char16 kWhitespaceASCIIAs16[] = { + 0x09, // CHARACTER TABULATION + 0x0A, // LINE FEED (LF) + 0x0B, // LINE TABULATION + 0x0C, // FORM FEED (FF) + 0x0D, // CARRIAGE RETURN (CR) + 0x20, // SPACE + 0 +}; + const char kUtf8ByteOrderMark[] = "\xEF\xBB\xBF"; } // namespace base diff --git a/base/strings/string_util_posix.h b/base/strings/string_util_posix.h index f4009d4ae7f1e..9e96697ff5625 100644 --- a/base/strings/string_util_posix.h +++ b/base/strings/string_util_posix.h @@ -20,27 +20,11 @@ inline char* strdup(const char* str) { return ::strdup(str); } -inline int strcasecmp(const char* string1, const char* string2) { - return ::strcasecmp(string1, string2); -} - -inline int strncasecmp(const char* string1, const char* string2, size_t count) { - return ::strncasecmp(string1, string2, count); -} - inline int vsnprintf(char* buffer, size_t size, const char* format, va_list arguments) { return ::vsnprintf(buffer, size, format, arguments); } -inline int strncmp16(const char16* s1, const char16* s2, size_t count) { -#if defined(WCHAR_T_IS_UTF16) - return ::wcsncmp(s1, s2, count); -#elif defined(WCHAR_T_IS_UTF32) - return c16memcmp(s1, s2, count); -#endif -} - inline int vswprintf(wchar_t* buffer, size_t size, const wchar_t* format, va_list arguments) { DCHECK(IsWprintfFormatPortable(format)); diff --git a/base/strings/string_util_unittest.cc b/base/strings/string_util_unittest.cc index fb0beada4b344..eb6cd7ecfc14d 100644 --- a/base/strings/string_util_unittest.cc +++ b/base/strings/string_util_unittest.cc @@ -669,128 +669,7 @@ TEST(StringUtilTest, HexDigitToInt) { EXPECT_EQ(15, HexDigitToInt('f')); } -// Test for Tokenize -template -void TokenizeTest() { - std::vector r; - size_t size; - - size = Tokenize(STR("This is a string"), STR(" "), &r); - EXPECT_EQ(4U, size); - ASSERT_EQ(4U, r.size()); - EXPECT_EQ(r[0], STR("This")); - EXPECT_EQ(r[1], STR("is")); - EXPECT_EQ(r[2], STR("a")); - EXPECT_EQ(r[3], STR("string")); - r.clear(); - - size = Tokenize(STR("one,two,three"), STR(","), &r); - EXPECT_EQ(3U, size); - ASSERT_EQ(3U, r.size()); - EXPECT_EQ(r[0], STR("one")); - EXPECT_EQ(r[1], STR("two")); - EXPECT_EQ(r[2], STR("three")); - r.clear(); - - size = Tokenize(STR("one,two:three;four"), STR(",:"), &r); - EXPECT_EQ(3U, size); - ASSERT_EQ(3U, r.size()); - EXPECT_EQ(r[0], STR("one")); - EXPECT_EQ(r[1], STR("two")); - EXPECT_EQ(r[2], STR("three;four")); - r.clear(); - - size = Tokenize(STR("one,two:three;four"), STR(";,:"), &r); - EXPECT_EQ(4U, size); - ASSERT_EQ(4U, r.size()); - EXPECT_EQ(r[0], STR("one")); - EXPECT_EQ(r[1], STR("two")); - EXPECT_EQ(r[2], STR("three")); - EXPECT_EQ(r[3], STR("four")); - r.clear(); - - size = Tokenize(STR("one, two, three"), STR(","), &r); - EXPECT_EQ(3U, size); - ASSERT_EQ(3U, r.size()); - EXPECT_EQ(r[0], STR("one")); - EXPECT_EQ(r[1], STR(" two")); - EXPECT_EQ(r[2], STR(" three")); - r.clear(); - - size = Tokenize(STR("one, two, three, "), STR(","), &r); - EXPECT_EQ(4U, size); - ASSERT_EQ(4U, r.size()); - EXPECT_EQ(r[0], STR("one")); - EXPECT_EQ(r[1], STR(" two")); - EXPECT_EQ(r[2], STR(" three")); - EXPECT_EQ(r[3], STR(" ")); - r.clear(); - - size = Tokenize(STR("one, two, three,"), STR(","), &r); - EXPECT_EQ(3U, size); - ASSERT_EQ(3U, r.size()); - EXPECT_EQ(r[0], STR("one")); - EXPECT_EQ(r[1], STR(" two")); - EXPECT_EQ(r[2], STR(" three")); - r.clear(); - - size = Tokenize(STR(), STR(","), &r); - EXPECT_EQ(0U, size); - ASSERT_EQ(0U, r.size()); - r.clear(); - - size = Tokenize(STR(","), STR(","), &r); - EXPECT_EQ(0U, size); - ASSERT_EQ(0U, r.size()); - r.clear(); - - size = Tokenize(STR(",;:."), STR(".:;,"), &r); - EXPECT_EQ(0U, size); - ASSERT_EQ(0U, r.size()); - r.clear(); - - size = Tokenize(STR("\t\ta\t"), STR("\t"), &r); - EXPECT_EQ(1U, size); - ASSERT_EQ(1U, r.size()); - EXPECT_EQ(r[0], STR("a")); - r.clear(); - - size = Tokenize(STR("\ta\t\nb\tcc"), STR("\n"), &r); - EXPECT_EQ(2U, size); - ASSERT_EQ(2U, r.size()); - EXPECT_EQ(r[0], STR("\ta\t")); - EXPECT_EQ(r[1], STR("b\tcc")); - r.clear(); -} - -TEST(StringUtilTest, TokenizeStdString) { - TokenizeTest(); -} - -TEST(StringUtilTest, TokenizeStringPiece) { - TokenizeTest(); -} - -// Test for JoinString TEST(StringUtilTest, JoinString) { - std::vector in; - EXPECT_EQ("", JoinString(in, ',')); - - in.push_back("a"); - EXPECT_EQ("a", JoinString(in, ',')); - - in.push_back("b"); - in.push_back("c"); - EXPECT_EQ("a,b,c", JoinString(in, ',')); - - in.push_back(std::string()); - EXPECT_EQ("a,b,c,", JoinString(in, ',')); - in.push_back(" "); - EXPECT_EQ("a|b|c|| ", JoinString(in, '|')); -} - -// Test for JoinString overloaded with std::string separator -TEST(StringUtilTest, JoinStringWithString) { std::string separator(", "); std::vector parts; EXPECT_EQ(std::string(), JoinString(parts, separator)); @@ -808,8 +687,7 @@ TEST(StringUtilTest, JoinStringWithString) { EXPECT_EQ("a|b|c|| ", JoinString(parts, "|")); } -// Test for JoinString overloaded with string16 separator -TEST(StringUtilTest, JoinStringWithString16) { +TEST(StringUtilTest, JoinString16) { string16 separator = ASCIIToUTF16(", "); std::vector parts; EXPECT_EQ(string16(), JoinString(parts, separator)); @@ -828,59 +706,83 @@ TEST(StringUtilTest, JoinStringWithString16) { } TEST(StringUtilTest, StartsWith) { - EXPECT_TRUE(StartsWithASCII("javascript:url", "javascript", true)); - EXPECT_FALSE(StartsWithASCII("JavaScript:url", "javascript", true)); - EXPECT_TRUE(StartsWithASCII("javascript:url", "javascript", false)); - EXPECT_TRUE(StartsWithASCII("JavaScript:url", "javascript", false)); - EXPECT_FALSE(StartsWithASCII("java", "javascript", true)); - EXPECT_FALSE(StartsWithASCII("java", "javascript", false)); - EXPECT_FALSE(StartsWithASCII(std::string(), "javascript", false)); - EXPECT_FALSE(StartsWithASCII(std::string(), "javascript", true)); - EXPECT_TRUE(StartsWithASCII("java", std::string(), false)); - EXPECT_TRUE(StartsWithASCII("java", std::string(), true)); + EXPECT_TRUE(StartsWith("javascript:url", "javascript", + base::CompareCase::SENSITIVE)); + EXPECT_FALSE(StartsWith("JavaScript:url", "javascript", + base::CompareCase::SENSITIVE)); + EXPECT_TRUE(StartsWith("javascript:url", "javascript", + base::CompareCase::INSENSITIVE_ASCII)); + EXPECT_TRUE(StartsWith("JavaScript:url", "javascript", + base::CompareCase::INSENSITIVE_ASCII)); + EXPECT_FALSE(StartsWith("java", "javascript", base::CompareCase::SENSITIVE)); + EXPECT_FALSE(StartsWith("java", "javascript", + base::CompareCase::INSENSITIVE_ASCII)); + EXPECT_FALSE(StartsWith(std::string(), "javascript", + base::CompareCase::INSENSITIVE_ASCII)); + EXPECT_FALSE(StartsWith(std::string(), "javascript", + base::CompareCase::SENSITIVE)); + EXPECT_TRUE(StartsWith("java", std::string(), + base::CompareCase::INSENSITIVE_ASCII)); + EXPECT_TRUE(StartsWith("java", std::string(), base::CompareCase::SENSITIVE)); EXPECT_TRUE(StartsWith(ASCIIToUTF16("javascript:url"), - ASCIIToUTF16("javascript"), true)); + ASCIIToUTF16("javascript"), + base::CompareCase::SENSITIVE)); EXPECT_FALSE(StartsWith(ASCIIToUTF16("JavaScript:url"), - ASCIIToUTF16("javascript"), true)); + ASCIIToUTF16("javascript"), + base::CompareCase::SENSITIVE)); EXPECT_TRUE(StartsWith(ASCIIToUTF16("javascript:url"), - ASCIIToUTF16("javascript"), false)); + ASCIIToUTF16("javascript"), + base::CompareCase::INSENSITIVE_ASCII)); EXPECT_TRUE(StartsWith(ASCIIToUTF16("JavaScript:url"), - ASCIIToUTF16("javascript"), false)); - EXPECT_FALSE(StartsWith(ASCIIToUTF16("java"), - ASCIIToUTF16("javascript"), true)); - EXPECT_FALSE(StartsWith(ASCIIToUTF16("java"), - ASCIIToUTF16("javascript"), false)); - EXPECT_FALSE(StartsWith(string16(), ASCIIToUTF16("javascript"), false)); - EXPECT_FALSE(StartsWith(string16(), ASCIIToUTF16("javascript"), true)); - EXPECT_TRUE(StartsWith(ASCIIToUTF16("java"), string16(), false)); - EXPECT_TRUE(StartsWith(ASCIIToUTF16("java"), string16(), true)); + ASCIIToUTF16("javascript"), + base::CompareCase::INSENSITIVE_ASCII)); + EXPECT_FALSE(StartsWith(ASCIIToUTF16("java"), ASCIIToUTF16("javascript"), + base::CompareCase::SENSITIVE)); + EXPECT_FALSE(StartsWith(ASCIIToUTF16("java"), ASCIIToUTF16("javascript"), + base::CompareCase::INSENSITIVE_ASCII)); + EXPECT_FALSE(StartsWith(string16(), ASCIIToUTF16("javascript"), + base::CompareCase::INSENSITIVE_ASCII)); + EXPECT_FALSE(StartsWith(string16(), ASCIIToUTF16("javascript"), + base::CompareCase::SENSITIVE)); + EXPECT_TRUE(StartsWith(ASCIIToUTF16("java"), string16(), + base::CompareCase::INSENSITIVE_ASCII)); + EXPECT_TRUE(StartsWith(ASCIIToUTF16("java"), string16(), + base::CompareCase::SENSITIVE)); } TEST(StringUtilTest, EndsWith) { - EXPECT_TRUE(EndsWith(ASCIIToUTF16("Foo.plugin"), - ASCIIToUTF16(".plugin"), true)); - EXPECT_FALSE(EndsWith(ASCIIToUTF16("Foo.Plugin"), - ASCIIToUTF16(".plugin"), true)); - EXPECT_TRUE(EndsWith(ASCIIToUTF16("Foo.plugin"), - ASCIIToUTF16(".plugin"), false)); - EXPECT_TRUE(EndsWith(ASCIIToUTF16("Foo.Plugin"), - ASCIIToUTF16(".plugin"), false)); - EXPECT_FALSE(EndsWith(ASCIIToUTF16(".plug"), ASCIIToUTF16(".plugin"), true)); - EXPECT_FALSE(EndsWith(ASCIIToUTF16(".plug"), ASCIIToUTF16(".plugin"), false)); - EXPECT_FALSE(EndsWith(ASCIIToUTF16("Foo.plugin Bar"), - ASCIIToUTF16(".plugin"), true)); - EXPECT_FALSE(EndsWith(ASCIIToUTF16("Foo.plugin Bar"), - ASCIIToUTF16(".plugin"), false)); - EXPECT_FALSE(EndsWith(string16(), ASCIIToUTF16(".plugin"), false)); - EXPECT_FALSE(EndsWith(string16(), ASCIIToUTF16(".plugin"), true)); - EXPECT_TRUE(EndsWith(ASCIIToUTF16("Foo.plugin"), string16(), false)); - EXPECT_TRUE(EndsWith(ASCIIToUTF16("Foo.plugin"), string16(), true)); - EXPECT_TRUE(EndsWith(ASCIIToUTF16(".plugin"), - ASCIIToUTF16(".plugin"), false)); - EXPECT_TRUE(EndsWith(ASCIIToUTF16(".plugin"), ASCIIToUTF16(".plugin"), true)); - EXPECT_TRUE(EndsWith(string16(), string16(), false)); - EXPECT_TRUE(EndsWith(string16(), string16(), true)); + EXPECT_TRUE(EndsWith(ASCIIToUTF16("Foo.plugin"), ASCIIToUTF16(".plugin"), + base::CompareCase::SENSITIVE)); + EXPECT_FALSE(EndsWith(ASCIIToUTF16("Foo.Plugin"), ASCIIToUTF16(".plugin"), + base::CompareCase::SENSITIVE)); + EXPECT_TRUE(EndsWith(ASCIIToUTF16("Foo.plugin"), ASCIIToUTF16(".plugin"), + base::CompareCase::INSENSITIVE_ASCII)); + EXPECT_TRUE(EndsWith(ASCIIToUTF16("Foo.Plugin"), ASCIIToUTF16(".plugin"), + base::CompareCase::INSENSITIVE_ASCII)); + EXPECT_FALSE(EndsWith(ASCIIToUTF16(".plug"), ASCIIToUTF16(".plugin"), + base::CompareCase::SENSITIVE)); + EXPECT_FALSE(EndsWith(ASCIIToUTF16(".plug"), ASCIIToUTF16(".plugin"), + base::CompareCase::INSENSITIVE_ASCII)); + EXPECT_FALSE(EndsWith(ASCIIToUTF16("Foo.plugin Bar"), ASCIIToUTF16(".plugin"), + base::CompareCase::SENSITIVE)); + EXPECT_FALSE(EndsWith(ASCIIToUTF16("Foo.plugin Bar"), ASCIIToUTF16(".plugin"), + base::CompareCase::INSENSITIVE_ASCII)); + EXPECT_FALSE(EndsWith(string16(), ASCIIToUTF16(".plugin"), + base::CompareCase::INSENSITIVE_ASCII)); + EXPECT_FALSE(EndsWith(string16(), ASCIIToUTF16(".plugin"), + base::CompareCase::SENSITIVE)); + EXPECT_TRUE(EndsWith(ASCIIToUTF16("Foo.plugin"), string16(), + base::CompareCase::INSENSITIVE_ASCII)); + EXPECT_TRUE(EndsWith(ASCIIToUTF16("Foo.plugin"), string16(), + base::CompareCase::SENSITIVE)); + EXPECT_TRUE(EndsWith(ASCIIToUTF16(".plugin"), ASCIIToUTF16(".plugin"), + base::CompareCase::INSENSITIVE_ASCII)); + EXPECT_TRUE(EndsWith(ASCIIToUTF16(".plugin"), ASCIIToUTF16(".plugin"), + base::CompareCase::SENSITIVE)); + EXPECT_TRUE( + EndsWith(string16(), string16(), base::CompareCase::INSENSITIVE_ASCII)); + EXPECT_TRUE(EndsWith(string16(), string16(), base::CompareCase::SENSITIVE)); } TEST(StringUtilTest, GetStringFWithOffsets) { @@ -994,45 +896,6 @@ TEST(StringUtilTest, ReplaceStringPlaceholdersConsecutiveDollarSigns) { "$1 $$2 $$$3"); } -TEST(StringUtilTest, MatchPatternTest) { - EXPECT_TRUE(MatchPattern("www.google.com", "*.com")); - EXPECT_TRUE(MatchPattern("www.google.com", "*")); - EXPECT_FALSE(MatchPattern("www.google.com", "www*.g*.org")); - EXPECT_TRUE(MatchPattern("Hello", "H?l?o")); - EXPECT_FALSE(MatchPattern("www.google.com", "http://*)")); - EXPECT_FALSE(MatchPattern("www.msn.com", "*.COM")); - EXPECT_TRUE(MatchPattern("Hello*1234", "He??o\\*1*")); - EXPECT_FALSE(MatchPattern("", "*.*")); - EXPECT_TRUE(MatchPattern("", "*")); - EXPECT_TRUE(MatchPattern("", "?")); - EXPECT_TRUE(MatchPattern("", "")); - EXPECT_FALSE(MatchPattern("Hello", "")); - EXPECT_TRUE(MatchPattern("Hello*", "Hello*")); - // Stop after a certain recursion depth. - EXPECT_FALSE(MatchPattern("123456789012345678", "?????????????????*")); - - // Test UTF8 matching. - EXPECT_TRUE(MatchPattern("heart: \xe2\x99\xa0", "*\xe2\x99\xa0")); - EXPECT_TRUE(MatchPattern("heart: \xe2\x99\xa0.", "heart: ?.")); - EXPECT_TRUE(MatchPattern("hearts: \xe2\x99\xa0\xe2\x99\xa0", "*")); - // Invalid sequences should be handled as a single invalid character. - EXPECT_TRUE(MatchPattern("invalid: \xef\xbf\xbe", "invalid: ?")); - // If the pattern has invalid characters, it shouldn't match anything. - EXPECT_FALSE(MatchPattern("\xf4\x90\x80\x80", "\xf4\x90\x80\x80")); - - // Test UTF16 character matching. - EXPECT_TRUE(MatchPattern(UTF8ToUTF16("www.google.com"), - UTF8ToUTF16("*.com"))); - EXPECT_TRUE(MatchPattern(UTF8ToUTF16("Hello*1234"), - UTF8ToUTF16("He??o\\*1*"))); - - // This test verifies that consecutive wild cards are collapsed into 1 - // wildcard (when this doesn't occur, MatchPattern reaches it's maximum - // recursion depth). - EXPECT_TRUE(MatchPattern(UTF8ToUTF16("Hello"), - UTF8ToUTF16("He********************************o"))); -} - TEST(StringUtilTest, LcpyTest) { // Test the normal case where we fit in our buffer. { @@ -1197,6 +1060,26 @@ TEST(StringUtilTest, ContainsOnlyChars) { kWhitespaceUTF16)); } +TEST(StringUtilTest, CompareCaseInsensitiveASCII) { + EXPECT_EQ(0, CompareCaseInsensitiveASCII("", "")); + EXPECT_EQ(0, CompareCaseInsensitiveASCII("Asdf", "aSDf")); + + // Differing lengths. + EXPECT_EQ(-1, CompareCaseInsensitiveASCII("Asdf", "aSDfA")); + EXPECT_EQ(1, CompareCaseInsensitiveASCII("AsdfA", "aSDf")); + + // Differing values. + EXPECT_EQ(-1, CompareCaseInsensitiveASCII("AsdfA", "aSDfb")); + EXPECT_EQ(1, CompareCaseInsensitiveASCII("Asdfb", "aSDfA")); +} + +TEST(StringUtilTest, EqualsCaseInsensitiveASCII) { + EXPECT_TRUE(EqualsCaseInsensitiveASCII("", "")); + EXPECT_TRUE(EqualsCaseInsensitiveASCII("Asdf", "aSDF")); + EXPECT_FALSE(EqualsCaseInsensitiveASCII("bsdf", "aSDF")); + EXPECT_FALSE(EqualsCaseInsensitiveASCII("Asdf", "aSDFz")); +} + class WriteIntoTest : public testing::Test { protected: static void WritesCorrectly(size_t num_chars) { diff --git a/base/strings/string_util_win.h b/base/strings/string_util_win.h index 61eda2009d087..839a799a157f0 100644 --- a/base/strings/string_util_win.h +++ b/base/strings/string_util_win.h @@ -20,18 +20,6 @@ inline char* strdup(const char* str) { return _strdup(str); } -inline int strcasecmp(const char* s1, const char* s2) { - return _stricmp(s1, s2); -} - -inline int strncasecmp(const char* s1, const char* s2, size_t count) { - return _strnicmp(s1, s2, count); -} - -inline int strncmp16(const char16* s1, const char16* s2, size_t count) { - return ::wcsncmp(s1, s2, count); -} - inline int vsnprintf(char* buffer, size_t size, const char* format, va_list arguments) { int length = vsnprintf_s(buffer, size, size - 1, format, arguments); diff --git a/base/strings/utf_string_conversions_unittest.cc b/base/strings/utf_string_conversions_unittest.cc index a7b12ffe0e01d..97d8cbb668c0f 100644 --- a/base/strings/utf_string_conversions_unittest.cc +++ b/base/strings/utf_string_conversions_unittest.cc @@ -185,11 +185,11 @@ TEST(UTFStringConversionsTest, ConvertUTF32ToUTF8) { #endif // defined(WCHAR_T_IS_UTF32) TEST(UTFStringConversionsTest, ConvertMultiString) { - static wchar_t wmulti[] = { - L'f', L'o', L'o', L'\0', - L'b', L'a', L'r', L'\0', - L'b', L'a', L'z', L'\0', - L'\0' + static char16 multi16[] = { + 'f', 'o', 'o', '\0', + 'b', 'a', 'r', '\0', + 'b', 'a', 'z', '\0', + '\0' }; static char multi[] = { 'f', 'o', 'o', '\0', @@ -197,13 +197,14 @@ TEST(UTFStringConversionsTest, ConvertMultiString) { 'b', 'a', 'z', '\0', '\0' }; - std::wstring wmultistring; - memcpy(WriteInto(&wmultistring, arraysize(wmulti)), wmulti, sizeof(wmulti)); - EXPECT_EQ(arraysize(wmulti) - 1, wmultistring.length()); + string16 multistring16; + memcpy(WriteInto(&multistring16, arraysize(multi16)), multi16, + sizeof(multi16)); + EXPECT_EQ(arraysize(multi16) - 1, multistring16.length()); std::string expected; memcpy(WriteInto(&expected, arraysize(multi)), multi, sizeof(multi)); EXPECT_EQ(arraysize(multi) - 1, expected.length()); - const std::string& converted = WideToUTF8(wmultistring); + const std::string& converted = UTF16ToUTF8(multistring16); EXPECT_EQ(arraysize(multi) - 1, converted.length()); EXPECT_EQ(expected, converted); } diff --git a/base/synchronization/condition_variable_win.cc b/base/synchronization/condition_variable_win.cc index 5f165c8a86ea7..470e564c5b071 100644 --- a/base/synchronization/condition_variable_win.cc +++ b/base/synchronization/condition_variable_win.cc @@ -205,10 +205,10 @@ class WinXPCondVar : public ConditionVarImpl { }; WinXPCondVar::WinXPCondVar(Lock* user_lock) - : user_lock_(*user_lock), - run_state_(RUNNING), - allocation_counter_(0), - recycling_list_size_(0) { + : run_state_(RUNNING), + user_lock_(*user_lock), + recycling_list_size_(0), + allocation_counter_(0) { DCHECK(user_lock); } diff --git a/base/sys_info.cc b/base/sys_info.cc index 8640dc14edcfc..f24ebd3547d80 100644 --- a/base/sys_info.cc +++ b/base/sys_info.cc @@ -41,14 +41,14 @@ bool SysInfo::IsLowEndDevice() { // Low End Device Mode will be enabled if this client is assigned to // one of those EnabledXXX groups. - if (StartsWithASCII(group_name, "Enabled", true)) + if (StartsWith(group_name, "Enabled", CompareCase::SENSITIVE)) return true; return g_lazy_low_end_device.Get().value(); } #endif -#if !defined(OS_MACOSX) || defined(OS_IOS) +#if (!defined(OS_MACOSX) || defined(OS_IOS)) && !defined(OS_ANDROID) std::string SysInfo::HardwareModelName() { return std::string(); } diff --git a/base/sys_info.h b/base/sys_info.h index 654d6945a34ba..5a81dc1583f45 100644 --- a/base/sys_info.h +++ b/base/sys_info.h @@ -52,9 +52,9 @@ class BASE_EXPORT SysInfo { static int64 Uptime(); // Returns a descriptive string for the current machine model or an empty - // string if machime model is unknown or an error occured. - // e.g. MacPro1,1 on Mac. - // Only implemented on OS X, will return an empty string on other platforms. + // string if the machine model is unknown or an error occured. + // e.g. "MacPro1,1" on Mac, or "Nexus 5" on Android. Only implemented on OS X, + // Android, and Chrome OS. This returns an empty string on other platforms. static std::string HardwareModelName(); // Returns the name of the host operating system. @@ -129,9 +129,6 @@ class BASE_EXPORT SysInfo { // Returns the Android build ID. static std::string GetAndroidBuildID(); - // Returns the device's name. - static std::string GetDeviceName(); - static int DalvikHeapSizeMB(); static int DalvikHeapGrowthLimitMB(); #endif // defined(OS_ANDROID) diff --git a/base/sys_info_android.cc b/base/sys_info_android.cc index 245097ffdc092..c288ae2fe87f7 100644 --- a/base/sys_info_android.cc +++ b/base/sys_info_android.cc @@ -155,28 +155,16 @@ int GetDalvikHeapGrowthLimitMB() { namespace base { -std::string SysInfo::OperatingSystemName() { - return "Android"; -} - -std::string SysInfo::GetAndroidBuildCodename() { - char os_version_codename_str[PROP_VALUE_MAX]; - __system_property_get("ro.build.version.codename", os_version_codename_str); - return std::string(os_version_codename_str); -} - -std::string SysInfo::GetAndroidBuildID() { - char os_build_id_str[PROP_VALUE_MAX]; - __system_property_get("ro.build.id", os_build_id_str); - return std::string(os_build_id_str); -} - -std::string SysInfo::GetDeviceName() { +std::string SysInfo::HardwareModelName() { char device_model_str[PROP_VALUE_MAX]; __system_property_get("ro.product.model", device_model_str); return std::string(device_model_str); } +std::string SysInfo::OperatingSystemName() { + return "Android"; +} + std::string SysInfo::OperatingSystemVersion() { int32 major, minor, bugfix; OperatingSystemVersionNumbers(&major, &minor, &bugfix); @@ -195,6 +183,18 @@ void SysInfo::OperatingSystemVersionNumbers(int32* major_version, bugfix_version); } +std::string SysInfo::GetAndroidBuildCodename() { + char os_version_codename_str[PROP_VALUE_MAX]; + __system_property_get("ro.build.version.codename", os_version_codename_str); + return std::string(os_version_codename_str); +} + +std::string SysInfo::GetAndroidBuildID() { + char os_build_id_str[PROP_VALUE_MAX]; + __system_property_get("ro.build.id", os_build_id_str); + return std::string(os_build_id_str); +} + int SysInfo::DalvikHeapSizeMB() { static int heap_size = GetDalvikHeapSizeMB(); return heap_size; diff --git a/base/task_runner.h b/base/task_runner.h index 7d07b8ceb028a..6369c4f65fa19 100644 --- a/base/task_runner.h +++ b/base/task_runner.h @@ -104,7 +104,7 @@ class BASE_EXPORT TaskRunner // public: // void GetData() { // scoped_refptr buffer = new DataBuffer(); - // target_thread_.message_loop_proxy()->PostTaskAndReply( + // target_thread_.task_runner()->PostTaskAndReply( // FROM_HERE, // base::Bind(&DataBuffer::AddData, buffer), // base::Bind(&DataLoader::OnDataReceived, AsWeakPtr(), buffer)); diff --git a/base/task_runner_util.h b/base/task_runner_util.h index b6dd0f36d69f1..da088db2a2192 100644 --- a/base/task_runner_util.h +++ b/base/task_runner_util.h @@ -47,7 +47,7 @@ void ReplyAdapter(const Callback& callback, // PostTaskAndReplyWithResult as in this example: // // PostTaskAndReplyWithResult( -// target_thread_.message_loop_proxy(), +// target_thread_.task_runner(), // FROM_HERE, // Bind(&DoWorkAndReturn), // Bind(&Callback)); diff --git a/base/test/BUILD.gn b/base/test/BUILD.gn index a8ae0cfb737b3..0d86f4e9fef82 100644 --- a/base/test/BUILD.gn +++ b/base/test/BUILD.gn @@ -128,6 +128,12 @@ source_set("test_support") { "values_test_util.h", ] + data = [ + # The isolate needs this script for setting up the test. It's not actually + # needed to run this target locally. + "//testing/test_env.py", + ] + public_deps = [ ":test_config", "//base", diff --git a/base/test/android/java/src/org/chromium/base/TestUiThread.java b/base/test/android/java/src/org/chromium/base/TestUiThread.java index 77f96606ad6db..4abec802fb2bc 100644 --- a/base/test/android/java/src/org/chromium/base/TestUiThread.java +++ b/base/test/android/java/src/org/chromium/base/TestUiThread.java @@ -19,7 +19,7 @@ @ThreadSafe public class TestUiThread { private static final AtomicBoolean sStarted = new AtomicBoolean(false); - private static final String TAG = Log.makeTag("TestUiThread"); + private static final String TAG = "cr.TestUiThread"; @CalledByNative private static void loop() { diff --git a/base/test/android/javatests/src/org/chromium/base/test/BaseActivityInstrumentationTestCase.java b/base/test/android/javatests/src/org/chromium/base/test/BaseActivityInstrumentationTestCase.java index 53dee4ab14594..4c7f3b88c4af9 100644 --- a/base/test/android/javatests/src/org/chromium/base/test/BaseActivityInstrumentationTestCase.java +++ b/base/test/android/javatests/src/org/chromium/base/test/BaseActivityInstrumentationTestCase.java @@ -10,17 +10,8 @@ import android.test.ActivityInstrumentationTestCase2; import android.util.Log; -import org.chromium.base.BaseChromiumApplication; -import org.chromium.base.CommandLine; import org.chromium.base.test.util.CommandLineFlags; -import java.lang.reflect.AnnotatedElement; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - /** * Base class for all Activity-based Instrumentation tests. * @@ -43,26 +34,10 @@ public BaseActivityInstrumentationTestCase(Class activityClass) { super(activityClass); } - /** - * Sets up the CommandLine with the appropriate flags. - * - * This will add the difference of the sets of flags specified by {@link CommandLineFlags.Add} - * and {@link CommandLineFlags.Remove} to the {@link org.chromium.base.CommandLine}. Note that - * trying to remove a flag set externally, i.e. by the command-line flags file, will not work. - */ @Override protected void setUp() throws Exception { super.setUp(); - - CommandLine.reset(); - Context targetContext = getTargetContext(); - assertNotNull("Unable to get a non-null target context.", targetContext); - - BaseChromiumApplication.initCommandLine(targetContext); - Set flags = getFlags(getClass().getMethod(getName())); - for (String flag : flags) { - CommandLine.getInstance().appendSwitch(flag); - } + CommandLineFlags.setUp(getTargetContext(), getClass().getMethod(getName())); } /** @@ -88,31 +63,4 @@ private Context getTargetContext() { } return targetContext; } - - private static Set getFlags(AnnotatedElement element) { - AnnotatedElement parent = (element instanceof Method) - ? ((Method) element).getDeclaringClass() - : ((Class) element).getSuperclass(); - Set flags = (parent == null) ? new HashSet() : getFlags(parent); - - if (element.isAnnotationPresent(CommandLineFlags.Add.class)) { - flags.addAll( - Arrays.asList(element.getAnnotation(CommandLineFlags.Add.class).value())); - } - - if (element.isAnnotationPresent(CommandLineFlags.Remove.class)) { - List flagsToRemove = - Arrays.asList(element.getAnnotation(CommandLineFlags.Remove.class).value()); - for (String flagToRemove : flagsToRemove) { - // If your test fails here, you have tried to remove a command-line flag via - // CommandLineFlags.Remove that was loaded into CommandLine via something other - // than CommandLineFlags.Add (probably the command-line flag file). - assertFalse("Unable to remove command-line flag \"" + flagToRemove + "\".", - CommandLine.getInstance().hasSwitch(flagToRemove)); - } - flags.removeAll(flagsToRemove); - } - - return flags; - } } diff --git a/base/test/android/javatests/src/org/chromium/base/test/BaseInstrumentationTestRunner.java b/base/test/android/javatests/src/org/chromium/base/test/BaseInstrumentationTestRunner.java index 8a3395ad7df98..c90ebf2d9b946 100644 --- a/base/test/android/javatests/src/org/chromium/base/test/BaseInstrumentationTestRunner.java +++ b/base/test/android/javatests/src/org/chromium/base/test/BaseInstrumentationTestRunner.java @@ -94,7 +94,7 @@ protected AndroidTestRunner getAndroidTestRunner() { @Override protected TestResult createTestResult() { SkippingTestResult r = new SkippingTestResult(); - r.addSkipCheck(new MinAndroidSdkLevelSkipCheck()); + addSkipChecks(r); return r; } }; @@ -102,6 +102,13 @@ protected TestResult createTestResult() { return runner; } + /** + * Adds the desired SkipChecks to result. Subclasses can add additional SkipChecks. + */ + protected void addSkipChecks(SkippingTestResult result) { + result.addSkipCheck(new MinAndroidSdkLevelSkipCheck()); + } + /** * Checks the device's SDK level against any specified minimum requirement. */ diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/CommandLineFlags.java b/base/test/android/javatests/src/org/chromium/base/test/util/CommandLineFlags.java index 2feb83d35c045..16697d3fc9704 100644 --- a/base/test/android/javatests/src/org/chromium/base/test/util/CommandLineFlags.java +++ b/base/test/android/javatests/src/org/chromium/base/test/util/CommandLineFlags.java @@ -4,11 +4,24 @@ package org.chromium.base.test.util; +import android.content.Context; + +import junit.framework.Assert; + +import org.chromium.base.BaseChromiumApplication; +import org.chromium.base.CommandLine; + import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import java.lang.reflect.AnnotatedElement; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; /** * Provides annotations related to command-line flag handling. @@ -44,5 +57,49 @@ public final class CommandLineFlags { String[] value(); } + /** + * Sets up the CommandLine with the appropriate flags. + * + * This will add the difference of the sets of flags specified by {@link CommandLineFlags.Add} + * and {@link CommandLineFlags.Remove} to the {@link org.chromium.base.CommandLine}. Note that + * trying to remove a flag set externally, i.e. by the command-line flags file, will not work. + */ + public static void setUp(Context targetContext, AnnotatedElement element) { + Assert.assertNotNull("Unable to get a non-null target context.", targetContext); + CommandLine.reset(); + BaseChromiumApplication.initCommandLine(targetContext); + Set flags = getFlags(element); + for (String flag : flags) { + CommandLine.getInstance().appendSwitch(flag); + } + } + + private static Set getFlags(AnnotatedElement element) { + AnnotatedElement parent = (element instanceof Method) + ? ((Method) element).getDeclaringClass() + : ((Class) element).getSuperclass(); + Set flags = (parent == null) ? new HashSet() : getFlags(parent); + + if (element.isAnnotationPresent(CommandLineFlags.Add.class)) { + flags.addAll( + Arrays.asList(element.getAnnotation(CommandLineFlags.Add.class).value())); + } + + if (element.isAnnotationPresent(CommandLineFlags.Remove.class)) { + List flagsToRemove = + Arrays.asList(element.getAnnotation(CommandLineFlags.Remove.class).value()); + for (String flagToRemove : flagsToRemove) { + // If your test fails here, you have tried to remove a command-line flag via + // CommandLineFlags.Remove that was loaded into CommandLine via something other + // than CommandLineFlags.Add (probably the command-line flag file). + Assert.assertFalse("Unable to remove command-line flag \"" + flagToRemove + "\".", + CommandLine.getInstance().hasSwitch(flagToRemove)); + } + flags.removeAll(flagsToRemove); + } + + return flags; + } + private CommandLineFlags() {} } diff --git a/base/test/expectations/parser.cc b/base/test/expectations/parser.cc index c7132e5d4844a..83c64c6ad06cb 100644 --- a/base/test/expectations/parser.cc +++ b/base/test/expectations/parser.cc @@ -39,7 +39,7 @@ inline bool Parser::HasNext() { Parser::StateFunc Parser::Start() { // If at the start of a line is whitespace, skip it and arrange to come back // here. - if (IsAsciiWhitespace(*pos_)) + if (base::IsAsciiWhitespace(*pos_)) return SkipWhitespaceAndNewLines(&Parser::Start); // Handle comments at the start of lines. @@ -161,7 +161,7 @@ Parser::StateFunc Parser::End() { Parser::StateFunc Parser::ExtractString(StateFunc success) { const char* start = pos_; - while (!IsAsciiWhitespace(*pos_) && *pos_ != ']' && HasNext()) { + while (!base::IsAsciiWhitespace(*pos_) && *pos_ != ']' && HasNext()) { ++pos_; if (*pos_ == '#') { return SyntaxError("Unexpected start of comment"); @@ -179,7 +179,7 @@ Parser::StateFunc Parser::SkipWhitespace(Parser::StateFunc next) { } Parser::StateFunc Parser::SkipWhitespaceAndNewLines(Parser::StateFunc next) { - while (IsAsciiWhitespace(*pos_) && HasNext()) { + while (base::IsAsciiWhitespace(*pos_) && HasNext()) { if (*pos_ == '\n') { ++line_number_; } diff --git a/base/test/histogram_tester.cc b/base/test/histogram_tester.cc index ea738b0557b6e..0eba3a9a27938 100644 --- a/base/test/histogram_tester.cc +++ b/base/test/histogram_tester.cc @@ -73,6 +73,19 @@ void HistogramTester::ExpectTotalCount(const std::string& name, } } +std::vector HistogramTester::GetAllSamples(const std::string& name) { + std::vector samples; + scoped_ptr snapshot = + GetHistogramSamplesSinceCreation(name); + for (auto it = snapshot->Iterator(); !it->Done(); it->Next()) { + HistogramBase::Sample sample; + HistogramBase::Count count; + it->Get(&sample, nullptr, &count); + samples.push_back(Bucket(sample, count)); + } + return samples; +} + scoped_ptr HistogramTester::GetHistogramSamplesSinceCreation( const std::string& histogram_name) { HistogramBase* histogram = StatisticsRecorder::FindHistogram(histogram_name); @@ -120,4 +133,12 @@ void HistogramTester::CheckTotalCount( << expected_count << "). It has (" << actual_count << ")."; } +bool Bucket::operator==(const Bucket& other) const { + return min == other.min && count == other.count; +} + +void PrintTo(const Bucket& bucket, std::ostream* os) { + *os << "Bucket " << bucket.min << ": " << bucket.count; +} + } // namespace base diff --git a/base/test/histogram_tester.h b/base/test/histogram_tester.h index 96317f98d2d33..7ac7ca67e7efa 100644 --- a/base/test/histogram_tester.h +++ b/base/test/histogram_tester.h @@ -6,7 +6,10 @@ #define BASE_TEST_HISTOGRAM_TESTER_H_ #include +#include #include +#include +#include #include "base/basictypes.h" #include "base/memory/scoped_ptr.h" @@ -15,6 +18,7 @@ namespace base { +struct Bucket; class HistogramSamples; // HistogramTester provides a simple interface for examining histograms, UMA @@ -47,6 +51,24 @@ class HistogramTester { void ExpectTotalCount(const std::string& name, base::HistogramBase::Count count) const; + // Returns a list of all of the buckets recorded since creation of this + // object, as vector, where the Bucket represents the min boundary of + // the bucket and the count of samples recorded to that bucket since creation. + // + // Example usage, using gMock: + // EXPECT_THAT(histogram_tester.GetAllSamples("HistogramName"), + // ElementsAre(Bucket(1, 5), Bucket(2, 10), Bucket(3, 5))); + // + // If you build the expected list programmatically, you can use ContainerEq: + // EXPECT_THAT(histogram_tester.GetAllSamples("HistogramName"), + // ContainerEq(expected_buckets)); + // + // or EXPECT_EQ if you prefer not to depend on gMock, at the expense of a + // slightly less helpful failure message: + // EXPECT_EQ(expected_buckets, + // histogram_tester.GetAllSamples("HistogramName")); + std::vector GetAllSamples(const std::string& name); + // Access a modified HistogramSamples containing only what has been logged // to the histogram since the creation of this object. scoped_ptr GetHistogramSamplesSinceCreation( @@ -76,6 +98,18 @@ class HistogramTester { DISALLOW_COPY_AND_ASSIGN(HistogramTester); }; +struct Bucket { + Bucket(base::HistogramBase::Sample min, base::HistogramBase::Count count) + : min(min), count(count) {} + + bool operator==(const Bucket& other) const; + + base::HistogramBase::Sample min; + base::HistogramBase::Count count; +}; + +void PrintTo(const Bucket& value, std::ostream* os); + } // namespace base #endif // BASE_TEST_HISTOGRAM_TESTER_H_ diff --git a/base/test/histogram_tester_unittest.cc b/base/test/histogram_tester_unittest.cc index a03ee131736af..f8755279c5ac7 100644 --- a/base/test/histogram_tester_unittest.cc +++ b/base/test/histogram_tester_unittest.cc @@ -5,16 +5,20 @@ #include "base/test/histogram_tester.h" #include "base/memory/scoped_ptr.h" -#include "base/metrics/histogram.h" +#include "base/metrics/histogram_macros.h" #include "base/metrics/histogram_samples.h" +#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" namespace base { +using ::testing::ElementsAre; + const std::string kHistogram1 = "Test1"; const std::string kHistogram2 = "Test2"; const std::string kHistogram3 = "Test3"; const std::string kHistogram4 = "Test4"; +const std::string kHistogram5 = "Test5"; typedef testing::Test HistogramTesterTest; @@ -78,4 +82,15 @@ TEST_F(HistogramTesterTest, TestBucketsSampleWithScope) { tester.ExpectTotalCount(kHistogram4, 1); } +TEST_F(HistogramTesterTest, TestGetAllSamples) { + HistogramTester tester; + UMA_HISTOGRAM_ENUMERATION(kHistogram5, 2, 5); + UMA_HISTOGRAM_ENUMERATION(kHistogram5, 3, 5); + UMA_HISTOGRAM_ENUMERATION(kHistogram5, 3, 5); + UMA_HISTOGRAM_ENUMERATION(kHistogram5, 5, 5); + + EXPECT_THAT(tester.GetAllSamples(kHistogram5), + ElementsAre(Bucket(2, 1), Bucket(3, 2), Bucket(5, 1))); +} + } // namespace base diff --git a/base/test/launcher/test_launcher.cc b/base/test/launcher/test_launcher.cc index 7f258f5f3953f..7c0bc4e9ed9fa 100644 --- a/base/test/launcher/test_launcher.cc +++ b/base/test/launcher/test_launcher.cc @@ -25,6 +25,7 @@ #include "base/process/kill.h" #include "base/process/launch.h" #include "base/single_thread_task_runner.h" +#include "base/strings/pattern.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" @@ -569,7 +570,7 @@ void TestLauncher::OnTestFinished(const TestResult& result) { snippet_lines.begin() + truncated_size); snippet_lines.insert(snippet_lines.begin(), ""); } - fprintf(stdout, "%s", JoinString(snippet_lines, "\n").c_str()); + fprintf(stdout, "%s", base::JoinString(snippet_lines, "\n").c_str()); fflush(stdout); } diff --git a/base/test/launcher/test_launcher_ios.cc b/base/test/launcher/test_launcher_ios.cc index ecd31aedf5d00..3179bb3af371f 100644 --- a/base/test/launcher/test_launcher_ios.cc +++ b/base/test/launcher/test_launcher_ios.cc @@ -121,7 +121,7 @@ class IOSUnitTestPlatformDelegate : public base::UnitTestPlatformDelegate { base::CommandLine cmd_line(dir_exe_.AppendASCII(test_name_ + ".app")); cmd_line.AppendSwitchPath(switches::kTestLauncherOutput, output_file); cmd_line.AppendSwitchASCII(base::kGTestFilterFlag, - JoinString(test_names, ":")); + base::JoinString(test_names, ":")); return cmd_line; } diff --git a/base/test/launcher/test_launcher_nacl_nonsfi.cc b/base/test/launcher/test_launcher_nacl_nonsfi.cc index fa526045cddcf..bf117affc68e2 100644 --- a/base/test/launcher/test_launcher_nacl_nonsfi.cc +++ b/base/test/launcher/test_launcher_nacl_nonsfi.cc @@ -113,7 +113,7 @@ class NonSfiUnitTestPlatformDelegate : public base::UnitTestPlatformDelegate { cmd_line.AppendSwitchPath( switches::kTestLauncherOutput, output_file); cmd_line.AppendSwitchASCII( - base::kGTestFilterFlag, JoinString(test_names, ":")); + base::kGTestFilterFlag, base::JoinString(test_names, ":")); return cmd_line; } diff --git a/base/test/test_pending_task_unittest.cc b/base/test/test_pending_task_unittest.cc index 32502f24d72e4..7623ce4a72dde 100644 --- a/base/test/test_pending_task_unittest.cc +++ b/base/test/test_pending_task_unittest.cc @@ -10,7 +10,7 @@ #include "testing/gtest/include/gtest/gtest-spi.h" #include "testing/gtest/include/gtest/gtest.h" -namespace { +namespace base { TEST(TestPendingTaskTest, TraceSupport) { base::TestPendingTask task; @@ -52,4 +52,4 @@ TEST(TestPendingTaskTest, ShouldRunBefore) { << task_first << ".ShouldRunBefore(" << task_after << ")\n"; } -} // namespace +} // namespace base diff --git a/base/test/test_reg_util_win.cc b/base/test/test_reg_util_win.cc index e3b1ffc90b048..a7d07f7ab2c61 100644 --- a/base/test/test_reg_util_win.cc +++ b/base/test/test_reg_util_win.cc @@ -7,6 +7,7 @@ #include "base/guid.h" #include "base/logging.h" #include "base/strings/string_number_conversions.h" +#include "base/strings/string_split.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "testing/gtest/include/gtest/gtest.h" @@ -32,8 +33,10 @@ void DeleteStaleTestKeys(const base::Time& now, test_key_root.c_str()); for (; iterator_test_root_key.Valid(); ++iterator_test_root_key) { base::string16 key_name = iterator_test_root_key.Name(); - std::vector tokens; - if (!Tokenize(key_name, base::string16(kTimestampDelimiter), &tokens)) + std::vector tokens = base::SplitString( + key_name, kTimestampDelimiter, base::KEEP_WHITESPACE, + base::SPLIT_WANT_NONEMPTY); + if (tokens.empty()) continue; int64 key_name_as_number = 0; diff --git a/base/test/test_suite.cc b/base/test/test_suite.cc index e281cff3da288..2910466f3e99e 100644 --- a/base/test/test_suite.cc +++ b/base/test/test_suite.cc @@ -338,7 +338,7 @@ void TestSuite::Initialize() { i18n::SetICUDefaultLocale("en_US"); #else std::string default_locale(uloc_getDefault()); - if (EndsWith(default_locale, "POSIX", false)) + if (EndsWith(default_locale, "POSIX", CompareCase::INSENSITIVE_ASCII)) i18n::SetICUDefaultLocale("en_US"); #endif #endif diff --git a/base/test/test_support_ios.mm b/base/test/test_support_ios.mm index 3b31da610b4ed..9e8261200c23d 100644 --- a/base/test/test_support_ios.mm +++ b/base/test/test_support_ios.mm @@ -80,6 +80,10 @@ - (BOOL)application:(UIApplication *)application label.textAlignment = NSTextAlignmentCenter; [window_ addSubview:label]; + // An NSInternalInconsistencyException is thrown if the app doesn't have a + // root view controller. Set an empty one here. + [window_ setRootViewController:[[[UIViewController alloc] init] autorelease]]; + if ([self shouldRedirectOutputToFile]) [self redirectOutput]; diff --git a/base/test/trace_event_analyzer.cc b/base/test/trace_event_analyzer.cc index e46c2a5170710..93d7f305cc320 100644 --- a/base/test/trace_event_analyzer.cc +++ b/base/test/trace_event_analyzer.cc @@ -10,6 +10,7 @@ #include "base/json/json_reader.h" #include "base/memory/scoped_ptr.h" +#include "base/strings/pattern.h" #include "base/values.h" namespace trace_analyzer { @@ -321,17 +322,17 @@ bool Query::CompareAsString(const TraceEvent& event, bool* result) const { switch (operator_) { case OP_EQ: if (right().is_pattern_) - *result = MatchPattern(lhs, rhs); + *result = base::MatchPattern(lhs, rhs); else if (left().is_pattern_) - *result = MatchPattern(rhs, lhs); + *result = base::MatchPattern(rhs, lhs); else *result = (lhs == rhs); return true; case OP_NE: if (right().is_pattern_) - *result = !MatchPattern(lhs, rhs); + *result = !base::MatchPattern(lhs, rhs); else if (left().is_pattern_) - *result = !MatchPattern(rhs, lhs); + *result = !base::MatchPattern(rhs, lhs); else *result = (lhs != rhs); return true; diff --git a/base/third_party/nspr/prtime.cc b/base/third_party/nspr/prtime.cc index 9335b01de863c..a7c5a3a949680 100644 --- a/base/third_party/nspr/prtime.cc +++ b/base/third_party/nspr/prtime.cc @@ -107,9 +107,9 @@ PR_ImplodeTime(const PRExplodedTime *exploded) static const PRTime kSecondsToMicroseconds = static_cast(1000000); #if defined(OS_WIN) // Create the system struct representing our exploded time. - SYSTEMTIME st = {0}; - FILETIME ft = {0}; - ULARGE_INTEGER uli = {0}; + SYSTEMTIME st = {}; + FILETIME ft = {}; + ULARGE_INTEGER uli = {}; st.wYear = exploded->tm_year; st.wMonth = static_cast(exploded->tm_month + 1); diff --git a/base/third_party/symbolize/symbolize.cc b/base/third_party/symbolize/symbolize.cc index b25f7479d0df0..f4861dfe523e7 100644 --- a/base/third_party/symbolize/symbolize.cc +++ b/base/third_party/symbolize/symbolize.cc @@ -651,7 +651,8 @@ char *itoa_r(intptr_t i, char *buf, size_t sz, int base, size_t padding) { // Handle negative numbers (only for base 10). if (i < 0 && base == 10) { - j = -i; + // This does "j = -i" while avoiding integer overflow. + j = static_cast(-(i + 1)) + 1; // Make sure we can write the '-' character. if (++n > sz) { diff --git a/base/threading/platform_thread.h b/base/threading/platform_thread.h index 3468f45f91efd..0b922650f0cf4 100644 --- a/base/threading/platform_thread.h +++ b/base/threading/platform_thread.h @@ -89,6 +89,7 @@ class PlatformThreadHandle { id_(id) { } + // TODO(toyoshim): Remove id() and use PlatformThread::CurrentId() instead. PlatformThreadId id() const { return id_; } @@ -112,8 +113,8 @@ class PlatformThreadHandle { const PlatformThreadId kInvalidThreadId(0); -// Valid values for SetThreadPriority(), listed in increasing order of -// importance. +// Valid values for priority of Thread::Options and SimpleThread::Options, and +// SetCurrentThreadPriority(), listed in increasing order of importance. enum class ThreadPriority { // Suitable for threads that shouldn't disrupt high priority work. BACKGROUND, @@ -176,8 +177,7 @@ class BASE_EXPORT PlatformThread { PlatformThreadHandle* thread_handle); // CreateWithPriority() does the same thing as Create() except the priority of - // the thread is set based on |priority|. Can be used in place of Create() - // followed by SetThreadPriority(). + // the thread is set based on |priority|. static bool CreateWithPriority(size_t stack_size, Delegate* delegate, PlatformThreadHandle* thread_handle, ThreadPriority priority); @@ -192,15 +192,15 @@ class BASE_EXPORT PlatformThread { // |thread_handle|. static void Join(PlatformThreadHandle thread_handle); - // Toggles the target thread's priority at runtime. Prefer - // CreateWithPriority() to set the thread's initial priority. - // NOTE: The call may fail if the caller thread is not the same as the - // target thread on POSIX. For example, seccomp-bpf blocks it by default - // in the sandbox. - static void SetThreadPriority(PlatformThreadHandle handle, - ThreadPriority priority); + // Toggles the current thread's priority at runtime. A thread may not be able + // to raise its priority back up after lowering it if the process does not + // have a proper permission, e.g. CAP_SYS_NICE on Linux. + // Since changing other threads' priority is not permitted in favor of + // security, this interface is restricted to change only the current thread + // priority (https://crbug.com/399473). + static void SetCurrentThreadPriority(ThreadPriority priority); - static ThreadPriority GetThreadPriority(PlatformThreadHandle handle); + static ThreadPriority GetCurrentThreadPriority(); private: DISALLOW_IMPLICIT_CONSTRUCTORS(PlatformThread); diff --git a/base/threading/platform_thread_android.cc b/base/threading/platform_thread_android.cc index 11e5e2e3c870d..176a6bdd087db 100644 --- a/base/threading/platform_thread_android.cc +++ b/base/threading/platform_thread_android.cc @@ -23,29 +23,21 @@ namespace base { namespace internal { -// These nice values are taken from Android, which uses nice values like linux, -// but defines some preset nice values. -// Process.THREAD_PRIORITY_AUDIO = -16 -// Process.THREAD_PRIORITY_BACKGROUND = 10 -// Process.THREAD_PRIORITY_DEFAULT = 0; -// Process.THREAD_PRIORITY_DISPLAY = -4; -// Process.THREAD_PRIORITY_FOREGROUND = -2; -// Process.THREAD_PRIORITY_LESS_FAVORABLE = 1; -// Process.THREAD_PRIORITY_LOWEST = 19; -// Process.THREAD_PRIORITY_MORE_FAVORABLE = -1; -// Process.THREAD_PRIORITY_URGENT_AUDIO = -19; -// Process.THREAD_PRIORITY_URGENT_DISPLAY = -8; -// We use -6 for display, but we may want to split this into urgent (-8) and -// non-urgent (-4). +// - BACKGROUND is 9 due to it being the nicest value we can use that's still +// above an Android system threshold that enables heavy throttling starting at +// 10; we want to be lower-priority than Chrome's other threads without +// incurring this behavior. +// - DISPLAY is -6 due to being midway between Android's DISPLAY (-4) and +// URGENT_DISPLAY (-8). +// - REALTIME_AUDIO corresponds to Android's THREAD_PRIORITY_AUDIO = -16 value. const ThreadPriorityToNiceValuePair kThreadPriorityToNiceValueMap[4] = { - {ThreadPriority::BACKGROUND, 10}, + {ThreadPriority::BACKGROUND, 9}, {ThreadPriority::NORMAL, 0}, {ThreadPriority::DISPLAY, -6}, {ThreadPriority::REALTIME_AUDIO, -16}, }; -bool SetThreadPriorityForPlatform(PlatformThreadHandle handle, - ThreadPriority priority) { +bool SetCurrentThreadPriorityForPlatform(ThreadPriority priority) { // On Android, we set the Audio priority through JNI as Audio priority // will also allow the process to run while it is backgrounded. if (priority == ThreadPriority::REALTIME_AUDIO) { @@ -56,8 +48,8 @@ bool SetThreadPriorityForPlatform(PlatformThreadHandle handle, return false; } -bool GetThreadPriorityForPlatform(PlatformThreadHandle handle, - ThreadPriority* priority) { +bool GetCurrentThreadPriorityForPlatform(ThreadPriority* priority) { + // See http://crbug.com/505474. NOTIMPLEMENTED(); return false; } @@ -88,8 +80,7 @@ void InitThreading() { void InitOnThread() { // Threads on linux/android may inherit their priority from the thread // where they were created. This sets all new threads to the default. - PlatformThread::SetThreadPriority(PlatformThread::CurrentHandle(), - ThreadPriority::NORMAL); + PlatformThread::SetCurrentThreadPriority(ThreadPriority::NORMAL); } void TerminateOnThread() { diff --git a/base/threading/platform_thread_freebsd.cc b/base/threading/platform_thread_freebsd.cc index f4fded0ebb2e1..e29e865e63b5c 100644 --- a/base/threading/platform_thread_freebsd.cc +++ b/base/threading/platform_thread_freebsd.cc @@ -36,11 +36,8 @@ const ThreadPriorityToNiceValuePair kThreadPriorityToNiceValueMap[4] = { {ThreadPriority::REALTIME_AUDIO, -10}, } -bool SetThreadPriorityForPlatform(PlatformThreadHandle handle, - ThreadPriority priority) { +bool SetCurrentThreadPriorityForPlatform(ThreadPriority priority) { #if !defined(OS_NACL) - // TODO(gab): Assess the correctness of using |pthread_self()| below instead - // of |handle|. http://crbug.com/468793. return priority == ThreadPriority::REALTIME_AUDIO && pthread_setschedparam(pthread_self(), SCHED_RR, &kRealTimePrio) == 0; #else @@ -48,11 +45,8 @@ bool SetThreadPriorityForPlatform(PlatformThreadHandle handle, #endif } -bool GetThreadPriorityForPlatform(PlatformThreadHandle handle, - ThreadPriority* priority) { +bool GetCurrentThreadPriorityForPlatform(ThreadPriority* priority) { #if !defined(OS_NACL) - // TODO(gab): Assess the correctness of using |pthread_self()| below instead - // of |handle|. http://crbug.com/468793. int maybe_sched_rr = 0; struct sched_param maybe_realtime_prio = {0}; if (pthread_getschedparam(pthread_self(), &maybe_sched_rr, diff --git a/base/threading/platform_thread_internal_posix.h b/base/threading/platform_thread_internal_posix.h index 62006ce13c962..05a8d1e26e78b 100644 --- a/base/threading/platform_thread_internal_posix.h +++ b/base/threading/platform_thread_internal_posix.h @@ -26,17 +26,15 @@ int ThreadPriorityToNiceValue(ThreadPriority priority); ThreadPriority NiceValueToThreadPriority(int nice_value); // Allows platform specific tweaks to the generic POSIX solution for -// SetThreadPriority. Returns true if the platform-specific implementation -// handled this |priority| change, false if the generic implementation should -// instead proceed. -bool SetThreadPriorityForPlatform(PlatformThreadHandle handle, - ThreadPriority priority); - -// Returns true if there is a platform-specific ThreadPriority set on |handle| -// (and returns the actual ThreadPriority via |priority|). Returns false -// otherwise, leaving |priority| untouched. -bool GetThreadPriorityForPlatform(PlatformThreadHandle handle, - ThreadPriority* priority); +// SetCurrentThreadPriority. Returns true if the platform-specific +// implementation handled this |priority| change, false if the generic +// implementation should instead proceed. +bool SetCurrentThreadPriorityForPlatform(ThreadPriority priority); + +// Returns true if there is a platform-specific ThreadPriority set on the +// current thread (and returns the actual ThreadPriority via |priority|). +// Returns false otherwise, leaving |priority| untouched. +bool GetCurrentThreadPriorityForPlatform(ThreadPriority* priority); } // namespace internal diff --git a/base/threading/platform_thread_linux.cc b/base/threading/platform_thread_linux.cc index 9f7437418a729..48cf7443f7d51 100644 --- a/base/threading/platform_thread_linux.cc +++ b/base/threading/platform_thread_linux.cc @@ -27,6 +27,7 @@ namespace internal { namespace { #if !defined(OS_NACL) const struct sched_param kRealTimePrio = {8}; +const struct sched_param kResetPrio = {0}; #endif } // namespace @@ -37,11 +38,18 @@ const ThreadPriorityToNiceValuePair kThreadPriorityToNiceValueMap[4] = { {ThreadPriority::REALTIME_AUDIO, -10}, }; -bool SetThreadPriorityForPlatform(PlatformThreadHandle handle, - ThreadPriority priority) { +bool SetCurrentThreadPriorityForPlatform(ThreadPriority priority) { #if !defined(OS_NACL) - // TODO(gab): Assess the correctness of using |pthread_self()| below instead - // of |handle|. http://crbug.com/468793. + ThreadPriority current_priority; + if (priority != ThreadPriority::REALTIME_AUDIO && + GetCurrentThreadPriorityForPlatform(¤t_priority) && + current_priority == ThreadPriority::REALTIME_AUDIO) { + // If the pthread's round-robin scheduler is already enabled, and the new + // priority will use setpriority() instead, the pthread scheduler should be + // reset to use SCHED_OTHER so that setpriority() just works. + pthread_setschedparam(pthread_self(), SCHED_OTHER, &kResetPrio); + return false; + } return priority == ThreadPriority::REALTIME_AUDIO && pthread_setschedparam(pthread_self(), SCHED_RR, &kRealTimePrio) == 0; #else @@ -49,13 +57,10 @@ bool SetThreadPriorityForPlatform(PlatformThreadHandle handle, #endif } -bool GetThreadPriorityForPlatform(PlatformThreadHandle handle, - ThreadPriority* priority) { +bool GetCurrentThreadPriorityForPlatform(ThreadPriority* priority) { #if !defined(OS_NACL) int maybe_sched_rr = 0; struct sched_param maybe_realtime_prio = {0}; - // TODO(gab): Assess the correctness of using |pthread_self()| below instead - // of |handle|. http://crbug.com/468793. if (pthread_getschedparam(pthread_self(), &maybe_sched_rr, &maybe_realtime_prio) == 0 && maybe_sched_rr == SCHED_RR && diff --git a/base/threading/platform_thread_mac.mm b/base/threading/platform_thread_mac.mm index 813cae26d2b4d..1ecbcd6ad91b9 100644 --- a/base/threading/platform_thread_mac.mm +++ b/base/threading/platform_thread_mac.mm @@ -155,10 +155,10 @@ void SetPriorityRealtimeAudio(mach_port_t mach_thread_id) { } // anonymous namespace // static -void PlatformThread::SetThreadPriority(PlatformThreadHandle handle, - ThreadPriority priority) { +void PlatformThread::SetCurrentThreadPriority(ThreadPriority priority) { // Convert from pthread_t to mach thread identifier. - mach_port_t mach_thread_id = pthread_mach_thread_np(handle.platform_handle()); + mach_port_t mach_thread_id = + pthread_mach_thread_np(PlatformThread::CurrentHandle().platform_handle()); switch (priority) { case ThreadPriority::NORMAL: @@ -174,7 +174,7 @@ void SetPriorityRealtimeAudio(mach_port_t mach_thread_id) { } // static -ThreadPriority PlatformThread::GetThreadPriority(PlatformThreadHandle handle) { +ThreadPriority PlatformThread::GetCurrentThreadPriority() { NOTIMPLEMENTED(); return ThreadPriority::NORMAL; } diff --git a/base/threading/platform_thread_posix.cc b/base/threading/platform_thread_posix.cc index 0d821a9b7ad80..f3a835e54f0b2 100644 --- a/base/threading/platform_thread_posix.cc +++ b/base/threading/platform_thread_posix.cc @@ -58,10 +58,8 @@ void* ThreadFunc(void* params) { if (!thread_params->joinable) base::ThreadRestrictions::SetSingletonAllowed(false); - if (thread_params->priority != ThreadPriority::NORMAL) { - PlatformThread::SetThreadPriority(PlatformThread::CurrentHandle(), - thread_params->priority); - } + if (thread_params->priority != ThreadPriority::NORMAL) + PlatformThread::SetCurrentThreadPriority(thread_params->priority); // Stash the id in the handle so the calling thread has a complete // handle, and unblock the parent thread. @@ -231,16 +229,15 @@ void PlatformThread::Join(PlatformThreadHandle thread_handle) { CHECK_EQ(0, pthread_join(thread_handle.platform_handle(), NULL)); } -// Mac has its own Set/GetThreadPriority() implementations. +// Mac has its own Set/GetCurrentThreadPriority() implementations. #if !defined(OS_MACOSX) // static -void PlatformThread::SetThreadPriority(PlatformThreadHandle handle, - ThreadPriority priority) { +void PlatformThread::SetCurrentThreadPriority(ThreadPriority priority) { #if defined(OS_NACL) NOTIMPLEMENTED(); #else - if (internal::SetThreadPriorityForPlatform(handle, priority)) + if (internal::SetCurrentThreadPriorityForPlatform(priority)) return; // setpriority(2) should change the whole thread group's (i.e. process) @@ -249,39 +246,34 @@ void PlatformThread::SetThreadPriority(PlatformThreadHandle handle, // Linux/NPTL implementation of POSIX threads, the nice value is a per-thread // attribute". Also, 0 is prefered to the current thread id since it is // equivalent but makes sandboxing easier (https://crbug.com/399473). - DCHECK_NE(handle.id(), kInvalidThreadId); const int nice_setting = internal::ThreadPriorityToNiceValue(priority); - const PlatformThreadId current_id = PlatformThread::CurrentId(); - if (setpriority(PRIO_PROCESS, handle.id() == current_id ? 0 : handle.id(), - nice_setting)) { - DVPLOG(1) << "Failed to set nice value of thread (" << handle.id() - << ") to " << nice_setting; + if (setpriority(PRIO_PROCESS, 0, nice_setting)) { + DVPLOG(1) << "Failed to set nice value of thread (" + << PlatformThread::CurrentId() << ") to " << nice_setting; } #endif // defined(OS_NACL) } // static -ThreadPriority PlatformThread::GetThreadPriority(PlatformThreadHandle handle) { +ThreadPriority PlatformThread::GetCurrentThreadPriority() { #if defined(OS_NACL) NOTIMPLEMENTED(); return ThreadPriority::NORMAL; #else - // Mirrors SetThreadPriority()'s implementation. + // Mirrors SetCurrentThreadPriority()'s implementation. ThreadPriority platform_specific_priority; - if (internal::GetThreadPriorityForPlatform(handle, - &platform_specific_priority)) { + if (internal::GetCurrentThreadPriorityForPlatform( + &platform_specific_priority)) { return platform_specific_priority; } - DCHECK_NE(handle.id(), kInvalidThreadId); - const PlatformThreadId current_id = PlatformThread::CurrentId(); // Need to clear errno before calling getpriority(): // http://man7.org/linux/man-pages/man2/getpriority.2.html errno = 0; - int nice_value = - getpriority(PRIO_PROCESS, handle.id() == current_id ? 0 : handle.id()); + int nice_value = getpriority(PRIO_PROCESS, 0); if (errno != 0) { - DVPLOG(1) << "Failed to get nice value of thread (" << handle.id() << ")"; + DVPLOG(1) << "Failed to get nice value of thread (" + << PlatformThread::CurrentId() << ")"; return ThreadPriority::NORMAL; } diff --git a/base/threading/platform_thread_unittest.cc b/base/threading/platform_thread_unittest.cc index c4b3d5d7ecc60..1ac08a77ae2de 100644 --- a/base/threading/platform_thread_unittest.cc +++ b/base/threading/platform_thread_unittest.cc @@ -8,7 +8,10 @@ #include "base/threading/platform_thread.h" #include "testing/gtest/include/gtest/gtest.h" -#if defined(OS_WIN) +#if defined(OS_POSIX) +#include +#include +#elif defined(OS_WIN) #include #endif @@ -16,6 +19,8 @@ namespace base { // Trivial tests that thread runs and doesn't crash on create and join --------- +namespace { + class TrivialThread : public PlatformThread::Delegate { public: TrivialThread() : did_run_(false) {} @@ -30,6 +35,8 @@ class TrivialThread : public PlatformThread::Delegate { DISALLOW_COPY_AND_ASSIGN(TrivialThread); }; +} // namespace + TEST(PlatformThreadTest, Trivial) { TrivialThread thread; PlatformThreadHandle handle; @@ -56,11 +63,13 @@ TEST(PlatformThreadTest, TrivialTimesTen) { // Tests of basic thread functions --------------------------------------------- +namespace { + class FunctionTestThread : public PlatformThread::Delegate { public: FunctionTestThread() : thread_id_(kInvalidThreadId), - thread_started_(true, false), + termination_ready_(true, false), terminate_thread_(true, false), done_(false) {} ~FunctionTestThread() override { @@ -70,8 +79,9 @@ class FunctionTestThread : public PlatformThread::Delegate { << "WaitableEvent blocking the underlying thread's main."; } - // Grabs |thread_id_|, signals |thread_started_|, and then waits for - // |terminate_thread_| to be signaled before exiting. + // Grabs |thread_id_|, runs an optional test on that thread, signals + // |termination_ready_|, and then waits for |terminate_thread_| to be + // signaled before exiting. void ThreadMain() override { thread_id_ = PlatformThread::CurrentId(); EXPECT_NE(thread_id_, kInvalidThreadId); @@ -79,39 +89,46 @@ class FunctionTestThread : public PlatformThread::Delegate { // Make sure that the thread ID is the same across calls. EXPECT_EQ(thread_id_, PlatformThread::CurrentId()); - thread_started_.Signal(); + // Run extra tests. + RunTest(); + termination_ready_.Signal(); terminate_thread_.Wait(); done_ = true; } PlatformThreadId thread_id() const { - EXPECT_TRUE(thread_started_.IsSignaled()) << "Thread ID still unknown"; + EXPECT_TRUE(termination_ready_.IsSignaled()) << "Thread ID still unknown"; return thread_id_; } bool IsRunning() const { - return thread_started_.IsSignaled() && !done_; + return termination_ready_.IsSignaled() && !done_; } - // Blocks until this thread is started. - void WaitForThreadStart() { thread_started_.Wait(); } + // Blocks until this thread is started and ready to be terminated. + void WaitForTerminationReady() { termination_ready_.Wait(); } - // Mark this thread for termination (callers must then join this thread to be + // Marks this thread for termination (callers must then join this thread to be // guaranteed of termination). void MarkForTermination() { terminate_thread_.Signal(); } private: + // Runs an optional test on the newly created thread. + virtual void RunTest() {} + PlatformThreadId thread_id_; - mutable WaitableEvent thread_started_; + mutable WaitableEvent termination_ready_; WaitableEvent terminate_thread_; bool done_; DISALLOW_COPY_AND_ASSIGN(FunctionTestThread); }; +} // namespace + TEST(PlatformThreadTest, Function) { PlatformThreadId main_thread_id = PlatformThread::CurrentId(); @@ -120,7 +137,7 @@ TEST(PlatformThreadTest, Function) { ASSERT_FALSE(thread.IsRunning()); ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle)); - thread.WaitForThreadStart(); + thread.WaitForTerminationReady(); ASSERT_TRUE(thread.IsRunning()); EXPECT_NE(thread.thread_id(), main_thread_id); @@ -144,7 +161,7 @@ TEST(PlatformThreadTest, FunctionTimesTen) { for (size_t n = 0; n < arraysize(thread); n++) ASSERT_TRUE(PlatformThread::Create(0, &thread[n], &handle[n])); for (size_t n = 0; n < arraysize(thread); n++) - thread[n].WaitForThreadStart(); + thread[n].WaitForTerminationReady(); for (size_t n = 0; n < arraysize(thread); n++) { ASSERT_TRUE(thread[n].IsRunning()); @@ -170,106 +187,86 @@ TEST(PlatformThreadTest, FunctionTimesTen) { namespace { const ThreadPriority kThreadPriorityTestValues[] = { -// Disable non-normal priority toggling on POSIX as it appears to be broken -// (http://crbug.com/468793). This is prefered to disabling the tests altogether -// on POSIX as it at least provides coverage for running this code under -// "normal" priority. -#if !defined(OS_POSIX) - ThreadPriority::DISPLAY, +// The order should be higher to lower to cover as much cases as possible on +// Linux trybots running without CAP_SYS_NICE permission. +#if !defined(OS_ANDROID) + // PlatformThread::GetCurrentThreadPriority() on Android does not support + // REALTIME_AUDIO case. See http://crbug.com/505474. ThreadPriority::REALTIME_AUDIO, - // Keep BACKGROUND second to last to test backgrounding from other - // priorities. +#endif + ThreadPriority::DISPLAY, + // This redundant BACKGROUND priority is to test backgrounding from other + // priorities, and unbackgrounding. ThreadPriority::BACKGROUND, -#endif // !defined(OS_POSIX) - // Keep NORMAL last to test unbackgrounding. - ThreadPriority::NORMAL -}; - -} // namespace - -// Test changing another thread's priority. -// NOTE: This test is partially disabled on POSIX, see note above and -// http://crbug.com/468793. -TEST(PlatformThreadTest, ThreadPriorityOtherThread) { - PlatformThreadHandle current_handle(PlatformThread::CurrentHandle()); - - // Confirm that the current thread's priority is as expected. - EXPECT_EQ(ThreadPriority::NORMAL, - PlatformThread::GetThreadPriority(current_handle)); - - // Create a test thread. - FunctionTestThread thread; - PlatformThreadHandle handle; - ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle)); - thread.WaitForThreadStart(); - EXPECT_NE(thread.thread_id(), kInvalidThreadId); - EXPECT_NE(thread.thread_id(), PlatformThread::CurrentId()); - - // New threads should get normal priority by default. - EXPECT_EQ(ThreadPriority::NORMAL, PlatformThread::GetThreadPriority(handle)); - - // Toggle each supported priority on the test thread and confirm it only - // affects it (and not the current thread). - for (size_t i = 0; i < arraysize(kThreadPriorityTestValues); ++i) { - SCOPED_TRACE(i); + ThreadPriority::NORMAL, + ThreadPriority::BACKGROUND}; + +bool IsBumpingPriorityAllowed() { +#if defined(OS_POSIX) + // Only root can raise thread priority on POSIX environment. On Linux, users + // who have CAP_SYS_NICE permission also can raise the thread priority, but + // libcap.so would be needed to check the capability. + return geteuid() == 0; +#else + return true; +#endif +} - // Alter and verify the test thread's priority. - PlatformThread::SetThreadPriority(handle, kThreadPriorityTestValues[i]); - EXPECT_EQ(kThreadPriorityTestValues[i], - PlatformThread::GetThreadPriority(handle)); +class ThreadPriorityTestThread : public FunctionTestThread { + public: + ThreadPriorityTestThread() = default; + ~ThreadPriorityTestThread() override = default; - // Make sure the current thread was otherwise unaffected. + private: + void RunTest() override { + // Confirm that the current thread's priority is as expected. EXPECT_EQ(ThreadPriority::NORMAL, - PlatformThread::GetThreadPriority(current_handle)); + PlatformThread::GetCurrentThreadPriority()); + + // Toggle each supported priority on the current thread and confirm it + // affects it. + const bool bumping_priority_allowed = IsBumpingPriorityAllowed(); + for (size_t i = 0; i < arraysize(kThreadPriorityTestValues); ++i) { + SCOPED_TRACE(i); + if (!bumping_priority_allowed && + kThreadPriorityTestValues[i] > + PlatformThread::GetCurrentThreadPriority()) { + continue; + } + + // Alter and verify the current thread's priority. + PlatformThread::SetCurrentThreadPriority(kThreadPriorityTestValues[i]); + EXPECT_EQ(kThreadPriorityTestValues[i], + PlatformThread::GetCurrentThreadPriority()); + } } - thread.MarkForTermination(); - PlatformThread::Join(handle); -} + DISALLOW_COPY_AND_ASSIGN(ThreadPriorityTestThread); +}; -// Test changing the current thread's priority (which has different semantics on -// some platforms). -// NOTE: This test is partially disabled on POSIX, see note above and -// http://crbug.com/468793. -TEST(PlatformThreadTest, ThreadPriorityCurrentThread) { - PlatformThreadHandle current_handle(PlatformThread::CurrentHandle()); +} // namespace - // Confirm that the current thread's priority is as expected. - EXPECT_EQ(ThreadPriority::NORMAL, - PlatformThread::GetThreadPriority(current_handle)); +#if defined(OS_MACOSX) +// PlatformThread::GetCurrentThreadPriority() is not implemented on OS X. +#define MAYBE_ThreadPriorityCurrentThread DISABLED_ThreadPriorityCurrentThread +#else +#define MAYBE_ThreadPriorityCurrentThread ThreadPriorityCurrentThread +#endif - // Create a test thread for verification purposes only. - FunctionTestThread thread; +// Test changing a created thread's priority (which has different semantics on +// some platforms). +TEST(PlatformThreadTest, MAYBE_ThreadPriorityCurrentThread) { + ThreadPriorityTestThread thread; PlatformThreadHandle handle; - ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle)); - thread.WaitForThreadStart(); - EXPECT_NE(thread.thread_id(), kInvalidThreadId); - EXPECT_NE(thread.thread_id(), PlatformThread::CurrentId()); - - // Confirm that the new thread's priority is as expected. - EXPECT_EQ(ThreadPriority::NORMAL, PlatformThread::GetThreadPriority(handle)); - - // Toggle each supported priority on the current thread and confirm it only - // affects it (and not the test thread). - for (size_t i = 0; i < arraysize(kThreadPriorityTestValues); ++i) { - SCOPED_TRACE(i); - - // Alter and verify the current thread's priority. - PlatformThread::SetThreadPriority(current_handle, - kThreadPriorityTestValues[i]); - EXPECT_EQ(kThreadPriorityTestValues[i], - PlatformThread::GetThreadPriority(current_handle)); - - // Make sure the test thread was otherwise unaffected. - EXPECT_EQ(ThreadPriority::NORMAL, - PlatformThread::GetThreadPriority(handle)); - } - // Restore current thread priority for follow-up tests. - PlatformThread::SetThreadPriority(current_handle, ThreadPriority::NORMAL); + ASSERT_FALSE(thread.IsRunning()); + ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle)); + thread.WaitForTerminationReady(); + ASSERT_TRUE(thread.IsRunning()); thread.MarkForTermination(); PlatformThread::Join(handle); + ASSERT_FALSE(thread.IsRunning()); } } // namespace base diff --git a/base/threading/platform_thread_win.cc b/base/threading/platform_thread_win.cc index 395fc9e20173a..059547b10ed27 100644 --- a/base/threading/platform_thread_win.cc +++ b/base/threading/platform_thread_win.cc @@ -46,6 +46,7 @@ void SetNameInternal(PlatformThreadId thread_id, const char* name) { struct ThreadParams { PlatformThread::Delegate* delegate; bool joinable; + ThreadPriority priority; }; DWORD __stdcall ThreadFunc(void* params) { @@ -54,6 +55,9 @@ DWORD __stdcall ThreadFunc(void* params) { if (!thread_params->joinable) base::ThreadRestrictions::SetSingletonAllowed(false); + if (thread_params->priority != ThreadPriority::NORMAL) + PlatformThread::SetCurrentThreadPriority(thread_params->priority); + // Retrieve a copy of the thread handle to use as the key in the // thread name mapping. PlatformThreadHandle::Handle platform_handle; @@ -86,12 +90,13 @@ DWORD __stdcall ThreadFunc(void* params) { return NULL; } -// CreateThreadInternal() matches PlatformThread::Create(), except that -// |out_thread_handle| may be NULL, in which case a non-joinable thread is +// CreateThreadInternal() matches PlatformThread::CreateWithPriority(), except +// that |out_thread_handle| may be NULL, in which case a non-joinable thread is // created. bool CreateThreadInternal(size_t stack_size, PlatformThread::Delegate* delegate, - PlatformThreadHandle* out_thread_handle) { + PlatformThreadHandle* out_thread_handle, + ThreadPriority priority) { unsigned int flags = 0; if (stack_size > 0 && base::win::GetVersion() >= base::win::VERSION_XP) { flags = STACK_SIZE_PARAM_IS_A_RESERVATION; @@ -102,6 +107,7 @@ bool CreateThreadInternal(size_t stack_size, ThreadParams* params = new ThreadParams; params->delegate = delegate; params->joinable = out_thread_handle != NULL; + params->priority = priority; // Using CreateThread here vs _beginthreadex makes thread creation a bit // faster and doesn't require the loader lock to be available. Our code will @@ -185,23 +191,22 @@ const char* PlatformThread::GetName() { // static bool PlatformThread::Create(size_t stack_size, Delegate* delegate, PlatformThreadHandle* thread_handle) { - DCHECK(thread_handle); - return CreateThreadInternal(stack_size, delegate, thread_handle); + return CreateWithPriority( + stack_size, delegate, thread_handle, ThreadPriority::NORMAL); } // static bool PlatformThread::CreateWithPriority(size_t stack_size, Delegate* delegate, PlatformThreadHandle* thread_handle, ThreadPriority priority) { - bool result = Create(stack_size, delegate, thread_handle); - if (result) - SetThreadPriority(*thread_handle, priority); - return result; + DCHECK(thread_handle); + return CreateThreadInternal(stack_size, delegate, thread_handle, priority); } // static bool PlatformThread::CreateNonJoinable(size_t stack_size, Delegate* delegate) { - return CreateThreadInternal(stack_size, delegate, NULL); + return CreateThreadInternal( + stack_size, delegate, NULL, ThreadPriority::NORMAL); } // static @@ -231,10 +236,7 @@ void PlatformThread::Join(PlatformThreadHandle thread_handle) { } // static -void PlatformThread::SetThreadPriority(PlatformThreadHandle handle, - ThreadPriority priority) { - DCHECK(!handle.is_null()); - +void PlatformThread::SetCurrentThreadPriority(ThreadPriority priority) { int desired_priority = THREAD_PRIORITY_ERROR_RETURN; switch (priority) { case ThreadPriority::BACKGROUND: @@ -258,16 +260,16 @@ void PlatformThread::SetThreadPriority(PlatformThreadHandle handle, #ifndef NDEBUG const BOOL success = #endif - ::SetThreadPriority(handle.platform_handle(), desired_priority); + ::SetThreadPriority(PlatformThread::CurrentHandle().platform_handle(), + desired_priority); DPLOG_IF(ERROR, !success) << "Failed to set thread priority to " << desired_priority; } // static -ThreadPriority PlatformThread::GetThreadPriority(PlatformThreadHandle handle) { - DCHECK(!handle.is_null()); - - int priority = ::GetThreadPriority(handle.platform_handle()); +ThreadPriority PlatformThread::GetCurrentThreadPriority() { + int priority = + ::GetThreadPriority(PlatformThread::CurrentHandle().platform_handle()); switch (priority) { case THREAD_PRIORITY_LOWEST: return ThreadPriority::BACKGROUND; diff --git a/base/threading/post_task_and_reply_impl.h b/base/threading/post_task_and_reply_impl.h index a5b9580e6dc43..d21ab78de8550 100644 --- a/base/threading/post_task_and_reply_impl.h +++ b/base/threading/post_task_and_reply_impl.h @@ -25,6 +25,8 @@ namespace internal { // may want base::WorkerPool. class PostTaskAndReplyImpl { public: + virtual ~PostTaskAndReplyImpl() = default; + // Implementation for TaskRunner::PostTaskAndReply and // WorkerPool::PostTaskAndReply. bool PostTaskAndReply(const tracked_objects::Location& from_here, diff --git a/base/threading/simple_thread.h b/base/threading/simple_thread.h index 36548d36fd5af..2f0eb4d778faa 100644 --- a/base/threading/simple_thread.h +++ b/base/threading/simple_thread.h @@ -59,8 +59,10 @@ class BASE_EXPORT SimpleThread : public PlatformThread::Delegate { public: class BASE_EXPORT Options { public: - Options() : stack_size_(0), priority_(ThreadPriority::NORMAL) { } - ~Options() { } + Options() : stack_size_(0), priority_(ThreadPriority::NORMAL) {} + explicit Options(ThreadPriority priority) + : stack_size_(0), priority_(priority) {} + ~Options() {} // We use the standard compiler-supplied copy constructor. @@ -109,12 +111,6 @@ class BASE_EXPORT SimpleThread : public PlatformThread::Delegate { // Overridden from PlatformThread::Delegate: void ThreadMain() override; - // Only set priorities with a careful understanding of the consequences. - // This is meant for very limited use cases. - void SetThreadPriority(ThreadPriority priority) { - PlatformThread::SetThreadPriority(thread_, priority); - } - private: const std::string name_prefix_; std::string name_; diff --git a/base/threading/thread.cc b/base/threading/thread.cc index 63b07cbce6935..7bff24232e2bf 100644 --- a/base/threading/thread.cc +++ b/base/threading/thread.cc @@ -94,8 +94,9 @@ bool Thread::StartWithOptions(const Options& options) { type = MessageLoop::TYPE_CUSTOM; message_loop_timer_slack_ = options.timer_slack; - message_loop_ = new MessageLoop(type, options.message_pump_factory); - + scoped_ptr message_loop = MessageLoop::CreateUnbound( + type, options.message_pump_factory); + message_loop_ = message_loop.get(); start_event_.reset(new WaitableEvent(false, false)); // Hold the thread_lock_ while starting a new thread, so that we can make sure @@ -111,13 +112,16 @@ bool Thread::StartWithOptions(const Options& options) { } if (!created) { DLOG(ERROR) << "failed to create thread"; - delete message_loop_; message_loop_ = nullptr; start_event_.reset(); return false; } } + // The ownership of message_loop is managemed by the newly created thread + // within the ThreadMain. + ignore_result(message_loop.release()); + DCHECK(message_loop_); return true; } @@ -190,13 +194,6 @@ bool Thread::IsRunning() const { return running_; } -void Thread::SetPriority(ThreadPriority priority) { - // The thread must be started (and id known) for this to be - // compatible with all platforms. - DCHECK(message_loop_ != nullptr); - PlatformThread::SetThreadPriority(thread_, priority); -} - void Thread::Run(MessageLoop* message_loop) { message_loop->Run(); } diff --git a/base/threading/thread.h b/base/threading/thread.h index 0bd5d12922f13..5126491b3861c 100644 --- a/base/threading/thread.h +++ b/base/threading/thread.h @@ -155,25 +155,13 @@ class BASE_EXPORT Thread : PlatformThread::Delegate { // MessageLoop* message_loop() const { return message_loop_; } - // Returns a MessageLoopProxy for this thread. Use the MessageLoopProxy's - // PostTask methods to execute code on the thread. Returns NULL if the thread - // is not running (e.g. before Start or after Stop have been called). Callers - // can hold on to this even after the thread is gone; in this situation, - // attempts to PostTask() will fail. - // - // Note: This method is deprecated. Callers should call task_runner() instead - // and use the TaskRunner interfaces for safely interfacing with the Thread. - scoped_refptr message_loop_proxy() const { - return message_loop_ ? message_loop_->message_loop_proxy() : NULL; - } - // Returns a TaskRunner for this thread. Use the TaskRunner's PostTask // methods to execute code on the thread. Returns NULL if the thread is not // running (e.g. before Start or after Stop have been called). Callers can // hold on to this even after the thread is gone; in this situation, attempts // to PostTask() will fail. scoped_refptr task_runner() const { - return message_loop_->task_runner(); + return message_loop_ ? message_loop_->task_runner() : nullptr; } // Returns the name of this thread (for display in debugger too). @@ -188,9 +176,6 @@ class BASE_EXPORT Thread : PlatformThread::Delegate { // Returns true if the thread has been started, and not yet stopped. bool IsRunning() const; - // Sets the thread priority. The thread must already be started. - void SetPriority(ThreadPriority priority); - protected: // Called just prior to starting the message loop virtual void Init() {} diff --git a/base/threading/thread_restrictions.h b/base/threading/thread_restrictions.h index 54f50ebca8796..b6cfa72320698 100644 --- a/base/threading/thread_restrictions.h +++ b/base/threading/thread_restrictions.h @@ -58,6 +58,7 @@ class WatcherThreadManager; } } namespace net { +class NetworkChangeNotifierMac; namespace internal { class AddressTrackerLinux; } @@ -206,6 +207,7 @@ class BASE_EXPORT ThreadRestrictions { friend class disk_cache::BackendImpl; // http://crbug.com/74623 friend class disk_cache::InFlightIO; // http://crbug.com/74623 friend class net::internal::AddressTrackerLinux; // http://crbug.com/125097 + friend class net::NetworkChangeNotifierMac; // http://crbug.com/125097 friend class ::BrowserProcessImpl; // http://crbug.com/125207 friend class ::NativeBackendKWallet; // http://crbug.com/125331 // END USAGE THAT NEEDS TO BE FIXED. diff --git a/base/threading/thread_unittest.cc b/base/threading/thread_unittest.cc index e86c7582e3199..3c3541657ebff 100644 --- a/base/threading/thread_unittest.cc +++ b/base/threading/thread_unittest.cc @@ -234,3 +234,8 @@ TEST_F(ThreadTest, CleanUp) { EXPECT_EQ(THREAD_EVENT_CLEANUP, captured_events[1]); EXPECT_EQ(THREAD_EVENT_MESSAGE_LOOP_DESTROYED, captured_events[2]); } + +TEST_F(ThreadTest, ThreadNotStarted) { + Thread a("Inert"); + EXPECT_EQ(nullptr, a.task_runner()); +} diff --git a/base/threading/worker_pool.cc b/base/threading/worker_pool.cc index bc016cec0d9d2..71b1a2bda3583 100644 --- a/base/threading/worker_pool.cc +++ b/base/threading/worker_pool.cc @@ -21,6 +21,7 @@ class PostTaskAndReplyWorkerPool : public internal::PostTaskAndReplyImpl { explicit PostTaskAndReplyWorkerPool(bool task_is_slow) : task_is_slow_(task_is_slow) { } + ~PostTaskAndReplyWorkerPool() override = default; private: bool PostTask(const tracked_objects::Location& from_here, diff --git a/base/time/time_posix.cc b/base/time/time_posix.cc index 7826fc681cd09..fc82c620b382a 100644 --- a/base/time/time_posix.cc +++ b/base/time/time_posix.cc @@ -17,7 +17,6 @@ #include "base/basictypes.h" #include "base/logging.h" -#include "base/port.h" #include "build/build_config.h" #if defined(OS_ANDROID) diff --git a/base/time/time_win.cc b/base/time/time_win.cc index 9144483000909..e9044603e9aed 100644 --- a/base/time/time_win.cc +++ b/base/time/time_win.cc @@ -428,7 +428,7 @@ bool IsBuggyAthlon(const base::CPU& cpu) { } void InitializeNowFunctionPointers() { - LARGE_INTEGER ticks_per_sec = {0}; + LARGE_INTEGER ticks_per_sec = {}; if (!QueryPerformanceFrequency(&ticks_per_sec)) ticks_per_sec.QuadPart = 0; diff --git a/base/trace_event/BUILD.gn b/base/trace_event/BUILD.gn index 64c76da38cb95..8f987479da451 100644 --- a/base/trace_event/BUILD.gn +++ b/base/trace_event/BUILD.gn @@ -13,6 +13,7 @@ source_set("trace_event") { "memory_dump_manager.cc", "memory_dump_manager.h", "memory_dump_provider.h", + "memory_dump_request_args.cc", "memory_dump_request_args.h", "memory_dump_session_state.cc", "memory_dump_session_state.h", @@ -39,6 +40,8 @@ source_set("trace_event") { "trace_event_impl_constants.cc", "trace_event_memory.cc", "trace_event_memory.h", + "trace_event_memory_overhead.cc", + "trace_event_memory_overhead.h", "trace_event_synthetic_delay.cc", "trace_event_synthetic_delay.h", "trace_event_system_stats_monitor.cc", diff --git a/base/trace_event/malloc_dump_provider.cc b/base/trace_event/malloc_dump_provider.cc index 92d513f99d3e3..3e593b02897cb 100644 --- a/base/trace_event/malloc_dump_provider.cc +++ b/base/trace_event/malloc_dump_provider.cc @@ -32,13 +32,13 @@ bool MallocDumpProvider::OnMemoryDump(ProcessMemoryDump* pmd) { struct mallinfo info = mallinfo(); DCHECK_GE(info.arena + info.hblkhd, info.uordblks); - // When the system allocator is implemented by tcmalloc, the total physical + // When the system allocator is implemented by tcmalloc, the total heap // size is given by |arena| and |hblkhd| is 0. In case of Android's jemalloc // |arena| is 0 and the outer pages size is reported by |hblkhd|. In case of // dlmalloc the total is given by |arena| + |hblkhd|. // For more details see link: http://goo.gl/fMR8lF. MemoryAllocatorDump* outer_dump = pmd->CreateAllocatorDump("malloc"); - outer_dump->AddScalar(MemoryAllocatorDump::kNameSize, + outer_dump->AddScalar("heap_virtual_size", MemoryAllocatorDump::kUnitsBytes, info.arena + info.hblkhd); diff --git a/base/trace_event/memory_allocator_dump.cc b/base/trace_event/memory_allocator_dump.cc index 5d11bb006e8b0..4037f946c9ef0 100644 --- a/base/trace_event/memory_allocator_dump.cc +++ b/base/trace_event/memory_allocator_dump.cc @@ -15,28 +15,7 @@ namespace base { namespace trace_event { -namespace { -// Returns the c-string pointer from a dictionary value without performing extra -// std::string copies. The ptr will be valid as long as the value exists. -bool GetDictionaryValueAsCStr(const DictionaryValue* dict_value, - const std::string& key, - const char** out_cstr) { - const Value* value = nullptr; - const StringValue* str_value = nullptr; - if (!dict_value->GetWithoutPathExpansion(key, &value)) - return false; - if (!value->GetAsString(&str_value)) - return false; - *out_cstr = str_value->GetString().c_str(); - return true; -} -} // namespace - -// TODO(primiano): remove kName{Inner,Outer}Size below after all the existing -// dump providers have been rewritten. const char MemoryAllocatorDump::kNameSize[] = "size"; -const char MemoryAllocatorDump::kNameInnerSize[] = "inner_size"; -const char MemoryAllocatorDump::kNameOuterSize[] = "outer_size"; const char MemoryAllocatorDump::kNameObjectsCount[] = "objects_count"; const char MemoryAllocatorDump::kTypeScalar[] = "scalar"; const char MemoryAllocatorDump::kTypeString[] = "string"; @@ -48,6 +27,7 @@ MemoryAllocatorDump::MemoryAllocatorDump(const std::string& absolute_name, const MemoryAllocatorDumpGuid& guid) : absolute_name_(absolute_name), process_memory_dump_(process_memory_dump), + attributes_(new TracedValue), guid_(guid) { // The |absolute_name| cannot be empty. DCHECK(!absolute_name.empty()); @@ -73,73 +53,47 @@ MemoryAllocatorDump::MemoryAllocatorDump(const std::string& absolute_name, "%d:%s", TraceLog::GetInstance()->process_id(), absolute_name.c_str()))) { + string_conversion_buffer_.reserve(16); } MemoryAllocatorDump::~MemoryAllocatorDump() { } -void MemoryAllocatorDump::Add(const std::string& name, - const char* type, - const char* units, - scoped_ptr value) { - scoped_ptr attribute(new DictionaryValue()); - DCHECK(!attributes_.HasKey(name)); - attribute->SetStringWithoutPathExpansion("type", type); - attribute->SetStringWithoutPathExpansion("units", units); - attribute->SetWithoutPathExpansion("value", value.Pass()); - attributes_.SetWithoutPathExpansion(name, attribute.Pass()); -} - -bool MemoryAllocatorDump::Get(const std::string& name, - const char** out_type, - const char** out_units, - const Value** out_value) const { - const DictionaryValue* attribute = nullptr; - if (!attributes_.GetDictionaryWithoutPathExpansion(name, &attribute)) - return false; - - if (!GetDictionaryValueAsCStr(attribute, "type", out_type)) - return false; - - if (!GetDictionaryValueAsCStr(attribute, "units", out_units)) - return false; - - if (!attribute->GetWithoutPathExpansion("value", out_value)) - return false; - - return true; -} - -void MemoryAllocatorDump::AddScalar(const std::string& name, +void MemoryAllocatorDump::AddScalar(const char* name, const char* units, uint64 value) { - scoped_ptr hex_value(new StringValue(StringPrintf("%" PRIx64, value))); - Add(name, kTypeScalar, units, hex_value.Pass()); + SStringPrintf(&string_conversion_buffer_, "%" PRIx64, value); + attributes_->BeginDictionary(name); + attributes_->SetString("type", kTypeScalar); + attributes_->SetString("units", units); + attributes_->SetString("value", string_conversion_buffer_); + attributes_->EndDictionary(); } -void MemoryAllocatorDump::AddScalarF(const std::string& name, +void MemoryAllocatorDump::AddScalarF(const char* name, const char* units, double value) { - Add(name, kTypeScalar, units, make_scoped_ptr(new FundamentalValue(value))); + attributes_->BeginDictionary(name); + attributes_->SetString("type", kTypeScalar); + attributes_->SetString("units", units); + attributes_->SetDouble("value", value); + attributes_->EndDictionary(); } -void MemoryAllocatorDump::AddString(const std::string& name, +void MemoryAllocatorDump::AddString(const char* name, const char* units, const std::string& value) { - scoped_ptr str_value(new StringValue(value)); - Add(name, kTypeString, units, str_value.Pass()); + attributes_->BeginDictionary(name); + attributes_->SetString("type", kTypeString); + attributes_->SetString("units", units); + attributes_->SetString("value", value); + attributes_->EndDictionary(); } void MemoryAllocatorDump::AsValueInto(TracedValue* value) const { - value->BeginDictionary(absolute_name_.c_str()); + value->BeginDictionaryWithCopiedName(absolute_name_); value->SetString("guid", guid_.ToString()); - - value->BeginDictionary("attrs"); - - for (DictionaryValue::Iterator it(attributes_); !it.IsAtEnd(); it.Advance()) - value->SetValue(it.key().c_str(), it.value().CreateDeepCopy()); - - value->EndDictionary(); // "attrs": { ... } + value->SetValue("attrs", *attributes_); value->EndDictionary(); // "allocator_name/heap_subheap": { ... } } diff --git a/base/trace_event/memory_allocator_dump.h b/base/trace_event/memory_allocator_dump.h index 9a151a6f9c5e2..2ded1733c3f97 100644 --- a/base/trace_event/memory_allocator_dump.h +++ b/base/trace_event/memory_allocator_dump.h @@ -5,9 +5,12 @@ #ifndef BASE_TRACE_EVENT_MEMORY_ALLOCATOR_DUMP_H_ #define BASE_TRACE_EVENT_MEMORY_ALLOCATOR_DUMP_H_ +#include + #include "base/base_export.h" #include "base/basictypes.h" #include "base/logging.h" +#include "base/memory/ref_counted.h" #include "base/trace_event/memory_allocator_dump_guid.h" #include "base/values.h" @@ -29,45 +32,32 @@ class BASE_EXPORT MemoryAllocatorDump { ProcessMemoryDump* process_memory_dump); ~MemoryAllocatorDump(); - // Standard attribute name to model allocated space. - static const char kNameSize[]; - - // Standard attribute name to model total space requested by the allocator - // (e.g., amount of pages requested to the system). - static const char kNameOuterSize[]; - - // Standard attribute name to model space for allocated objects, without - // taking into account allocator metadata or fragmentation. - static const char kNameInnerSize[]; - - // Standard attribute name to model the number of objects allocated. - static const char kNameObjectsCount[]; + // Standard attribute |name|s for the AddScalar and AddString() methods. + static const char kNameSize[]; // To represent allocated space. + static const char kNameObjectsCount[]; // To represent number of objects. - static const char kTypeScalar[]; // Type name for scalar attributes. - static const char kTypeString[]; // Type name for string attributes. + // Standard attribute |unit|s for the AddScalar and AddString() methods. static const char kUnitsBytes[]; // Unit name to represent bytes. static const char kUnitsObjects[]; // Unit name to represent #objects. + // Constants used only internally and by tests. + static const char kTypeScalar[]; // Type name for scalar attributes. + static const char kTypeString[]; // Type name for string attributes. + + // Setters for scalar attributes. Some examples: + // - "size" column (all dumps are expected to have at least this one): + // AddScalar(kNameSize, kUnitsBytes, 1234); + // - Some extra-column reporting internal details of the subsystem: + // AddScalar("number_of_freelist_entires", kUnitsObjects, 42) + // - Other informational column (will not be auto-added in the UI) + // AddScalarF("kittens_ratio", "ratio", 42.0f) + void AddScalar(const char* name, const char* units, uint64 value); + void AddScalarF(const char* name, const char* units, double value); + void AddString(const char* name, const char* units, const std::string& value); + // Absolute name, unique within the scope of an entire ProcessMemoryDump. const std::string& absolute_name() const { return absolute_name_; } - // Generic attribute setter / getter. - void Add(const std::string& name, - const char* type, - const char* units, - scoped_ptr value); - bool Get(const std::string& name, - const char** out_type, - const char** out_units, - const Value** out_value) const; - - // Helper setter for scalar attributes. - void AddScalar(const std::string& name, const char* units, uint64 value); - void AddScalarF(const std::string& name, const char* units, double value); - void AddString(const std::string& name, - const char* units, - const std::string& value); - // Called at trace generation time to populate the TracedValue. void AsValueInto(TracedValue* value) const; @@ -84,12 +74,18 @@ class BASE_EXPORT MemoryAllocatorDump { // expected to have the same guid. const MemoryAllocatorDumpGuid& guid() const { return guid_; } + TracedValue* attributes_for_testing() const { return attributes_.get(); } + private: const std::string absolute_name_; ProcessMemoryDump* const process_memory_dump_; // Not owned (PMD owns this). - DictionaryValue attributes_; + scoped_refptr attributes_; MemoryAllocatorDumpGuid guid_; + // A local buffer for Sprintf conversion on fastpath. Avoids allocating + // temporary strings on each AddScalar() call. + std::string string_conversion_buffer_; + DISALLOW_COPY_AND_ASSIGN(MemoryAllocatorDump); }; diff --git a/base/trace_event/memory_allocator_dump_guid.cc b/base/trace_event/memory_allocator_dump_guid.cc index a4ea50d416a0d..d4ed900b9febc 100644 --- a/base/trace_event/memory_allocator_dump_guid.cc +++ b/base/trace_event/memory_allocator_dump_guid.cc @@ -5,12 +5,21 @@ #include "base/trace_event/memory_allocator_dump_guid.h" #include "base/format_macros.h" -#include "base/hash.h" +#include "base/sha1.h" #include "base/strings/stringprintf.h" namespace base { namespace trace_event { +namespace { +uint64 HashString(const std::string& str) { + uint64 hash[(kSHA1Length + sizeof(uint64) - 1) / sizeof(uint64)] = { 0 }; + SHA1HashBytes(reinterpret_cast(str.data()), str.size(), + reinterpret_cast(hash)); + return hash[0]; +} +} // namespace + MemoryAllocatorDumpGuid::MemoryAllocatorDumpGuid(uint64 guid) : guid_(guid) { } @@ -19,7 +28,7 @@ MemoryAllocatorDumpGuid::MemoryAllocatorDumpGuid() } MemoryAllocatorDumpGuid::MemoryAllocatorDumpGuid(const std::string& guid_str) - : MemoryAllocatorDumpGuid(Hash(guid_str)) { + : MemoryAllocatorDumpGuid(HashString(guid_str)) { } std::string MemoryAllocatorDumpGuid::ToString() const { diff --git a/base/trace_event/memory_allocator_dump_guid.h b/base/trace_event/memory_allocator_dump_guid.h index 84c12ef037401..634ca8133b532 100644 --- a/base/trace_event/memory_allocator_dump_guid.h +++ b/base/trace_event/memory_allocator_dump_guid.h @@ -23,6 +23,8 @@ class BASE_EXPORT MemoryAllocatorDumpGuid { // global scope of all the traced processes. explicit MemoryAllocatorDumpGuid(const std::string& guid_str); + uint64 ToUint64() const { return guid_; } + // Returns a (hex-encoded) string representation of the guid. std::string ToString() const; diff --git a/base/trace_event/memory_allocator_dump_unittest.cc b/base/trace_event/memory_allocator_dump_unittest.cc index b9adbae07da09..85b98d65511ed 100644 --- a/base/trace_event/memory_allocator_dump_unittest.cc +++ b/base/trace_event/memory_allocator_dump_unittest.cc @@ -11,6 +11,7 @@ #include "base/trace_event/memory_dump_session_state.h" #include "base/trace_event/process_memory_dump.h" #include "base/trace_event/trace_event_argument.h" +#include "base/values.h" #include "testing/gtest/include/gtest/gtest.h" namespace base { @@ -47,20 +48,23 @@ class FakeMemoryAllocatorDumpProvider : public MemoryDumpProvider { } }; -bool CheckAttribute(const MemoryAllocatorDump* dump, - const std::string& name, - const char* expected_type, - const char* expected_units, - const Value** out_value) { - const char* attr_type; - const char* attr_units; - bool res = dump->Get(name, &attr_type, &attr_units, out_value); - EXPECT_TRUE(res); - if (!res) - return false; - EXPECT_EQ(expected_type, std::string(attr_type)); - EXPECT_EQ(expected_units, std::string(attr_units)); - return true; +scoped_ptr CheckAttribute(const MemoryAllocatorDump* dump, + const std::string& name, + const char* expected_type, + const char* expected_units) { + scoped_ptr raw_attrs = dump->attributes_for_testing()->ToBaseValue(); + DictionaryValue* args = nullptr; + DictionaryValue* arg = nullptr; + std::string arg_value; + const Value* out_value = nullptr; + EXPECT_TRUE(raw_attrs->GetAsDictionary(&args)); + EXPECT_TRUE(args->GetDictionary(name, &arg)); + EXPECT_TRUE(arg->GetString("type", &arg_value)); + EXPECT_EQ(expected_type, arg_value); + EXPECT_TRUE(arg->GetString("units", &arg_value)); + EXPECT_EQ(expected_units, arg_value); + EXPECT_TRUE(arg->Get("value", &out_value)); + return out_value ? out_value->CreateDeepCopy() : scoped_ptr(); } void CheckString(const MemoryAllocatorDump* dump, @@ -68,12 +72,8 @@ void CheckString(const MemoryAllocatorDump* dump, const char* expected_type, const char* expected_units, const std::string& expected_value) { - const Value* attr_value = nullptr; std::string attr_str_value; - bool res = - CheckAttribute(dump, name, expected_type, expected_units, &attr_value); - if (!res) - return; + auto attr_value = CheckAttribute(dump, name, expected_type, expected_units); EXPECT_TRUE(attr_value->GetAsString(&attr_str_value)); EXPECT_EQ(expected_value, attr_str_value); } @@ -90,12 +90,9 @@ void CheckScalarF(const MemoryAllocatorDump* dump, const std::string& name, const char* expected_units, double expected_value) { - const Value* attr_value = nullptr; + auto attr_value = CheckAttribute(dump, name, MemoryAllocatorDump::kTypeScalar, + expected_units); double attr_double_value; - bool res = CheckAttribute(dump, name, MemoryAllocatorDump::kTypeScalar, - expected_units, &attr_value); - if (!res) - return; EXPECT_TRUE(attr_value->GetAsDouble(&attr_double_value)); EXPECT_EQ(expected_value, attr_double_value); } @@ -154,15 +151,15 @@ TEST(MemoryAllocatorDumpTest, DumpIntoProcessMemoryDump) { MemoryAllocatorDump::kUnitsBytes, 1); CheckScalar(sub_heap, MemoryAllocatorDump::kNameObjectsCount, MemoryAllocatorDump::kUnitsObjects, 3); - const MemoryAllocatorDump* empty_sub_heap = pmd.GetAllocatorDump("foobar_allocator/sub_heap/empty"); ASSERT_NE(nullptr, empty_sub_heap); EXPECT_EQ("foobar_allocator/sub_heap/empty", empty_sub_heap->absolute_name()); - ASSERT_FALSE(empty_sub_heap->Get(MemoryAllocatorDump::kNameSize, nullptr, - nullptr, nullptr)); - ASSERT_FALSE(empty_sub_heap->Get(MemoryAllocatorDump::kNameObjectsCount, - nullptr, nullptr, nullptr)); + auto raw_attrs = empty_sub_heap->attributes_for_testing()->ToBaseValue(); + DictionaryValue* attrs = nullptr; + ASSERT_TRUE(raw_attrs->GetAsDictionary(&attrs)); + ASSERT_FALSE(attrs->HasKey(MemoryAllocatorDump::kNameSize)); + ASSERT_FALSE(attrs->HasKey(MemoryAllocatorDump::kNameObjectsCount)); // Check that the AsValueInfo doesn't hit any DCHECK. scoped_refptr traced_value(new TracedValue()); diff --git a/base/trace_event/memory_dump_manager.cc b/base/trace_event/memory_dump_manager.cc index 1e4d8229aef0b..537984672a787 100644 --- a/base/trace_event/memory_dump_manager.cc +++ b/base/trace_event/memory_dump_manager.cc @@ -8,6 +8,8 @@ #include "base/atomic_sequence_num.h" #include "base/compiler_specific.h" +#include "base/hash.h" +#include "base/thread_task_runner_handle.h" #include "base/trace_event/memory_dump_provider.h" #include "base/trace_event/memory_dump_session_state.h" #include "base/trace_event/process_memory_dump.h" @@ -40,96 +42,26 @@ namespace { // trace event synthetic delays. const char kTraceCategory[] = TRACE_DISABLED_BY_DEFAULT("memory-infra"); -MemoryDumpManager* g_instance_for_testing = nullptr; -const int kDumpIntervalSeconds = 2; +// Throttle mmaps at a rate of once every kHeavyMmapsDumpsRate standard dumps. +const int kHeavyMmapsDumpsRate = 8; // 250 ms * 8 = 2000 ms. +const int kDumpIntervalMs = 250; const int kTraceEventNumArgs = 1; const char* kTraceEventArgNames[] = {"dumps"}; const unsigned char kTraceEventArgTypes[] = {TRACE_VALUE_TYPE_CONVERTABLE}; -StaticAtomicSequenceNumber g_next_guid; - -const char* MemoryDumpTypeToString(const MemoryDumpType& dump_type) { - switch (dump_type) { - case MemoryDumpType::TASK_BEGIN: - return "TASK_BEGIN"; - case MemoryDumpType::TASK_END: - return "TASK_END"; - case MemoryDumpType::PERIODIC_INTERVAL: - return "PERIODIC_INTERVAL"; - case MemoryDumpType::EXPLICITLY_TRIGGERED: - return "EXPLICITLY_TRIGGERED"; - } - NOTREACHED(); - return "UNKNOWN"; -} -// Internal class used to hold details about ProcessMemoryDump requests for the -// current process. -// TODO(primiano): In the upcoming CLs, ProcessMemoryDump will become async. -// and this class will be used to convey more details across PostTask()s. -class ProcessMemoryDumpHolder - : public RefCountedThreadSafe { - public: - ProcessMemoryDumpHolder( - MemoryDumpRequestArgs req_args, - const scoped_refptr& session_state, - MemoryDumpCallback callback) - : process_memory_dump(session_state), - req_args(req_args), - callback(callback), - task_runner(MessageLoop::current()->task_runner()), - num_pending_async_requests(0) {} - - ProcessMemoryDump process_memory_dump; - const MemoryDumpRequestArgs req_args; - - // Callback passed to the initial call to CreateProcessDump(). - MemoryDumpCallback callback; - - // Thread on which FinalizeDumpAndAddToTrace() should be called, which is the - // same that invoked the initial CreateProcessDump(). - const scoped_refptr task_runner; - - // Number of pending ContinueAsyncProcessDump() calls. - int num_pending_async_requests; - - private: - friend class RefCountedThreadSafe; - virtual ~ProcessMemoryDumpHolder() {} - DISALLOW_COPY_AND_ASSIGN(ProcessMemoryDumpHolder); -}; - -void FinalizeDumpAndAddToTrace( - const scoped_refptr& pmd_holder) { - DCHECK_EQ(0, pmd_holder->num_pending_async_requests); - - if (!pmd_holder->task_runner->BelongsToCurrentThread()) { - pmd_holder->task_runner->PostTask( - FROM_HERE, Bind(&FinalizeDumpAndAddToTrace, pmd_holder)); - return; - } - - scoped_refptr event_value(new TracedValue()); - pmd_holder->process_memory_dump.AsValueInto( - static_cast(event_value.get())); - const char* const event_name = - MemoryDumpTypeToString(pmd_holder->req_args.dump_type); - - TRACE_EVENT_API_ADD_TRACE_EVENT( - TRACE_EVENT_PHASE_MEMORY_DUMP, - TraceLog::GetCategoryGroupEnabled(kTraceCategory), event_name, - pmd_holder->req_args.dump_guid, kTraceEventNumArgs, kTraceEventArgNames, - kTraceEventArgTypes, nullptr /* arg_values */, &event_value, - TRACE_EVENT_FLAG_HAS_ID); - - if (!pmd_holder->callback.is_null()) { - pmd_holder->callback.Run(pmd_holder->req_args.dump_guid, true); - pmd_holder->callback.Reset(); - } -} +StaticAtomicSequenceNumber g_next_guid; +uint32 g_periodic_dumps_count = 0; +MemoryDumpManager* g_instance_for_testing = nullptr; +MemoryDumpProvider* g_mmaps_dump_provider = nullptr; void RequestPeriodicGlobalDump() { - MemoryDumpManager::GetInstance()->RequestGlobalDump( - MemoryDumpType::PERIODIC_INTERVAL); + MemoryDumpType dump_type = g_periodic_dumps_count == 0 + ? MemoryDumpType::PERIODIC_INTERVAL_WITH_MMAPS + : MemoryDumpType::PERIODIC_INTERVAL; + if (++g_periodic_dumps_count == kHeavyMmapsDumpsRate) + g_periodic_dumps_count = 0; + + MemoryDumpManager::GetInstance()->RequestGlobalDump(dump_type); } } // namespace @@ -137,6 +69,12 @@ void RequestPeriodicGlobalDump() { // static const char* const MemoryDumpManager::kTraceCategoryForTesting = kTraceCategory; +// static +const uint64 MemoryDumpManager::kInvalidTracingProcessId = 0; + +// static +const int MemoryDumpManager::kMaxConsecutiveFailuresCount = 3; + // static MemoryDumpManager* MemoryDumpManager::GetInstance() { if (g_instance_for_testing) @@ -154,8 +92,10 @@ void MemoryDumpManager::SetInstanceForTesting(MemoryDumpManager* instance) { } MemoryDumpManager::MemoryDumpManager() - : delegate_(nullptr), + : did_unregister_dump_provider_(false), + delegate_(nullptr), memory_tracing_enabled_(0), + tracing_process_id_(kInvalidTracingProcessId), skip_core_dumpers_auto_registration_for_testing_(false) { g_next_guid.GetNext(); // Make sure that first guid is not zero. } @@ -177,7 +117,8 @@ void MemoryDumpManager::Initialize() { #endif #if defined(OS_LINUX) || defined(OS_ANDROID) - RegisterDumpProvider(ProcessMemoryMapsDumpProvider::GetInstance()); + g_mmaps_dump_provider = ProcessMemoryMapsDumpProvider::GetInstance(); + RegisterDumpProvider(g_mmaps_dump_provider); RegisterDumpProvider(MallocDumpProvider::GetInstance()); #endif @@ -199,9 +140,9 @@ void MemoryDumpManager::SetDelegate(MemoryDumpManagerDelegate* delegate) { void MemoryDumpManager::RegisterDumpProvider( MemoryDumpProvider* mdp, const scoped_refptr& task_runner) { - MemoryDumpProviderInfo mdp_info(task_runner); + MemoryDumpProviderInfo mdp_info(mdp, task_runner); AutoLock lock(lock_); - dump_providers_.insert(std::make_pair(mdp, mdp_info)); + dump_providers_.insert(mdp_info); } void MemoryDumpManager::RegisterDumpProvider(MemoryDumpProvider* mdp) { @@ -211,11 +152,15 @@ void MemoryDumpManager::RegisterDumpProvider(MemoryDumpProvider* mdp) { void MemoryDumpManager::UnregisterDumpProvider(MemoryDumpProvider* mdp) { AutoLock lock(lock_); - auto it = dump_providers_.find(mdp); - if (it == dump_providers_.end()) + auto mdp_iter = dump_providers_.begin(); + for (; mdp_iter != dump_providers_.end(); ++mdp_iter) { + if (mdp_iter->dump_provider == mdp) + break; + } + + if (mdp_iter == dump_providers_.end()) return; - const MemoryDumpProviderInfo& mdp_info = it->second; // Unregistration of a MemoryDumpProvider while tracing is ongoing is safe // only if the MDP has specified a thread affinity (via task_runner()) AND // the unregistration happens on the same thread (so the MDP cannot unregister @@ -224,13 +169,12 @@ void MemoryDumpManager::UnregisterDumpProvider(MemoryDumpProvider* mdp) { // race-free. If you hit this DCHECK, your MDP has a bug. DCHECK_IMPLIES( subtle::NoBarrier_Load(&memory_tracing_enabled_), - mdp_info.task_runner && mdp_info.task_runner->BelongsToCurrentThread()) + mdp_iter->task_runner && mdp_iter->task_runner->BelongsToCurrentThread()) << "The MemoryDumpProvider attempted to unregister itself in a racy way. " - << " Please file a crbug."; + << "Please file a crbug."; - // Remove from the enabled providers list. This is to deal with the case that - // UnregisterDumpProvider is called while the trace is enabled. - dump_providers_.erase(it); + dump_providers_.erase(mdp_iter); + did_unregister_dump_provider_ = true; } void MemoryDumpManager::RequestGlobalDump( @@ -265,96 +209,179 @@ void MemoryDumpManager::RequestGlobalDump(MemoryDumpType dump_type) { RequestGlobalDump(dump_type, MemoryDumpCallback()); } -// Creates a memory dump for the current process and appends it to the trace. void MemoryDumpManager::CreateProcessDump(const MemoryDumpRequestArgs& args, const MemoryDumpCallback& callback) { - scoped_refptr pmd_holder( - new ProcessMemoryDumpHolder(args, session_state_, callback)); - ProcessMemoryDump* pmd = &pmd_holder->process_memory_dump; - bool did_any_provider_dump = false; - - // Iterate over the active dump providers and invoke OnMemoryDump(pmd). - // The MDM guarantees linearity (at most one MDP is active within one - // process) and thread-safety (MDM enforces the right locking when entering / - // leaving the MDP.OnMemoryDump() call). This is to simplify the clients' - // design - // and not let the MDPs worry about locking. - // As regards thread affinity, depending on the MDP configuration (see - // memory_dump_provider.h), the OnMemoryDump() invocation can happen: - // - Synchronousy on the MDM thread, when MDP.task_runner() is not set. - // - Posted on MDP.task_runner(), when MDP.task_runner() is set. + scoped_ptr pmd_async_state; { AutoLock lock(lock_); - for (auto it = dump_providers_.begin(); it != dump_providers_.end(); ++it) { - MemoryDumpProvider* mdp = it->first; - MemoryDumpProviderInfo* mdp_info = &it->second; - if (mdp_info->disabled) - continue; - if (mdp_info->task_runner) { - // The OnMemoryDump() call must be posted. - bool did_post_async_task = mdp_info->task_runner->PostTask( - FROM_HERE, Bind(&MemoryDumpManager::ContinueAsyncProcessDump, - Unretained(this), Unretained(mdp), pmd_holder)); - // The thread underlying the TaskRunner might have gone away. - if (did_post_async_task) - ++pmd_holder->num_pending_async_requests; - } else { - // Invoke the dump provider synchronously. - did_any_provider_dump |= InvokeDumpProviderLocked(mdp, pmd); - } - } - } // AutoLock + did_unregister_dump_provider_ = false; + pmd_async_state.reset(new ProcessMemoryDumpAsyncState( + args, dump_providers_.begin(), session_state_, callback)); + } - // If at least one synchronous provider did dump and there are no pending - // asynchronous requests, add the dump to the trace and invoke the callback - // straight away (FinalizeDumpAndAddToTrace() takes care of the callback). - if (did_any_provider_dump && pmd_holder->num_pending_async_requests == 0) - FinalizeDumpAndAddToTrace(pmd_holder); + // Start the thread hop. |dump_providers_| are kept sorted by thread, so + // ContinueAsyncProcessDump will hop at most once per thread (w.r.t. thread + // affinity specified by the MemoryDumpProvider(s) in RegisterDumpProvider()). + ContinueAsyncProcessDump(pmd_async_state.Pass()); } -// Invokes the MemoryDumpProvider.OnMemoryDump(), taking care of the fail-safe -// logic which disables the dumper when failing (crbug.com/461788). -bool MemoryDumpManager::InvokeDumpProviderLocked(MemoryDumpProvider* mdp, - ProcessMemoryDump* pmd) { - lock_.AssertAcquired(); - bool dump_successful = mdp->OnMemoryDump(pmd); - if (!dump_successful) { - LOG(ERROR) << "The memory dumper failed, possibly due to sandboxing " - "(crbug.com/461788), disabling it for current process. Try " - "restarting chrome with the --no-sandbox switch."; - dump_providers_.find(mdp)->second.disabled = true; - } - return dump_successful; -} +// At most one ContinueAsyncProcessDump() can be active at any time for a given +// PMD, regardless of status of the |lock_|. |lock_| is used here purely to +// ensure consistency w.r.t. (un)registrations of |dump_providers_|. +// The linearization of dump providers' OnMemoryDump invocations is achieved by +// means of subsequent PostTask(s). +// +// 1) Prologue: +// - Check if the dump provider is disabled, if so skip the dump. +// - Check if we are on the right thread. If not hop and continue there. +// 2) Invoke the dump provider's OnMemoryDump() (unless skipped). +// 3) Epilogue: +// - Unregister the dump provider if it failed too many times consecutively. +// - Advance the |next_dump_provider| iterator to the next dump provider. +// - If this was the last hop, create a trace event, add it to the trace +// and finalize (invoke callback). -// This is posted to arbitrary threads as a continuation of CreateProcessDump(), -// when one or more MemoryDumpProvider(s) require the OnMemoryDump() call to -// happen on a different thread. void MemoryDumpManager::ContinueAsyncProcessDump( - MemoryDumpProvider* mdp, - scoped_refptr pmd_holder) { - bool should_finalize_dump = false; + scoped_ptr pmd_async_state) { + // Initalizes the ThreadLocalEventBuffer to guarantee that the TRACE_EVENTs + // in the PostTask below don't end up registering their own dump providers + // (for discounting trace memory overhead) while holding the |lock_|. + TraceLog::GetInstance()->InitializeThreadLocalEventBufferIfSupported(); + + // DO NOT put any LOG() statement in the locked sections, as in some contexts + // (GPU process) LOG() ends up performing PostTask/IPCs. + MemoryDumpProvider* mdp; + bool skip_dump = false; { - // The lock here is to guarantee that different asynchronous dumps on - // different threads are still serialized, so that the MemoryDumpProvider - // has a consistent view of the |pmd| argument passed. AutoLock lock(lock_); - ProcessMemoryDump* pmd = &pmd_holder->process_memory_dump; - - // Check if the MemoryDumpProvider is still there. It might have been - // destroyed and unregistered while hopping threads. - if (dump_providers_.count(mdp)) - InvokeDumpProviderLocked(mdp, pmd); - - // Finalize the dump appending it to the trace if this was the last - // asynchronous request pending. - --pmd_holder->num_pending_async_requests; - if (pmd_holder->num_pending_async_requests == 0) - should_finalize_dump = true; + // In the unlikely event that a dump provider was unregistered while + // dumping, abort the dump, as that would make |next_dump_provider| invalid. + // Registration, on the other hand, is safe as per std::set<> contract. + if (did_unregister_dump_provider_) { + return AbortDumpLocked(pmd_async_state->callback, + pmd_async_state->task_runner, + pmd_async_state->req_args.dump_guid); + } + + auto* mdp_info = &*pmd_async_state->next_dump_provider; + mdp = mdp_info->dump_provider; + if (mdp_info->disabled) { + skip_dump = true; + } else if (mdp == g_mmaps_dump_provider && + pmd_async_state->req_args.dump_type != + MemoryDumpType::PERIODIC_INTERVAL_WITH_MMAPS) { + // Mmaps dumping is very heavyweight and cannot be performed at the same + // rate of other dumps. TODO(primiano): this is a hack and should be + // cleaned up as part of crbug.com/499731. + skip_dump = true; + } else if (mdp_info->task_runner && + !mdp_info->task_runner->BelongsToCurrentThread()) { + // It's time to hop onto another thread. + + // Copy the callback + arguments just for the unlikley case in which + // PostTask fails. In such case the Bind helper will destroy the + // pmd_async_state and we must keep a copy of the fields to notify the + // abort. + MemoryDumpCallback callback = pmd_async_state->callback; + scoped_refptr callback_task_runner = + pmd_async_state->task_runner; + const uint64 dump_guid = pmd_async_state->req_args.dump_guid; + + const bool did_post_task = mdp_info->task_runner->PostTask( + FROM_HERE, Bind(&MemoryDumpManager::ContinueAsyncProcessDump, + Unretained(this), Passed(pmd_async_state.Pass()))); + if (did_post_task) + return; + + // The thread is gone. At this point the best thing we can do is to + // disable the dump provider and abort this dump. + mdp_info->disabled = true; + return AbortDumpLocked(callback, callback_task_runner, dump_guid); + } } // AutoLock(lock_) - if (should_finalize_dump) - FinalizeDumpAndAddToTrace(pmd_holder); + // Invoke the dump provider without holding the |lock_|. + bool finalize = false; + bool dump_successful = false; + if (!skip_dump) + dump_successful = mdp->OnMemoryDump(&pmd_async_state->process_memory_dump); + + { + AutoLock lock(lock_); + if (did_unregister_dump_provider_) { + return AbortDumpLocked(pmd_async_state->callback, + pmd_async_state->task_runner, + pmd_async_state->req_args.dump_guid); + } + auto* mdp_info = &*pmd_async_state->next_dump_provider; + if (dump_successful) { + mdp_info->consecutive_failures = 0; + } else if (!skip_dump) { + ++mdp_info->consecutive_failures; + if (mdp_info->consecutive_failures >= kMaxConsecutiveFailuresCount) { + mdp_info->disabled = true; + } + } + ++pmd_async_state->next_dump_provider; + finalize = pmd_async_state->next_dump_provider == dump_providers_.end(); + } + + if (!skip_dump && !dump_successful) { + LOG(ERROR) << "A memory dumper failed, possibly due to sandboxing " + "(crbug.com/461788). Disabling dumper for current process. " + "Try restarting chrome with the --no-sandbox switch."; + } + + if (finalize) + return FinalizeDumpAndAddToTrace(pmd_async_state.Pass()); + + ContinueAsyncProcessDump(pmd_async_state.Pass()); +} + +// static +void MemoryDumpManager::FinalizeDumpAndAddToTrace( + scoped_ptr pmd_async_state) { + if (!pmd_async_state->task_runner->BelongsToCurrentThread()) { + scoped_refptr task_runner = + pmd_async_state->task_runner; + task_runner->PostTask(FROM_HERE, + Bind(&MemoryDumpManager::FinalizeDumpAndAddToTrace, + Passed(pmd_async_state.Pass()))); + return; + } + + scoped_refptr event_value(new TracedValue()); + pmd_async_state->process_memory_dump.AsValueInto( + static_cast(event_value.get())); + const char* const event_name = + MemoryDumpTypeToString(pmd_async_state->req_args.dump_type); + + TRACE_EVENT_API_ADD_TRACE_EVENT( + TRACE_EVENT_PHASE_MEMORY_DUMP, + TraceLog::GetCategoryGroupEnabled(kTraceCategory), event_name, + pmd_async_state->req_args.dump_guid, kTraceEventNumArgs, + kTraceEventArgNames, kTraceEventArgTypes, nullptr /* arg_values */, + &event_value, TRACE_EVENT_FLAG_HAS_ID); + + if (!pmd_async_state->callback.is_null()) { + pmd_async_state->callback.Run(pmd_async_state->req_args.dump_guid, + true /* success */); + pmd_async_state->callback.Reset(); + } +} + +// static +void MemoryDumpManager::AbortDumpLocked( + MemoryDumpCallback callback, + scoped_refptr task_runner, + uint64 dump_guid) { + if (callback.is_null()) + return; // There is nothing to NACK. + + // Post the callback even if we are already on the right thread to avoid + // invoking the callback while holding the lock_. + task_runner->PostTask(FROM_HERE, + Bind(callback, dump_guid, false /* success */)); } void MemoryDumpManager::OnTraceLogEnabled() { @@ -364,25 +391,33 @@ void MemoryDumpManager::OnTraceLogEnabled() { bool enabled; TRACE_EVENT_CATEGORY_GROUP_ENABLED(kTraceCategory, &enabled); + // Initialize the TraceLog for the current thread. This is to avoid that the + // TraceLog memory dump provider is registered lazily in the PostTask() below + // while the |lock_| is taken; + TraceLog::GetInstance()->InitializeThreadLocalEventBufferIfSupported(); + AutoLock lock(lock_); // There is no point starting the tracing without a delegate. if (!enabled || !delegate_) { // Disable all the providers. for (auto it = dump_providers_.begin(); it != dump_providers_.end(); ++it) - it->second.disabled = true; + it->disabled = true; return; } session_state_ = new MemoryDumpSessionState(); - for (auto it = dump_providers_.begin(); it != dump_providers_.end(); ++it) - it->second.disabled = false; + for (auto it = dump_providers_.begin(); it != dump_providers_.end(); ++it) { + it->disabled = false; + it->consecutive_failures = 0; + } subtle::NoBarrier_Store(&memory_tracing_enabled_, 1); if (delegate_->IsCoordinatorProcess()) { + g_periodic_dumps_count = 0; periodic_dump_timer_.Start(FROM_HERE, - TimeDelta::FromSeconds(kDumpIntervalSeconds), + TimeDelta::FromMilliseconds(kDumpIntervalMs), base::Bind(&RequestPeriodicGlobalDump)); } } @@ -394,12 +429,48 @@ void MemoryDumpManager::OnTraceLogDisabled() { session_state_ = nullptr; } +// static +uint64 MemoryDumpManager::ChildProcessIdToTracingProcessId( + int child_process_id) { + return static_cast( + Hash(reinterpret_cast(&child_process_id), + sizeof(child_process_id))) + + 1; +} + MemoryDumpManager::MemoryDumpProviderInfo::MemoryDumpProviderInfo( + MemoryDumpProvider* dump_provider, const scoped_refptr& task_runner) - : task_runner(task_runner), disabled(false) { + : dump_provider(dump_provider), + task_runner(task_runner), + consecutive_failures(0), + disabled(false) { } + MemoryDumpManager::MemoryDumpProviderInfo::~MemoryDumpProviderInfo() { } +bool MemoryDumpManager::MemoryDumpProviderInfo::operator<( + const MemoryDumpProviderInfo& other) const { + if (task_runner == other.task_runner) + return dump_provider < other.dump_provider; + return task_runner < other.task_runner; +} + +MemoryDumpManager::ProcessMemoryDumpAsyncState::ProcessMemoryDumpAsyncState( + MemoryDumpRequestArgs req_args, + MemoryDumpProviderInfoSet::iterator next_dump_provider, + const scoped_refptr& session_state, + MemoryDumpCallback callback) + : process_memory_dump(session_state), + req_args(req_args), + next_dump_provider(next_dump_provider), + callback(callback), + task_runner(MessageLoop::current()->task_runner()) { +} + +MemoryDumpManager::ProcessMemoryDumpAsyncState::~ProcessMemoryDumpAsyncState() { +} + } // namespace trace_event } // namespace base diff --git a/base/trace_event/memory_dump_manager.h b/base/trace_event/memory_dump_manager.h index 3645ac18ba414..f9ece6e14f22a 100644 --- a/base/trace_event/memory_dump_manager.h +++ b/base/trace_event/memory_dump_manager.h @@ -5,7 +5,7 @@ #ifndef BASE_TRACE_EVENT_MEMORY_DUMP_MANAGER_H_ #define BASE_TRACE_EVENT_MEMORY_DUMP_MANAGER_H_ -#include +#include #include "base/atomicops.h" #include "base/containers/hash_tables.h" @@ -14,6 +14,7 @@ #include "base/synchronization/lock.h" #include "base/timer/timer.h" #include "base/trace_event/memory_dump_request_args.h" +#include "base/trace_event/process_memory_dump.h" #include "base/trace_event/trace_event.h" namespace base { @@ -22,13 +23,8 @@ class SingleThreadTaskRunner; namespace trace_event { -namespace { -class ProcessMemoryDumpHolder; -} - class MemoryDumpManagerDelegate; class MemoryDumpProvider; -class ProcessMemoryDump; class MemoryDumpSessionState; // This is the interface exposed to the rest of the codebase to deal with @@ -36,6 +32,7 @@ class MemoryDumpSessionState; // RequestDumpPoint(). The extension by Un(RegisterDumpProvider). class BASE_EXPORT MemoryDumpManager : public TraceLog::EnabledStateObserver { public: + static const uint64 kInvalidTracingProcessId; static const char* const kTraceCategoryForTesting; static MemoryDumpManager* GetInstance(); @@ -81,27 +78,97 @@ class BASE_EXPORT MemoryDumpManager : public TraceLog::EnabledStateObserver { return session_state_; } + // Derives a tracing process id from a child process id. Child process ids + // cannot be used directly in tracing for security reasons (see: discussion in + // crrev.com/1173263004). This method is meant to be used when dumping + // cross-process shared memory from a process which knows the child process id + // of its endpoints. The value returned by this method is guaranteed to be + // equal to the value returned by tracing_process_id() in the corresponding + // child process. + // This will never return kInvalidTracingProcessId. + static uint64 ChildProcessIdToTracingProcessId(int child_id); + + // Returns a unique id for the current process. The id can be retrieved only + // by child processes and only when tracing is enabled. This is intended to + // express cross-process sharing of memory dumps on the child-process side, + // without having to know its own child process id. + uint64 tracing_process_id() const { return tracing_process_id_; } + private: + friend struct DefaultDeleter; // For the testing instance. + friend struct DefaultSingletonTraits; + friend class MemoryDumpManagerDelegate; + friend class MemoryDumpManagerTest; + FRIEND_TEST_ALL_PREFIXES(MemoryDumpManagerTest, DisableFailingDumpers); + // Descriptor struct used to hold information about registered MDPs. It is - // deliberately copyable, in order to allow to be used as hash_map value. + // deliberately copyable, in order to allow it to be used as std::set value. struct MemoryDumpProviderInfo { MemoryDumpProviderInfo( + MemoryDumpProvider* dump_provider, const scoped_refptr& task_runner); ~MemoryDumpProviderInfo(); + // Define a total order based on the thread (i.e. |task_runner|) affinity, + // so that all MDP belonging to the same thread are adjacent in the set. + bool operator<(const MemoryDumpProviderInfo& other) const; + + MemoryDumpProvider* const dump_provider; scoped_refptr task_runner; // Optional. - bool disabled; // For fail-safe logic (auto-disable failing MDPs). + + // For fail-safe logic (auto-disable failing MDPs). These fields are mutable + // as can be safely changed without impacting the order within the set. + mutable int consecutive_failures; + mutable bool disabled; }; - friend struct DefaultDeleter; // For the testing instance. - friend struct DefaultSingletonTraits; - friend class MemoryDumpManagerDelegate; - friend class MemoryDumpManagerTest; + using MemoryDumpProviderInfoSet = std::set; - static void SetInstanceForTesting(MemoryDumpManager* instance); + // Holds the state of a process memory dump that needs to be carried over + // across threads in order to fulfil an asynchronous CreateProcessDump() + // request. At any time exactly one thread owns a ProcessMemoryDumpAsyncState. + struct ProcessMemoryDumpAsyncState { + ProcessMemoryDumpAsyncState( + MemoryDumpRequestArgs req_args, + MemoryDumpProviderInfoSet::iterator next_dump_provider, + const scoped_refptr& session_state, + MemoryDumpCallback callback); + ~ProcessMemoryDumpAsyncState(); + + // The ProcessMemoryDump container, where each dump provider will dump its + // own MemoryAllocatorDump(s) upon the OnMemoryDump() call. + ProcessMemoryDump process_memory_dump; + + // The arguments passed to the initial CreateProcessDump() request. + const MemoryDumpRequestArgs req_args; + + // The |dump_providers_| iterator to the next dump provider that should be + // invoked (or dump_providers_.end() if at the end of the sequence). + MemoryDumpProviderInfoSet::iterator next_dump_provider; + + // Callback passed to the initial call to CreateProcessDump(). + MemoryDumpCallback callback; + + // The thread on which FinalizeDumpAndAddToTrace() (and hence |callback|) + // should be invoked. This is the thread on which the initial + // CreateProcessDump() request was called. + const scoped_refptr task_runner; + + private: + DISALLOW_COPY_AND_ASSIGN(ProcessMemoryDumpAsyncState); + }; + + static const int kMaxConsecutiveFailuresCount; MemoryDumpManager(); - virtual ~MemoryDumpManager(); + ~MemoryDumpManager() override; + + static void SetInstanceForTesting(MemoryDumpManager* instance); + static void FinalizeDumpAndAddToTrace( + scoped_ptr pmd_async_state); + static void AbortDumpLocked(MemoryDumpCallback callback, + scoped_refptr task_runner, + uint64 dump_guid); // Internal, used only by MemoryDumpManagerDelegate. // Creates a memory dump for the current process and appends it to the trace. @@ -110,13 +177,25 @@ class BASE_EXPORT MemoryDumpManager : public TraceLog::EnabledStateObserver { void CreateProcessDump(const MemoryDumpRequestArgs& args, const MemoryDumpCallback& callback); - bool InvokeDumpProviderLocked(MemoryDumpProvider* mdp, - ProcessMemoryDump* pmd); + // Continues the ProcessMemoryDump started by CreateProcessDump(), hopping + // across threads as needed as specified by MDPs in RegisterDumpProvider(). void ContinueAsyncProcessDump( - MemoryDumpProvider* mdp, - scoped_refptr pmd_holder); + scoped_ptr pmd_async_state); + + // Pass kInvalidTracingProcessId to invalidate the id. + void set_tracing_process_id(uint64 id) { + DCHECK(tracing_process_id_ == kInvalidTracingProcessId || + id == kInvalidTracingProcessId || tracing_process_id_ == id); + tracing_process_id_ = id; + } + + // An ordererd set of registered MemoryDumpProviderInfo(s), sorted by thread + // affinity (MDPs belonging to the same thread are adjacent). + MemoryDumpProviderInfoSet dump_providers_; - hash_map dump_providers_; + // Flag used to signal that some provider was removed from |dump_providers_| + // and therefore the current memory dump (if any) should be aborted. + bool did_unregister_dump_provider_; // Shared among all the PMDs to keep state scoped to the tracing session. scoped_refptr session_state_; @@ -134,6 +213,10 @@ class BASE_EXPORT MemoryDumpManager : public TraceLog::EnabledStateObserver { // For time-triggered periodic dumps. RepeatingTimer periodic_dump_timer_; + // The unique id of the child process. This is created only for tracing and is + // expected to be valid only when tracing is enabled. + uint64 tracing_process_id_; + // Skips the auto-registration of the core dumpers during Initialize(). bool skip_core_dumpers_auto_registration_for_testing_; @@ -160,6 +243,10 @@ class BASE_EXPORT MemoryDumpManagerDelegate { MemoryDumpManager::GetInstance()->CreateProcessDump(args, callback); } + void set_tracing_process_id(uint64 id) { + MemoryDumpManager::GetInstance()->set_tracing_process_id(id); + } + private: DISALLOW_COPY_AND_ASSIGN(MemoryDumpManagerDelegate); }; diff --git a/base/trace_event/memory_dump_manager_unittest.cc b/base/trace_event/memory_dump_manager_unittest.cc index c15748c9ab71e..53c7d9250dab4 100644 --- a/base/trace_event/memory_dump_manager_unittest.cc +++ b/base/trace_event/memory_dump_manager_unittest.cc @@ -8,6 +8,7 @@ #include "base/memory/scoped_vector.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" +#include "base/thread_task_runner_handle.h" #include "base/threading/thread.h" #include "base/trace_event/memory_dump_provider.h" #include "base/trace_event/process_memory_dump.h" @@ -15,6 +16,7 @@ #include "testing/gtest/include/gtest/gtest.h" using testing::_; +using testing::Between; using testing::Invoke; using testing::Return; @@ -25,9 +27,8 @@ namespace trace_event { // instead of performing IPC dances. class MemoryDumpManagerDelegateForTesting : public MemoryDumpManagerDelegate { public: - void RequestGlobalMemoryDump( - const base::trace_event::MemoryDumpRequestArgs& args, - const MemoryDumpCallback& callback) override { + void RequestGlobalMemoryDump(const MemoryDumpRequestArgs& args, + const MemoryDumpCallback& callback) override { CreateProcessDump(args, callback); } @@ -81,7 +82,9 @@ class MemoryDumpManagerTest : public testing::Test { class MockDumpProvider : public MemoryDumpProvider { public: - MockDumpProvider() : last_session_state_(nullptr) {} + MockDumpProvider() + : dump_provider_to_register_or_unregister(nullptr), + last_session_state_(nullptr) {} // Ctor used by the RespectTaskRunnerAffinity test. explicit MockDumpProvider( @@ -107,6 +110,23 @@ class MockDumpProvider : public MemoryDumpProvider { return true; } + // OnMemoryDump() override for the RegisterDumperWhileDumping test. + bool OnMemoryDump_RegisterExtraDumpProvider(ProcessMemoryDump* pmd) { + MemoryDumpManager::GetInstance()->RegisterDumpProvider( + dump_provider_to_register_or_unregister); + return true; + } + + // OnMemoryDump() override for the UnegisterDumperWhileDumping test. + bool OnMemoryDump_UnregisterDumpProvider(ProcessMemoryDump* pmd) { + MemoryDumpManager::GetInstance()->UnregisterDumpProvider( + dump_provider_to_register_or_unregister); + return true; + } + + // Used by OnMemoryDump_(Un)RegisterExtraDumpProvider. + MemoryDumpProvider* dump_provider_to_register_or_unregister; + private: MemoryDumpSessionState* last_session_state_; scoped_refptr task_runner_; @@ -250,9 +270,8 @@ TEST_F(MemoryDumpManagerTest, RespectTaskRunnerAffinity) { DisableTracing(); } -// Enable both dump providers, make mdp1 fail and assert that only mdp2 is -// invoked the 2nd time. -// FIXME(primiano): remove once crbug.com/461788 gets fixed. +// Enable both dump providers, make sure that mdp gets disabled after 3 failures +// and not disabled after 1. TEST_F(MemoryDumpManagerTest, DisableFailingDumpers) { MockDumpProvider mdp1; MockDumpProvider mdp2; @@ -261,13 +280,78 @@ TEST_F(MemoryDumpManagerTest, DisableFailingDumpers) { mdm_->RegisterDumpProvider(&mdp2); EnableTracing(kTraceCategory); - EXPECT_CALL(mdp1, OnMemoryDump(_)).Times(1).WillRepeatedly(Return(false)); - EXPECT_CALL(mdp2, OnMemoryDump(_)).Times(1).WillRepeatedly(Return(true)); - mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED); + EXPECT_CALL(mdp1, OnMemoryDump(_)) + .Times(MemoryDumpManager::kMaxConsecutiveFailuresCount) + .WillRepeatedly(Return(false)); - EXPECT_CALL(mdp1, OnMemoryDump(_)).Times(0); - EXPECT_CALL(mdp2, OnMemoryDump(_)).Times(1).WillRepeatedly(Return(false)); - mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED); + EXPECT_CALL(mdp2, OnMemoryDump(_)) + .Times(1 + MemoryDumpManager::kMaxConsecutiveFailuresCount) + .WillOnce(Return(false)) + .WillRepeatedly(Return(true)); + for (int i = 0; i < 1 + MemoryDumpManager::kMaxConsecutiveFailuresCount; + i++) { + mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED); + } + + DisableTracing(); +} + +// Sneakily register an extra memory dump provider while an existing one is +// dumping and expect it to take part in the already active tracing session. +TEST_F(MemoryDumpManagerTest, RegisterDumperWhileDumping) { + MockDumpProvider mdp1; + MockDumpProvider mdp2; + + mdp1.dump_provider_to_register_or_unregister = &mdp2; + mdm_->RegisterDumpProvider(&mdp1); + EnableTracing(kTraceCategory); + + EXPECT_CALL(mdp1, OnMemoryDump(_)) + .Times(4) + .WillOnce(Return(true)) + .WillOnce(Invoke( + &mdp1, &MockDumpProvider::OnMemoryDump_RegisterExtraDumpProvider)) + .WillRepeatedly(Return(true)); + + // Depending on the insertion order (before or after mdp1), mdp2 might be + // called also immediately after it gets registered. + EXPECT_CALL(mdp2, OnMemoryDump(_)) + .Times(Between(2, 3)) + .WillRepeatedly(Return(true)); + + for (int i = 0; i < 4; i++) { + mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED); + } + + DisableTracing(); +} + +// Like the above, but suddenly unregister the dump provider. +TEST_F(MemoryDumpManagerTest, UnregisterDumperWhileDumping) { + MockDumpProvider mdp1; + MockDumpProvider mdp2; + + mdm_->RegisterDumpProvider(&mdp1, ThreadTaskRunnerHandle::Get()); + mdm_->RegisterDumpProvider(&mdp2, ThreadTaskRunnerHandle::Get()); + mdp1.dump_provider_to_register_or_unregister = &mdp2; + EnableTracing(kTraceCategory); + + EXPECT_CALL(mdp1, OnMemoryDump(_)) + .Times(4) + .WillOnce(Return(true)) + .WillOnce(Invoke(&mdp1, + &MockDumpProvider::OnMemoryDump_UnregisterDumpProvider)) + .WillRepeatedly(Return(true)); + + // Depending on the insertion order (before or after mdp1), mdp2 might have + // been already called when OnMemoryDump_UnregisterDumpProvider happens. + EXPECT_CALL(mdp2, OnMemoryDump(_)) + .Times(Between(1, 2)) + .WillRepeatedly(Return(true)); + + for (int i = 0; i < 4; i++) { + mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED); + } DisableTracing(); } diff --git a/base/trace_event/memory_dump_request_args.cc b/base/trace_event/memory_dump_request_args.cc new file mode 100644 index 0000000000000..a24bc72671d7c --- /dev/null +++ b/base/trace_event/memory_dump_request_args.cc @@ -0,0 +1,32 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/trace_event/memory_dump_request_args.h" + +#include "base/logging.h" + +namespace base { +namespace trace_event { + +// static +const char* MemoryDumpTypeToString( + const MemoryDumpType& dump_type) { + switch (dump_type) { + case MemoryDumpType::TASK_BEGIN: + return "TASK_BEGIN"; + case MemoryDumpType::TASK_END: + return "TASK_END"; + case MemoryDumpType::PERIODIC_INTERVAL: + return "PERIODIC_INTERVAL"; + case MemoryDumpType::PERIODIC_INTERVAL_WITH_MMAPS: + return "PERIODIC_INTERVAL_WITH_MMAPS"; + case MemoryDumpType::EXPLICITLY_TRIGGERED: + return "EXPLICITLY_TRIGGERED"; + } + NOTREACHED(); + return "UNKNOWN"; +} + +} // namespace trace_event +} // namespace base diff --git a/base/trace_event/memory_dump_request_args.h b/base/trace_event/memory_dump_request_args.h index 4d3763acf16a1..747daabf9eddc 100644 --- a/base/trace_event/memory_dump_request_args.h +++ b/base/trace_event/memory_dump_request_args.h @@ -20,10 +20,15 @@ enum class MemoryDumpType { TASK_BEGIN, // Dumping memory at the beginning of a message-loop task. TASK_END, // Dumping memory at the ending of a message-loop task. PERIODIC_INTERVAL, // Dumping memory at periodic intervals. + PERIODIC_INTERVAL_WITH_MMAPS, // As above but w/ heavyweight mmaps dumps. + // Temporary workaround for crbug.com/499731. EXPLICITLY_TRIGGERED, // Non maskable dump request. LAST = EXPLICITLY_TRIGGERED // For IPC macros. }; +// Returns the name in string for the dump type given. +BASE_EXPORT const char* MemoryDumpTypeToString(const MemoryDumpType& dump_type); + using MemoryDumpCallback = Callback; struct BASE_EXPORT MemoryDumpRequestArgs { diff --git a/base/trace_event/process_memory_dump.h b/base/trace_event/process_memory_dump.h index 88ce28abe245a..3b71a2c41ae04 100644 --- a/base/trace_event/process_memory_dump.h +++ b/base/trace_event/process_memory_dump.h @@ -48,29 +48,6 @@ class BASE_EXPORT ProcessMemoryDump { ProcessMemoryDump(const scoped_refptr& session_state); ~ProcessMemoryDump(); - // Called at trace generation time to populate the TracedValue. - void AsValueInto(TracedValue* value) const; - - // Removes all the MemoryAllocatorDump(s) contained in this instance. This - // ProcessMemoryDump can be safely reused as if it was new once this returns. - void Clear(); - - // Merges all MemoryAllocatorDump(s) contained in |other| inside this - // ProcessMemoryDump, transferring their ownership to this instance. - // |other| will be an empty ProcessMemoryDump after this method returns. - // This is to allow dump providers to pre-populate ProcessMemoryDump instances - // and later move their contents into the ProcessMemoryDump passed as argument - // of the MemoryDumpProvider::OnMemoryDump(ProcessMemoryDump*) callback. - void TakeAllDumpsFrom(ProcessMemoryDump* other); - - ProcessMemoryTotals* process_totals() { return &process_totals_; } - bool has_process_totals() const { return has_process_totals_; } - void set_has_process_totals() { has_process_totals_ = true; } - - ProcessMemoryMaps* process_mmaps() { return &process_mmaps_; } - bool has_process_mmaps() const { return has_process_mmaps_; } - void set_has_process_mmaps() { has_process_mmaps_ = true; } - // Creates a new MemoryAllocatorDump with the given name and returns the // empty object back to the caller. // Arguments: @@ -80,7 +57,8 @@ class BASE_EXPORT ProcessMemoryDump { // Leading or trailing slashes are not allowed. // guid: an optional identifier, unique among all processes within the // scope of a global dump. This is only relevant when using - // AddOwnershipEdge(). If omitted, it will be automatically generated. + // AddOwnershipEdge() to express memory sharing. If omitted, + // it will be automatically generated. // ProcessMemoryDump handles the memory ownership of its MemoryAllocatorDumps. MemoryAllocatorDump* CreateAllocatorDump(const std::string& absolute_name); MemoryAllocatorDump* CreateAllocatorDump(const std::string& absolute_name, @@ -131,6 +109,29 @@ class BASE_EXPORT ProcessMemoryDump { return session_state_; } + // Removes all the MemoryAllocatorDump(s) contained in this instance. This + // ProcessMemoryDump can be safely reused as if it was new once this returns. + void Clear(); + + // Merges all MemoryAllocatorDump(s) contained in |other| inside this + // ProcessMemoryDump, transferring their ownership to this instance. + // |other| will be an empty ProcessMemoryDump after this method returns. + // This is to allow dump providers to pre-populate ProcessMemoryDump instances + // and later move their contents into the ProcessMemoryDump passed as argument + // of the MemoryDumpProvider::OnMemoryDump(ProcessMemoryDump*) callback. + void TakeAllDumpsFrom(ProcessMemoryDump* other); + + // Called at trace generation time to populate the TracedValue. + void AsValueInto(TracedValue* value) const; + + ProcessMemoryTotals* process_totals() { return &process_totals_; } + bool has_process_totals() const { return has_process_totals_; } + void set_has_process_totals() { has_process_totals_ = true; } + + ProcessMemoryMaps* process_mmaps() { return &process_mmaps_; } + bool has_process_mmaps() const { return has_process_mmaps_; } + void set_has_process_mmaps() { has_process_mmaps_ = true; } + private: void AddAllocatorDumpInternal(MemoryAllocatorDump* mad); diff --git a/base/trace_event/trace_config.cc b/base/trace_event/trace_config.cc index ef9b8925fff6c..2a15ec578fcef 100644 --- a/base/trace_event/trace_config.cc +++ b/base/trace_event/trace_config.cc @@ -6,6 +6,7 @@ #include "base/json/json_reader.h" #include "base/json/json_writer.h" +#include "base/strings/pattern.h" #include "base/strings/string_split.h" #include "base/strings/string_tokenizer.h" #include "base/strings/stringprintf.h" @@ -147,8 +148,8 @@ bool TraceConfig::IsCategoryGroupEnabled( if (IsCategoryEnabled(category_group_token.c_str())) { return true; } - if (!MatchPattern(category_group_token.c_str(), - TRACE_DISABLED_BY_DEFAULT("*"))) + if (!base::MatchPattern(category_group_token.c_str(), + TRACE_DISABLED_BY_DEFAULT("*"))) had_enabled_by_default = true; } // Do a second pass to check for explicitly disabled categories @@ -160,7 +161,7 @@ bool TraceConfig::IsCategoryGroupEnabled( for (StringList::const_iterator ci = excluded_categories_.begin(); ci != excluded_categories_.end(); ++ci) { - if (MatchPattern(category_group_token.c_str(), ci->c_str())) { + if (base::MatchPattern(category_group_token.c_str(), ci->c_str())) { // Current token of category_group_name is present in excluded_list. // Flag the exclusion and proceed further to check if any of the // remaining categories of category_group_name is not present in the @@ -515,17 +516,17 @@ bool TraceConfig::IsCategoryEnabled(const char* category_name) const { for (ci = disabled_categories_.begin(); ci != disabled_categories_.end(); ++ci) { - if (MatchPattern(category_name, ci->c_str())) + if (base::MatchPattern(category_name, ci->c_str())) return true; } - if (MatchPattern(category_name, TRACE_DISABLED_BY_DEFAULT("*"))) + if (base::MatchPattern(category_name, TRACE_DISABLED_BY_DEFAULT("*"))) return false; for (ci = included_categories_.begin(); ci != included_categories_.end(); ++ci) { - if (MatchPattern(category_name, ci->c_str())) + if (base::MatchPattern(category_name, ci->c_str())) return true; } diff --git a/base/trace_event/trace_event.gypi b/base/trace_event/trace_event.gypi index b595004da6228..05ec283d64d31 100644 --- a/base/trace_event/trace_event.gypi +++ b/base/trace_event/trace_event.gypi @@ -13,6 +13,7 @@ 'trace_event/memory_dump_manager.cc', 'trace_event/memory_dump_manager.h', 'trace_event/memory_dump_provider.h', + 'trace_event/memory_dump_request_args.cc', 'trace_event/memory_dump_request_args.h', 'trace_event/memory_dump_session_state.cc', 'trace_event/memory_dump_session_state.h', @@ -39,6 +40,8 @@ 'trace_event/trace_event_impl_constants.cc', 'trace_event/trace_event_memory.cc', 'trace_event/trace_event_memory.h', + 'trace_event/trace_event_memory_overhead.cc', + 'trace_event/trace_event_memory_overhead.h', 'trace_event/trace_event_synthetic_delay.cc', 'trace_event/trace_event_synthetic_delay.h', 'trace_event/trace_event_system_stats_monitor.cc', diff --git a/base/trace_event/trace_event.h b/base/trace_event/trace_event.h index 397bafc3550fa..1e5b42a753a90 100644 --- a/base/trace_event/trace_event.h +++ b/base/trace_event/trace_event.h @@ -852,6 +852,9 @@ #define TRACE_EVENT_FLOW_END0(category_group, name, id) \ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, \ category_group, name, id, TRACE_EVENT_FLAG_NONE) +#define TRACE_EVENT_FLOW_END_BIND_TO_ENCLOSING0(category_group, name, id) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, \ + category_group, name, id, TRACE_EVENT_FLAG_BIND_TO_ENCLOSING) #define TRACE_EVENT_FLOW_END1(category_group, name, id, arg1_name, arg1_val) \ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, \ category_group, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) @@ -885,6 +888,14 @@ category_group, name, TRACE_ID_DONT_MANGLE(id), TRACE_EVENT_FLAG_NONE,\ "snapshot", snapshot) +#define TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID_AND_TIMESTAMP( \ + category_group, name, id, timestamp, snapshot) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ + TRACE_EVENT_PHASE_SNAPSHOT_OBJECT, category_group, name, \ + TRACE_ID_DONT_MANGLE(id), \ + static_cast(base::PlatformThread::CurrentId()), timestamp, \ + TRACE_EVENT_FLAG_NONE, "snapshot", snapshot) + #define TRACE_EVENT_OBJECT_DELETED_WITH_ID(category_group, name, id) \ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_DELETE_OBJECT, \ category_group, name, TRACE_ID_DONT_MANGLE(id), TRACE_EVENT_FLAG_NONE) @@ -954,7 +965,7 @@ // const char** arg_names, // const unsigned char* arg_types, // const unsigned long long* arg_values, -// unsigned char flags) +// unsigned int flags) #define TRACE_EVENT_API_ADD_TRACE_EVENT \ base::trace_event::TraceLog::GetInstance()->AddTraceEvent @@ -971,7 +982,7 @@ // const char** arg_names, // const unsigned char* arg_types, // const unsigned long long* arg_values, -// unsigned char flags) +// unsigned int flags) #define TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP \ base::trace_event::TraceLog::GetInstance() \ ->AddTraceEventWithThreadIdAndTimestamp @@ -1072,7 +1083,7 @@ TRACE_EVENT_API_CLASS_EXPORT extern \ do { \ INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \ if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \ - unsigned char trace_event_flags = flags | TRACE_EVENT_FLAG_HAS_ID; \ + unsigned int trace_event_flags = flags | TRACE_EVENT_FLAG_HAS_ID; \ trace_event_internal::TraceID trace_event_trace_id( \ id, &trace_event_flags); \ trace_event_internal::AddTraceEvent( \ @@ -1089,7 +1100,7 @@ TRACE_EVENT_API_CLASS_EXPORT extern \ do { \ INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \ if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \ - unsigned char trace_event_flags = flags | TRACE_EVENT_FLAG_HAS_ID; \ + unsigned int trace_event_flags = flags | TRACE_EVENT_FLAG_HAS_ID; \ trace_event_internal::TraceID trace_event_trace_id( \ id, &trace_event_flags); \ trace_event_internal::AddTraceEventWithThreadIdAndTimestamp( \ @@ -1130,16 +1141,17 @@ TRACE_EVENT_API_CLASS_EXPORT extern \ #define TRACE_EVENT_PHASE_MEMORY_DUMP ('v') // Flags for changing the behavior of TRACE_EVENT_API_ADD_TRACE_EVENT. -#define TRACE_EVENT_FLAG_NONE (static_cast(0)) -#define TRACE_EVENT_FLAG_COPY (static_cast(1 << 0)) -#define TRACE_EVENT_FLAG_HAS_ID (static_cast(1 << 1)) -#define TRACE_EVENT_FLAG_MANGLE_ID (static_cast(1 << 2)) -#define TRACE_EVENT_FLAG_SCOPE_OFFSET (static_cast(1 << 3)) -#define TRACE_EVENT_FLAG_SCOPE_EXTRA (static_cast(1 << 4)) -#define TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP (static_cast(1 << 5)) -#define TRACE_EVENT_FLAG_ASYNC_TTS (static_cast(1 << 6)) - -#define TRACE_EVENT_FLAG_SCOPE_MASK (static_cast( \ +#define TRACE_EVENT_FLAG_NONE (static_cast(0)) +#define TRACE_EVENT_FLAG_COPY (static_cast(1 << 0)) +#define TRACE_EVENT_FLAG_HAS_ID (static_cast(1 << 1)) +#define TRACE_EVENT_FLAG_MANGLE_ID (static_cast(1 << 2)) +#define TRACE_EVENT_FLAG_SCOPE_OFFSET (static_cast(1 << 3)) +#define TRACE_EVENT_FLAG_SCOPE_EXTRA (static_cast(1 << 4)) +#define TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP (static_cast(1 << 5)) +#define TRACE_EVENT_FLAG_ASYNC_TTS (static_cast(1 << 6)) +#define TRACE_EVENT_FLAG_BIND_TO_ENCLOSING (static_cast(1 << 7)) + +#define TRACE_EVENT_FLAG_SCOPE_MASK (static_cast( \ TRACE_EVENT_FLAG_SCOPE_OFFSET | TRACE_EVENT_FLAG_SCOPE_EXTRA)) // Type values for identifying types in the TraceValue union. @@ -1220,35 +1232,35 @@ class TraceID { private: unsigned long long data_; }; - TraceID(const void* id, unsigned char* flags) + TraceID(const void* id, unsigned int* flags) : data_(static_cast( reinterpret_cast(id))) { *flags |= TRACE_EVENT_FLAG_MANGLE_ID; } - TraceID(ForceMangle id, unsigned char* flags) : data_(id.data()) { + TraceID(ForceMangle id, unsigned int* flags) : data_(id.data()) { *flags |= TRACE_EVENT_FLAG_MANGLE_ID; } - TraceID(DontMangle id, unsigned char* flags) : data_(id.data()) { + TraceID(DontMangle id, unsigned int* flags) : data_(id.data()) { } - TraceID(unsigned long long id, unsigned char* flags) + TraceID(unsigned long long id, unsigned int* flags) : data_(id) { (void)flags; } - TraceID(unsigned long id, unsigned char* flags) + TraceID(unsigned long id, unsigned int* flags) : data_(id) { (void)flags; } - TraceID(unsigned int id, unsigned char* flags) + TraceID(unsigned int id, unsigned int* flags) : data_(id) { (void)flags; } - TraceID(unsigned short id, unsigned char* flags) + TraceID(unsigned short id, unsigned int* flags) : data_(id) { (void)flags; } - TraceID(unsigned char id, unsigned char* flags) + TraceID(unsigned char id, unsigned int* flags) : data_(id) { (void)flags; } - TraceID(long long id, unsigned char* flags) + TraceID(long long id, unsigned int* flags) : data_(static_cast(id)) { (void)flags; } - TraceID(long id, unsigned char* flags) + TraceID(long id, unsigned int* flags) : data_(static_cast(id)) { (void)flags; } - TraceID(int id, unsigned char* flags) + TraceID(int id, unsigned int* flags) : data_(static_cast(id)) { (void)flags; } - TraceID(short id, unsigned char* flags) + TraceID(short id, unsigned int* flags) : data_(static_cast(id)) { (void)flags; } - TraceID(signed char id, unsigned char* flags) + TraceID(signed char id, unsigned int* flags) : data_(static_cast(id)) { (void)flags; } unsigned long long data() const { return data_; } @@ -1380,7 +1392,7 @@ AddTraceEventWithThreadIdAndTimestamp( unsigned long long id, int thread_id, const base::TraceTicks& timestamp, - unsigned char flags, + unsigned int flags, const char* arg1_name, const scoped_refptr& arg1_val) { @@ -1400,7 +1412,7 @@ AddTraceEventWithThreadIdAndTimestamp( unsigned long long id, int thread_id, const base::TraceTicks& timestamp, - unsigned char flags, + unsigned int flags, const char* arg1_name, const ARG1_TYPE& arg1_val, const char* arg2_name, @@ -1432,7 +1444,7 @@ AddTraceEventWithThreadIdAndTimestamp( unsigned long long id, int thread_id, const base::TraceTicks& timestamp, - unsigned char flags, + unsigned int flags, const char* arg1_name, const scoped_refptr& arg1_val, const char* arg2_name, @@ -1463,7 +1475,7 @@ AddTraceEventWithThreadIdAndTimestamp( unsigned long long id, int thread_id, const base::TraceTicks& timestamp, - unsigned char flags, + unsigned int flags, const char* arg1_name, const scoped_refptr& arg1_val, const char* arg2_name, @@ -1489,7 +1501,7 @@ AddTraceEventWithThreadIdAndTimestamp( unsigned long long id, int thread_id, const base::TraceTicks& timestamp, - unsigned char flags) { + unsigned int flags) { return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP( phase, category_group_enabled, name, id, thread_id, timestamp, kZeroNumArgs, NULL, NULL, NULL, NULL, flags); @@ -1500,7 +1512,7 @@ static inline base::trace_event::TraceEventHandle AddTraceEvent( const unsigned char* category_group_enabled, const char* name, unsigned long long id, - unsigned char flags) { + unsigned int flags) { const int thread_id = static_cast(base::PlatformThread::CurrentId()); const base::TraceTicks now = base::TraceTicks::Now(); return AddTraceEventWithThreadIdAndTimestamp(phase, category_group_enabled, @@ -1516,7 +1528,7 @@ AddTraceEventWithThreadIdAndTimestamp( unsigned long long id, int thread_id, const base::TraceTicks& timestamp, - unsigned char flags, + unsigned int flags, const char* arg1_name, const ARG1_TYPE& arg1_val) { const int num_args = 1; @@ -1534,7 +1546,7 @@ static inline base::trace_event::TraceEventHandle AddTraceEvent( const unsigned char* category_group_enabled, const char* name, unsigned long long id, - unsigned char flags, + unsigned int flags, const char* arg1_name, const ARG1_TYPE& arg1_val) { int thread_id = static_cast(base::PlatformThread::CurrentId()); @@ -1553,7 +1565,7 @@ AddTraceEventWithThreadIdAndTimestamp( unsigned long long id, int thread_id, const base::TraceTicks& timestamp, - unsigned char flags, + unsigned int flags, const char* arg1_name, const ARG1_TYPE& arg1_val, const char* arg2_name, @@ -1575,7 +1587,7 @@ static inline base::trace_event::TraceEventHandle AddTraceEvent( const unsigned char* category_group_enabled, const char* name, unsigned long long id, - unsigned char flags, + unsigned int flags, const char* arg1_name, const ARG1_TYPE& arg1_val, const char* arg2_name, diff --git a/base/trace_event/trace_event_android.cc b/base/trace_event/trace_event_android.cc index 465649d44d5ac..7815107b76e87 100644 --- a/base/trace_event/trace_event_android.cc +++ b/base/trace_event/trace_event_android.cc @@ -12,6 +12,9 @@ #include "base/synchronization/waitable_event.h" #include "base/trace_event/trace_event.h" +namespace base { +namespace trace_event { + namespace { int g_atrace_fd = -1; @@ -24,28 +27,26 @@ void WriteEvent( unsigned long long id, const char** arg_names, const unsigned char* arg_types, - const base::trace_event::TraceEvent::TraceValue* arg_values, - const scoped_refptr* - convertable_values, - unsigned char flags) { - std::string out = base::StringPrintf("%c|%d|%s", phase, getpid(), name); + const TraceEvent::TraceValue* arg_values, + const scoped_refptr* convertable_values, + unsigned int flags) { + std::string out = StringPrintf("%c|%d|%s", phase, getpid(), name); if (flags & TRACE_EVENT_FLAG_HAS_ID) - base::StringAppendF(&out, "-%" PRIx64, static_cast(id)); + StringAppendF(&out, "-%" PRIx64, static_cast(id)); out += '|'; - for (int i = 0; i < base::trace_event::kTraceMaxNumArgs && arg_names[i]; + for (int i = 0; i < kTraceMaxNumArgs && arg_names[i]; ++i) { if (i) out += ';'; out += arg_names[i]; out += '='; std::string::size_type value_start = out.length(); - if (arg_types[i] == TRACE_VALUE_TYPE_CONVERTABLE) { + if (arg_types[i] == TRACE_VALUE_TYPE_CONVERTABLE) convertable_values[i]->AppendAsTraceFormat(&out); - } else { - base::trace_event::TraceEvent::AppendValueAsJSON(arg_types[i], - arg_values[i], &out); - } + else + TraceEvent::AppendValueAsJSON(arg_types[i], arg_values[i], &out); + // Remove the quotes which may confuse the atrace script. ReplaceSubstringsAfterOffset(&out, value_start, "\\\"", "'"); ReplaceSubstringsAfterOffset(&out, value_start, "\"", ""); @@ -59,25 +60,22 @@ void WriteEvent( write(g_atrace_fd, out.c_str(), out.size()); } -void NoOpOutputCallback(base::WaitableEvent* complete_event, - const scoped_refptr&, +void NoOpOutputCallback(WaitableEvent* complete_event, + const scoped_refptr&, bool has_more_events) { if (!has_more_events) complete_event->Signal(); } -void EndChromeTracing(base::trace_event::TraceLog* trace_log, - base::WaitableEvent* complete_event) { +void EndChromeTracing(TraceLog* trace_log, + WaitableEvent* complete_event) { trace_log->SetDisabled(); // Delete the buffered trace events as they have been sent to atrace. - trace_log->Flush(base::Bind(&NoOpOutputCallback, complete_event)); + trace_log->Flush(Bind(&NoOpOutputCallback, complete_event)); } } // namespace -namespace base { -namespace trace_event { - // These functions support Android systrace.py when 'webview' category is // traced. With the new adb_profile_chrome, we may have two phases: // - before WebView is ready for combined tracing, we can use adb_profile_chrome diff --git a/base/trace_event/trace_event_argument.cc b/base/trace_event/trace_event_argument.cc index e83aa7372480b..14a4499c1f6c5 100644 --- a/base/trace_event/trace_event_argument.cc +++ b/base/trace_event/trace_event_argument.cc @@ -5,112 +5,457 @@ #include "base/trace_event/trace_event_argument.h" #include "base/json/json_writer.h" +#include "base/trace_event/trace_event_memory_overhead.h" #include "base/values.h" namespace base { namespace trace_event { -TracedValue::TracedValue() : root_(new DictionaryValue()) { - stack_.push_back(root_.get()); +namespace { +const char kTypeStartDict = '{'; +const char kTypeEndDict = '}'; +const char kTypeStartArray = '['; +const char kTypeEndArray = ']'; +const char kTypeBool = 'b'; +const char kTypeInt = 'i'; +const char kTypeDouble = 'd'; +const char kTypeString = 's'; +const char kTypeCStr = '*'; + +#ifndef NDEBUG +const bool kStackTypeDict = false; +const bool kStackTypeArray = true; +#define DCHECK_CURRENT_CONTAINER_IS(x) DCHECK_EQ(x, nesting_stack_.back()) +#define DCHECK_CONTAINER_STACK_DEPTH_EQ(x) DCHECK_EQ(x, nesting_stack_.size()) +#define DEBUG_PUSH_CONTAINER(x) nesting_stack_.push_back(x) +#define DEBUG_POP_CONTAINER() nesting_stack_.pop_back() +#else +#define DCHECK_CURRENT_CONTAINER_IS(x) do {} while (0) +#define DCHECK_CONTAINER_STACK_DEPTH_EQ(x) do {} while (0) +#define DEBUG_PUSH_CONTAINER(x) do {} while (0) +#define DEBUG_POP_CONTAINER() do {} while (0) +#endif + +inline void WriteKeyNameAsRawPtr(Pickle& pickle, const char* ptr) { + pickle.WriteBytes(&kTypeCStr, 1); + pickle.WriteUInt64(static_cast(reinterpret_cast(ptr))); +} + +inline void WriteKeyNameAsStdString(Pickle& pickle, const std::string& str) { + pickle.WriteBytes(&kTypeString, 1); + pickle.WriteString(str); +} + +std::string ReadKeyName(PickleIterator& pickle_iterator) { + const char* type = nullptr; + bool res = pickle_iterator.ReadBytes(&type, 1); + std::string key_name; + if (res && *type == kTypeCStr) { + uint64 ptr_value = 0; + res = pickle_iterator.ReadUInt64(&ptr_value); + key_name = reinterpret_cast(static_cast(ptr_value)); + } else if (res && *type == kTypeString) { + res = pickle_iterator.ReadString(&key_name); + } + DCHECK(res); + return key_name; +} +} // namespace + +TracedValue::TracedValue() : TracedValue(0) { +} + +TracedValue::TracedValue(size_t capacity) { + DEBUG_PUSH_CONTAINER(kStackTypeDict); + if (capacity) + pickle_.Reserve(capacity); } TracedValue::~TracedValue() { - DCHECK_EQ(1u, stack_.size()); + DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); + DEBUG_POP_CONTAINER(); + DCHECK_CONTAINER_STACK_DEPTH_EQ(0u); } void TracedValue::SetInteger(const char* name, int value) { - GetCurrentDictionary()->SetInteger(name, value); + DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); + pickle_.WriteBytes(&kTypeInt, 1); + pickle_.WriteInt(value); + WriteKeyNameAsRawPtr(pickle_, name); +} + +void TracedValue::SetIntegerWithCopiedName(const std::string& name, int value) { + DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); + pickle_.WriteBytes(&kTypeInt, 1); + pickle_.WriteInt(value); + WriteKeyNameAsStdString(pickle_, name); } void TracedValue::SetDouble(const char* name, double value) { - GetCurrentDictionary()->SetDouble(name, value); + DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); + pickle_.WriteBytes(&kTypeDouble, 1); + pickle_.WriteDouble(value); + WriteKeyNameAsRawPtr(pickle_, name); +} + +void TracedValue::SetDoubleWithCopiedName(const std::string& name, + double value) { + DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); + pickle_.WriteBytes(&kTypeDouble, 1); + pickle_.WriteDouble(value); + WriteKeyNameAsStdString(pickle_, name); } void TracedValue::SetBoolean(const char* name, bool value) { - GetCurrentDictionary()->SetBoolean(name, value); + DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); + pickle_.WriteBytes(&kTypeBool, 1); + pickle_.WriteBool(value); + WriteKeyNameAsRawPtr(pickle_, name); +} + +void TracedValue::SetBooleanWithCopiedName(const std::string& name, + bool value) { + DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); + pickle_.WriteBytes(&kTypeBool, 1); + pickle_.WriteBool(value); + WriteKeyNameAsStdString(pickle_, name); } void TracedValue::SetString(const char* name, const std::string& value) { - GetCurrentDictionary()->SetString(name, value); + DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); + pickle_.WriteBytes(&kTypeString, 1); + pickle_.WriteString(value); + WriteKeyNameAsRawPtr(pickle_, name); +} + +void TracedValue::SetStringWithCopiedName(const std::string& name, + const std::string& value) { + DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); + pickle_.WriteBytes(&kTypeString, 1); + pickle_.WriteString(value); + WriteKeyNameAsStdString(pickle_, name); +} + +void TracedValue::SetValue(const char* name, const TracedValue& value) { + DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); + BeginDictionary(name); + pickle_.WriteBytes(value.pickle_.payload(), + static_cast(value.pickle_.payload_size())); + EndDictionary(); } -void TracedValue::SetValue(const char* name, scoped_ptr value) { - GetCurrentDictionary()->Set(name, value.Pass()); +void TracedValue::SetValueWithCopiedName(const std::string& name, + const TracedValue& value) { + DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); + BeginDictionaryWithCopiedName(name); + pickle_.WriteBytes(value.pickle_.payload(), + static_cast(value.pickle_.payload_size())); + EndDictionary(); } void TracedValue::BeginDictionary(const char* name) { - DictionaryValue* dictionary = new DictionaryValue(); - GetCurrentDictionary()->Set(name, make_scoped_ptr(dictionary)); - stack_.push_back(dictionary); + DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); + DEBUG_PUSH_CONTAINER(kStackTypeDict); + pickle_.WriteBytes(&kTypeStartDict, 1); + WriteKeyNameAsRawPtr(pickle_, name); +} + +void TracedValue::BeginDictionaryWithCopiedName(const std::string& name) { + DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); + DEBUG_PUSH_CONTAINER(kStackTypeDict); + pickle_.WriteBytes(&kTypeStartDict, 1); + WriteKeyNameAsStdString(pickle_, name); } void TracedValue::BeginArray(const char* name) { - ListValue* array = new ListValue(); - GetCurrentDictionary()->Set(name, make_scoped_ptr(array)); - stack_.push_back(array); + DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); + DEBUG_PUSH_CONTAINER(kStackTypeArray); + pickle_.WriteBytes(&kTypeStartArray, 1); + WriteKeyNameAsRawPtr(pickle_, name); +} + +void TracedValue::BeginArrayWithCopiedName(const std::string& name) { + DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); + DEBUG_PUSH_CONTAINER(kStackTypeArray); + pickle_.WriteBytes(&kTypeStartArray, 1); + WriteKeyNameAsStdString(pickle_, name); } void TracedValue::EndDictionary() { - DCHECK_GT(stack_.size(), 1u); - DCHECK(GetCurrentDictionary()); - stack_.pop_back(); + DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); + DEBUG_POP_CONTAINER(); + pickle_.WriteBytes(&kTypeEndDict, 1); } void TracedValue::AppendInteger(int value) { - GetCurrentArray()->AppendInteger(value); + DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray); + pickle_.WriteBytes(&kTypeInt, 1); + pickle_.WriteInt(value); } void TracedValue::AppendDouble(double value) { - GetCurrentArray()->AppendDouble(value); + DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray); + pickle_.WriteBytes(&kTypeDouble, 1); + pickle_.WriteDouble(value); } void TracedValue::AppendBoolean(bool value) { - GetCurrentArray()->AppendBoolean(value); + DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray); + pickle_.WriteBytes(&kTypeBool, 1); + pickle_.WriteBool(value); } void TracedValue::AppendString(const std::string& value) { - GetCurrentArray()->AppendString(value); + DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray); + pickle_.WriteBytes(&kTypeString, 1); + pickle_.WriteString(value); } void TracedValue::BeginArray() { - ListValue* array = new ListValue(); - GetCurrentArray()->Append(array); - stack_.push_back(array); + DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray); + DEBUG_PUSH_CONTAINER(kStackTypeArray); + pickle_.WriteBytes(&kTypeStartArray, 1); } void TracedValue::BeginDictionary() { - DictionaryValue* dictionary = new DictionaryValue(); - GetCurrentArray()->Append(dictionary); - stack_.push_back(dictionary); + DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray); + DEBUG_PUSH_CONTAINER(kStackTypeDict); + pickle_.WriteBytes(&kTypeStartDict, 1); } void TracedValue::EndArray() { - DCHECK_GT(stack_.size(), 1u); - DCHECK(GetCurrentArray()); - stack_.pop_back(); + DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray); + DEBUG_POP_CONTAINER(); + pickle_.WriteBytes(&kTypeEndArray, 1); } -DictionaryValue* TracedValue::GetCurrentDictionary() { - DCHECK(!stack_.empty()); - DictionaryValue* dictionary = NULL; - stack_.back()->GetAsDictionary(&dictionary); - DCHECK(dictionary); - return dictionary; +void TracedValue::SetValue(const char* name, scoped_ptr value) { + SetBaseValueWithCopiedName(name, *value); } -ListValue* TracedValue::GetCurrentArray() { - DCHECK(!stack_.empty()); - ListValue* list = NULL; - stack_.back()->GetAsList(&list); - DCHECK(list); - return list; +void TracedValue::SetBaseValueWithCopiedName(const std::string& name, + const base::Value& value) { + DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); + switch (value.GetType()) { + case base::Value::TYPE_NULL: + case base::Value::TYPE_BINARY: + NOTREACHED(); + break; + + case base::Value::TYPE_BOOLEAN: { + bool bool_value; + value.GetAsBoolean(&bool_value); + SetBooleanWithCopiedName(name, bool_value); + } break; + + case base::Value::TYPE_INTEGER: { + int int_value; + value.GetAsInteger(&int_value); + SetIntegerWithCopiedName(name, int_value); + } break; + + case base::Value::TYPE_DOUBLE: { + double double_value; + value.GetAsDouble(&double_value); + SetDoubleWithCopiedName(name, double_value); + } break; + + case base::Value::TYPE_STRING: { + const StringValue* string_value; + value.GetAsString(&string_value); + SetStringWithCopiedName(name, string_value->GetString()); + } break; + + case base::Value::TYPE_DICTIONARY: { + const DictionaryValue* dict_value; + value.GetAsDictionary(&dict_value); + BeginDictionaryWithCopiedName(name); + for (DictionaryValue::Iterator it(*dict_value); !it.IsAtEnd(); + it.Advance()) { + SetBaseValueWithCopiedName(it.key(), it.value()); + } + EndDictionary(); + } break; + + case base::Value::TYPE_LIST: { + const ListValue* list_value; + value.GetAsList(&list_value); + BeginArrayWithCopiedName(name); + for (base::Value* base_value : *list_value) + AppendBaseValue(*base_value); + EndArray(); + } break; + } +} + +void TracedValue::AppendBaseValue(const base::Value& value) { + DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray); + switch (value.GetType()) { + case base::Value::TYPE_NULL: + case base::Value::TYPE_BINARY: + NOTREACHED(); + break; + + case base::Value::TYPE_BOOLEAN: { + bool bool_value; + value.GetAsBoolean(&bool_value); + AppendBoolean(bool_value); + } break; + + case base::Value::TYPE_INTEGER: { + int int_value; + value.GetAsInteger(&int_value); + AppendInteger(int_value); + } break; + + case base::Value::TYPE_DOUBLE: { + double double_value; + value.GetAsDouble(&double_value); + AppendDouble(double_value); + } break; + + case base::Value::TYPE_STRING: { + const StringValue* string_value; + value.GetAsString(&string_value); + AppendString(string_value->GetString()); + } break; + + case base::Value::TYPE_DICTIONARY: { + const DictionaryValue* dict_value; + value.GetAsDictionary(&dict_value); + BeginDictionary(); + for (DictionaryValue::Iterator it(*dict_value); !it.IsAtEnd(); + it.Advance()) { + SetBaseValueWithCopiedName(it.key(), it.value()); + } + EndDictionary(); + } break; + + case base::Value::TYPE_LIST: { + const ListValue* list_value; + value.GetAsList(&list_value); + BeginArray(); + for (base::Value* base_value : *list_value) + AppendBaseValue(*base_value); + EndArray(); + } break; + } +} + +scoped_ptr TracedValue::ToBaseValue() const { + scoped_ptr root(new DictionaryValue); + DictionaryValue* cur_dict = root.get(); + ListValue* cur_list = nullptr; + std::vector stack; + PickleIterator it(pickle_); + const char* type; + + while (it.ReadBytes(&type, 1)) { + DCHECK((cur_dict && !cur_list) || (cur_list && !cur_dict)); + switch (*type) { + case kTypeStartDict: { + auto new_dict = new DictionaryValue(); + if (cur_dict) { + cur_dict->Set(ReadKeyName(it), make_scoped_ptr(new_dict)); + stack.push_back(cur_dict); + cur_dict = new_dict; + } else { + cur_list->Append(make_scoped_ptr(new_dict)); + stack.push_back(cur_list); + cur_list = nullptr; + cur_dict = new_dict; + } + } break; + + case kTypeEndArray: + case kTypeEndDict: { + if (stack.back()->GetAsDictionary(&cur_dict)) { + cur_list = nullptr; + } else if (stack.back()->GetAsList(&cur_list)) { + cur_dict = nullptr; + } + stack.pop_back(); + } break; + + case kTypeStartArray: { + auto new_list = new ListValue(); + if (cur_dict) { + cur_dict->Set(ReadKeyName(it), make_scoped_ptr(new_list)); + stack.push_back(cur_dict); + cur_dict = nullptr; + cur_list = new_list; + } else { + cur_list->Append(make_scoped_ptr(new_list)); + stack.push_back(cur_list); + cur_list = new_list; + } + } break; + + case kTypeBool: { + bool value; + CHECK(it.ReadBool(&value)); + if (cur_dict) { + cur_dict->SetBoolean(ReadKeyName(it), value); + } else { + cur_list->AppendBoolean(value); + } + } break; + + case kTypeInt: { + int value; + CHECK(it.ReadInt(&value)); + if (cur_dict) { + cur_dict->SetInteger(ReadKeyName(it), value); + } else { + cur_list->AppendInteger(value); + } + } break; + + case kTypeDouble: { + double value; + CHECK(it.ReadDouble(&value)); + if (cur_dict) { + cur_dict->SetDouble(ReadKeyName(it), value); + } else { + cur_list->AppendDouble(value); + } + } break; + + case kTypeString: { + std::string value; + CHECK(it.ReadString(&value)); + if (cur_dict) { + cur_dict->SetString(ReadKeyName(it), value); + } else { + cur_list->AppendString(value); + } + } break; + + default: + NOTREACHED(); + } + } + DCHECK(stack.empty()); + return root.Pass(); } void TracedValue::AppendAsTraceFormat(std::string* out) const { + DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); + DCHECK_CONTAINER_STACK_DEPTH_EQ(1u); + + // TODO(primiano): this could be smarter, skip the ToBaseValue encoding and + // produce the JSON on its own. This will require refactoring JSONWriter + // to decouple the base::Value traversal from the JSON writing bits std::string tmp; - JSONWriter::Write(*stack_.front(), &tmp); + JSONWriter::Write(*ToBaseValue(), &tmp); *out += tmp; - DCHECK_EQ(1u, stack_.size()) << tmp; +} + +void TracedValue::EstimateTraceMemoryOverhead( + TraceEventMemoryOverhead* overhead) { + overhead->Add("TracedValue", + pickle_.GetTotalAllocatedSize() /* allocated size */, + pickle_.size() /* resident size */); } } // namespace trace_event diff --git a/base/trace_event/trace_event_argument.h b/base/trace_event/trace_event_argument.h index 56f7c617f9e8e..aab58bc5ba75b 100644 --- a/base/trace_event/trace_event_argument.h +++ b/base/trace_event/trace_event_argument.h @@ -9,11 +9,11 @@ #include #include "base/memory/scoped_ptr.h" +#include "base/pickle.h" #include "base/trace_event/trace_event.h" namespace base { -class DictionaryValue; -class ListValue; + class Value; namespace trace_event { @@ -21,18 +21,31 @@ namespace trace_event { class BASE_EXPORT TracedValue : public ConvertableToTraceFormat { public: TracedValue(); + explicit TracedValue(size_t capacity); void EndDictionary(); void EndArray(); + // These methods assume that |name| is a long lived "quoted" string. void SetInteger(const char* name, int value); void SetDouble(const char* name, double value); void SetBoolean(const char* name, bool value); void SetString(const char* name, const std::string& value); - void SetValue(const char* name, scoped_ptr value); + void SetValue(const char* name, const TracedValue& value); void BeginDictionary(const char* name); void BeginArray(const char* name); + // These, instead, can be safely passed a temporary string. + void SetIntegerWithCopiedName(const std::string& name, int value); + void SetDoubleWithCopiedName(const std::string& name, double value); + void SetBooleanWithCopiedName(const std::string& name, bool value); + void SetStringWithCopiedName(const std::string& name, + const std::string& value); + void SetValueWithCopiedName(const std::string& name, + const TracedValue& value); + void BeginDictionaryWithCopiedName(const std::string& name); + void BeginArrayWithCopiedName(const std::string& name); + void AppendInteger(int); void AppendDouble(double); void AppendBoolean(bool); @@ -40,16 +53,33 @@ class BASE_EXPORT TracedValue : public ConvertableToTraceFormat { void BeginArray(); void BeginDictionary(); + // ConvertableToTraceFormat implementation. void AppendAsTraceFormat(std::string* out) const override; + void EstimateTraceMemoryOverhead(TraceEventMemoryOverhead* overhead) override; + + // DEPRECATED: do not use, here only for legacy reasons. These methods causes + // a copy-and-translation of the base::Value into the equivalent TracedValue. + // TODO(primiano): migrate the (three) existing clients to the cheaper + // SetValue(TracedValue) API. crbug.com/495628. + void SetValue(const char* name, scoped_ptr value); + void SetBaseValueWithCopiedName(const std::string& name, + const base::Value& value); + void AppendBaseValue(const base::Value& value); + + // Public for tests only. + scoped_ptr ToBaseValue() const; + private: ~TracedValue() override; - DictionaryValue* GetCurrentDictionary(); - ListValue* GetCurrentArray(); + Pickle pickle_; + +#ifndef NDEBUG + // In debug builds checks the pairings of {Start,End}{Dictionary,Array} + std::vector nesting_stack_; +#endif - scoped_ptr root_; - std::vector stack_; // Weak references. DISALLOW_COPY_AND_ASSIGN(TracedValue); }; diff --git a/base/trace_event/trace_event_argument_unittest.cc b/base/trace_event/trace_event_argument_unittest.cc index c59910e446535..cb1cf2ef1d57c 100644 --- a/base/trace_event/trace_event_argument_unittest.cc +++ b/base/trace_event/trace_event_argument_unittest.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "base/trace_event/trace_event_argument.h" +#include "base/values.h" #include "testing/gtest/include/gtest/gtest.h" namespace base { @@ -14,10 +15,11 @@ TEST(TraceEventArgumentTest, FlatDictionary) { value->SetDouble("double", 0.0); value->SetBoolean("bool", true); value->SetString("string", "string"); - std::string json; + std::string json = "PREFIX"; value->AppendAsTraceFormat(&json); - EXPECT_EQ("{\"bool\":true,\"double\":0.0,\"int\":2014,\"string\":\"string\"}", - json); + EXPECT_EQ( + "PREFIX{\"bool\":true,\"double\":0.0,\"int\":2014,\"string\":\"string\"}", + json); } TEST(TraceEventArgumentTest, Hierarchy) { @@ -49,5 +51,96 @@ TEST(TraceEventArgumentTest, Hierarchy) { json); } +TEST(TraceEventArgumentTest, LongStrings) { + std::string kLongString = "supercalifragilisticexpialidocious"; + std::string kLongString2 = "0123456789012345678901234567890123456789"; + char kLongString3[4096]; + for (size_t i = 0; i < sizeof(kLongString3); ++i) + kLongString3[i] = 'a' + (i % 25); + kLongString3[sizeof(kLongString3) - 1] = '\0'; + + scoped_refptr value = new TracedValue(); + value->SetString("a", "short"); + value->SetString("b", kLongString); + value->BeginArray("c"); + value->AppendString(kLongString2); + value->AppendString(""); + value->BeginDictionary(); + value->SetString("a", kLongString3); + value->EndDictionary(); + value->EndArray(); + + std::string json; + value->AppendAsTraceFormat(&json); + EXPECT_EQ("{\"a\":\"short\",\"b\":\"" + kLongString + "\",\"c\":[\"" + + kLongString2 + "\",\"\",{\"a\":\"" + kLongString3 + "\"}]}", + json); +} + +TEST(TraceEventArgumentTest, PassBaseValue) { + FundamentalValue int_value(42); + FundamentalValue bool_value(true); + FundamentalValue double_value(42.0f); + + auto dict_value = make_scoped_ptr(new DictionaryValue); + dict_value->SetBoolean("bool", true); + dict_value->SetInteger("int", 42); + dict_value->SetDouble("double", 42.0f); + dict_value->SetString("string", std::string("a") + "b"); + dict_value->SetString("string", std::string("a") + "b"); + + auto list_value = make_scoped_ptr(new ListValue); + list_value->AppendBoolean(false); + list_value->AppendInteger(1); + list_value->AppendString("in_list"); + list_value->Append(dict_value.Pass()); + + scoped_refptr value = new TracedValue(); + value->BeginDictionary("outer_dict"); + value->SetValue("inner_list", list_value.Pass()); + value->EndDictionary(); + + dict_value.reset(); + list_value.reset(); + + std::string json; + value->AppendAsTraceFormat(&json); + EXPECT_EQ( + "{\"outer_dict\":{\"inner_list\":[false,1,\"in_list\",{\"bool\":true," + "\"double\":42.0,\"int\":42,\"string\":\"ab\"}]}}", + json); +} + +TEST(TraceEventArgumentTest, PassTracedValue) { + auto dict_value = make_scoped_refptr(new TracedValue); + dict_value->SetInteger("a", 1); + + auto nested_dict_value = make_scoped_refptr(new TracedValue); + nested_dict_value->SetInteger("b", 2); + nested_dict_value->BeginArray("c"); + nested_dict_value->AppendString("foo"); + nested_dict_value->EndArray(); + + dict_value->SetValue("e", *nested_dict_value); + + // Check the merged result. + std::string json; + dict_value->AppendAsTraceFormat(&json); + EXPECT_EQ("{\"a\":1,\"e\":{\"b\":2,\"c\":[\"foo\"]}}", json); + + // Check that the passed nestd dict was left unouthced. + json = ""; + nested_dict_value->AppendAsTraceFormat(&json); + EXPECT_EQ("{\"b\":2,\"c\":[\"foo\"]}", json); + + // And that it is still usable. + nested_dict_value->SetInteger("f", 3); + nested_dict_value->BeginDictionary("g"); + nested_dict_value->EndDictionary(); + json = ""; + nested_dict_value->AppendAsTraceFormat(&json); + EXPECT_EQ("{\"b\":2,\"c\":[\"foo\"],\"f\":3,\"g\":{}}", json); +} + } // namespace trace_event } // namespace base diff --git a/base/trace_event/trace_event_etw_export_win.cc b/base/trace_event/trace_event_etw_export_win.cc index d199bf5c8b2e4..e61a7b2964599 100644 --- a/base/trace_event/trace_event_etw_export_win.cc +++ b/base/trace_event/trace_event_etw_export_win.cc @@ -7,6 +7,7 @@ #include "base/command_line.h" #include "base/logging.h" #include "base/memory/singleton.h" +#include "base/strings/string_tokenizer.h" #include "base/strings/utf_string_conversions.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event_impl.h" @@ -40,6 +41,55 @@ typedef ULONG(__stdcall* tEventUnregister)(REGHANDLE RegHandle); tEventRegister EventRegisterProc = nullptr; tEventWrite EventWriteProc = nullptr; tEventUnregister EventUnregisterProc = nullptr; + +// |filtered_event_group_names| contains the event categories that can be +// exported individually. These categories can be enabled by passing the correct +// keyword when starting the trace. A keyword is a 64-bit flag and we attribute +// one bit per category. We can therefore enable a particular category by +// setting its corresponding bit in the keyword. For events that are not present +// in |filtered_event_group_names|, we have two bits that control their +// behaviour. When bit 61 is enabled, any event that is not disabled by default +// (ie. doesn't start with disabled-by-default-) will be exported. Likewise, +// when bit 62 is enabled, any event that is disabled by default will be +// exported. +// +// Note that bit 63 (MSB) must always be set, otherwise tracing will be disabled +// by ETW. Therefore, the keyword will always be greater than +// 0x8000000000000000. +// +// Examples of passing keywords to the provider using xperf: +// # This exports "benchmark" and "cc" events +// xperf -start chrome -on Chrome:0x8000000000000009 +// +// # This exports "gpu", "netlog" and all other events that are not disabled by +// # default +// xperf -start chrome -on Chrome:0xA0000000000000A0 +// +// More info about starting a trace and keyword can be obtained by using the +// help section of xperf (xperf -help start). Note that xperf documentation +// refers to keywords as flags and there are two ways to enable them, using +// group names or the hex representation. We only support the latter. Also, we +// ignore the level. +const char* const filtered_event_group_names[] = { + "benchmark", // 0x1 + "blink", // 0x2 + "browser", // 0x4 + "cc", // 0x8 + "evdev", // 0x10 + "gpu", // 0x20 + "input", // 0x40 + "netlog", // 0x80 + "renderer.scheduler", // 0x100 + "toplevel", // 0x200 + "v8", // 0x400 + "disabled-by-default-cc.debug", // 0x800 + "disabled-by-default-cc.debug.picture", // 0x1000 + "disabled-by-default-toplevel.flow"}; // 0x2000 +const char* other_events_group_name = "__OTHER_EVENTS"; // 0x2000000000000000 +const char* disabled_other_events_group_name = + "__DISABLED_OTHER_EVENTS"; // 0x4000000000000000 +uint64 other_events_keyword_bit = 1ULL << 61; +uint64 disabled_other_events_keyword_bit = 1ULL << 62; } // namespace // Redirector function for EventRegister. Called by macros in @@ -77,7 +127,8 @@ ULONG EVNTAPI EventUnregister(REGHANDLE RegHandle) { namespace base { namespace trace_event { -TraceEventETWExport::TraceEventETWExport() : ETWExportEnabled_(false) { +TraceEventETWExport::TraceEventETWExport() + : etw_export_enabled_(false), etw_match_any_keyword_(0ULL) { // Find Advapi32.dll. This should always succeed. HMODULE AdvapiDLL = ::LoadLibraryW(L"Advapi32.dll"); if (AdvapiDLL) { @@ -92,6 +143,8 @@ TraceEventETWExport::TraceEventETWExport() : ETWExportEnabled_(false) { // Register the ETW provider. If registration fails then the event logging // calls will fail (on XP this call will do nothing). EventRegisterChrome(); + + UpdateEnabledCategories(); } } @@ -108,13 +161,18 @@ TraceEventETWExport* TraceEventETWExport::GetInstance() { // static void TraceEventETWExport::EnableETWExport() { if (GetInstance()) - GetInstance()->ETWExportEnabled_ = true; + GetInstance()->etw_export_enabled_ = true; } // static void TraceEventETWExport::DisableETWExport() { if (GetInstance()) - GetInstance()->ETWExportEnabled_ = false; + GetInstance()->etw_export_enabled_ = false; +} + +// static +bool TraceEventETWExport::IsETWExportEnabled() { + return (GetInstance() && GetInstance()->etw_export_enabled_); } // static @@ -129,7 +187,7 @@ void TraceEventETWExport::AddEvent( const unsigned long long* arg_values, const scoped_refptr* convertable_values) { // We bail early in case exporting is disabled or no consumer is listening. - if (!GetInstance() || !GetInstance()->ETWExportEnabled_ || + if (!GetInstance() || !GetInstance()->etw_export_enabled_ || !EventEnabledChromeEvent()) return; @@ -211,7 +269,7 @@ void TraceEventETWExport::AddEvent( // *total* process CPU time when ETW tracing, and many of the strings // created exceed WPA's 4094 byte limit and are shown as: // "Unable to parse data". See crbug.com/488257 - //convertable_values[i]->AppendAsTraceFormat(arg_values_string + i); + // convertable_values[i]->AppendAsTraceFormat(arg_values_string + i); } else { TraceEvent::TraceValue trace_event; trace_event.as_uint = arg_values[i]; @@ -236,7 +294,7 @@ void TraceEventETWExport::AddCustomEvent(const char* name, const char* arg_value_2, const char* arg_name_3, const char* arg_value_3) { - if (!GetInstance() || !GetInstance()->ETWExportEnabled_ || + if (!GetInstance() || !GetInstance()->etw_export_enabled_ || !EventEnabledChromeEvent()) return; @@ -244,8 +302,78 @@ void TraceEventETWExport::AddCustomEvent(const char* name, arg_value_2, arg_name_3, arg_value_3); } -void TraceEventETWExport::Resurrect() { - StaticMemorySingletonTraits::Resurrect(); +// static +bool TraceEventETWExport::IsCategoryGroupEnabled( + const char* category_group_name) { + DCHECK(category_group_name); + auto instance = GetInstance(); + if (instance == nullptr) + return false; + + if (!instance->IsETWExportEnabled()) + return false; + + CStringTokenizer category_group_tokens( + category_group_name, category_group_name + strlen(category_group_name), + ","); + while (category_group_tokens.GetNext()) { + std::string category_group_token = category_group_tokens.token(); + if (instance->IsCategoryEnabled(category_group_token.c_str())) { + return true; + } + } + return false; +} + +bool TraceEventETWExport::UpdateEnabledCategories() { + if (etw_match_any_keyword_ == CHROME_Context.MatchAnyKeyword) + return false; + + // If the keyword has changed, update each category. + // Chrome_Context.MatchAnyKeyword is set by UIforETW (or other ETW trace + // recording tools) using the ETW infrastructure. This value will be set in + // all Chrome processes that have registered their ETW provider. + etw_match_any_keyword_ = CHROME_Context.MatchAnyKeyword; + for (int i = 0; i < ARRAYSIZE(filtered_event_group_names); i++) { + if (etw_match_any_keyword_ & (1ULL << i)) { + categories_status_[filtered_event_group_names[i]] = true; + } else { + categories_status_[filtered_event_group_names[i]] = false; + } + } + + // Also update the two default categories. + if (etw_match_any_keyword_ & other_events_keyword_bit) { + categories_status_[other_events_group_name] = true; + } else { + categories_status_[other_events_group_name] = false; + } + if (etw_match_any_keyword_ & disabled_other_events_keyword_bit) { + categories_status_[disabled_other_events_group_name] = true; + } else { + categories_status_[disabled_other_events_group_name] = false; + } + + return true; +} + +bool TraceEventETWExport::IsCategoryEnabled(const char* category_name) const { + // Try to find the category and return its status if found + auto it = categories_status_.find(category_name); + if (it != categories_status_.end()) + return it->second; + + // Otherwise return the corresponding default status by first checking if the + // category is disabled by default. + if (StringPiece(category_name).starts_with("disabled-by-default")) { + DCHECK(categories_status_.find(disabled_other_events_group_name) != + categories_status_.end()); + return categories_status_.find(disabled_other_events_group_name)->second; + } else { + DCHECK(categories_status_.find(other_events_group_name) != + categories_status_.end()); + return categories_status_.find(other_events_group_name)->second; + } } } // namespace trace_event diff --git a/base/trace_event/trace_event_etw_export_win.h b/base/trace_event/trace_event_etw_export_win.h index eefe820481217..9f73d781f7358 100644 --- a/base/trace_event/trace_event_etw_export_win.h +++ b/base/trace_event/trace_event_etw_export_win.h @@ -6,7 +6,10 @@ #ifndef BASE_TRACE_EVENT_TRACE_EVENT_ETW_EXPORT_WIN_H_ #define BASE_TRACE_EVENT_TRACE_EVENT_ETW_EXPORT_WIN_H_ +#include + #include "base/base_export.h" +#include "base/strings/string_piece.h" #include "base/trace_event/trace_event_impl.h" // Fwd. @@ -29,9 +32,9 @@ class BASE_EXPORT TraceEventETWExport { static void EnableETWExport(); static void DisableETWExport(); - static bool isETWExportEnabled() { - return (GetInstance() && GetInstance()->ETWExportEnabled_); - } + // Returns true if ETW is enabled. For now, this is true if the command line + // flag is specified. + static bool IsETWExportEnabled(); // Exports an event to ETW. This is mainly used in // TraceLog::AddTraceEventWithThreadIdAndTimestamp to export internal events. @@ -50,7 +53,7 @@ class BASE_EXPORT TraceEventETWExport { // to ETW. Supports three arguments to be passed to ETW. // TODO(georgesak): Allow different providers. static void AddCustomEvent(const char* name, - char const* phase, + const char* phase, const char* arg_name_1, const char* arg_value_1, const char* arg_name_2, @@ -58,14 +61,30 @@ class BASE_EXPORT TraceEventETWExport { const char* arg_name_3, const char* arg_value_3); - void Resurrect(); + // Returns true if any category in the group is enabled. + static bool IsCategoryGroupEnabled(const char* category_group_name); private: - bool ETWExportEnabled_; // Ensure only the provider can construct us. friend struct StaticMemorySingletonTraits; TraceEventETWExport(); + // Updates the list of enabled categories by consulting the ETW keyword. + // Returns true if there was a change, false otherwise. + bool UpdateEnabledCategories(); + + // Returns true if the category is enabled. + bool IsCategoryEnabled(const char* category_name) const; + + // True if ETW is enabled. Allows hiding the exporting behind a flag. + bool etw_export_enabled_; + + // Maps category names to their status (enabled/disabled). + std::map categories_status_; + + // Local copy of the ETW keyword. + uint64 etw_match_any_keyword_; + DISALLOW_COPY_AND_ASSIGN(TraceEventETWExport); }; diff --git a/base/trace_event/trace_event_impl.cc b/base/trace_event/trace_event_impl.cc index 3d58d873ad525..cd8cf4aa90c46 100644 --- a/base/trace_event/trace_event_impl.cc +++ b/base/trace_event/trace_event_impl.cc @@ -33,6 +33,9 @@ #include "base/threading/thread_id_name_manager.h" #include "base/threading/worker_pool.h" #include "base/time/time.h" +#include "base/trace_event/memory_dump_manager.h" +#include "base/trace_event/memory_dump_provider.h" +#include "base/trace_event/process_memory_dump.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event_synthetic_delay.h" @@ -214,6 +217,18 @@ class TraceBufferRingBuffer : public TraceBuffer { return cloned_buffer.Pass(); } + void EstimateTraceMemoryOverhead( + TraceEventMemoryOverhead* overhead) override { + overhead->Add("TraceBufferRingBuffer", sizeof(*this)); + for (size_t queue_index = queue_head_; queue_index != queue_tail_; + queue_index = NextQueueIndex(queue_index)) { + size_t chunk_index = recyclable_chunks_queue_[queue_index]; + if (chunk_index >= chunks_.size()) // Skip uninitialized chunks. + continue; + chunks_[chunk_index]->EstimateTraceMemoryOverhead(overhead); + } + } + private: class ClonedTraceBuffer : public TraceBuffer { public: @@ -242,6 +257,10 @@ class TraceBufferRingBuffer : public TraceBuffer { NOTIMPLEMENTED(); return scoped_ptr(); } + void EstimateTraceMemoryOverhead( + TraceEventMemoryOverhead* overhead) override { + NOTIMPLEMENTED(); + } size_t current_iteration_index_; ScopedVector chunks_; @@ -350,6 +369,23 @@ class TraceBufferVector : public TraceBuffer { return scoped_ptr(); } + void EstimateTraceMemoryOverhead( + TraceEventMemoryOverhead* overhead) override { + const size_t chunks_ptr_vector_allocated_size = + sizeof(*this) + max_chunks_ * sizeof(decltype(chunks_)::value_type); + const size_t chunks_ptr_vector_resident_size = + sizeof(*this) + chunks_.size() * sizeof(decltype(chunks_)::value_type); + overhead->Add("TraceBufferVector", chunks_ptr_vector_allocated_size, + chunks_ptr_vector_resident_size); + for (size_t i = 0; i < chunks_.size(); ++i) { + TraceBufferChunk* chunk = chunks_[i]; + // Skip the in-flight (nullptr) chunks. They will be accounted by the + // per-thread-local dumpers, see ThreadLocalEventBuffer::OnMemoryDump. + if (chunk) + chunk->EstimateTraceMemoryOverhead(overhead); + } + } + private: size_t in_flight_chunk_count_; size_t current_iteration_index_; @@ -398,11 +434,18 @@ class AutoThreadLocalBoolean { } // namespace +TraceBufferChunk::TraceBufferChunk(uint32 seq) : next_free_(0), seq_(seq) { +} + +TraceBufferChunk::~TraceBufferChunk() { +} + void TraceBufferChunk::Reset(uint32 new_seq) { for (size_t i = 0; i < next_free_; ++i) chunk_[i].Reset(); next_free_ = 0; seq_ = new_seq; + cached_overhead_estimate_when_full_.reset(); } TraceEvent* TraceBufferChunk::AddTraceEvent(size_t* event_index) { @@ -419,6 +462,31 @@ scoped_ptr TraceBufferChunk::Clone() const { return cloned_chunk.Pass(); } +void TraceBufferChunk::EstimateTraceMemoryOverhead( + TraceEventMemoryOverhead* overhead) { + if (cached_overhead_estimate_when_full_) { + DCHECK(IsFull()); + overhead->Update(*cached_overhead_estimate_when_full_); + return; + } + + // Cache the memory overhead estimate only if the chunk is full. + TraceEventMemoryOverhead* estimate = overhead; + if (IsFull()) { + cached_overhead_estimate_when_full_.reset(new TraceEventMemoryOverhead); + estimate = cached_overhead_estimate_when_full_.get(); + } + + estimate->Add("TraceBufferChunk", sizeof(*this)); + for (size_t i = 0; i < next_free_; ++i) + chunk_[i].EstimateTraceMemoryOverhead(estimate); + + if (IsFull()) { + estimate->AddSelf(); + overhead->Update(*estimate); + } +} + // A helper class that allows the lock to be acquired in the middle of the scope // and unlocks at the end of scope if locked. class TraceLog::OptionalAutoLock { @@ -529,7 +597,7 @@ void TraceEvent::Initialize( const unsigned char* arg_types, const unsigned long long* arg_values, const scoped_refptr* convertable_values, - unsigned char flags) { + unsigned int flags) { timestamp_ = timestamp; thread_timestamp_ = thread_timestamp; duration_ = TimeDelta::FromInternalValue(-1); @@ -610,6 +678,7 @@ void TraceEvent::Reset() { parameter_copy_storage_ = NULL; for (int i = 0; i < kTraceMaxNumArgs; ++i) convertable_values_[i] = NULL; + cached_memory_overhead_estimate_.reset(); } void TraceEvent::UpdateDuration(const TraceTicks& now, @@ -619,6 +688,29 @@ void TraceEvent::UpdateDuration(const TraceTicks& now, thread_duration_ = thread_now - thread_timestamp_; } +void TraceEvent::EstimateTraceMemoryOverhead( + TraceEventMemoryOverhead* overhead) { + if (!cached_memory_overhead_estimate_) { + cached_memory_overhead_estimate_.reset(new TraceEventMemoryOverhead); + cached_memory_overhead_estimate_->Add("TraceEvent", sizeof(*this)); + // TODO(primiano): parameter_copy_storage_ is refcounted and, in theory, + // could be shared by several events and we might overcount. In practice + // this is unlikely but it's worth checking. + if (parameter_copy_storage_) { + cached_memory_overhead_estimate_->AddRefCountedString( + *parameter_copy_storage_.get()); + } + for (size_t i = 0; i < kTraceMaxNumArgs; ++i) { + if (arg_types_[i] == TRACE_VALUE_TYPE_CONVERTABLE) { + convertable_values_[i]->EstimateTraceMemoryOverhead( + cached_memory_overhead_estimate_.get()); + } + } + cached_memory_overhead_estimate_->AddSelf(); + } + overhead->Update(*cached_memory_overhead_estimate_); +} + // static void TraceEvent::AppendValueAsJSON(unsigned char type, TraceEvent::TraceValue value, @@ -697,34 +789,34 @@ void TraceEvent::AppendAsJSON( DCHECK(!strchr(name_, '"')); StringAppendF(out, "{\"pid\":%i,\"tid\":%i,\"ts\":%" PRId64 "," - "\"ph\":\"%c\",\"cat\":\"%s\",\"name\":\"%s\",\"args\":{", + "\"ph\":\"%c\",\"cat\":\"%s\",\"name\":\"%s\",\"args\":", process_id, thread_id_, time_int64, phase_, category_group_name, name_); // Output argument names and values, stop at first NULL argument name. - if (arg_names_[0]) { - bool allow_args = argument_filter_predicate.is_null() || - argument_filter_predicate.Run(category_group_name, name_); - - if (allow_args) { - for (int i = 0; i < kTraceMaxNumArgs && arg_names_[i]; ++i) { - if (i > 0) - *out += ","; - *out += "\""; - *out += arg_names_[i]; - *out += "\":"; - - if (arg_types_[i] == TRACE_VALUE_TYPE_CONVERTABLE) - convertable_values_[i]->AppendAsTraceFormat(out); - else - AppendValueAsJSON(arg_types_[i], arg_values_[i], out); - } - } else { - *out += "\"stripped\":1"; + bool strip_args = arg_names_[0] && !argument_filter_predicate.is_null() && + !argument_filter_predicate.Run(category_group_name, name_); + + if (strip_args) { + *out += "\"__stripped__\""; + } else { + *out += "{"; + + for (int i = 0; i < kTraceMaxNumArgs && arg_names_[i]; ++i) { + if (i > 0) + *out += ","; + *out += "\""; + *out += arg_names_[i]; + *out += "\":"; + + if (arg_types_[i] == TRACE_VALUE_TYPE_CONVERTABLE) + convertable_values_[i]->AppendAsTraceFormat(out); + else + AppendValueAsJSON(arg_types_[i], arg_values_[i], out); } - } - *out += "}"; + *out += "}"; + } if (phase_ == TRACE_EVENT_PHASE_COMPLETE) { int64 duration = duration_.ToInternalValue(); @@ -753,6 +845,9 @@ void TraceEvent::AppendAsJSON( if (flags_ & TRACE_EVENT_FLAG_HAS_ID) StringAppendF(out, ",\"id\":\"0x%" PRIx64 "\"", static_cast(id_)); + if (flags_ & TRACE_EVENT_FLAG_BIND_TO_ENCLOSING) + StringAppendF(out, ",\"bp\":\"e\""); + // Instant events also output their scope. if (phase_ == TRACE_EVENT_PHASE_INSTANT) { char scope = '?'; @@ -984,7 +1079,8 @@ TraceBucketData::~TraceBucketData() { //////////////////////////////////////////////////////////////////////////////// class TraceLog::ThreadLocalEventBuffer - : public MessageLoop::DestructionObserver { + : public MessageLoop::DestructionObserver, + public MemoryDumpProvider { public: ThreadLocalEventBuffer(TraceLog* trace_log); ~ThreadLocalEventBuffer() override; @@ -1008,6 +1104,9 @@ class TraceLog::ThreadLocalEventBuffer // MessageLoop::DestructionObserver void WillDestroyCurrentMessageLoop() override; + // MemoryDumpProvider implementation. + bool OnMemoryDump(ProcessMemoryDump* pmd) override; + void FlushWhileLocked(); void CheckThisIsCurrentBuffer() const { @@ -1036,6 +1135,10 @@ TraceLog::ThreadLocalEventBuffer::ThreadLocalEventBuffer(TraceLog* trace_log) MessageLoop* message_loop = MessageLoop::current(); message_loop->AddDestructionObserver(this); + // This is to report the local memory usage when memory-infra is enabled. + MemoryDumpManager::GetInstance()->RegisterDumpProvider( + this, ThreadTaskRunnerHandle::Get()); + AutoLock lock(trace_log->lock_); trace_log->thread_message_loops_.insert(message_loop); } @@ -1043,6 +1146,7 @@ TraceLog::ThreadLocalEventBuffer::ThreadLocalEventBuffer(TraceLog* trace_log) TraceLog::ThreadLocalEventBuffer::~ThreadLocalEventBuffer() { CheckThisIsCurrentBuffer(); MessageLoop::current()->RemoveDestructionObserver(this); + MemoryDumpManager::GetInstance()->UnregisterDumpProvider(this); // Zero event_count_ happens in either of the following cases: // - no event generated for the thread; @@ -1119,6 +1223,17 @@ void TraceLog::ThreadLocalEventBuffer::WillDestroyCurrentMessageLoop() { delete this; } +bool TraceLog::ThreadLocalEventBuffer::OnMemoryDump(ProcessMemoryDump* pmd) { + if (!chunk_) + return true; + std::string dump_base_name = StringPrintf( + "tracing/thread_%d", static_cast(PlatformThread::CurrentId())); + TraceEventMemoryOverhead overhead; + chunk_->EstimateTraceMemoryOverhead(&overhead); + overhead.DumpInto(dump_base_name.c_str(), pmd); + return true; +} + void TraceLog::ThreadLocalEventBuffer::FlushWhileLocked() { if (!chunk_) return; @@ -1195,11 +1310,46 @@ TraceLog::TraceLog() #endif logged_events_.reset(CreateTraceBuffer()); + + MemoryDumpManager::GetInstance()->RegisterDumpProvider(this); } TraceLog::~TraceLog() { } +void TraceLog::InitializeThreadLocalEventBufferIfSupported() { + // A ThreadLocalEventBuffer needs the message loop + // - to know when the thread exits; + // - to handle the final flush. + // For a thread without a message loop or the message loop may be blocked, the + // trace events will be added into the main buffer directly. + if (thread_blocks_message_loop_.Get() || !MessageLoop::current()) + return; + auto thread_local_event_buffer = thread_local_event_buffer_.Get(); + if (thread_local_event_buffer && + !CheckGeneration(thread_local_event_buffer->generation())) { + delete thread_local_event_buffer; + thread_local_event_buffer = NULL; + } + if (!thread_local_event_buffer) { + thread_local_event_buffer = new ThreadLocalEventBuffer(this); + thread_local_event_buffer_.Set(thread_local_event_buffer); + } +} + +bool TraceLog::OnMemoryDump(ProcessMemoryDump* pmd) { + TraceEventMemoryOverhead overhead; + overhead.Add("TraceLog", sizeof(*this)); + { + AutoLock lock(lock_); + if (logged_events_) + logged_events_->EstimateTraceMemoryOverhead(&overhead); + } + overhead.AddSelf(); + overhead.DumpInto("tracing/main_trace_log", pmd); + return true; +} + const unsigned char* TraceLog::GetCategoryGroupEnabled( const char* category_group) { TraceLog* tracelog = GetInstance(); @@ -1239,8 +1389,10 @@ void TraceLog::UpdateCategoryGroupEnabledFlag(size_t category_index) { event_callback_trace_config_.IsCategoryGroupEnabled(category_group)) enabled_flag |= ENABLED_FOR_EVENT_CALLBACK; #if defined(OS_WIN) - if (base::trace_event::TraceEventETWExport::isETWExportEnabled()) + if (base::trace_event::TraceEventETWExport::IsCategoryGroupEnabled( + category_group)) { enabled_flag |= ENABLED_FOR_ETW_EXPORT; + } #endif g_category_group_enabled[category_index] = enabled_flag; @@ -1627,6 +1779,17 @@ void TraceLog::SetEventCallbackDisabled() { // 4. If any thread hasn't finish its flush in time, finish the flush. void TraceLog::Flush(const TraceLog::OutputCallback& cb, bool use_worker_thread) { + FlushInternal(cb, use_worker_thread, false); +} + +void TraceLog::CancelTracing(const OutputCallback& cb) { + SetDisabled(); + FlushInternal(cb, false, true); +} + +void TraceLog::FlushInternal(const TraceLog::OutputCallback& cb, + bool use_worker_thread, + bool discard_events) { use_worker_thread_ = use_worker_thread; if (IsEnabled()) { // Can't flush when tracing is enabled because otherwise PostTask would @@ -1670,17 +1833,17 @@ void TraceLog::Flush(const TraceLog::OutputCallback& cb, if (thread_message_loop_task_runners.size()) { for (size_t i = 0; i < thread_message_loop_task_runners.size(); ++i) { thread_message_loop_task_runners[i]->PostTask( - FROM_HERE, - Bind(&TraceLog::FlushCurrentThread, Unretained(this), generation)); + FROM_HERE, Bind(&TraceLog::FlushCurrentThread, Unretained(this), + generation, discard_events)); } flush_task_runner_->PostDelayedTask( - FROM_HERE, - Bind(&TraceLog::OnFlushTimeout, Unretained(this), generation), + FROM_HERE, Bind(&TraceLog::OnFlushTimeout, Unretained(this), generation, + discard_events), TimeDelta::FromMilliseconds(kThreadFlushTimeoutMs)); return; } - FinishFlush(generation); + FinishFlush(generation, discard_events); } // Usually it runs on a different thread. @@ -1693,28 +1856,24 @@ void TraceLog::ConvertTraceEventsToTraceFormat( // The callback need to be called at least once even if there is no events // to let the caller know the completion of flush. - bool has_more_events = true; - do { - scoped_refptr json_events_str_ptr = - new RefCountedString(); - - while (json_events_str_ptr->size() < kTraceEventBufferSizeInBytes) { - const TraceBufferChunk* chunk = logged_events->NextChunk(); - has_more_events = chunk != NULL; - if (!chunk) - break; - for (size_t j = 0; j < chunk->size(); ++j) { - if (json_events_str_ptr->size()) - json_events_str_ptr->data().append(",\n"); - chunk->GetEventAt(j)->AppendAsJSON(&(json_events_str_ptr->data()), - argument_filter_predicate); + scoped_refptr json_events_str_ptr = new RefCountedString(); + while (const TraceBufferChunk* chunk = logged_events->NextChunk()) { + for (size_t j = 0; j < chunk->size(); ++j) { + size_t size = json_events_str_ptr->size(); + if (size > kTraceEventBufferSizeInBytes) { + flush_output_callback.Run(json_events_str_ptr, true); + json_events_str_ptr = new RefCountedString(); + } else if (size) { + json_events_str_ptr->data().append(",\n"); } + chunk->GetEventAt(j)->AppendAsJSON(&(json_events_str_ptr->data()), + argument_filter_predicate); } - flush_output_callback.Run(json_events_str_ptr, has_more_events); - } while (has_more_events); + } + flush_output_callback.Run(json_events_str_ptr, false); } -void TraceLog::FinishFlush(int generation) { +void TraceLog::FinishFlush(int generation, bool discard_events) { scoped_ptr previous_logged_events; OutputCallback flush_output_callback; TraceEvent::ArgumentFilterPredicate argument_filter_predicate; @@ -1739,6 +1898,14 @@ void TraceLog::FinishFlush(int generation) { } } + if (discard_events) { + if (!flush_output_callback.is_null()) { + scoped_refptr empty_result = new RefCountedString; + flush_output_callback.Run(empty_result, false); + } + return; + } + if (use_worker_thread_ && WorkerPool::PostTask( FROM_HERE, Bind(&TraceLog::ConvertTraceEventsToTraceFormat, @@ -1754,7 +1921,7 @@ void TraceLog::FinishFlush(int generation) { } // Run in each thread holding a local event buffer. -void TraceLog::FlushCurrentThread(int generation) { +void TraceLog::FlushCurrentThread(int generation, bool discard_events) { { AutoLock lock(lock_); if (!CheckGeneration(generation) || !flush_task_runner_) { @@ -1772,10 +1939,11 @@ void TraceLog::FlushCurrentThread(int generation) { return; flush_task_runner_->PostTask( - FROM_HERE, Bind(&TraceLog::FinishFlush, Unretained(this), generation)); + FROM_HERE, Bind(&TraceLog::FinishFlush, Unretained(this), generation, + discard_events)); } -void TraceLog::OnFlushTimeout(int generation) { +void TraceLog::OnFlushTimeout(int generation, bool discard_events) { { AutoLock lock(lock_); if (!CheckGeneration(generation) || !flush_task_runner_) { @@ -1794,7 +1962,7 @@ void TraceLog::OnFlushTimeout(int generation) { LOG(WARNING) << "Thread: " << (*it)->thread_name(); } } - FinishFlush(generation); + FinishFlush(generation, discard_events); } void TraceLog::FlushButLeaveBufferIntact( @@ -1839,7 +2007,7 @@ TraceEventHandle TraceLog::AddTraceEvent( const unsigned char* arg_types, const unsigned long long* arg_values, const scoped_refptr* convertable_values, - unsigned char flags) { + unsigned int flags) { int thread_id = static_cast(base::PlatformThread::CurrentId()); base::TraceTicks now = base::TraceTicks::Now(); return AddTraceEventWithThreadIdAndTimestamp(phase, category_group_enabled, @@ -1861,7 +2029,7 @@ TraceEventHandle TraceLog::AddTraceEventWithThreadIdAndTimestamp( const unsigned char* arg_types, const unsigned long long* arg_values, const scoped_refptr* convertable_values, - unsigned char flags) { + unsigned int flags) { TraceEventHandle handle = { 0, 0, 0 }; if (!*category_group_enabled) return handle; @@ -1885,24 +2053,10 @@ TraceEventHandle TraceLog::AddTraceEventWithThreadIdAndTimestamp( OffsetNow() : offset_event_timestamp; ThreadTicks thread_now = ThreadNow(); - ThreadLocalEventBuffer* thread_local_event_buffer = NULL; - // A ThreadLocalEventBuffer needs the message loop - // - to know when the thread exits; - // - to handle the final flush. - // For a thread without a message loop or the message loop may be blocked, the - // trace events will be added into the main buffer directly. - if (!thread_blocks_message_loop_.Get() && MessageLoop::current()) { - thread_local_event_buffer = thread_local_event_buffer_.Get(); - if (thread_local_event_buffer && - !CheckGeneration(thread_local_event_buffer->generation())) { - delete thread_local_event_buffer; - thread_local_event_buffer = NULL; - } - if (!thread_local_event_buffer) { - thread_local_event_buffer = new ThreadLocalEventBuffer(this); - thread_local_event_buffer_.Set(thread_local_event_buffer); - } - } + // |thread_local_event_buffer_| can be null if the current thread doesn't have + // a message loop or the message loop is blocked. + InitializeThreadLocalEventBufferIfSupported(); + auto thread_local_event_buffer = thread_local_event_buffer_.Get(); // Check and update the current thread name only if the event is for the // current thread to avoid locks in most cases. @@ -1927,8 +2081,10 @@ TraceEventHandle TraceLog::AddTraceEventWithThreadIdAndTimestamp( } else { // This is a thread id that we've seen before, but potentially with a // new name. - std::vector existing_names; - Tokenize(existing_name->second, ",", &existing_names); + std::vector existing_names = + base::SplitStringPiece(existing_name->second, ",", + base::KEEP_WHITESPACE, + base::SPLIT_WANT_NONEMPTY); bool found = std::find(existing_names.begin(), existing_names.end(), new_name) != existing_names.end(); @@ -2196,7 +2352,7 @@ void TraceLog::AddMetadataEventsWhileLocked() { InitializeMetadataEvent(AddEventToThreadSharedChunkWhileLocked(NULL, false), current_thread_id, "process_labels", "labels", - JoinString(labels, ',')); + base::JoinString(labels, ",")); } // Thread sort indices. @@ -2334,6 +2490,11 @@ void TraceLog::SetCurrentThreadBlocksMessageLoop() { } } +void ConvertableToTraceFormat::EstimateTraceMemoryOverhead( + TraceEventMemoryOverhead* overhead) { + overhead->Add("ConvertableToTraceFormat(Unknown)", sizeof(*this)); +} + } // namespace trace_event } // namespace base diff --git a/base/trace_event/trace_event_impl.h b/base/trace_event/trace_event_impl.h index 7fdc5e395a491..a6e95f4152a03 100644 --- a/base/trace_event/trace_event_impl.h +++ b/base/trace_event/trace_event_impl.h @@ -24,7 +24,9 @@ #include "base/synchronization/lock.h" #include "base/threading/thread.h" #include "base/threading/thread_local.h" +#include "base/trace_event/memory_dump_provider.h" #include "base/trace_event/trace_config.h" +#include "base/trace_event/trace_event_memory_overhead.h" // Older style trace macros with explicit id and extra data // Only these macros result in publishing data to ETW as currently implemented. @@ -65,6 +67,8 @@ class BASE_EXPORT ConvertableToTraceFormat // appended. virtual void AppendAsTraceFormat(std::string* out) const = 0; + virtual void EstimateTraceMemoryOverhead(TraceEventMemoryOverhead* overhead); + std::string ToString() const { std::string result; AppendAsTraceFormat(&result); @@ -117,12 +121,14 @@ class BASE_EXPORT TraceEvent { const unsigned char* arg_types, const unsigned long long* arg_values, const scoped_refptr* convertable_values, - unsigned char flags); + unsigned int flags); void Reset(); void UpdateDuration(const TraceTicks& now, const ThreadTicks& thread_now); + void EstimateTraceMemoryOverhead(TraceEventMemoryOverhead*); + // Serialize event data to JSON typedef base::Callback ArgumentFilterPredicate; @@ -142,7 +148,7 @@ class BASE_EXPORT TraceEvent { TimeDelta duration() const { return duration_; } TimeDelta thread_duration() const { return thread_duration_; } unsigned long long id() const { return id_; } - unsigned char flags() const { return flags_; } + unsigned int flags() const { return flags_; } // Exposed for unittesting: @@ -168,6 +174,7 @@ class BASE_EXPORT TraceEvent { TimeDelta thread_duration_; // id_ can be used to store phase-specific data. unsigned long long id_; + scoped_ptr cached_memory_overhead_estimate_; TraceValue arg_values_[kTraceMaxNumArgs]; const char* arg_names_[kTraceMaxNumArgs]; scoped_refptr convertable_values_[kTraceMaxNumArgs]; @@ -176,7 +183,7 @@ class BASE_EXPORT TraceEvent { scoped_refptr parameter_copy_storage_; int thread_id_; char phase_; - unsigned char flags_; + unsigned int flags_; unsigned char arg_types_[kTraceMaxNumArgs]; DISALLOW_COPY_AND_ASSIGN(TraceEvent); @@ -185,10 +192,8 @@ class BASE_EXPORT TraceEvent { // TraceBufferChunk is the basic unit of TraceBuffer. class BASE_EXPORT TraceBufferChunk { public: - explicit TraceBufferChunk(uint32 seq) - : next_free_(0), - seq_(seq) { - } + explicit TraceBufferChunk(uint32 seq); + ~TraceBufferChunk(); void Reset(uint32 new_seq); TraceEvent* AddTraceEvent(size_t* event_index); @@ -209,10 +214,13 @@ class BASE_EXPORT TraceBufferChunk { scoped_ptr Clone() const; + void EstimateTraceMemoryOverhead(TraceEventMemoryOverhead* overhead); + static const size_t kTraceBufferChunkSize = 64; private: size_t next_free_; + scoped_ptr cached_overhead_estimate_when_full_; TraceEvent chunk_[kTraceBufferChunkSize]; uint32 seq_; }; @@ -235,6 +243,11 @@ class BASE_EXPORT TraceBuffer { virtual const TraceBufferChunk* NextChunk() = 0; virtual scoped_ptr CloneForIteration() const = 0; + + // Computes an estimate of the size of the buffer, including all the retained + // objects. + virtual void EstimateTraceMemoryOverhead( + TraceEventMemoryOverhead* overhead) = 0; }; // TraceResultBuffer collects and converts trace fragments returned by TraceLog @@ -289,7 +302,7 @@ struct BASE_EXPORT TraceLogStatus { size_t event_count; }; -class BASE_EXPORT TraceLog { +class BASE_EXPORT TraceLog : public MemoryDumpProvider { public: enum Mode { DISABLED = 0, @@ -321,6 +334,10 @@ class BASE_EXPORT TraceLog { // Retrieves a copy (for thread-safety) of the current TraceConfig. TraceConfig GetCurrentTraceConfig() const; + // Initializes the thread-local event buffer, if not already initialized and + // if the current thread supports that (has a message loop). + void InitializeThreadLocalEventBufferIfSupported(); + // Enables normal tracing (recording trace events in the trace buffer). // See TraceConfig comments for details on how to control what categories // will be traced. If tracing has already been enabled, |category_filter| will @@ -350,6 +367,8 @@ class BASE_EXPORT TraceLog { // on-demand. class BASE_EXPORT EnabledStateObserver { public: + virtual ~EnabledStateObserver() = default; + // Called just after the tracing system becomes enabled, outside of the // |lock_|. TraceLog::IsEnabled() is true at this point. virtual void OnTraceLogEnabled() = 0; @@ -365,6 +384,10 @@ class BASE_EXPORT TraceLog { TraceLogStatus GetStatus() const; bool BufferIsFull() const; + // Computes an estimate of the size of the TraceLog including all the retained + // objects. + void EstimateTraceMemoryOverhead(TraceEventMemoryOverhead* overhead); + // Not using base::Callback because of its limited by 7 parameters. // Also, using primitive type allows directly passing callback from WebCore. // WARNING: It is possible for the previously set callback to be called @@ -383,7 +406,7 @@ class BASE_EXPORT TraceLog { const char* const arg_names[], const unsigned char arg_types[], const unsigned long long arg_values[], - unsigned char flags); + unsigned int flags); // Enable tracing for EventCallback. void SetEventCallbackEnabled(const TraceConfig& trace_config, @@ -407,6 +430,9 @@ class BASE_EXPORT TraceLog { void Flush(const OutputCallback& cb, bool use_worker_thread = false); void FlushButLeaveBufferIntact(const OutputCallback& flush_output_callback); + // Cancels tracing and discards collected data. + void CancelTracing(const OutputCallback& cb); + // Called by TRACE_EVENT* macros, don't call this directly. // The name parameter is a category group for example: // TRACE_EVENT0("renderer,webkit", "WebViewImpl::HandleInputEvent") @@ -427,7 +453,7 @@ class BASE_EXPORT TraceLog { const unsigned char* arg_types, const unsigned long long* arg_values, const scoped_refptr* convertable_values, - unsigned char flags); + unsigned int flags); TraceEventHandle AddTraceEventWithThreadIdAndTimestamp( char phase, const unsigned char* category_group_enabled, @@ -440,7 +466,7 @@ class BASE_EXPORT TraceLog { const unsigned char* arg_types, const unsigned long long* arg_values, const scoped_refptr* convertable_values, - unsigned char flags); + unsigned int flags); static void AddTraceEventEtw(char phase, const char* category_group, const void* id, @@ -528,6 +554,9 @@ class BASE_EXPORT TraceLog { // by the Singleton class. friend struct DefaultSingletonTraits; + // MemoryDumpProvider implementation. + bool OnMemoryDump(ProcessMemoryDump* pmd) override; + // Enable/disable each category group based on the current mode_, // category_filter_, event_callback_ and event_callback_category_filter_. // Enable the category group in the enabled mode if category_filter_ matches @@ -547,7 +576,7 @@ class BASE_EXPORT TraceLog { class OptionalAutoLock; TraceLog(); - ~TraceLog(); + ~TraceLog() override; const unsigned char* GetCategoryGroupEnabledInternal(const char* name); void AddMetadataEventsWhileLocked(); @@ -572,16 +601,20 @@ class BASE_EXPORT TraceLog { TraceEvent* GetEventByHandleInternal(TraceEventHandle handle, OptionalAutoLock* lock); + void FlushInternal(const OutputCallback& cb, + bool use_worker_thread, + bool discard_events); + // |generation| is used in the following callbacks to check if the callback // is called for the flush of the current |logged_events_|. - void FlushCurrentThread(int generation); + void FlushCurrentThread(int generation, bool discard_events); // Usually it runs on a different thread. static void ConvertTraceEventsToTraceFormat( scoped_ptr logged_events, const TraceLog::OutputCallback& flush_output_callback, const TraceEvent::ArgumentFilterPredicate& argument_filter_predicate); - void FinishFlush(int generation); - void OnFlushTimeout(int generation); + void FinishFlush(int generation, bool discard_events); + void OnFlushTimeout(int generation, bool discard_events); int generation() const { return static_cast(subtle::NoBarrier_Load(&generation_)); diff --git a/base/trace_event/trace_event_memory.cc b/base/trace_event/trace_event_memory.cc index 89595890aec54..73c8536cac2a8 100644 --- a/base/trace_event/trace_event_memory.cc +++ b/base/trace_event/trace_event_memory.cc @@ -11,6 +11,7 @@ #include "base/memory/scoped_ptr.h" #include "base/single_thread_task_runner.h" #include "base/strings/string_number_conversions.h" +#include "base/strings/string_split.h" #include "base/strings/string_util.h" #include "base/threading/thread_local_storage.h" #include "base/trace_event/trace_event.h" @@ -318,9 +319,9 @@ void AppendHeapProfileAsTraceFormat(const char* input, std::string* output) { input_string.assign(input); } - std::vector lines; - size_t line_count = Tokenize(input_string, "\n", &lines); - if (line_count == 0) { + std::vector lines = base::SplitString( + input_string, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY); + if (lines.empty()) { DLOG(WARNING) << "No lines found"; return; } @@ -330,10 +331,8 @@ void AppendHeapProfileAsTraceFormat(const char* input, std::string* output) { AppendHeapProfileTotalsAsTraceFormat(lines[0], output); // Handle the following stack trace lines. - for (size_t i = 1; i < line_count; ++i) { - const std::string& line = lines[i]; - AppendHeapProfileLineAsTraceFormat(line, output); - } + for (size_t i = 1; i < lines.size(); i++) + AppendHeapProfileLineAsTraceFormat(lines[i], output); output->append("]\n"); } @@ -348,8 +347,8 @@ void AppendHeapProfileTotalsAsTraceFormat(const std::string& line, // 55227 = Outstanding bytes (malloc bytes - free bytes) // 14653 = Total allocations (mallocs) // 2624014 = Total bytes (malloc bytes) - std::vector tokens; - Tokenize(line, " :[]@", &tokens); + std::vector tokens = base::SplitString( + line, " :[]@", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY); if (tokens.size() < 4) { DLOG(WARNING) << "Invalid totals line " << line; return; @@ -378,8 +377,8 @@ bool AppendHeapProfileLineAsTraceFormat(const std::string& line, // 0x7fa7fa9b9ba0 0x7fa7f4b3be13 = Stack trace represented as pointers to // static strings from trace event categories // and names. - std::vector tokens; - Tokenize(line, " :[]@", &tokens); + std::vector tokens = base::SplitString( + line, " :[]@", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY); // It's valid to have no stack addresses, so only require 4 tokens. if (tokens.size() < 4) { DLOG(WARNING) << "Invalid line " << line; diff --git a/base/trace_event/trace_event_memory.h b/base/trace_event/trace_event_memory.h index e2b3ae93060ad..5b63db0365c39 100644 --- a/base/trace_event/trace_event_memory.h +++ b/base/trace_event/trace_event_memory.h @@ -43,7 +43,7 @@ class BASE_EXPORT TraceMemoryController HeapProfilerStartFunction heap_profiler_start_function, HeapProfilerStopFunction heap_profiler_stop_function, GetHeapProfileFunction get_heap_profile_function); - virtual ~TraceMemoryController(); + ~TraceMemoryController() override; // base::trace_event::TraceLog::EnabledStateChangedObserver overrides: void OnTraceLogEnabled() override; diff --git a/base/trace_event/trace_event_memory_overhead.cc b/base/trace_event/trace_event_memory_overhead.cc new file mode 100644 index 0000000000000..0cc3d59890c57 --- /dev/null +++ b/base/trace_event/trace_event_memory_overhead.cc @@ -0,0 +1,154 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/trace_event/trace_event_memory_overhead.h" + +#include + +#include "base/memory/ref_counted_memory.h" +#include "base/strings/stringprintf.h" +#include "base/trace_event/memory_allocator_dump.h" +#include "base/trace_event/process_memory_dump.h" +#include "base/values.h" + +namespace { +size_t RoundUp(size_t size, size_t alignment) { + return (size + alignment - 1) & ~(alignment - 1); +} +} // namespace + +namespace base { +namespace trace_event { + +TraceEventMemoryOverhead::TraceEventMemoryOverhead() { +} + +TraceEventMemoryOverhead::~TraceEventMemoryOverhead() { +} + +void TraceEventMemoryOverhead::AddOrCreateInternal( + const char* object_type, + size_t count, + size_t allocated_size_in_bytes, + size_t resident_size_in_bytes) { + auto it = allocated_objects_.find(object_type); + if (it == allocated_objects_.end()) { + allocated_objects_.insert(std::make_pair( + object_type, + ObjectCountAndSize( + {count, allocated_size_in_bytes, resident_size_in_bytes}))); + return; + } + it->second.count += count; + it->second.allocated_size_in_bytes += allocated_size_in_bytes; + it->second.resident_size_in_bytes += resident_size_in_bytes; +} + +void TraceEventMemoryOverhead::Add(const char* object_type, + size_t allocated_size_in_bytes) { + Add(object_type, allocated_size_in_bytes, allocated_size_in_bytes); +} + +void TraceEventMemoryOverhead::Add(const char* object_type, + size_t allocated_size_in_bytes, + size_t resident_size_in_bytes) { + AddOrCreateInternal(object_type, 1, allocated_size_in_bytes, + resident_size_in_bytes); +} + +void TraceEventMemoryOverhead::AddString(const std::string& str) { + // The number below are empirical and mainly based on profiling of real-world + // std::string implementations: + // - even short string end up malloc()-inc at least 32 bytes. + // - longer stings seem to malloc() multiples of 16 bytes. + Add("std::string", + sizeof(std::string) + std::max(RoundUp(str.capacity(), 16), 32u)); +} + +void TraceEventMemoryOverhead::AddRefCountedString( + const RefCountedString& str) { + Add("RefCountedString", sizeof(RefCountedString)); + AddString(str.data()); +} + +void TraceEventMemoryOverhead::AddValue(const Value& value) { + switch (value.GetType()) { + case Value::TYPE_NULL: + case Value::TYPE_BOOLEAN: + case Value::TYPE_INTEGER: + case Value::TYPE_DOUBLE: + Add("FundamentalValue", sizeof(Value)); + break; + + case Value::TYPE_STRING: { + const StringValue* string_value = nullptr; + value.GetAsString(&string_value); + Add("StringValue", sizeof(StringValue)); + AddString(string_value->GetString()); + } break; + + case Value::TYPE_BINARY: { + const BinaryValue* binary_value = nullptr; + value.GetAsBinary(&binary_value); + Add("BinaryValue", sizeof(BinaryValue) + binary_value->GetSize()); + } break; + + case Value::TYPE_DICTIONARY: { + const DictionaryValue* dictionary_value = nullptr; + value.GetAsDictionary(&dictionary_value); + Add("DictionaryValue", sizeof(DictionaryValue)); + for (DictionaryValue::Iterator it(*dictionary_value); !it.IsAtEnd(); + it.Advance()) { + AddString(it.key()); + AddValue(it.value()); + } + } break; + + case Value::TYPE_LIST: { + const ListValue* list_value = nullptr; + value.GetAsList(&list_value); + Add("ListValue", sizeof(ListValue)); + for (const Value* v : *list_value) + AddValue(*v); + } break; + + default: + NOTREACHED(); + } +} + +void TraceEventMemoryOverhead::AddSelf() { + size_t estimated_size = sizeof(*this); + // If the SmallMap did overflow its static capacity, its elements will be + // allocated on the heap and have to be accounted separately. + if (allocated_objects_.UsingFullMap()) + estimated_size += sizeof(map_type::value_type) * allocated_objects_.size(); + Add("TraceEventMemoryOverhead", estimated_size); +} + +void TraceEventMemoryOverhead::Update(const TraceEventMemoryOverhead& other) { + for (const auto& it : other.allocated_objects_) { + AddOrCreateInternal(it.first, it.second.count, + it.second.allocated_size_in_bytes, + it.second.resident_size_in_bytes); + } +} + +void TraceEventMemoryOverhead::DumpInto(const char* base_name, + ProcessMemoryDump* pmd) const { + for (const auto& it : allocated_objects_) { + std::string dump_name = StringPrintf("%s/%s", base_name, it.first); + MemoryAllocatorDump* mad = pmd->CreateAllocatorDump(dump_name); + mad->AddScalar(MemoryAllocatorDump::kNameSize, + MemoryAllocatorDump::kUnitsBytes, + it.second.allocated_size_in_bytes); + mad->AddScalar("resident_size", MemoryAllocatorDump::kUnitsBytes, + it.second.resident_size_in_bytes); + mad->AddScalar(MemoryAllocatorDump::kNameObjectsCount, + MemoryAllocatorDump::kUnitsObjects, it.second.count); + } +} + +} // namespace trace_event +} // namespace base diff --git a/base/trace_event/trace_event_memory_overhead.h b/base/trace_event/trace_event_memory_overhead.h new file mode 100644 index 0000000000000..8ecf12dc969eb --- /dev/null +++ b/base/trace_event/trace_event_memory_overhead.h @@ -0,0 +1,71 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_TRACE_EVENT_TRACE_EVENT_MEMORY_OVERHEAD_H_ +#define BASE_TRACE_EVENT_TRACE_EVENT_MEMORY_OVERHEAD_H_ + +#include "base/base_export.h" +#include "base/containers/hash_tables.h" +#include "base/containers/small_map.h" + +namespace base { + +class RefCountedString; +class Value; + +namespace trace_event { + +class ProcessMemoryDump; + +// Used to estimate the memory overhead of the tracing infrastructure. +class BASE_EXPORT TraceEventMemoryOverhead { + public: + TraceEventMemoryOverhead(); + ~TraceEventMemoryOverhead(); + + // Use this method to account the overhead of an object for which an estimate + // is known for both the allocated and resident memory. + void Add(const char* object_type, + size_t allocated_size_in_bytes, + size_t resident_size_in_bytes); + + // Similar to Add() above, but assumes that + // |resident_size_in_bytes| == |allocated_size_in_bytes|. + void Add(const char* object_type, size_t allocated_size_in_bytes); + + // Specialized profiling functions for commonly used object types. + void AddString(const std::string& str); + void AddValue(const Value& value); + void AddRefCountedString(const RefCountedString& str); + + // Call this after all the Add* methods above to account the memory used by + // this TraceEventMemoryOverhead instance itself. + void AddSelf(); + + // Adds up and merges all the values from |other| to this instance. + void Update(const TraceEventMemoryOverhead& other); + + void DumpInto(const char* base_name, ProcessMemoryDump* pmd) const; + + private: + struct ObjectCountAndSize { + size_t count; + size_t allocated_size_in_bytes; + size_t resident_size_in_bytes; + }; + using map_type = SmallMap, 16>; + map_type allocated_objects_; + + void AddOrCreateInternal(const char* object_type, + size_t count, + size_t allocated_size_in_bytes, + size_t resident_size_in_bytes); + + DISALLOW_COPY_AND_ASSIGN(TraceEventMemoryOverhead); +}; + +} // namespace trace_event +} // namespace base + +#endif // BASE_TRACE_EVENT_TRACE_EVENT_MEMORY_OVERHEAD_H_ diff --git a/base/trace_event/trace_event_system_stats_monitor.h b/base/trace_event/trace_event_system_stats_monitor.h index 051669a35f5ac..7a63a1429e20d 100644 --- a/base/trace_event/trace_event_system_stats_monitor.h +++ b/base/trace_event/trace_event_system_stats_monitor.h @@ -33,7 +33,7 @@ class BASE_EXPORT TraceEventSystemStatsMonitor explicit TraceEventSystemStatsMonitor( scoped_refptr task_runner); - virtual ~TraceEventSystemStatsMonitor(); + ~TraceEventSystemStatsMonitor() override; // base::trace_event::TraceLog::EnabledStateChangedObserver overrides: void OnTraceLogEnabled() override; diff --git a/base/trace_event/trace_event_unittest.cc b/base/trace_event/trace_event_unittest.cc index 2449d54cf63b1..afee8a90df957 100644 --- a/base/trace_event/trace_event_unittest.cc +++ b/base/trace_event/trace_event_unittest.cc @@ -15,6 +15,7 @@ #include "base/memory/singleton.h" #include "base/process/process_handle.h" #include "base/single_thread_task_runner.h" +#include "base/strings/pattern.h" #include "base/strings/stringprintf.h" #include "base/synchronization/waitable_event.h" #include "base/threading/platform_thread.h" @@ -47,6 +48,8 @@ const int kAsyncId = 5; const char kAsyncIdStr[] = "0x5"; const int kAsyncId2 = 6; const char kAsyncId2Str[] = "0x6"; +const int kFlowId = 7; +const char kFlowIdStr[] = "0x7"; const char kRecordAllCategoryFilter[] = "*"; @@ -85,7 +88,14 @@ class TraceEventTestFixture : public testing::Test { TraceLog::RECORDING_MODE); } + void CancelTrace() { + WaitableEvent flush_complete_event(false, false); + CancelTraceAsync(&flush_complete_event); + flush_complete_event.Wait(); + } + void EndTraceAndFlush() { + num_flush_callbacks_ = 0; WaitableEvent flush_complete_event(false, false); EndTraceAndFlushAsync(&flush_complete_event); flush_complete_event.Wait(); @@ -103,6 +113,13 @@ class TraceEventTestFixture : public testing::Test { flush_complete_event.Wait(); } + void CancelTraceAsync(WaitableEvent* flush_complete_event) { + TraceLog::GetInstance()->CancelTracing( + base::Bind(&TraceEventTestFixture::OnTraceDataCollected, + base::Unretained(static_cast(this)), + base::Unretained(flush_complete_event))); + } + void EndTraceAndFlushAsync(WaitableEvent* flush_complete_event) { TraceLog::GetInstance()->SetDisabled(); TraceLog::GetInstance()->Flush( @@ -134,6 +151,7 @@ class TraceEventTestFixture : public testing::Test { ASSERT_FALSE(tracelog->IsEnabled()); trace_buffer_.SetOutputCallback(json_output_.GetCallback()); event_watch_notification_ = 0; + num_flush_callbacks_ = 0; } void TearDown() override { if (TraceLog::GetInstance()) @@ -150,6 +168,7 @@ class TraceEventTestFixture : public testing::Test { TraceResultBuffer trace_buffer_; TraceResultBuffer::SimpleOutput json_output_; int event_watch_notification_; + size_t num_flush_callbacks_; private: // We want our singleton torn down after each test. @@ -161,6 +180,10 @@ void TraceEventTestFixture::OnTraceDataCollected( WaitableEvent* flush_complete_event, const scoped_refptr& events_str, bool has_more_events) { + num_flush_callbacks_++; + if (num_flush_callbacks_ > 1) { + EXPECT_FALSE(events_str->data().empty()); + } AutoLock lock(lock_); json_output_.json_output.clear(); trace_buffer_.Start(); @@ -430,6 +453,12 @@ void TraceWithAllMacroVariants(WaitableEvent* task_complete_event) { "name1", "value1", "name2", "value2"); + TRACE_EVENT_FLOW_BEGIN0("all", "TRACE_EVENT_FLOW_BEGIN0 call", kFlowId); + TRACE_EVENT_FLOW_STEP0("all", "TRACE_EVENT_FLOW_STEP0 call", + kFlowId, "step1"); + TRACE_EVENT_FLOW_END_BIND_TO_ENCLOSING0("all", + "TRACE_EVENT_FLOW_END_BIND_TO_ENCLOSING0 call", kFlowId); + TRACE_EVENT_BEGIN_ETW("TRACE_EVENT_BEGIN_ETW0 call", kAsyncId, NULL); TRACE_EVENT_BEGIN_ETW("TRACE_EVENT_BEGIN_ETW1 call", kAsyncId, "value"); TRACE_EVENT_END_ETW("TRACE_EVENT_END_ETW0 call", kAsyncId, NULL); @@ -613,6 +642,17 @@ void ValidateAllTraceMacrosCreatedData(const ListValue& trace_parsed) { EXPECT_SUB_FIND_("name2"); EXPECT_SUB_FIND_("value2"); + EXPECT_FIND_("TRACE_EVENT_FLOW_BEGIN0 call"); + EXPECT_SUB_FIND_("id"); + EXPECT_SUB_FIND_(kFlowIdStr); + EXPECT_FIND_("TRACE_EVENT_FLOW_STEP0 call"); + EXPECT_SUB_FIND_("id"); + EXPECT_SUB_FIND_(kFlowIdStr); + EXPECT_SUB_FIND_("step1"); + EXPECT_FIND_("TRACE_EVENT_FLOW_END_BIND_TO_ENCLOSING0 call"); + EXPECT_SUB_FIND_("id"); + EXPECT_SUB_FIND_(kFlowIdStr); + EXPECT_FIND_("TRACE_EVENT_BEGIN_ETW0 call"); EXPECT_SUB_FIND_("id"); EXPECT_SUB_FIND_(kAsyncIdStr); @@ -882,6 +922,19 @@ TEST_F(TraceEventTestFixture, DataCaptured) { ValidateAllTraceMacrosCreatedData(trace_parsed_); } +// Emit some events and validate that only empty strings are received +// if we tell Flush() to discard events. +TEST_F(TraceEventTestFixture, DataDiscarded) { + TraceLog::GetInstance()->SetEnabled(TraceConfig(kRecordAllCategoryFilter, ""), + TraceLog::RECORDING_MODE); + + TraceWithAllMacroVariants(NULL); + + CancelTrace(); + + EXPECT_TRUE(trace_parsed_.empty()); +} + class MockEnabledStateChangedObserver : public TraceLog::EnabledStateObserver { public: @@ -968,7 +1021,7 @@ class AfterStateChangeEnabledStateObserver : public TraceLog::EnabledStateObserver { public: AfterStateChangeEnabledStateObserver() {} - virtual ~AfterStateChangeEnabledStateObserver() {} + ~AfterStateChangeEnabledStateObserver() override {} // TraceLog::EnabledStateObserver overrides: void OnTraceLogEnabled() override { @@ -999,7 +1052,7 @@ class SelfRemovingEnabledStateObserver : public TraceLog::EnabledStateObserver { public: SelfRemovingEnabledStateObserver() {} - virtual ~SelfRemovingEnabledStateObserver() {} + ~SelfRemovingEnabledStateObserver() override {} // TraceLog::EnabledStateObserver overrides: void OnTraceLogEnabled() override {} @@ -1052,6 +1105,43 @@ TEST_F(TraceEventTestFixture, NewTraceRecording) { EndTraceAndFlush(); } +TEST_F(TraceEventTestFixture, TestTraceFlush) { + size_t min_traces = 1; + size_t max_traces = 1; + do { + max_traces *= 2; + TraceLog::GetInstance()->SetEnabled(TraceConfig(), + TraceLog::RECORDING_MODE); + for (size_t i = 0; i < max_traces; i++) { + TRACE_EVENT_INSTANT0("x", "y", TRACE_EVENT_SCOPE_THREAD); + } + EndTraceAndFlush(); + } while (num_flush_callbacks_ < 2); + + while (min_traces + 50 < max_traces) { + size_t traces = (min_traces + max_traces) / 2; + TraceLog::GetInstance()->SetEnabled(TraceConfig(), + TraceLog::RECORDING_MODE); + for (size_t i = 0; i < traces; i++) { + TRACE_EVENT_INSTANT0("x", "y", TRACE_EVENT_SCOPE_THREAD); + } + EndTraceAndFlush(); + if (num_flush_callbacks_ < 2) { + min_traces = traces - 10; + } else { + max_traces = traces + 10; + } + } + + for (size_t traces = min_traces; traces < max_traces; traces++) { + TraceLog::GetInstance()->SetEnabled(TraceConfig(), + TraceLog::RECORDING_MODE); + for (size_t i = 0; i < traces; i++) { + TRACE_EVENT_INSTANT0("x", "y", TRACE_EVENT_SCOPE_THREAD); + } + EndTraceAndFlush(); + } +} // Test that categories work. TEST_F(TraceEventTestFixture, Categories) { @@ -2149,8 +2239,8 @@ namespace { bool IsTraceEventArgsWhitelisted(const char* category_group_name, const char* event_name) { - if (MatchPattern(category_group_name, "toplevel") && - MatchPattern(event_name, "*")) { + if (base::MatchPattern(category_group_name, "toplevel") && + base::MatchPattern(event_name, "*")) { return true; } @@ -2187,7 +2277,10 @@ TEST_F(TraceEventTestFixture, ArgsWhitelisting) { dict->GetDictionary("args", &args_dict); ASSERT_TRUE(args_dict); EXPECT_FALSE(args_dict->GetInteger("int_two", &int_value)); - EXPECT_TRUE(args_dict->GetInteger("stripped", &int_value)); + + std::string args_string; + EXPECT_TRUE(dict->GetString("args", &args_string)); + EXPECT_EQ(args_string, "__stripped__"); } class TraceEventCallbackTest : public TraceEventTestFixture { @@ -2247,7 +2340,7 @@ class TraceEventCallbackTest : public TraceEventTestFixture { const char* const arg_names[], const unsigned char arg_types[], const unsigned long long arg_values[], - unsigned char flags) { + unsigned int flags) { s_instance->collected_events_phases_.push_back(phase); s_instance->collected_events_categories_.push_back( TraceLog::GetCategoryGroupName(category_group_enabled)); diff --git a/base/trace_event/trace_event_win.cc b/base/trace_event/trace_event_win.cc index ebb55c844923d..fdbd35a0e2fed 100644 --- a/base/trace_event/trace_event_win.cc +++ b/base/trace_event/trace_event_win.cc @@ -16,16 +16,24 @@ using base::win::EtwMofEvent; // {3DADA31D-19EF-4dc1-B345-037927193422} const GUID kChromeTraceProviderName = { - 0x3dada31d, 0x19ef, 0x4dc1, 0xb3, 0x45, 0x3, 0x79, 0x27, 0x19, 0x34, 0x22 }; + 0x3dada31d, + 0x19ef, + 0x4dc1, + {0xb3, 0x45, 0x3, 0x79, 0x27, 0x19, 0x34, 0x22}}; // {B967AE67-BB22-49d7-9406-55D91EE1D560} const GUID kTraceEventClass32 = { - 0xb967ae67, 0xbb22, 0x49d7, 0x94, 0x6, 0x55, 0xd9, 0x1e, 0xe1, 0xd5, 0x60 }; + 0xb967ae67, + 0xbb22, + 0x49d7, + {0x94, 0x6, 0x55, 0xd9, 0x1e, 0xe1, 0xd5, 0x60}}; // {97BE602D-2930-4ac3-8046-B6763B631DFE} const GUID kTraceEventClass64 = { - 0x97be602d, 0x2930, 0x4ac3, 0x80, 0x46, 0xb6, 0x76, 0x3b, 0x63, 0x1d, 0xfe}; - + 0x97be602d, + 0x2930, + 0x4ac3, + {0x80, 0x46, 0xb6, 0x76, 0x3b, 0x63, 0x1d, 0xfe}}; TraceEventETWProvider::TraceEventETWProvider() : EtwTraceProvider(kChromeTraceProviderName) { diff --git a/base/trace_event/winheap_dump_provider_win.cc b/base/trace_event/winheap_dump_provider_win.cc index 82bb01646f9f9..c8921f445a685 100644 --- a/base/trace_event/winheap_dump_provider_win.cc +++ b/base/trace_event/winheap_dump_provider_win.cc @@ -6,6 +6,7 @@ #include +#include "base/debug/profiler.h" #include "base/trace_event/process_memory_dump.h" #include "base/win/windows_version.h" @@ -59,6 +60,13 @@ bool WinHeapDumpProvider::OnMemoryDump(ProcessMemoryDump* pmd) { if (base::win::GetVersion() < base::win::VERSION_VISTA) return false; + // Disable this dump provider for the SyzyASan instrumented build + // because they don't support the heap walking functions yet. +#if defined(SYZYASAN) + if (base::debug::IsBinaryInstrumented()) + return false; +#endif + // Retrieves the number of heaps in the current process. DWORD number_of_heaps = ::GetProcessHeaps(0, NULL); WinHeapInfo all_heap_info = {0}; diff --git a/base/values.cc b/base/values.cc index 4534d27dff59a..c829a7f2f884f 100644 --- a/base/values.cc +++ b/base/values.cc @@ -482,27 +482,30 @@ void DictionaryValue::SetStringWithoutPathExpansion( SetWithoutPathExpansion(path, new StringValue(in_value)); } -bool DictionaryValue::Get(const std::string& path, +bool DictionaryValue::Get(StringPiece path, const Value** out_value) const { DCHECK(IsStringUTF8(path)); - std::string current_path(path); + StringPiece current_path(path); const DictionaryValue* current_dictionary = this; for (size_t delimiter_position = current_path.find('.'); delimiter_position != std::string::npos; delimiter_position = current_path.find('.')) { const DictionaryValue* child_dictionary = NULL; - if (!current_dictionary->GetDictionary( - current_path.substr(0, delimiter_position), &child_dictionary)) + if (!current_dictionary->GetDictionaryWithoutPathExpansion( + current_path.substr(0, delimiter_position).as_string(), + &child_dictionary)) { return false; + } current_dictionary = child_dictionary; - current_path.erase(0, delimiter_position + 1); + current_path = current_path.substr(delimiter_position + 1); } - return current_dictionary->GetWithoutPathExpansion(current_path, out_value); + return current_dictionary->GetWithoutPathExpansion(current_path.as_string(), + out_value); } -bool DictionaryValue::Get(const std::string& path, Value** out_value) { +bool DictionaryValue::Get(StringPiece path, Value** out_value) { return static_cast(*this).Get( path, const_cast(out_value)); @@ -588,7 +591,7 @@ bool DictionaryValue::GetBinary(const std::string& path, const_cast(out_value)); } -bool DictionaryValue::GetDictionary(const std::string& path, +bool DictionaryValue::GetDictionary(StringPiece path, const DictionaryValue** out_value) const { const Value* value; bool result = Get(path, &value); @@ -601,7 +604,7 @@ bool DictionaryValue::GetDictionary(const std::string& path, return true; } -bool DictionaryValue::GetDictionary(const std::string& path, +bool DictionaryValue::GetDictionary(StringPiece path, DictionaryValue** out_value) { return static_cast(*this).GetDictionary( path, diff --git a/base/values.h b/base/values.h index 7feef9da541b0..8756debdbdf76 100644 --- a/base/values.h +++ b/base/values.h @@ -30,6 +30,7 @@ #include "base/compiler_specific.h" #include "base/memory/scoped_ptr.h" #include "base/strings/string16.h" +#include "base/strings/string_piece.h" namespace base { @@ -270,8 +271,8 @@ class BASE_EXPORT DictionaryValue : public Value { // Otherwise, it will return false and |out_value| will be untouched. // Note that the dictionary always owns the value that's returned. // |out_value| is optional and will only be set if non-NULL. - bool Get(const std::string& path, const Value** out_value) const; - bool Get(const std::string& path, Value** out_value); + bool Get(StringPiece path, const Value** out_value) const; + bool Get(StringPiece path, Value** out_value); // These are convenience forms of Get(). The value will be retrieved // and the return value will be true if the path is valid and the value at @@ -287,9 +288,9 @@ class BASE_EXPORT DictionaryValue : public Value { bool GetStringASCII(const std::string& path, std::string* out_value) const; bool GetBinary(const std::string& path, const BinaryValue** out_value) const; bool GetBinary(const std::string& path, BinaryValue** out_value); - bool GetDictionary(const std::string& path, + bool GetDictionary(StringPiece path, const DictionaryValue** out_value) const; - bool GetDictionary(const std::string& path, DictionaryValue** out_value); + bool GetDictionary(StringPiece path, DictionaryValue** out_value); bool GetList(const std::string& path, const ListValue** out_value) const; bool GetList(const std::string& path, ListValue** out_value); diff --git a/base/version.cc b/base/version.cc index ede8a4586eb9b..228dcb8aef20e 100644 --- a/base/version.cc +++ b/base/version.cc @@ -24,15 +24,17 @@ namespace { // parsed successfully, false otherwise. bool ParseVersionNumbers(const std::string& version_str, std::vector* parsed) { - std::vector numbers; - SplitString(version_str, '.', &numbers); + std::vector numbers = + SplitStringPiece(version_str, ".", KEEP_WHITESPACE, SPLIT_WANT_ALL); if (numbers.empty()) return false; - for (std::vector::const_iterator it = numbers.begin(); - it != numbers.end(); ++it) { - if (StartsWithASCII(*it, "+", false)) + for (auto it = numbers.begin(); it != numbers.end(); ++it) { + if (StartsWith(*it, "+", CompareCase::SENSITIVE)) return false; + + // TODO(brettw) when we have a StringPiece version of StringToUint, delete + // this string conversion. unsigned int num; if (!StringToUint(*it, &num)) return false; @@ -98,8 +100,8 @@ bool Version::IsValid() const { // static bool Version::IsValidWildcardString(const std::string& wildcard_string) { std::string version_string = wildcard_string; - if (EndsWith(wildcard_string.c_str(), ".*", false)) - version_string = wildcard_string.substr(0, wildcard_string.size() - 2); + if (EndsWith(version_string, ".*", CompareCase::SENSITIVE)) + version_string.resize(version_string.size() - 2); Version version(version_string); return version.IsValid(); @@ -117,7 +119,7 @@ int Version::CompareToWildcardString(const std::string& wildcard_string) const { DCHECK(Version::IsValidWildcardString(wildcard_string)); // Default behavior if the string doesn't end with a wildcard. - if (!EndsWith(wildcard_string.c_str(), ".*", false)) { + if (!EndsWith(wildcard_string, ".*", CompareCase::SENSITIVE)) { Version version(wildcard_string); DCHECK(version.IsValid()); return CompareTo(version); diff --git a/base/win/iat_patch_function.cc b/base/win/iat_patch_function.cc index 13acd65ee4d06..31659c6c82dc8 100644 --- a/base/win/iat_patch_function.cc +++ b/base/win/iat_patch_function.cc @@ -219,9 +219,9 @@ DWORD ModifyCode(void* old_code, void* new_code, int length) { IATPatchFunction::IATPatchFunction() : module_handle_(NULL), + intercept_function_(NULL), original_function_(NULL), - iat_thunk_(NULL), - intercept_function_(NULL) { + iat_thunk_(NULL) { } IATPatchFunction::~IATPatchFunction() { diff --git a/base/win/scoped_comptr.h b/base/win/scoped_comptr.h index 373c0c3ba5098..ade12fe549abb 100644 --- a/base/win/scoped_comptr.h +++ b/base/win/scoped_comptr.h @@ -52,24 +52,24 @@ class ScopedComPtr : public scoped_refptr { // Note that this function equates to IUnknown::Release and should not // be confused with e.g. scoped_ptr::release(). void Release() { - if (ptr_ != NULL) { - ptr_->Release(); - ptr_ = NULL; + if (this->ptr_ != NULL) { + this->ptr_->Release(); + this->ptr_ = NULL; } } // Sets the internal pointer to NULL and returns the held object without // releasing the reference. Interface* Detach() { - Interface* p = ptr_; - ptr_ = NULL; + Interface* p = this->ptr_; + this->ptr_ = NULL; return p; } // Accepts an interface pointer that has already been addref-ed. void Attach(Interface* p) { - DCHECK(!ptr_); - ptr_ = p; + DCHECK(!this->ptr_); + this->ptr_ = p; } // Retrieves the pointer address. @@ -77,8 +77,8 @@ class ScopedComPtr : public scoped_refptr { // The function DCHECKs on the current value being NULL. // Usage: Foo(p.Receive()); Interface** Receive() { - DCHECK(!ptr_) << "Object leak. Pointer must be NULL"; - return &ptr_; + DCHECK(!this->ptr_) << "Object leak. Pointer must be NULL"; + return &this->ptr_; } // A convenience for whenever a void pointer is needed as an out argument. @@ -89,18 +89,18 @@ class ScopedComPtr : public scoped_refptr { template HRESULT QueryInterface(Query** p) { DCHECK(p != NULL); - DCHECK(ptr_ != NULL); + DCHECK(this->ptr_ != NULL); // IUnknown already has a template version of QueryInterface // so the iid parameter is implicit here. The only thing this // function adds are the DCHECKs. - return ptr_->QueryInterface(p); + return this->ptr_->QueryInterface(p); } // QI for times when the IID is not associated with the type. HRESULT QueryInterface(const IID& iid, void** obj) { DCHECK(obj != NULL); - DCHECK(ptr_ != NULL); - return ptr_->QueryInterface(iid, obj); + DCHECK(this->ptr_ != NULL); + return this->ptr_->QueryInterface(iid, obj); } // Queries |other| for the interface this object wraps and returns the @@ -113,18 +113,18 @@ class ScopedComPtr : public scoped_refptr { // Convenience wrapper around CoCreateInstance HRESULT CreateInstance(const CLSID& clsid, IUnknown* outer = NULL, DWORD context = CLSCTX_ALL) { - DCHECK(!ptr_); + DCHECK(!this->ptr_); HRESULT hr = ::CoCreateInstance(clsid, outer, context, *interface_id, - reinterpret_cast(&ptr_)); + reinterpret_cast(&this->ptr_)); return hr; } // Checks if the identity of |other| and this object is the same. bool IsSameObject(IUnknown* other) { - if (!other && !ptr_) + if (!other && !this->ptr_) return true; - if (!other || !ptr_) + if (!other || !this->ptr_) return false; ScopedComPtr my_identity; @@ -147,8 +147,8 @@ class ScopedComPtr : public scoped_refptr { // by statically casting the ScopedComPtr instance to the wrapped interface // and then making the call... but generally that shouldn't be necessary. BlockIUnknownMethods* operator->() const { - DCHECK(ptr_ != NULL); - return reinterpret_cast(ptr_); + DCHECK(this->ptr_ != NULL); + return reinterpret_cast(this->ptr_); } // Pull in operator=() from the parent class. diff --git a/base/win/scoped_comptr_unittest.cc b/base/win/scoped_comptr_unittest.cc index d38752dfb9fed..23090b043664d 100644 --- a/base/win/scoped_comptr_unittest.cc +++ b/base/win/scoped_comptr_unittest.cc @@ -25,8 +25,10 @@ struct Dummy { }; extern const IID dummy_iid; -const IID dummy_iid = { 0x12345678u, 0x1234u, 0x5678u, 01, 23, 45, 67, 89, - 01, 23, 45 }; +const IID dummy_iid = {0x12345678u, + 0x1234u, + 0x5678u, + {01, 23, 45, 67, 89, 01, 23, 45}}; } // namespace diff --git a/base/win/scoped_variant.cc b/base/win/scoped_variant.cc index f57ab93f6c667..2cf265740d8b5 100644 --- a/base/win/scoped_variant.cc +++ b/base/win/scoped_variant.cc @@ -9,7 +9,7 @@ namespace base { namespace win { // Global, const instance of an empty variant. -const VARIANT ScopedVariant::kEmptyVariant = { VT_EMPTY }; +const VARIANT ScopedVariant::kEmptyVariant = {{{VT_EMPTY}}}; ScopedVariant::~ScopedVariant() { COMPILE_ASSERT(sizeof(ScopedVariant) == sizeof(VARIANT), ScopedVariantSize); @@ -82,7 +82,7 @@ VARIANT* ScopedVariant::Receive() { } VARIANT ScopedVariant::Copy() const { - VARIANT ret = { VT_EMPTY }; + VARIANT ret = {{{VT_EMPTY}}}; ::VariantCopy(&ret, &var_); return ret; } diff --git a/base/win/shortcut.cc b/base/win/shortcut.cc index f8b2182b28664..57f8e615d1dc5 100644 --- a/base/win/shortcut.cc +++ b/base/win/shortcut.cc @@ -5,13 +5,18 @@ #include "base/win/shortcut.h" #include +#include #include #include #include "base/files/file_util.h" +#include "base/strings/string_util.h" #include "base/threading/thread_restrictions.h" +#include "base/win/scoped_bstr.h" #include "base/win/scoped_comptr.h" +#include "base/win/scoped_handle.h" #include "base/win/scoped_propvariant.h" +#include "base/win/scoped_variant.h" #include "base/win/win_util.h" #include "base/win/windows_version.h" @@ -20,6 +25,90 @@ namespace win { namespace { +// String resource IDs in shell32.dll. +const uint32_t kPinToTaskbarID = 5386; +const uint32_t kUnpinFromTaskbarID = 5387; + +// Traits for a GenericScopedHandle that will free a module on closure. +struct ModuleTraits { + typedef HMODULE Handle; + static Handle NullHandle() { return nullptr; } + static bool IsHandleValid(Handle module) { return !!module; } + static bool CloseHandle(Handle module) { return !!::FreeLibrary(module); } + + private: + DISALLOW_IMPLICIT_CONSTRUCTORS(ModuleTraits); +}; + +// An object that will free a module when it goes out of scope. +using ScopedLibrary = GenericScopedHandle; + +// Returns the shell resource string identified by |resource_id|, or an empty +// string on error. +string16 LoadShellResourceString(uint32_t resource_id) { + ScopedLibrary shell32(::LoadLibrary(L"shell32.dll")); + if (!shell32.IsValid()) + return string16(); + + const wchar_t* resource_ptr = nullptr; + int length = ::LoadStringW(shell32.Get(), resource_id, + reinterpret_cast(&resource_ptr), 0); + if (!length || !resource_ptr) + return string16(); + return string16(resource_ptr, length); +} + +// Uses the shell to perform the verb identified by |resource_id| on |path|. +bool DoVerbOnFile(uint32_t resource_id, const FilePath& path) { + string16 verb_name(LoadShellResourceString(resource_id)); + if (verb_name.empty()) + return false; + + ScopedComPtr shell_dispatch; + HRESULT hresult = + shell_dispatch.CreateInstance(CLSID_Shell, nullptr, CLSCTX_INPROC_SERVER); + if (FAILED(hresult) || !shell_dispatch.get()) + return false; + + ScopedComPtr folder; + hresult = shell_dispatch->NameSpace( + ScopedVariant(path.DirName().value().c_str()), folder.Receive()); + if (FAILED(hresult) || !folder.get()) + return false; + + ScopedComPtr item; + hresult = folder->ParseName(ScopedBstr(path.BaseName().value().c_str()), + item.Receive()); + if (FAILED(hresult) || !item.get()) + return false; + + ScopedComPtr verbs; + hresult = item->Verbs(verbs.Receive()); + if (FAILED(hresult) || !verbs.get()) + return false; + + long verb_count = 0; + hresult = verbs->get_Count(&verb_count); + if (FAILED(hresult)) + return false; + + for (long i = 0; i < verb_count; ++i) { + ScopedComPtr verb; + hresult = verbs->Item(ScopedVariant(i, VT_I4), verb.Receive()); + if (FAILED(hresult) || !verb.get()) + continue; + ScopedBstr name; + hresult = verb->get_Name(name.Receive()); + if (FAILED(hresult)) + continue; + if (StringPiece16(name, name.Length()) == verb_name) { + hresult = verb->DoIt(); + return SUCCEEDED(hresult); + } + } + return false; +} + // Initializes |i_shell_link| and |i_persist_file| (releasing them first if they // are already initialized). // If |shortcut| is not NULL, loads |shortcut| into |i_persist_file|. @@ -314,28 +403,24 @@ bool ResolveShortcut(const FilePath& shortcut_path, return true; } -bool TaskbarPinShortcutLink(const wchar_t* shortcut) { +bool TaskbarPinShortcutLink(const FilePath& shortcut) { base::ThreadRestrictions::AssertIOAllowed(); // "Pin to taskbar" is only supported after Win7. if (GetVersion() < VERSION_WIN7) return false; - intptr_t result = reinterpret_cast( - ShellExecute(NULL, L"taskbarpin", shortcut, NULL, NULL, 0)); - return result > 32; + return DoVerbOnFile(kPinToTaskbarID, shortcut); } -bool TaskbarUnpinShortcutLink(const wchar_t* shortcut) { +bool TaskbarUnpinShortcutLink(const FilePath& shortcut) { base::ThreadRestrictions::AssertIOAllowed(); // "Unpin from taskbar" is only supported after Win7. if (GetVersion() < VERSION_WIN7) return false; - intptr_t result = reinterpret_cast( - ShellExecute(NULL, L"taskbarunpin", shortcut, NULL, NULL, 0)); - return result > 32; + return DoVerbOnFile(kUnpinFromTaskbarID, shortcut); } } // namespace win diff --git a/base/win/shortcut.h b/base/win/shortcut.h index 6f7d10c8ee715..6c85f0151d8fa 100644 --- a/base/win/shortcut.h +++ b/base/win/shortcut.h @@ -155,12 +155,12 @@ BASE_EXPORT bool ResolveShortcut(const FilePath& shortcut_path, // Pins a shortcut to the Windows 7 taskbar. The shortcut file must already // exist and be a shortcut that points to an executable. The app id of the // shortcut is used to group windows and must be set correctly. -BASE_EXPORT bool TaskbarPinShortcutLink(const wchar_t* shortcut); +BASE_EXPORT bool TaskbarPinShortcutLink(const FilePath& shortcut); // Unpins a shortcut from the Windows 7 taskbar. The shortcut must exist and // already be pinned to the taskbar. The app id of the shortcut is used as the // identifier for the taskbar item to remove and must be set correctly. -BASE_EXPORT bool TaskbarUnpinShortcutLink(const wchar_t* shortcut); +BASE_EXPORT bool TaskbarUnpinShortcutLink(const FilePath& shortcut); } // namespace win } // namespace base diff --git a/base/win/win_util.cc b/base/win/win_util.cc index c5b06c48f8a10..96d646ad31f92 100644 --- a/base/win/win_util.cc +++ b/base/win/win_util.cc @@ -19,11 +19,14 @@ #include #include +#include "base/base_switches.h" +#include "base/command_line.h" #include "base/lazy_instance.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" +#include "base/strings/utf_string_conversions.h" #include "base/threading/thread_restrictions.h" #include "base/win/metro.h" #include "base/win/registry.h" @@ -32,13 +35,16 @@ #include "base/win/scoped_propvariant.h" #include "base/win/windows_version.h" +namespace base { +namespace win { + namespace { // Sets the value of |property_key| to |property_value| in |property_store|. bool SetPropVariantValueForPropertyStore( IPropertyStore* property_store, const PROPERTYKEY& property_key, - const base::win::ScopedPropVariant& property_value) { + const ScopedPropVariant& property_value) { DCHECK(property_store); HRESULT result = property_store->SetValue(property_key, property_value.get()); @@ -48,31 +54,56 @@ bool SetPropVariantValueForPropertyStore( } void __cdecl ForceCrashOnSigAbort(int) { - *((int*)0) = 0x1337; + *((volatile int*)0) = 0x1337; } const wchar_t kWindows8OSKRegPath[] = L"Software\\Classes\\CLSID\\{054AAE20-4BEA-4347-8A35-64A533254A9D}" L"\\LocalServer32"; +} // namespace + // Returns true if a physical keyboard is detected on Windows 8 and up. // Uses the Setup APIs to enumerate the attached keyboards and returns true // if the keyboard count is 1 or more.. While this will work in most cases // it won't work if there are devices which expose keyboard interfaces which // are attached to the machine. -bool IsKeyboardPresentOnSlate() { +bool IsKeyboardPresentOnSlate(std::string* reason) { + bool result = false; + + if (GetVersion() < VERSION_WIN7) { + *reason = "Detection not supported"; + return false; + } + // This function is only supported for Windows 8 and up. - DCHECK(base::win::GetVersion() >= base::win::VERSION_WIN8); + if (CommandLine::ForCurrentProcess()->HasSwitch( + switches::kDisableUsbKeyboardDetect)) { + if (reason) + *reason = "Detection disabled"; + return false; + } // This function should be only invoked for machines with touch screens. if ((GetSystemMetrics(SM_DIGITIZER) & NID_INTEGRATED_TOUCH) != NID_INTEGRATED_TOUCH) { - return true; + if (reason) { + *reason += "NID_INTEGRATED_TOUCH\n"; + result = true; + } else { + return true; + } } // If the device is docked, the user is treating the device as a PC. - if (GetSystemMetrics(SM_SYSTEMDOCKED) != 0) - return true; + if (GetSystemMetrics(SM_SYSTEMDOCKED) != 0) { + if (reason) { + *reason += "SM_SYSTEMDOCKED\n"; + result = true; + } else { + return true; + } + } // To determine whether a keyboard is present on the device, we do the // following:- @@ -103,7 +134,13 @@ bool IsKeyboardPresentOnSlate() { // If there is no auto rotation sensor or rotation is not supported in // the current configuration, then we can assume that this is a desktop // or a traditional laptop. - return true; + if (reason) { + *reason += (auto_rotation_state & AR_NOSENSOR) ? "AR_NOSENSOR\n" : + "AR_NOT_SUPPORTED\n"; + result = true; + } else { + return true; + } } } @@ -114,8 +151,15 @@ bool IsKeyboardPresentOnSlate() { POWER_PLATFORM_ROLE role = PowerDeterminePlatformRole(); if (((role == PlatformRoleMobile) || (role == PlatformRoleSlate)) && - (GetSystemMetrics(SM_CONVERTIBLESLATEMODE) == 0)) - return false; + (GetSystemMetrics(SM_CONVERTIBLESLATEMODE) == 0)) { + if (reason) { + *reason += (role == PlatformRoleMobile) ? "PlatformRoleMobile\n" : + "PlatformRoleSlate\n"; + // Don't change result here if it's already true. + } else { + return false; + } + } const GUID KEYBOARD_CLASS_GUID = { 0x4D36E96B, 0xE325, 0x11CE, @@ -124,13 +168,15 @@ bool IsKeyboardPresentOnSlate() { // Query for all the keyboard devices. HDEVINFO device_info = SetupDiGetClassDevs(&KEYBOARD_CLASS_GUID, NULL, NULL, DIGCF_PRESENT); - if (device_info == INVALID_HANDLE_VALUE) - return false; + if (device_info == INVALID_HANDLE_VALUE) { + if (reason) + *reason += "No keyboard info\n"; + return result; + } // Enumerate all keyboards and look for ACPI\PNP and HID\VID devices. If // the count is more than 1 we assume that a keyboard is present. This is // under the assumption that there will always be one keyboard device. - int keyboard_count = 0; for (DWORD i = 0;; ++i) { SP_DEVINFO_DATA device_info_data = { 0 }; device_info_data.cbSize = sizeof(device_info_data); @@ -146,23 +192,24 @@ bool IsKeyboardPresentOnSlate() { if (status == CR_SUCCESS) { // To reduce the scope of the hack we only look for ACPI and HID\\VID // prefixes in the keyboard device ids. - if (StartsWith(device_id, L"ACPI", false) || - StartsWith(device_id, L"HID\\VID", false)) { - keyboard_count++; + if (StartsWith(device_id, L"ACPI", CompareCase::INSENSITIVE_ASCII) || + StartsWith(device_id, L"HID\\VID", CompareCase::INSENSITIVE_ASCII)) { + if (reason) { + *reason += "device: "; + *reason += WideToUTF8(device_id); + *reason += '\n'; + } + // The heuristic we are using is to check the count of keyboards and + // return true if the API's report one or more keyboards. Please note + // that this will break for non keyboard devices which expose a + // keyboard PDO. + result = true; } } } - // The heuristic we are using is to check the count of keyboards and return - // true if the API's report one or more keyboards. Please note that this - // will break for non keyboard devices which expose a keyboard PDO. - return keyboard_count >= 1; + return result; } -} // namespace - -namespace base { -namespace win { - static bool g_crash_on_process_detach = false; void GetNonClientMetrics(NONCLIENTMETRICS_XP* metrics) { @@ -181,7 +228,7 @@ bool GetUserSidString(std::wstring* user_sid) { HANDLE token = NULL; if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY, &token)) return false; - base::win::ScopedHandle token_scoped(token); + ScopedHandle token_scoped(token); DWORD size = sizeof(TOKEN_USER) + SECURITY_MAX_SID_SIZE; scoped_ptr user_bytes(new BYTE[size]); @@ -226,11 +273,11 @@ bool UserAccountControlIsEnabled() { // This can be slow if Windows ends up going to disk. Should watch this key // for changes and only read it once, preferably on the file thread. // http://code.google.com/p/chromium/issues/detail?id=61644 - base::ThreadRestrictions::ScopedAllowIO allow_io; + ThreadRestrictions::ScopedAllowIO allow_io; - base::win::RegKey key(HKEY_LOCAL_MACHINE, - L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System", - KEY_READ); + RegKey key(HKEY_LOCAL_MACHINE, + L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System", + KEY_READ); DWORD uac_enabled; if (key.ReadValueDW(L"EnableLUA", &uac_enabled) != ERROR_SUCCESS) return true; @@ -284,20 +331,20 @@ static const char16 kAutoRunKeyPath[] = bool AddCommandToAutoRun(HKEY root_key, const string16& name, const string16& command) { - base::win::RegKey autorun_key(root_key, kAutoRunKeyPath, KEY_SET_VALUE); + RegKey autorun_key(root_key, kAutoRunKeyPath, KEY_SET_VALUE); return (autorun_key.WriteValue(name.c_str(), command.c_str()) == ERROR_SUCCESS); } bool RemoveCommandFromAutoRun(HKEY root_key, const string16& name) { - base::win::RegKey autorun_key(root_key, kAutoRunKeyPath, KEY_SET_VALUE); + RegKey autorun_key(root_key, kAutoRunKeyPath, KEY_SET_VALUE); return (autorun_key.DeleteValue(name.c_str()) == ERROR_SUCCESS); } bool ReadCommandFromAutoRun(HKEY root_key, const string16& name, string16* command) { - base::win::RegKey autorun_key(root_key, kAutoRunKeyPath, KEY_QUERY_VALUE); + RegKey autorun_key(root_key, kAutoRunKeyPath, KEY_QUERY_VALUE); return (autorun_key.ReadValue(name.c_str(), command) == ERROR_SUCCESS); } @@ -326,8 +373,8 @@ bool IsTabletDevice() { if (GetSystemMetrics(SM_MAXIMUMTOUCHES) == 0) return false; - base::win::Version version = base::win::GetVersion(); - if (version == base::win::VERSION_XP) + Version version = GetVersion(); + if (version == VERSION_XP) return (GetSystemMetrics(SM_TABLETPC) != 0); // If the device is docked, the user is treating the device as a PC. @@ -339,7 +386,7 @@ bool IsTabletDevice() { POWER_PLATFORM_ROLE role = PowerDeterminePlatformRole(); bool mobile_power_profile = (role == PlatformRoleMobile); bool slate_power_profile = false; - if (version >= base::win::VERSION_WIN8) + if (version >= VERSION_WIN8) slate_power_profile = (role == PlatformRoleSlate); if (mobile_power_profile || slate_power_profile) @@ -349,14 +396,13 @@ bool IsTabletDevice() { } bool DisplayVirtualKeyboard() { - if (base::win::GetVersion() < base::win::VERSION_WIN8) + if (GetVersion() < VERSION_WIN8) return false; - if (IsKeyboardPresentOnSlate()) + if (IsKeyboardPresentOnSlate(nullptr)) return false; - static base::LazyInstance::Leaky osk_path = - LAZY_INSTANCE_INITIALIZER; + static LazyInstance::Leaky osk_path = LAZY_INSTANCE_INITIALIZER; if (osk_path.Get().empty()) { // We need to launch TabTip.exe from the location specified under the @@ -367,9 +413,8 @@ bool DisplayVirtualKeyboard() { // We don't want to launch TabTip.exe from // c:\program files (x86)\common files\microsoft shared\ink. This path is // normally found on 64 bit Windows. - base::win::RegKey key(HKEY_LOCAL_MACHINE, - kWindows8OSKRegPath, - KEY_READ | KEY_WOW64_64KEY); + RegKey key(HKEY_LOCAL_MACHINE, kWindows8OSKRegPath, + KEY_READ | KEY_WOW64_64KEY); DWORD osk_path_length = 1024; if (key.ReadValue(NULL, WriteInto(&osk_path.Get(), osk_path_length), @@ -410,7 +455,7 @@ bool DisplayVirtualKeyboard() { common_program_files_path = common_program_files_wow6432.get(); DCHECK(!common_program_files_path.empty()); } else { - base::win::ScopedCoMem common_program_files; + ScopedCoMem common_program_files; if (FAILED(SHGetKnownFolderPath(FOLDERID_ProgramFilesCommon, 0, NULL, &common_program_files))) { return false; @@ -432,7 +477,7 @@ bool DisplayVirtualKeyboard() { } bool DismissVirtualKeyboard() { - if (base::win::GetVersion() < base::win::VERSION_WIN8) + if (GetVersion() < VERSION_WIN8) return false; // We dismiss the virtual keyboard by generating the ESC keystroke @@ -474,21 +519,21 @@ void SetDomainStateForTesting(bool state) { } bool MaybeHasSHA256Support() { - const base::win::OSInfo* os_info = base::win::OSInfo::GetInstance(); + const OSInfo* os_info = OSInfo::GetInstance(); - if (os_info->version() == base::win::VERSION_PRE_XP) + if (os_info->version() == VERSION_PRE_XP) return false; // Too old to have it and this OS is not supported anyway. - if (os_info->version() == base::win::VERSION_XP) + if (os_info->version() == VERSION_XP) return os_info->service_pack().major >= 3; // Windows XP SP3 has it. // Assume it is missing in this case, although it may not be. This category // includes Windows XP x64, and Windows Server, where a hotfix could be // deployed. - if (os_info->version() == base::win::VERSION_SERVER_2003) + if (os_info->version() == VERSION_SERVER_2003) return false; - DCHECK(os_info->version() >= base::win::VERSION_VISTA); + DCHECK(os_info->version() >= VERSION_VISTA); return true; // New enough to have SHA-256 support. } diff --git a/base/win/win_util.h b/base/win/win_util.h index 8513f62bf1915..9f42e445748f3 100644 --- a/base/win/win_util.h +++ b/base/win/win_util.h @@ -132,6 +132,11 @@ BASE_EXPORT void SetAbortBehaviorForCrashReporting(); // insight into how users use Chrome. BASE_EXPORT bool IsTabletDevice(); +// A slate is a touch device that may have a keyboard attached. This function +// returns true if a keyboard is attached and optionally will set the reason +// parameter to the detection method that was used to detect the keyboard. +BASE_EXPORT bool IsKeyboardPresentOnSlate(std::string* reason); + // Get the size of a struct up to and including the specified member. // This is necessary to set compatible struct sizes for different versions // of certain Windows APIs (e.g. SystemParametersInfo). diff --git a/base/win/windows_version.cc b/base/win/windows_version.cc index fc2def39194e3..35cdbb3538ad6 100644 --- a/base/win/windows_version.cc +++ b/base/win/windows_version.cc @@ -73,7 +73,7 @@ OSInfo::OSInfo() service_pack_.major = version_info.wServicePackMajor; service_pack_.minor = version_info.wServicePackMinor; - SYSTEM_INFO system_info = { 0 }; + SYSTEM_INFO system_info = {}; ::GetNativeSystemInfo(&system_info); switch (system_info.wProcessorArchitecture) { case PROCESSOR_ARCHITECTURE_INTEL: architecture_ = X86_ARCHITECTURE; break; diff --git a/build/all.gyp b/build/all.gyp index 6b8ad831a4355..b36fae6a575d2 100644 --- a/build/all.gyp +++ b/build/all.gyp @@ -86,16 +86,15 @@ '../android_webview/android_webview.gyp:android_webview_apk', '../android_webview/android_webview.gyp:system_webview_apk', '../android_webview/android_webview_shell.gyp:android_webview_shell_apk', - '../android_webview/android_webview_telemetry_shell.gyp:android_webview_telemetry_shell_apk', '../chrome/android/chrome_apk.gyp:chrome_public_apk', '../chrome/chrome.gyp:chrome_shell_apk', '../chrome/chrome.gyp:chrome_sync_shell_apk', '../remoting/remoting.gyp:remoting_apk', ], }], - ['target_arch == "arm" or target_arch == "arm64"', { + # TODO: Enable packed relocations for x64. See: b/20532404 + ['target_arch != "x64"', { 'dependencies': [ - # The relocation packer is currently used only for ARM or ARM64. '../third_party/android_platform/relocation_packer.gyp:android_relocation_packer_unittests#host', ], }], @@ -161,6 +160,7 @@ 'dependencies': [ '../device/bluetooth/bluetooth.gyp:*', '../device/device_tests.gyp:*', + '../gpu/skia_runner/skia_runner.gyp:*', ], }], ['use_openssl==0 and (OS=="mac" or OS=="ios" or OS=="win")', { @@ -379,6 +379,7 @@ 'dependencies': [ '../chrome/chrome.gyp:crash_service', '../chrome/chrome.gyp:installer_util_unittests', + '../chrome/chrome.gyp:setup_unittests', # ../chrome/test/mini_installer requires mini_installer. '../chrome/installer/mini_installer.gyp:mini_installer', '../chrome_elf/chrome_elf.gyp:chrome_elf_unittests', @@ -809,7 +810,6 @@ '../breakpad/breakpad.gyp:symupload#host', '../breakpad/breakpad.gyp:minidump_dump#host', '../breakpad/breakpad.gyp:minidump_stackwalk#host', - '../build/android/tests/multiple_proguards/multiple_proguards.gyp:multiple_proguards_test_apk', '../build/android/pylib/device/commands/commands.gyp:chromium_commands', '../cc/blink/cc_blink_tests.gyp:cc_blink_unittests', '../cc/cc_tests.gyp:cc_perftests_apk', @@ -887,6 +887,7 @@ '../chrome/chrome.gyp:chrome_shell_uiautomator_tests', '../chrome/chrome.gyp:chromedriver_webview_shell_apk', '../chrome/chrome.gyp:unit_tests_apk', + '../third_party/custom_tabs_client/src/custom_tabs_client.gyp:custom_tabs_client_example_apk', ], }], ], @@ -1070,6 +1071,7 @@ '../chrome/chrome.gyp:installer_util_unittests', '../chrome/chrome.gyp:interactive_ui_tests', '../chrome/chrome.gyp:performance_browser_tests', + '../chrome/chrome.gyp:setup_unittests', '../chrome/chrome.gyp:sync_integration_tests', '../chrome/chrome.gyp:unit_tests', '../cloud_print/cloud_print.gyp:cloud_print_unittests', @@ -1162,6 +1164,7 @@ '../chrome/chrome.gyp:chrome_app_unittests', '../chrome/chrome.gyp:chromedriver_unittests', '../chrome/chrome.gyp:installer_util_unittests', + '../chrome/chrome.gyp:setup_unittests', '../chrome/chrome.gyp:unit_tests', '../chrome_elf/chrome_elf.gyp:chrome_elf_unittests', '../cloud_print/cloud_print.gyp:cloud_print_unittests', @@ -1272,6 +1275,36 @@ }], # branding=="Chrome" ], # conditions }], # OS="win" + ['chromeos==1', { + 'targets': [ + { + 'target_name': 'chromiumos_preflight', + 'type': 'none', + 'dependencies': [ + '../breakpad/breakpad.gyp:minidump_stackwalk', + '../chrome/chrome.gyp:chrome', + '../chrome/chrome.gyp:chromedriver', + '../content/content_shell_and_tests.gyp:video_decode_accelerator_unittest', + '../content/content_shell_and_tests.gyp:video_encode_accelerator_unittest', + '../media/media.gyp:media_unittests', + '../ppapi/ppapi_internal.gyp:ppapi_example_video_decode', + '../sandbox/sandbox.gyp:chrome_sandbox', + '../sandbox/sandbox.gyp:sandbox_linux_unittests', + '../third_party/mesa/mesa.gyp:osmesa', + '../tools/telemetry/telemetry.gyp:bitmaptools#host', + '../tools/perf/clear_system_cache/clear_system_cache.gyp:clear_system_cache', + ], + 'conditions': [ + ['disable_nacl==0', { + 'dependencies': [ + '../components/nacl.gyp:nacl_helper', + '../native_client/src/trusted/service_runtime/linux/nacl_bootstrap.gyp:nacl_helper_bootstrap', + ], + }], + ], + }, + ], # targets + }], # "chromeos==1" ['use_aura==1', { 'targets': [ { @@ -1387,7 +1420,7 @@ 'target_name': 'chromoting_swarm_tests', 'type': 'none', 'dependencies': [ - '../testing/chromoting/integration_tests.gyp:chromoting_integration_tests_run', + '../testing/chromoting/integration_tests.gyp:*', ], }, # target_name: chromoting_swarm_tests ] diff --git a/build/android/BUILD.gn b/build/android/BUILD.gn new file mode 100644 index 0000000000000..d90ad70abe643 --- /dev/null +++ b/build/android/BUILD.gn @@ -0,0 +1,56 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/android/rules.gni") + +sun_tools_jar_path = "$root_gen_dir/sun_tools_jar/tools.jar" + +action("find_sun_tools_jar") { + script = "//build/android/gyp/find_sun_tools_jar.py" + depfile = "$target_gen_dir/$target_name.d" + outputs = [ + depfile, + sun_tools_jar_path, + ] + args = [ + "--depfile", + rebase_path(depfile, root_build_dir), + "--output", + rebase_path(sun_tools_jar_path, root_build_dir), + ] +} + +java_prebuilt("sun_tools_java") { + jar_path = sun_tools_jar_path + jar_dep = ":find_sun_tools_jar" +} + +action("cpplib_stripped") { + _strip_bin = "${android_tool_prefix}strip" + _soname = "libc++_shared.so" + _input_so = "${android_libcpp_root}/libs/${android_app_abi}/${_soname}" + _output_so = "${root_out_dir}/lib.stripped/${_soname}" + + script = "//build/gn_run_binary.py" + inputs = [ + _strip_bin, + ] + sources = [ + _input_so, + ] + outputs = [ + _output_so, + ] + + _rebased_strip_bin = rebase_path(_strip_bin, root_out_dir) + _rebased_input_so = rebase_path(_input_so, root_out_dir) + _rebased_output_so = rebase_path(_output_so, root_out_dir) + args = [ + _rebased_strip_bin, + "--strip-unneeded", + "-o", + _rebased_output_so, + _rebased_input_so, + ] +} diff --git a/build/android/adb_install_apk.py b/build/android/adb_install_apk.py index 00bd38e1821d7..50faea7d29110 100755 --- a/build/android/adb_install_apk.py +++ b/build/android/adb_install_apk.py @@ -6,84 +6,109 @@ """Utility script to install APKs from the command line quickly.""" -import optparse +import argparse +import glob +import logging import os import sys from pylib import constants +from pylib.device import device_blacklist from pylib.device import device_errors from pylib.device import device_utils - - -def AddInstallAPKOption(option_parser): - """Adds apk option used to install the APK to the OptionParser.""" - option_parser.add_option('--apk', - help=('DEPRECATED The name of the apk containing the' - ' application (with the .apk extension).')) - option_parser.add_option('--apk_package', - help=('DEPRECATED The package name used by the apk ' - 'containing the application.')) - option_parser.add_option('--keep_data', - action='store_true', - default=False, - help=('Keep the package data when installing ' - 'the application.')) - option_parser.add_option('--debug', action='store_const', const='Debug', - dest='build_type', - default=os.environ.get('BUILDTYPE', 'Debug'), - help='If set, run test suites under out/Debug. ' +from pylib.utils import apk_helper +from pylib.utils import run_tests_helper + + +def main(): + parser = argparse.ArgumentParser() + + apk_group = parser.add_mutually_exclusive_group(required=True) + apk_group.add_argument('--apk', dest='apk_name', + help='DEPRECATED The name of the apk containing the' + ' application (with the .apk extension).') + apk_group.add_argument('apk_path', nargs='?', + help='The path to the APK to install.') + + # TODO(jbudorick): Remove once no clients pass --apk_package + parser.add_argument('--apk_package', help='DEPRECATED unused') + parser.add_argument('--split', + action='append', + dest='splits', + help='A glob matching the apk splits. ' + 'Can be specified multiple times.') + parser.add_argument('--keep_data', + action='store_true', + default=False, + help='Keep the package data when installing ' + 'the application.') + parser.add_argument('--debug', action='store_const', const='Debug', + dest='build_type', + default=os.environ.get('BUILDTYPE', 'Debug'), + help='If set, run test suites under out/Debug. ' 'Default is env var BUILDTYPE or Debug') - option_parser.add_option('--release', action='store_const', const='Release', - dest='build_type', - help='If set, run test suites under out/Release. ' + parser.add_argument('--release', action='store_const', const='Release', + dest='build_type', + help='If set, run test suites under out/Release. ' 'Default is env var BUILDTYPE or Debug.') - option_parser.add_option('-d', '--device', dest='device', - help='Target device for apk to install on.') - - -def ValidateInstallAPKOption(option_parser, options, args): - """Validates the apk option and potentially qualifies the path.""" - if not options.apk: - if len(args) > 1: - options.apk = args[1] - else: - option_parser.error('apk target not specified.') - - if not options.apk.endswith('.apk'): - options.apk += '.apk' - - if not os.path.exists(options.apk): - options.apk = os.path.join(constants.GetOutDirectory(), 'apks', - options.apk) - - -def main(argv): - parser = optparse.OptionParser() - parser.set_usage("usage: %prog [options] target") - AddInstallAPKOption(parser) - options, args = parser.parse_args(argv) - - if len(args) > 1 and options.apk: - parser.error("Appending the apk as argument can't be used with --apk.") - elif len(args) > 2: - parser.error("Too many arguments.") - - constants.SetBuildType(options.build_type) - ValidateInstallAPKOption(parser, options, args) + parser.add_argument('-d', '--device', dest='device', + help='Target device for apk to install on.') + parser.add_argument('-v', '--verbose', action='count', + help='Enable verbose logging.') + + args = parser.parse_args() + + run_tests_helper.SetLogLevel(args.verbose) + constants.SetBuildType(args.build_type) + + apk = args.apk_path or args.apk_name + if not apk.endswith('.apk'): + apk += '.apk' + if not os.path.exists(apk): + apk = os.path.join(constants.GetOutDirectory(), 'apks', apk) + if not os.path.exists(apk): + parser.error('%s not found.' % apk) + + if args.splits: + splits = [] + base_apk_package = apk_helper.ApkHelper(apk).GetPackageName() + for split_glob in args.splits: + apks = [f for f in glob.glob(split_glob) if f.endswith('.apk')] + if not apks: + logging.warning('No apks matched for %s.' % split_glob) + for f in apks: + helper = apk_helper.ApkHelper(f) + if (helper.GetPackageName() == base_apk_package + and helper.GetSplitName()): + splits.append(f) devices = device_utils.DeviceUtils.HealthyDevices() - if options.device: - devices = [d for d in devices if d == options.device] + if args.device: + devices = [d for d in devices if d == args.device] if not devices: - raise device_errors.DeviceUnreachableError(options.device) + raise device_errors.DeviceUnreachableError(args.device) elif not devices: raise device_errors.NoDevicesError() - device_utils.DeviceUtils.parallel(devices).Install( - options.apk, reinstall=options.keep_data) + def blacklisting_install(device): + try: + if args.splits: + device.InstallSplitApk(apk, splits, reinstall=args.keep_data) + else: + device.Install(apk, reinstall=args.keep_data) + except device_errors.CommandFailedError: + logging.exception('Failed to install %s', args.apk_name) + device_blacklist.ExtendBlacklist([str(device)]) + logging.warning('Blacklisting %s', str(device)) + except device_errors.CommandTimeoutError: + logging.exception('Timed out while installing %s', args.apk_name) + device_blacklist.ExtendBlacklist([str(device)]) + logging.warning('Blacklisting %s', str(device)) + + device_utils.DeviceUtils.parallel(devices).pMap(blacklisting_install) if __name__ == '__main__': - sys.exit(main(sys.argv)) + sys.exit(main()) diff --git a/build/android/dex_action.gypi b/build/android/dex_action.gypi index 9ea3e714d9b28..56d386ffad1e7 100644 --- a/build/android/dex_action.gypi +++ b/build/android/dex_action.gypi @@ -48,6 +48,7 @@ 'python', '<(DEPTH)/build/android/gyp/dex.py', '--dex-path=<(output_path)', '--android-sdk-tools=<(android_sdk_tools)', + '--output-directory=<(PRODUCT_DIR)', '--configuration-name=<(CONFIGURATION_NAME)', '--proguard-enabled=>(proguard_enabled)', '--proguard-enabled-input-path=<(proguard_enabled_input_path)', diff --git a/build/android/finalize_splits_action.gypi b/build/android/finalize_splits_action.gypi index 0d0fe88b7fbc2..daa7f834ebb08 100644 --- a/build/android/finalize_splits_action.gypi +++ b/build/android/finalize_splits_action.gypi @@ -18,7 +18,7 @@ 'keystore_password%': 'chromium', 'zipalign_path%': '<(android_sdk_tools)/zipalign', 'density_splits%': 0, - 'language_splits%': 0, + 'language_splits%': [], 'resource_packaged_apk_name': '<(apk_name)-resources.ap_', 'resource_packaged_apk_path': '<(intermediate_dir)/<(resource_packaged_apk_name)', 'base_output_path': '<(PRODUCT_DIR)/apks/<(apk_name)', @@ -42,27 +42,33 @@ ['density_splits == 1', { 'message': 'Signing/aligning <(_target_name) density splits', 'inputs': [ - '<(resource_packaged_apk_path)-hdpi', - '<(resource_packaged_apk_path)-xhdpi', - '<(resource_packaged_apk_path)-xxhdpi', - '<(resource_packaged_apk_path)-tvdpi', + '<(resource_packaged_apk_path)_hdpi', + '<(resource_packaged_apk_path)_xhdpi', + '<(resource_packaged_apk_path)_xxhdpi', + '<(resource_packaged_apk_path)_xxxhdpi', + '<(resource_packaged_apk_path)_tvdpi', ], 'outputs': [ '<(base_output_path)-density-hdpi.apk', '<(base_output_path)-density-xhdpi.apk', '<(base_output_path)-density-xxhdpi.apk', + '<(base_output_path)-density-xxxhdpi.apk', '<(base_output_path)-density-tvdpi.apk', ], 'action': [ - '--densities=hdpi,xhdpi,xxhdpi,tvdpi', + '--densities=hdpi,xhdpi,xxhdpi,xxxhdpi,tvdpi', ], }], - # TODO(agrieve): Implement language splits - ['language_splits == 1', { + ['language_splits != []', { 'message': 'Signing/aligning <(_target_name) language splits', 'inputs': [ + "> sys.stderr, msg - return 1 if can_fail_build else 0 + return 1 return 0 @@ -198,7 +197,7 @@ def main(): options.processed_config_path, options.manifest_path, options.result_path, options.product_dir, sources, options.jar_path, - options.resource_dir, options.can_fail_build) + options.resource_dir) if options.depfile: build_utils.WriteDepfile( @@ -208,7 +207,7 @@ def main(): if options.stamp and not rc: build_utils.Touch(options.stamp) - return rc + return rc if options.can_fail_build else 0 if __name__ == '__main__': diff --git a/build/android/gyp/locale_pak_resources.py b/build/android/gyp/locale_pak_resources.py new file mode 100755 index 0000000000000..84c4a37ba9254 --- /dev/null +++ b/build/android/gyp/locale_pak_resources.py @@ -0,0 +1,126 @@ +#!/usr/bin/env python +# +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +"""Creates a resources.zip for locale .pak files. + +Places the locale.pak files into appropriate resource configs +(e.g. en-GB.pak -> res/raw-en/en_gb.lpak). Also generates a locale_paks +TypedArray so that resource files can be enumerated at runtime. +""" + +import collections +import optparse +import os +import sys +import zipfile + +from util import build_utils + + +# This should stay in sync with: +# base/android/java/src/org/chromium/base/LocaleUtils.java +_CHROME_TO_ANDROID_LOCALE_MAP = { + 'he': 'iw', + 'id': 'in', + 'fil': 'tl', +} + + +def ToResourceFileName(name): + """Returns the resource-compatible file name for the given file.""" + # Resources file names must consist of [a-z0-9_.]. + # Changes extension to .lpak so that compression can be toggled separately for + # locale pak files vs other pak files. + return name.replace('-', '_').replace('.pak', '.lpak').lower() + + +def CreateLocalePaksXml(names): + """Creates the contents for the locale-paks.xml files.""" + VALUES_FILE_TEMPLATE = ''' + + %s + + +''' + VALUES_ITEM_TEMPLATE = ''' + @raw/%s''' + + res_names = (os.path.splitext(name)[0] for name in names) + items = ''.join((VALUES_ITEM_TEMPLATE % name for name in res_names)) + return VALUES_FILE_TEMPLATE % items + + +def ComputeMappings(sources): + """Computes the mappings of sources -> resources. + + Returns a tuple of: + - mappings: List of (src, dest) paths + - lang_to_locale_map: Map of language -> list of resource names + e.g. "en" -> ["en_gb.lpak"] + """ + lang_to_locale_map = collections.defaultdict(list) + mappings = [] + for src_path in sources: + basename = os.path.basename(src_path) + name = os.path.splitext(basename)[0] + res_name = ToResourceFileName(basename) + if name == 'en-US': + dest_dir = 'raw' + else: + # Chrome's uses different region mapping logic from Android, so include + # all regions for each language. + android_locale = _CHROME_TO_ANDROID_LOCALE_MAP.get(name, name) + lang = android_locale[0:2] + dest_dir = 'raw-' + lang + lang_to_locale_map[lang].append(res_name) + mappings.append((src_path, os.path.join(dest_dir, res_name))) + return mappings, lang_to_locale_map + + +def main(): + parser = optparse.OptionParser() + build_utils.AddDepfileOption(parser) + parser.add_option('--locale-paks', help='List of files for res/raw-LOCALE') + parser.add_option('--resources-zip', help='Path to output resources.zip') + parser.add_option('--print-languages', + action='store_true', + help='Print out the list of languages that cover the given locale paks ' + '(using Android\'s language codes)') + + options, _ = parser.parse_args() + build_utils.CheckOptions(options, parser, + required=['locale_paks']) + + sources = build_utils.ParseGypList(options.locale_paks) + + if options.depfile: + deps = sources + build_utils.GetPythonDependencies() + build_utils.WriteDepfile(options.depfile, deps) + + mappings, lang_to_locale_map = ComputeMappings(sources) + if options.print_languages: + print '\n'.join(sorted(lang_to_locale_map)) + + if options.resources_zip: + with zipfile.ZipFile(options.resources_zip, 'w', zipfile.ZIP_STORED) as out: + for mapping in mappings: + out.write(mapping[0], mapping[1]) + + # Create TypedArray resources so ResourceExtractor can enumerate files. + def WriteValuesFile(lang, names): + dest_dir = 'values' + if lang: + dest_dir += '-' + lang + # Always extract en-US.lpak since it's the fallback. + xml = CreateLocalePaksXml(names + ['en_us.lpak']) + out.writestr(os.path.join(dest_dir, 'locale-paks.xml'), xml) + + for lang, names in lang_to_locale_map.iteritems(): + WriteValuesFile(lang, names) + WriteValuesFile(None, []) + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/build/android/gyp/pack_arm_relocations.py b/build/android/gyp/pack_relocations.py similarity index 100% rename from build/android/gyp/pack_arm_relocations.py rename to build/android/gyp/pack_relocations.py diff --git a/build/android/gyp/package_resources.py b/build/android/gyp/package_resources.py index f2c2a6ed9ee63..d17d1fe2f95b9 100755 --- a/build/android/gyp/package_resources.py +++ b/build/android/gyp/package_resources.py @@ -15,6 +15,7 @@ import optparse import os +import re import shutil import zipfile @@ -54,6 +55,14 @@ 'ldrtl-sw600dp-xxhdpi-v17', 'xxhdpi-v21', ), + 'xxxhdpi': ( + 'xxxhdpi-v4', + 'ldrtl-xxxhdpi-v4', + 'sw600dp-xxxhdpi-v13', + 'ldrtl-xxxhdpi-v17', + 'ldrtl-sw600dp-xxxhdpi-v17', + 'xxxhdpi-v21', + ), 'tvdpi': ( 'tvdpi-v4', 'sw600dp-tvdpi-v13', @@ -95,6 +104,8 @@ def ParseArgs(): '--create-density-splits', action='store_true', help='Enables density splits') + parser.add_option('--language-splits', + help='GYP list of languages to create splits for') parser.add_option('--apk-path', help='Path to output (partial) apk.') @@ -165,23 +176,28 @@ def RenameDensitySplits(apk_path): """Renames all density splits to have shorter / predictable names.""" for density, config in DENSITY_SPLITS.iteritems(): src_path = '%s_%s' % (apk_path, '_'.join(config)) - dst_path = '%s-%s' % (apk_path, density) - if os.path.exists(dst_path): - os.unlink(dst_path) - os.rename(src_path, dst_path) - - -def CheckDensityMissedConfigs(apk_path): - """Raises an exception if apk_path contains any density-specifc files.""" - triggers = ['-%s' % density for density in DENSITY_SPLITS] + dst_path = '%s_%s' % (apk_path, density) + if src_path != dst_path: + if os.path.exists(dst_path): + os.unlink(dst_path) + os.rename(src_path, dst_path) + + +def CheckForMissedConfigs(apk_path, check_density, languages): + """Raises an exception if apk_path contains any unexpected configs.""" + triggers = [] + if check_density: + triggers.extend(re.compile('-%s' % density) for density in DENSITY_SPLITS) + if languages: + triggers.extend(re.compile(r'-%s\b' % lang) for lang in languages) with zipfile.ZipFile(apk_path) as main_apk_zip: for name in main_apk_zip.namelist(): for trigger in triggers: - if trigger in name and not 'mipmap-' in name: - raise Exception(('Found density in main apk that should have been ' + + if trigger.search(name) and not 'mipmap-' in name: + raise Exception(('Found config in main apk that should have been ' + 'put into a split: %s\nYou need to update ' + 'package_resources.py to include this new ' + - 'config.') % name) + 'config (trigger=%s)') % (name, trigger.pattern)) def main(): @@ -225,14 +241,23 @@ def main(): for config in DENSITY_SPLITS.itervalues(): package_command.extend(('--split', ','.join(config))) + language_splits = None + if options.language_splits: + language_splits = build_utils.ParseGypList(options.language_splits) + for lang in language_splits: + package_command.extend(('--split', lang)) + if 'Debug' in options.configuration_name: package_command += ['--debug-mode'] build_utils.CheckOutput( package_command, print_stdout=False, print_stderr=False) + if options.create_density_splits or language_splits: + CheckForMissedConfigs( + options.apk_path, options.create_density_splits, language_splits) + if options.create_density_splits: - CheckDensityMissedConfigs(options.apk_path) RenameDensitySplits(options.apk_path) if options.depfile: diff --git a/build/android/gyp/util/build_device.py b/build/android/gyp/util/build_device.py index 7e0d57ba388a8..8ab11124f7446 100644 --- a/build/android/gyp/util/build_device.py +++ b/build/android/gyp/util/build_device.py @@ -42,6 +42,9 @@ def GetSerialNumber(self): def Install(self, *args, **kwargs): return self.device.Install(*args, **kwargs) + def InstallSplitApk(self, *args, **kwargs): + return self.device.InstallSplitApk(*args, **kwargs) + def GetInstallMetadata(self, apk_package): """Gets the metadata on the device for the apk_package apk.""" # Matches lines like: diff --git a/build/android/gyp/write_build_config.py b/build/android/gyp/write_build_config.py index 8507a95d0b982..3773e98bc70be 100755 --- a/build/android/gyp/write_build_config.py +++ b/build/android/gyp/write_build_config.py @@ -181,7 +181,8 @@ def main(argv): possible_deps_config_paths = build_utils.ParseGypList( options.possible_deps_configs) - allow_unknown_deps = options.type == 'android_apk' + allow_unknown_deps = (options.type == 'android_apk' or + options.type == 'android_resources') unknown_deps = [ c for c in possible_deps_config_paths if not os.path.exists(c)] if unknown_deps and not allow_unknown_deps: diff --git a/build/android/gyp/write_ordered_libraries.py b/build/android/gyp/write_ordered_libraries.py index 67e7805cd2bdd..0fc9a8ca3ef2d 100755 --- a/build/android/gyp/write_ordered_libraries.py +++ b/build/android/gyp/write_ordered_libraries.py @@ -73,7 +73,7 @@ def GetDependencies(library_or_executable): def GetNonSystemDependencies(library_name): - all_deps = GetDependencies(FullLibraryPath(library_name)) + all_deps = GetDependencies(library_name) return set((lib for lib in all_deps if not IsSystemLibrary(lib))) @@ -119,8 +119,13 @@ def main(): java_libraries_list = ( '{%s}' % ','.join(['"%s"' % s[3:-3] for s in libraries])) + out_json = { + 'libraries': libraries, + 'lib_paths': [FullLibraryPath(l) for l in libraries], + 'java_libraries_list': java_libraries_list + } build_utils.WriteJson( - {'libraries': libraries, 'java_libraries_list': java_libraries_list}, + out_json, options.output, only_if_changed=True) diff --git a/build/android/lint/suppressions.xml b/build/android/lint/suppressions.xml index 6921695e6a398..e44faef7f62a3 100644 --- a/build/android/lint/suppressions.xml +++ b/build/android/lint/suppressions.xml @@ -51,11 +51,16 @@ Still reading? + - + + + + + @@ -72,6 +77,7 @@ Still reading? + @@ -87,11 +93,13 @@ Still reading? - - + + + + + + + diff --git a/build/android/lint_action.gypi b/build/android/lint_action.gypi index e0421303f0852..e1adf1f842c30 100644 --- a/build/android/lint_action.gypi +++ b/build/android/lint_action.gypi @@ -36,6 +36,7 @@ '--product-dir=<(PRODUCT_DIR)', '--src-dirs=>(src_dirs)', '--jar-path=<(lint_jar_path)', + '--can-fail-build', '--stamp=<(stamp_path)', '<(is_enabled)', ], diff --git a/build/android/locale_pak_resources.gypi b/build/android/locale_pak_resources.gypi new file mode 100644 index 0000000000000..6f8e56f8f15c2 --- /dev/null +++ b/build/android/locale_pak_resources.gypi @@ -0,0 +1,52 @@ +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Creates a resources.zip with locale.pak files placed into appropriate +# resource configs (e.g. en-GB.pak -> res/raw-en/en_gb.pak). Also generates +# a locale_paks TypedArray so that resource files can be enumerated at runtime. +# +# If this target is included in the deps of an android resources/library/apk, +# the resources will be included with that target. +# +# Variables: +# locale_pak_files - List of .pak files to process. +# Names must be of the form "en.pak" or "en-US.pak". +# +# Example +# { +# 'target_name': 'my_locale_resources', +# 'type': 'none', +# 'variables': { +# 'locale_paks_files': ['path1/fr.pak'], +# }, +# 'includes': [ '../build/android/locale_pak_resources.gypi' ], +# }, +# +{ + 'variables': { + 'resources_zip_path': '<(PRODUCT_DIR)/res.java/<(_target_name).zip', + }, + 'all_dependent_settings': { + 'variables': { + 'additional_input_paths': ['<(resources_zip_path)'], + 'dependencies_res_zip_paths': ['<(resources_zip_path)'], + }, + }, + 'actions': [{ + 'action_name': '<(_target_name)_locale_pak_resources', + 'inputs': [ + '<(DEPTH)/build/android/gyp/util/build_utils.py', + '<(DEPTH)/build/android/gyp/locale_pak_resources.py', + '<@(locale_pak_files)', + ], + 'outputs': [ + '<(resources_zip_path)', + ], + 'action': [ + 'python', '<(DEPTH)/build/android/gyp/locale_pak_resources.py', + '--locale-paks', '<(locale_pak_files)', + '--resources-zip', '<(resources_zip_path)', + ], + }], +} diff --git a/build/android/method_count.py b/build/android/method_count.py new file mode 100755 index 0000000000000..93250b5c542fb --- /dev/null +++ b/build/android/method_count.py @@ -0,0 +1,55 @@ +#! /usr/bin/env python +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import argparse +import os +import re +import sys + +from pylib import constants +from pylib.sdk import dexdump + +sys.path.append(os.path.join(constants.DIR_SOURCE_ROOT, 'build', 'util', 'lib', + 'common')) +import perf_tests_results_helper + + +_METHOD_IDS_SIZE_RE = re.compile(r'^method_ids_size +: +(\d+)$') + +def MethodCount(dexfile): + for line in dexdump.DexDump(dexfile, file_summary=True): + m = _METHOD_IDS_SIZE_RE.match(line) + if m: + return m.group(1) + raise Exception('"method_ids_size" not found in dex dump of %s' % dexfile) + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument( + '--apk-name', help='Name of the APK to which the dexfile corresponds.') + parser.add_argument('dexfile') + + args = parser.parse_args() + + if not args.apk_name: + dirname, basename = os.path.split(args.dexfile) + while basename: + if 'apk' in basename: + args.apk_name = basename + break + dirname, basename = os.path.split(dirname) + else: + parser.error( + 'Unable to determine apk name from %s, ' + 'and --apk-name was not provided.' % args.dexfile) + + method_count = MethodCount(args.dexfile) + perf_tests_results_helper.PrintPerfResult( + '%s_methods' % args.apk_name, 'total', [method_count], 'methods') + return 0 + +if __name__ == '__main__': + sys.exit(main()) + diff --git a/build/android/pack_arm_relocations.gypi b/build/android/pack_relocations.gypi similarity index 89% rename from build/android/pack_arm_relocations.gypi rename to build/android/pack_relocations.gypi index 2c801576838ba..8567fa6e45f18 100644 --- a/build/android/pack_arm_relocations.gypi +++ b/build/android/pack_relocations.gypi @@ -7,7 +7,7 @@ # # To use this, create a gyp target with the following form: # { -# 'action_name': 'pack_arm_relocations', +# 'action_name': 'pack_relocations', # 'actions': [ # 'variables': { # 'enable_packing': 'pack relocations if 1, plain file copy if 0' @@ -17,7 +17,7 @@ # 'stamp': 'file to touch when the action is complete' # 'stripped_libraries_dir': 'directory holding stripped libraries', # 'packed_libraries_dir': 'directory holding packed libraries', -# 'includes': [ '../../build/android/pack_arm_relocations.gypi' ], +# 'includes': [ '../../build/android/pack_relocations.gypi' ], # ], # }, # @@ -28,7 +28,7 @@ }, 'inputs': [ '<(DEPTH)/build/android/gyp/util/build_utils.py', - '<(DEPTH)/build/android/gyp/pack_arm_relocations.py', + '<(DEPTH)/build/android/gyp/pack_relocations.py', '<(ordered_libraries_file)', '>@(input_paths)', ], @@ -45,7 +45,7 @@ '<(PRODUCT_DIR)/android_relocation_packer', ], 'action': [ - 'python', '<(DEPTH)/build/android/gyp/pack_arm_relocations.py', + 'python', '<(DEPTH)/build/android/gyp/pack_relocations.py', '--configuration-name=<(CONFIGURATION_NAME)', '--enable-packing=1', '--exclude-packing-list=<@(exclude_packing_list)', @@ -58,7 +58,7 @@ }, { 'message': 'Copying libraries (no relocation packing) for <(_target_name)', 'action': [ - 'python', '<(DEPTH)/build/android/gyp/pack_arm_relocations.py', + 'python', '<(DEPTH)/build/android/gyp/pack_relocations.py', '--configuration-name=<(CONFIGURATION_NAME)', '--enable-packing=0', '--stripped-libraries-dir=<(stripped_libraries_dir)', diff --git a/build/android/package_resources_action.gypi b/build/android/package_resources_action.gypi index 82615cae3cf68..eb608718951b2 100644 --- a/build/android/package_resources_action.gypi +++ b/build/android/package_resources_action.gypi @@ -14,6 +14,7 @@ # asset_location - The directory where assets are located (if any). # create_density_splits - Whether to create density-based apk splits. Splits # are supported only for minSdkVersion >= 21. +# language_splits - List of languages to create apk splits for. # resource_zips - List of paths to resource zip files. # shared_resources - Make a resource package that can be loaded by a different # application at runtime to access the package's resources. @@ -69,10 +70,19 @@ '--create-density-splits', ], 'outputs': [ - '<(resource_packaged_apk_path)-hdpi', - '<(resource_packaged_apk_path)-xhdpi', - '<(resource_packaged_apk_path)-xxhdpi', - '<(resource_packaged_apk_path)-tvdpi', + '<(resource_packaged_apk_path)_hdpi', + '<(resource_packaged_apk_path)_xhdpi', + '<(resource_packaged_apk_path)_xxhdpi', + '<(resource_packaged_apk_path)_xxxhdpi', + '<(resource_packaged_apk_path)_tvdpi', + ], + }], + ['language_splits != []', { + 'action': [ + '--language-splits=<(language_splits)', + ], + 'outputs': [ + " ' '/sys/bus/i2c/drivers/bq2419x/0-006b/input_cable_state && ' 'dumpsys battery set ac 0 && dumpsys battery set usb 0'), - 'charge_counter': ( - '/sys/class/power_supply/max170xx_battery/charge_counter_ext'), - 'voltage': '/sys/class/power_supply/max170xx_battery/voltage_now', - 'current': '/sys/class/power_supply/max170xx_battery/current_now', + 'charge_counter': '/sys/class/power_supply/battery/charge_counter_ext', + 'voltage': '/sys/class/power_supply/battery/voltage_now', + 'current': '/sys/class/power_supply/battery/current_now', }, { 'name': 'Nexus 10', 'witness_file': None, 'enable_command': None, 'disable_command': None, - 'charge_counter': ( - '/sys/class/power_supply/ds2784-fuelgauge/charge_counter_ext'), + 'charge_counter': None, 'voltage': '/sys/class/power_supply/ds2784-fuelgauge/voltage_now', 'current': '/sys/class/power_supply/ds2784-fuelgauge/current_now', diff --git a/build/android/pylib/device/commands/java/src/org/chromium/android/commands/unzip/Unzip.java b/build/android/pylib/device/commands/java/src/org/chromium/android/commands/unzip/Unzip.java index 4d2a04518ecea..7cbbb732ced37 100644 --- a/build/android/pylib/device/commands/java/src/org/chromium/android/commands/unzip/Unzip.java +++ b/build/android/pylib/device/commands/java/src/org/chromium/android/commands/unzip/Unzip.java @@ -38,6 +38,7 @@ private void showUsage(PrintStream s) { s.println("unzip [zipfile]"); } + @SuppressWarnings("Finally") private void unzip(String[] args) { ZipInputStream zis = null; try { diff --git a/build/android/pylib/device/device_utils.py b/build/android/pylib/device/device_utils.py index 3a6563e8442e7..f201ef36b8bf0 100644 --- a/build/android/pylib/device/device_utils.py +++ b/build/android/pylib/device/device_utils.py @@ -949,7 +949,8 @@ def PushChangedFiles(self, host_device_tuples, timeout=None, for h, d in host_device_tuples: if os.path.isdir(h): self.RunShellCommand(['mkdir', '-p', d], check_return=True) - (changed_files, stale_files) = self._GetChangedAndStaleFiles(h, d) + changed_files, stale_files = ( + self._GetChangedAndStaleFiles(h, d, delete_device_stale)) all_changed_files += changed_files all_stale_files += stale_files @@ -962,17 +963,19 @@ def PushChangedFiles(self, host_device_tuples, timeout=None, self._PushFilesImpl(host_device_tuples, all_changed_files) - def _GetChangedAndStaleFiles(self, host_path, device_path): + def _GetChangedAndStaleFiles(self, host_path, device_path, track_stale=False): """Get files to push and delete Args: host_path: an absolute path of a file or directory on the host device_path: an absolute path of a file or directory on the device + track_stale: whether to bother looking for stale files (slower) Returns: a two-element tuple 1st element: a list of (host_files_path, device_files_path) tuples to push - 2nd element: a list of stale files under device_path + 2nd element: a list of stale files under device_path, or [] when + track_stale == False """ real_host_path = os.path.realpath(host_path) try: @@ -985,8 +988,13 @@ def _GetChangedAndStaleFiles(self, host_path, device_path): try: host_checksums = md5sum.CalculateHostMd5Sums([real_host_path]) + interesting_device_paths = [real_device_path] + if not track_stale and os.path.isdir(real_host_path): + interesting_device_paths = [ + posixpath.join(real_device_path, os.path.relpath(p, real_host_path)) + for p in host_checksums.keys()] device_checksums = md5sum.CalculateDeviceMd5Sums( - [real_device_path], self) + interesting_device_paths, self) except EnvironmentError as e: logging.warning('Error calculating md5: %s', e) return ([(host_path, device_path)], []) diff --git a/build/android/pylib/device_settings.py b/build/android/pylib/device_settings.py index 97e966322ce08..beabcff1f3ac3 100644 --- a/build/android/pylib/device_settings.py +++ b/build/android/pylib/device_settings.py @@ -127,6 +127,18 @@ def get_lock_settings(table): ]), ] +ENABLE_MOCK_LOCATION_SETTINGS = [ + ('settings/secure', [ + ('mock_location', 1), + ]), +] + +DISABLE_MOCK_LOCATION_SETTINGS = [ + ('settings/secure', [ + ('mock_location', 0), + ]), +] + DETERMINISTIC_DEVICE_SETTINGS = [ ('settings/global', [ ('assisted_gps_enabled', 0), diff --git a/build/android/pylib/gtest/filter/content_browsertests_disabled b/build/android/pylib/gtest/filter/content_browsertests_disabled index 39eff4dfcb694..dcad240a40e86 100644 --- a/build/android/pylib/gtest/filter/content_browsertests_disabled +++ b/build/android/pylib/gtest/filter/content_browsertests_disabled @@ -49,9 +49,6 @@ DownloadContentTest.ResumeWithDeletedFile # http://crbug.com/386227 IndexedDBBrowserTest.VersionChangeCrashResilience -# http://crbug.com/386222 -IndexedDBBrowserTest.DoesntHangTest - # http://crbug.com/233118 IndexedDBBrowserTest.NullKeyPathPersistence diff --git a/build/android/pylib/gtest/test_package_apk.py b/build/android/pylib/gtest/test_package_apk.py index 16ef21c6e4490..a679b0358edbb 100644 --- a/build/android/pylib/gtest/test_package_apk.py +++ b/build/android/pylib/gtest/test_package_apk.py @@ -43,6 +43,11 @@ def __init__(self, suite_name): else: self._package_info = constants.PACKAGE_INFO['gtest'] + if suite_name == 'net_unittests': + self._extras = {'RunInSubThread': ''} + else: + self._extras = [] + def _CreateCommandLineFileOnDevice(self, device, options): device.WriteFile(self._package_info.cmdline_file, self.suite_name + ' ' + options) @@ -74,7 +79,8 @@ def _StartActivity(self, device, force_stop=True): device.StartActivity( intent.Intent(package=self._package_info.package, activity=self._package_info.activity, - action='android.intent.action.MAIN'), + action='android.intent.action.MAIN', + extras=self._extras), # No wait since the runner waits for FIFO creation anyway. blocking=False, force_stop=force_stop) diff --git a/build/android/pylib/instrumentation/test_package.py b/build/android/pylib/instrumentation/test_package.py index f32556f33d00c..5be061d4af8fb 100644 --- a/build/android/pylib/instrumentation/test_package.py +++ b/build/android/pylib/instrumentation/test_package.py @@ -16,6 +16,8 @@ def __init__(self, apk_path, jar_path, test_support_apk_path): if not os.path.exists(apk_path): raise Exception('%s not found, please build it' % apk_path) + if test_support_apk_path and not os.path.exists(test_support_apk_path): + raise Exception('%s not found, please build it' % test_support_apk_path) self._apk_path = apk_path self._apk_name = os.path.splitext(os.path.basename(apk_path))[0] self._package_name = apk_helper.GetPackageName(self._apk_path) diff --git a/build/android/pylib/perf/test_options.py b/build/android/pylib/perf/test_options.py index e6ef5602d92af..eff928e115557 100644 --- a/build/android/pylib/perf/test_options.py +++ b/build/android/pylib/perf/test_options.py @@ -18,4 +18,5 @@ 'collect_chartjson_data', 'output_chartjson_data', 'max_battery_temp', + 'min_battery_level', ]) diff --git a/build/android/pylib/perf/test_runner.py b/build/android/pylib/perf/test_runner.py index 31eb0e9e9a4e4..d21a9b71b1044 100644 --- a/build/android/pylib/perf/test_runner.py +++ b/build/android/pylib/perf/test_runner.py @@ -277,6 +277,12 @@ def _LaunchPerfTest(self, test_name): self._device_battery.LetBatteryCoolToTemperature( self._options.max_battery_temp) + logging.info('Charge level: %s%%', + str(self._device_battery.GetBatteryInfo().get('level'))) + if self._options.min_battery_level: + self._device_battery.ChargeDeviceToLevel( + self._options.min_battery_level) + logging.info('%s : %s', test_name, cmd) start_time = datetime.datetime.now() diff --git a/build/android/pylib/sdk/aapt.py b/build/android/pylib/sdk/aapt.py new file mode 100644 index 0000000000000..3d317ff2c59a8 --- /dev/null +++ b/build/android/pylib/sdk/aapt.py @@ -0,0 +1,42 @@ +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""This module wraps the Android Asset Packaging Tool.""" + +import os + +from pylib import cmd_helper +from pylib import constants +from pylib.utils import timeout_retry + +_AAPT_PATH = os.path.join(constants.ANDROID_SDK_TOOLS, 'aapt') + +def _RunAaptCmd(args): + """Runs an aapt command. + + Args: + args: A list of arguments for aapt. + + Returns: + The output of the command. + """ + cmd = [_AAPT_PATH] + args + status, output = cmd_helper.GetCmdStatusAndOutput(cmd) + if status != 0: + raise Exception('Failed running aapt command: "%s" with output "%s".' % + (' '.join(cmd), output)) + return output + +def Dump(what, apk, assets=None): + """Returns the output of the aapt dump command. + + Args: + what: What you want to dump. + apk: Path to apk you want to dump information for. + assets: List of assets in apk you want to dump information for. + """ + assets = assets or [] + if isinstance(assets, basestring): + assets = [assets] + return _RunAaptCmd(['dump', what, apk] + assets).splitlines() \ No newline at end of file diff --git a/build/android/pylib/sdk/split_select.py b/build/android/pylib/sdk/split_select.py index 8752129c04c4a..e20466214239d 100644 --- a/build/android/pylib/sdk/split_select.py +++ b/build/android/pylib/sdk/split_select.py @@ -3,7 +3,6 @@ # found in the LICENSE file. """This module wraps Android's split-select tool.""" -# pylint: disable=unused-argument import os @@ -12,25 +11,21 @@ from pylib.utils import timeout_retry _SPLIT_SELECT_PATH = os.path.join(constants.ANDROID_SDK_TOOLS, 'split-select') -_DEFAULT_TIMEOUT = 30 -_DEFAULT_RETRIES = 2 -def _RunSplitSelectCmd(args, timeout=None, retries=None): +def _RunSplitSelectCmd(args): """Runs a split-select command. Args: args: A list of arguments for split-select. - timeout: Timeout in seconds. - retries: Number of retries. Returns: The output of the command. """ cmd = [_SPLIT_SELECT_PATH] + args - status, output = cmd_helper.GetCmdStatusAndOutputWithTimeout( - cmd, timeout_retry.CurrentTimeoutThread().GetRemainingTime()) + status, output = cmd_helper.GetCmdStatusAndOutput(cmd) if status != 0: - raise Exception('Failed running command %s' % str(cmd)) + raise Exception('Failed running command "%s" with output "%s".' % + (' '.join(cmd), output)) return output def _SplitConfig(device): @@ -45,16 +40,13 @@ def _SplitConfig(device): device.screen_density, device.product_cpu_abi)) -def SelectSplits(device, base_apk, split_apks, - timeout=_DEFAULT_TIMEOUT, retries=_DEFAULT_RETRIES): +def SelectSplits(device, base_apk, split_apks): """Determines which APK splits the device requires. Args: device: A DeviceUtils object. base_apk: The path of the base APK. split_apks: A list of paths of APK splits. - timeout: Timeout in seconds. - retries: Number of retries. Returns: The list of APK splits that the device requires. @@ -63,4 +55,4 @@ def SelectSplits(device, base_apk, split_apks, args = ['--target', config, '--base', base_apk] for split in split_apks: args.extend(['--split', split]) - return _RunSplitSelectCmd(args, timeout=timeout, retries=retries).splitlines() \ No newline at end of file + return _RunSplitSelectCmd(args).splitlines() \ No newline at end of file diff --git a/build/android/pylib/utils/apk_helper.py b/build/android/pylib/utils/apk_helper.py index 6dd209e3dc179..a556e7b31e668 100644 --- a/build/android/pylib/utils/apk_helper.py +++ b/build/android/pylib/utils/apk_helper.py @@ -9,12 +9,15 @@ from pylib import cmd_helper from pylib import constants +from pylib.sdk import aapt _AAPT_PATH = os.path.join(constants.ANDROID_SDK_TOOLS, 'aapt') _MANIFEST_ATTRIBUTE_RE = re.compile( r'\s*A: ([^\(\)= ]*)\([^\(\)= ]*\)="(.*)" \(Raw: .*\)$') _MANIFEST_ELEMENT_RE = re.compile(r'\s*(?:E|N): (\S*) .*$') +_PACKAGE_NAME_RE = re.compile(r'package: .*name=\'(\S*)\'') +_SPLIT_NAME_RE = re.compile(r'package: .*split=\'(\S*)\'') def GetPackageName(apk_path): @@ -30,8 +33,7 @@ def GetInstrumentationName(apk_path): def _ParseManifestFromApk(apk_path): - aapt_cmd = [_AAPT_PATH, 'dump', 'xmltree', apk_path, 'AndroidManifest.xml'] - aapt_output = cmd_helper.GetCmdOutput(aapt_cmd).split('\n') + aapt_output = aapt.Dump('xmltree', apk_path, 'AndroidManifest.xml') parsed_manifest = {} node_stack = [parsed_manifest] @@ -70,6 +72,7 @@ def __init__(self, apk_path): self._apk_path = apk_path self._manifest = None self._package_name = None + self._split_name = None def GetActivityName(self): """Returns the name of the Activity in the apk.""" @@ -100,16 +103,27 @@ def GetPackageName(self): if self._package_name: return self._package_name - aapt_cmd = [_AAPT_PATH, 'dump', 'badging', self._apk_path] - aapt_output = cmd_helper.GetCmdOutput(aapt_cmd).split('\n') - package_name_re = re.compile(r'package: .*name=\'(\S*)\'') + aapt_output = aapt.Dump('badging', self._apk_path) for line in aapt_output: - m = package_name_re.match(line) + m = _PACKAGE_NAME_RE.match(line) if m: self._package_name = m.group(1) return self._package_name raise Exception('Failed to determine package name of %s' % self._apk_path) + def GetSplitName(self): + """Returns the name of the split of the apk.""" + if self._split_name: + return self._split_name + + aapt_output = aapt.Dump('badging', self._apk_path) + for line in aapt_output: + m = _SPLIT_NAME_RE.match(line) + if m: + self._split_name = m.group(1) + return self._split_name + return None + def _GetManifest(self): if not self._manifest: self._manifest = _ParseManifestFromApk(self._apk_path) diff --git a/build/android/setup.gyp b/build/android/setup.gyp index b3c3422163fd0..0e1c2c4b492a7 100644 --- a/build/android/setup.gyp +++ b/build/android/setup.gyp @@ -77,6 +77,35 @@ }, ], }, # build_output_dirs + { + 'target_name': 'sun_tools_java', + 'type': 'none', + 'variables': { + 'found_jar_path': '<(PRODUCT_DIR)/sun_tools_java/tools.jar', + 'jar_path': '<(found_jar_path)', + }, + 'includes': [ + '../../build/host_prebuilt_jar.gypi', + ], + 'actions': [ + { + 'action_name': 'find_sun_tools_jar', + 'variables' : { + }, + 'inputs' : [ + 'gyp/find_sun_tools_jar.py', + 'gyp/util/build_utils.py', + ], + 'outputs': [ + '<(found_jar_path)', + ], + 'action': [ + 'python', 'gyp/find_sun_tools_jar.py', + '--output', '<(found_jar_path)', + ], + }, + ], + }, # sun_tools_java ] } diff --git a/build/android/test_runner.gypi b/build/android/test_runner.gypi index 92f355bf1fb4a..f92b7cedc0e2c 100644 --- a/build/android/test_runner.gypi +++ b/build/android/test_runner.gypi @@ -33,6 +33,7 @@ 'variables': { 'variables': { 'isolate_file%': '', + 'support_apk_path%': '', }, 'test_runner_args': ['--output-directory', '<(PRODUCT_DIR)'], 'conditions': [ @@ -43,6 +44,14 @@ ['test_type == "instrumentation"', { 'test_runner_args': ['--test-apk', '<(apk_name)'], 'script_name': 'run_<(_target_name)', + 'conditions': [ + ['support_apk_path != ""', { + 'test_runner_args': [ + '--support-apk', + '<(support_apk_path)' + ], + }], + ], }], ['isolate_file != ""', { 'test_runner_args': ['--isolate-file-path', '<(isolate_file)'] diff --git a/build/android/test_runner.py b/build/android/test_runner.py index d508ef8d7c446..1fc48ecf5050a 100755 --- a/build/android/test_runner.py +++ b/build/android/test_runner.py @@ -332,6 +332,11 @@ def AddInstrumentationTestOptions(parser): help=('The name of the apk containing the tests ' '(without the .apk extension; ' 'e.g. "ContentShellTest").')) + group.add_argument('--support-apk', dest='test_support_apk_path', + help=('The path to an optional support apk to be ' + 'installed alongside the test apk. The ' + 'path should be relative to the output ' + 'directory (--output-directory).')) group.add_argument('--coverage-dir', help=('Directory in which to place all generated ' 'EMMA coverage files.')) @@ -379,8 +384,6 @@ def ProcessInstrumentationOptions(args): constants.GetOutDirectory(), constants.SDK_BUILD_TEST_JAVALIB_DIR, '%s.jar' % args.test_apk) - args.test_support_apk_path = '%sSupport%s' % ( - os.path.splitext(args.test_apk_path)) args.test_runner = apk_helper.GetInstrumentationName(args.test_apk_path) @@ -613,6 +616,9 @@ def __call__(self, parser, namespace, values, option_string=None): 'temperature (0.1 C)') group.add_argument('single_step_command', nargs='*', action=SingleStepAction, help='If --single-step is specified, the command to run.') + group.add_argument('--min-battery-level', type=int, + help='Only starts tests when the battery is charged above ' + 'given level.') AddCommonOptions(parser) AddDeviceOptions(parser) @@ -635,7 +641,7 @@ def ProcessPerfTestOptions(args): args.steps, args.flaky_steps, args.output_json_list, args.print_step, args.no_timeout, args.test_filter, args.dry_run, args.single_step, args.collect_chartjson_data, - args.output_chartjson_data, args.max_battery_temp) + args.output_chartjson_data, args.max_battery_temp, args.min_battery_level) def AddPythonTestOptions(parser): diff --git a/build/android/tests/multiple_proguards/AndroidManifest.xml b/build/android/tests/multiple_proguards/AndroidManifest.xml deleted file mode 100644 index 1794712bb3c8a..0000000000000 --- a/build/android/tests/multiple_proguards/AndroidManifest.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - diff --git a/build/android/tests/multiple_proguards/multiple_proguards.gyp b/build/android/tests/multiple_proguards/multiple_proguards.gyp deleted file mode 100644 index 48a5d7ba8bd42..0000000000000 --- a/build/android/tests/multiple_proguards/multiple_proguards.gyp +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright (c) 2013 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -{ - 'variables': { - 'chromium_code': 1, - }, - 'targets': [ - { - 'target_name': 'multiple_proguards_test_apk', - 'type': 'none', - 'variables': { - 'app_manifest_version_name%': '<(android_app_version_name)', - 'java_in_dir': '.', - 'proguard_enabled': 'true', - 'proguard_flags_paths': [ - # Both these proguard?.flags files need to be part of the build to - # remove both warnings from the src/dummy/DummyActivity.java file, else the - # build will fail. - 'proguard1.flags', - 'proguard2.flags', - ], - 'R_package': 'dummy', - 'R_package_relpath': 'dummy', - 'apk_name': 'MultipleProguards', - # This is a build-only test. There's nothing to install. - 'gyp_managed_install': 0, - # The Java code produces warnings, so force the build to not show them. - 'chromium_code': 0, - }, - 'includes': [ '../../../../build/java_apk.gypi' ], - }, - ], -} diff --git a/build/android/tests/multiple_proguards/proguard1.flags b/build/android/tests/multiple_proguards/proguard1.flags deleted file mode 100644 index 95a814cda6c7a..0000000000000 --- a/build/android/tests/multiple_proguards/proguard1.flags +++ /dev/null @@ -1 +0,0 @@ --dontwarn sun.misc.Unsafe diff --git a/build/android/tests/multiple_proguards/proguard2.flags b/build/android/tests/multiple_proguards/proguard2.flags deleted file mode 100644 index ceac62b1c6f78..0000000000000 --- a/build/android/tests/multiple_proguards/proguard2.flags +++ /dev/null @@ -1 +0,0 @@ --dontwarn sun.reflect.Reflection diff --git a/build/android/tests/multiple_proguards/src/dummy/DummyActivity.java b/build/android/tests/multiple_proguards/src/dummy/DummyActivity.java deleted file mode 100644 index e138acca5fa1f..0000000000000 --- a/build/android/tests/multiple_proguards/src/dummy/DummyActivity.java +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package dummy; - -import android.app.Activity; - -/** - * Dummy activity to build apk. - * - * This class is created to ensure that proguard will produce two separate warnings. - */ -public class DummyActivity extends Activity { - private static void doBadThings1() { - try { - sun.misc.Unsafe.getUnsafe(); - } catch (Exception e) { - throw new Error(e); - } - } - - private static void doBadThings2() { - sun.reflect.Reflection.getCallerClass(2); - } -} diff --git a/build/android/tests/multiple_proguards/src/dummy/NativeLibraries.java b/build/android/tests/multiple_proguards/src/dummy/NativeLibraries.java deleted file mode 100644 index 2f7db71958dbc..0000000000000 --- a/build/android/tests/multiple_proguards/src/dummy/NativeLibraries.java +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.base.library_loader; - -/** - * This is a complete dummy, required because base now requires a version of - * NativeLibraries to build, but doesn't include it in its jar file. - */ -public class NativeLibraries { - public static boolean sUseLinker = false; - public static boolean sUseLibraryInZipFile = false; - public static boolean sEnableLinkerTests = false; - static final String[] LIBRARIES = {}; - static String sVersionNumber = ""; -} diff --git a/build/android/update_verification.py b/build/android/update_verification.py index 06cd2d695422e..05d083b32a3d2 100755 --- a/build/android/update_verification.py +++ b/build/android/update_verification.py @@ -49,7 +49,7 @@ def TestUpdate(device, old_apk, new_apk, app_data, package_name): # Restore command is not synchronous raw_input('Select "Restore my data" on the device. Then press enter to ' 'continue.') - device_path = device.GetApplicationPath(package_name) + device_path = device.GetApplicationPaths(package_name) if not device_path: raise Exception('Expected package %s to already be installed. ' 'Package name might have changed!' % package_name) diff --git a/build/android_sdk_extras.json b/build/android_sdk_extras.json index 456272627eb9e..25b47c360a0bf 100644 --- a/build/android_sdk_extras.json +++ b/build/android_sdk_extras.json @@ -3,6 +3,7 @@ "dir_name": "google", "version": "21.0.0", "zip": "google_google_play_services_21.0.0.zip", - "package": "google_play_services" + "package": "google_play_services", + "package_id": "extra-google-google_play_services" } ] diff --git a/build/apk_test.gypi b/build/apk_test.gypi index 2a6d312b632e3..e0d323f74a36b 100644 --- a/build/apk_test.gypi +++ b/build/apk_test.gypi @@ -23,6 +23,7 @@ '<(DEPTH)/build/android/pylib/device/commands/commands.gyp:chromium_commands', '<(DEPTH)/build/android/pylib/remote/device/dummy/dummy.gyp:remote_device_dummy_apk', '<(DEPTH)/testing/android/appurify_support.gyp:appurify_support_java', + '<(DEPTH)/testing/android/on_device_instrumentation.gyp:reporter_java', '<(DEPTH)/tools/android/android_tools.gyp:android_tools', ], 'conditions': [ diff --git a/build/check_sdk_extras_version.py b/build/check_sdk_extras_version.py new file mode 100755 index 0000000000000..9b2f10d2abc03 --- /dev/null +++ b/build/check_sdk_extras_version.py @@ -0,0 +1,131 @@ +#!/usr/bin/env python +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +'''Checks the status of an Android SDK package. + +Verifies the given package has been installed from the Android SDK Manager and +that its version is at least the minimum version required by the project +configuration. +''' + +import argparse +import json +import os +import re +import sys + + +COLORAMA_ROOT = os.path.join(os.path.dirname(__file__), + os.pardir, 'third_party', 'colorama', 'src') + +sys.path.append(COLORAMA_ROOT) +import colorama + + +UDPATE_SCRIPT_PATH = 'build/install-android-sdks.sh' + +SDK_EXTRAS_JSON_FILE = os.path.join(os.path.dirname(__file__), + 'android_sdk_extras.json') + +PACKAGE_VERSION_PATTERN = r'^Pkg\.Revision=(?P\d+).*$' + +PKG_NOT_FOUND_MSG = ('Error while checking Android SDK extras versions. ' + 'Could not find the "{package_id}" package in ' + '{checked_location}. Please run {script} to download it.') +UPDATE_NEEDED_MSG = ('Error while checking Android SDK extras versions. ' + 'Version {minimum_version} or greater is required for the ' + 'package "{package_id}". Version {actual_version} found. ' + 'Please run {script} to update it.') +REQUIRED_VERSION_ERROR_MSG = ('Error while checking Android SDK extras ' + 'versions. ' + 'Could not retrieve the required version for ' + 'package "{package_id}".') + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--package-id', + help=('id of the package to check for. The list of ' + 'available packages and their ids can be obtained ' + 'by running ' + 'third_party/android_tools/sdk/tools/android list ' + 'sdk --extended')) + parser.add_argument('--package-location', + help='path to the package\'s expected install location.', + metavar='DIR') + parser.add_argument('--stamp', + help=('if specified, a stamp file will be created at the ' + 'provided location.'), + metavar='FILE') + + args = parser.parse_args() + + if not ShouldSkipVersionCheck(): + minimum_version = GetRequiredMinimumVersion(args.package_id) + CheckPackageVersion(args.package_id, args.package_location, minimum_version) + + # Create the stamp file. + if args.stamp: + with open(args.stamp, 'a'): + os.utime(args.stamp, None) + + sys.exit(0) + +def ExitError(msg): + sys.exit(colorama.Fore.MAGENTA + colorama.Style.BRIGHT + msg + + colorama.Style.RESET_ALL) + + +def GetRequiredMinimumVersion(package_id): + with open(SDK_EXTRAS_JSON_FILE, 'r') as json_file: + packages = json.load(json_file) + + for package in packages: + if package['package_id'] == package_id: + return int(package['version'].split('.')[0]) + + ExitError(REQUIRED_VERSION_ERROR_MSG.format(package_id=package_id)) + + +def CheckPackageVersion(pkg_id, location, minimum_version): + version_file_path = os.path.join(location, 'source.properties') + # Extracts the version of the package described by the property file. We only + # care about the major version number here. + version_pattern = re.compile(PACKAGE_VERSION_PATTERN, re.MULTILINE) + + if not os.path.isfile(version_file_path): + ExitError(PKG_NOT_FOUND_MSG.format( + package_id=pkg_id, + checked_location=location, + script=UDPATE_SCRIPT_PATH)) + + with open(version_file_path, 'r') as f: + match = version_pattern.search(f.read()) + + if not match: + ExitError(PKG_NOT_FOUND_MSG.format( + package_id=pkg_id, + checked_location=location, + script=UDPATE_SCRIPT_PATH)) + + pkg_version = int(match.group('version')) + if pkg_version < minimum_version: + ExitError(UPDATE_NEEDED_MSG.format( + package_id=pkg_id, + minimum_version=minimum_version, + actual_version=pkg_version, + script=UDPATE_SCRIPT_PATH)) + + # Everything looks ok, print nothing. + +def ShouldSkipVersionCheck(): + ''' + Bots should not run the version check, since they download the sdk extras + in a different way. + ''' + return bool(os.environ.get('CHROME_HEADLESS')) + +if __name__ == '__main__': + main() diff --git a/build/clobber.py b/build/clobber.py new file mode 100755 index 0000000000000..785011a171d83 --- /dev/null +++ b/build/clobber.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""This script provides methods for clobbering build directories.""" + +import argparse +import os +import shutil +import sys + + +def extract_gn_build_commands(build_ninja_file): + """Extracts from a build.ninja the commands to run GN. + + The commands to run GN are the gn rule and build.ninja build step at the + top of the build.ninja file. We want to keep these when deleting GN builds + since we want to preserve the command-line flags to GN. + + On error, returns the empty string.""" + result = "" + with open(build_ninja_file, 'r') as f: + # Read until the second blank line. The first thing GN writes to the file + # is the "rule gn" and the second is the section for "build build.ninja", + # separated by blank lines. + num_blank_lines = 0 + while num_blank_lines < 2: + line = f.readline() + if len(line) == 0: + return '' # Unexpected EOF. + result += line + if line[0] == '\n': + num_blank_lines = num_blank_lines + 1 + return result + + +def delete_build_dir(build_dir): + # GN writes a build.ninja.d file. Note that not all GN builds have args.gn. + build_ninja_d_file = os.path.join(build_dir, 'build.ninja.d') + if not os.path.exists(build_ninja_d_file): + shutil.rmtree(build_dir) + return + + # GN builds aren't automatically regenerated when you sync. To avoid + # messing with the GN workflow, erase everything but the args file, and + # write a dummy build.ninja file that will automatically rerun GN the next + # time Ninja is run. + build_ninja_file = os.path.join(build_dir, 'build.ninja') + build_commands = extract_gn_build_commands(build_ninja_file) + + try: + gn_args_file = os.path.join(build_dir, 'args.gn') + with open(gn_args_file, 'r') as f: + args_contents = f.read() + except IOError: + args_contents = '' + + shutil.rmtree(build_dir) + + # Put back the args file (if any). + os.mkdir(build_dir) + if args_contents != '': + with open(gn_args_file, 'w') as f: + f.write(args_contents) + + # Write the build.ninja file sufficiently to regenerate itself. + with open(os.path.join(build_dir, 'build.ninja'), 'w') as f: + if build_commands != '': + f.write(build_commands) + else: + # Couldn't parse the build.ninja file, write a default thing. + f.write('''rule gn +command = gn -q gen //out/%s/ +description = Regenerating ninja files + +build build.ninja: gn +generator = 1 +depfile = build.ninja.d +''' % (os.path.split(build_dir)[1])) + + # Write a .d file for the build which references a nonexistant file. This + # will make Ninja always mark the build as dirty. + with open(build_ninja_d_file, 'w') as f: + f.write('build.ninja: nonexistant_file.gn\n') + + +def clobber(out_dir): + """Clobber contents of build directory. + + Don't delete the directory itself: some checkouts have the build directory + mounted.""" + for f in os.listdir(out_dir): + path = os.path.join(out_dir, f) + if os.path.isfile(path): + os.unlink(path) + elif os.path.isdir(path): + delete_build_dir(path) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('out_dir', help='The output directory to clobber') + args = parser.parse_args() + clobber(args.out_dir) + return 0 + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/build/common.gypi b/build/common.gypi index 1f26bdadba5eb..3a2df58447cdd 100644 --- a/build/common.gypi +++ b/build/common.gypi @@ -68,7 +68,7 @@ # implementation. Certificate verification will in most cases be # handled by the OS. If OpenSSL's struct X509 is used to represent # certificates, use_openssl_certs must be set. - 'use_openssl%': 0, + 'use_openssl%': 1, # Use OpenSSL for representing certificates. When targeting Android, # the platform certificate library is used for certificate @@ -104,8 +104,8 @@ 'branding%': 'Chromium', 'conditions': [ - # ChromeOS and Windows use Aura and Ash. - ['chromeos==1 or OS=="win" or OS=="linux"', { + # Windows and Linux (including Chrome OS) use Aura and Ash. + ['OS=="win" or OS=="linux"', { 'use_ash%': 1, 'use_aura%': 1, }], @@ -225,19 +225,19 @@ 'toolkit_views%': 0, }], - # Enable HiDPI on Mac OS, Chrome OS, Windows and Linux. - ['OS=="mac" or chromeos==1 or OS=="win" or OS=="linux"', { + # Enable HiDPI on Mac OS, Windows and Linux (including Chrome OS). + ['OS=="mac" or OS=="win" or OS=="linux"', { 'enable_hidpi%': 1, }], - # Enable Top Chrome Material Design on Chrome OS, and Windows. - ['chromeos==1 or OS=="win"', { + # Enable Top Chrome Material Design on Chrome OS, Windows, and Linux. + ['chromeos==1 or OS=="win" or OS=="linux"', { 'enable_topchrome_md%': 1, }], - # Enable the OpenSSL backend on Mac OS and Windows. - ['OS=="mac" or OS=="win"', { - 'use_openssl%': 1, + # On iOS, use NSS rather than OpenSSL. See http://crbug.com/338886. + ['OS=="ios"', { + 'use_openssl%': 0, }], # Enable App Launcher everywhere but mobile. @@ -290,16 +290,16 @@ ['OS=="linux" and target_arch=="arm" and chromeos==0', { # sysroot needs to be an absolute path otherwise it generates # incorrect results when passed to pkg-config - 'sysroot%': '= 7.0)}\')==1', { 'clang_xcode%': 1, }], ], @@ -2197,19 +2218,6 @@ 'use_sanitizer_options%': 1, }], - # Allowed level of identical code folding in the gold linker. - ['OS=="linux" and target_arch=="x64"', { - # --icf=safe disables much more folding on x86_64 than elsewhere, see - # http://crbug.com/492177. Turning it on saves over 12 MB of binary - # size, but it seems to regress cold startup time by over a second - # (see http://crbug.com/492809). - # TODO(thakis): Check if disabling ICF would inmprove android cold start - # times by several seconds too. - 'gold_icf_level%': 'safe', - }, { - 'gold_icf_level%': 'all', - }], - ['OS=="linux" and asan==0 and msan==0 and lsan==0 and tsan==0', { # PNaCl toolchain Non-SFI build only supports linux OS build. # Also, it does not support sanitizers. @@ -2311,9 +2319,15 @@ 'release_valgrind_build': 1, }], - # Enable RLZ on Win, Mac, iOS and ChromeOS. - ['branding=="Chrome" and (OS=="win" or OS=="mac" or OS=="ios" or chromeos==1)', { - 'enable_rlz%': 1, + # RLZ library is used on Win, Mac, iOS and ChromeOS. + ['OS=="win" or OS=="mac" or OS=="ios" or chromeos==1', { + 'enable_rlz_support%': 1, + 'conditions': [ + # RLZ is enabled for "Chrome" builds. + ['branding=="Chrome"', { + 'enable_rlz%': 1, + }], + ], }], # Set default compiler flags depending on ARM version. @@ -2361,7 +2375,6 @@ # Build all platforms whose deps are in install-build-deps.sh. # Only these platforms will be compile tested by buildbots. - 'ozone_platform_dri%': 1, 'ozone_platform_drm%': 1, 'ozone_platform_test%': 1, 'ozone_platform_egltest%': 1, @@ -2593,8 +2606,11 @@ # http://crbug.com/255186 '-Wno-deprecated-register', - # TODO(hans): Get this cleaned up. + # TODO(hans): Get this cleaned up, http://crbug.com/428099 '-Wno-inconsistent-missing-override', + + # TODO(thakis): Enable this, crbug.com/507717 + '-Wno-shift-negative-value', ], }, 'includes': [ 'set_clang_warning_flags.gypi', ], @@ -2663,9 +2679,6 @@ ['component=="shared_library"', { 'defines': ['COMPONENT_BUILD'], }], - ['toolkit_views==1', { - 'defines': ['TOOLKIT_VIEWS=1'], - }], ['ui_compositor_image_transport==1', { 'defines': ['UI_COMPOSITOR_IMAGE_TRANSPORT'], }], @@ -2892,8 +2905,7 @@ # override WarnAsError. # Also, disable various noisy warnings that have low value. 'AdditionalOptions': [ - '/analyze', - '/WX-', + '/analyze:WX-', '/wd6011', # Dereferencing NULL pointer '/wd6312', # Possible infinite loop: use of the constant # EXCEPTION_CONTINUE_EXECUTION in the exception-filter @@ -2990,6 +3002,9 @@ ['enable_spellcheck==1', { 'defines': ['ENABLE_SPELLCHECK=1'], }], + ['use_platform_spellchecker', { + 'defines': ['USE_PLATFORM_SPELLCHECKER=1'], + }], ['enable_captive_portal_detection==1', { 'defines': ['ENABLE_CAPTIVE_PORTAL_DETECTION=1'], }], @@ -3029,6 +3044,9 @@ ['v8_use_external_startup_data==1', { 'defines': ['V8_USE_EXTERNAL_STARTUP_DATA'], }], + ['enable_webvr==1', { + 'defines': ['ENABLE_WEBVR'], + }], # SAFE_BROWSING_SERVICE - browser manages a safe-browsing service. # SAFE_BROWSING_DB_LOCAL - service manages a local database. @@ -3089,6 +3107,16 @@ 'variables': { 'clang_warning_flags': ['-Wexit-time-destructors']}, }], ['chromium_code==0', { + 'variables': { + 'clang_warning_flags': [ + # TODO(mgiuca): Move this suppression into individual third-party + # libraries as required. http://crbug.com/505301. + '-Wno-overloaded-virtual', + # Lots of third-party libraries have unused variables. Instead of + # suppressing them individually, we just blanket suppress them here. + '-Wno-unused-variable', + ], + }, 'conditions': [ [ 'os_posix==1 and OS!="mac" and OS!="ios"', { # We don't want to get warnings from third-party code, @@ -3228,9 +3256,14 @@ 'IntermediateDirectory': '$(OutDir)\\obj\\$(ProjectName)', 'CharacterSet': '1', }, - # Add the default import libs. 'msvs_settings':{ + 'VCCLCompilerTool': { + 'AdditionalOptions': [ + '/bigobj', + ], + }, 'VCLinkerTool': { + # Add the default import libs. 'AdditionalDependencies': [ 'kernel32.lib', 'gdi32.lib', @@ -3688,7 +3721,6 @@ 'cflags': [ '-O>(debug_optimize)', '-g', - '-gdwarf-4', ], 'conditions' : [ ['OS=="android" and target_arch!="mipsel" and target_arch!="mips64el"', { @@ -3819,14 +3851,6 @@ 'cflags': ['-fno-unwind-tables', '-fno-asynchronous-unwind-tables'], 'defines': ['NO_UNWIND_TABLES'], }], - ['clang==1', { - # Non-unique section names appears to make linker dead stripping - # less effective. See http://crbug.com/483026#c20 - # TODO(hans): Remove this if resolved upstream. - 'cflags': [ - '-funique-section-names', - ], - }], ], }, }, @@ -4787,6 +4811,7 @@ '-pthread', # Not supported by Android toolchain. ], 'ldflags': [ + '-Wl,--build-id=sha1', '-Wl,--no-undefined', '--sysroot=<(android_ndk_sysroot)', '-nostdlib', @@ -5342,6 +5367,9 @@ ['clang_xcode==1', { 'WARNING_CFLAGS': [ '-Wno-unknown-warning-option', + # It's not possible to achieve nullability completeness before + # all builders are running Xcode 7. crbug.com/499809 + '-Wno-nullability-completeness', ], }], @@ -5584,6 +5612,12 @@ # trying to prevent it. 4503, + # Warning C4589 says: "Constructor of abstract class ignores + # initializer for virtual base class." Disable this warning because it + # is flaky in VS 2015 RTM. It triggers on compiler generated + # copy-constructors in some cases. + 4589, + # C4611: interaction between 'function' and C++ object destruction is # non-portable # This warning is unavoidable when using e.g. setjmp/longjmp. MSDN @@ -5700,40 +5734,14 @@ # TODO(hans): Fix those files, or move this to sub-GYPs. '/FIIntrin.h', - # TODO(hans): Make this list shorter eventually. - '-Qunused-arguments', - '-Wno-c++11-compat-deprecated-writable-strings', - '-Wno-deprecated-declarations', - '-Wno-empty-body', - '-Wno-enum-conversion', - '-Wno-extra-tokens', - '-Wno-ignored-attributes', - '-Wno-incompatible-pointer-types', - '-Wno-int-to-void-pointer-cast', - '-Wno-invalid-noreturn', - '-Wno-logical-op-parentheses', - '-Wno-microsoft', - '-Wno-missing-braces', - '-Wno-missing-declarations', - '-Wno-msvc-include', - '-Wno-null-dereference', - '-Wno-overloaded-virtual', - '-Wno-parentheses', - '-Wno-pointer-sign', - '-Wno-reorder', - '-Wno-return-type-c-linkage', - '-Wno-self-assign', - '-Wno-sometimes-uninitialized', - '-Wno-switch', - '-Wno-tautological-compare', - '-Wno-unknown-pragmas', - '-Wno-unsequenced', - '-Wno-unused-function', - '-Wno-unused-private-field', - '-Wno-unused-value', - '-Wno-unused-variable', + # TODO(hans): Make this list shorter eventually, http://crbug.com/504657 + '-Qunused-arguments', # http://crbug.com/504658 + '-Wno-microsoft', # http://crbug.com/505296 + '-Wno-switch', # http://crbug.com/505308 + '-Wno-unknown-pragmas', # http://crbug.com/505314 + '-Wno-unused-function', # http://crbug.com/505316 + '-Wno-unused-value', # http://crbug.com/505318 '-Wno-unused-local-typedef', # http://crbug.com/411648 - '-Wno-inconsistent-missing-override', #http://crbug.com/428099 ], }, }], @@ -5766,6 +5774,17 @@ ], }, }], + ['clang==1 and " res/raw-en/en_gb.pak). Also generates +# a locale_paks TypedArray so that resource files can be enumerated at runtime. +# +# If this target is included in the deps of an android resources/library/apk, +# the resources will be included with that target. +# +# Variables: +# sources: List of .pak files. Names must be of the form "en.pak" or +# "en-US.pak". +# deps: (optional) List of dependencies that might be needed to generate +# the .pak files. +# +# Example +# locale_pak_resources("locale_paks") { +# sources = [ "path/en-US.pak", "path/fr.pak", ... ] +# } +template("locale_pak_resources") { + set_sources_assignment_filter([]) + assert(defined(invoker.sources)) + + _base_path = "$target_gen_dir/$target_name" + _resources_zip = _base_path + ".resources.zip" + _build_config = _base_path + ".build_config" + + write_build_config("${target_name}__build_config") { + build_config = _build_config + resources_zip = _resources_zip + type = "android_resources" + } + + action("${target_name}__create_resources_zip") { + sources = invoker.sources + script = "//build/android/gyp/locale_pak_resources.py" + depfile = "$target_gen_dir/$target_name.d" + + outputs = [ + depfile, + _resources_zip, + ] + + _rebased_sources = rebase_path(invoker.sources, root_build_dir) + args = [ + "--locale-paks=${_rebased_sources}", + "--resources-zip", + rebase_path(_resources_zip, root_build_dir), + "--depfile", + rebase_path(depfile, root_build_dir), + ] + + if (defined(invoker.deps)) { + deps = invoker.deps + } + } + + group(target_name) { + deps = [ + ":${target_name}__build_config", + ":${target_name}__create_resources_zip", + ] + } +} + # Declare an Android resources target # # This creates a resources zip file that will be used when building an Android @@ -798,6 +861,7 @@ template("java_strings_grd_prebuilt") { # android_library target, for example. # # chromium_code: If true, extra analysis warning/errors will be enabled. +# enable_errorprone: If true, enables the errorprone compiler. # # data_deps, testonly # @@ -825,6 +889,9 @@ template("java_binary") { if (defined(invoker.deps)) { deps = invoker.deps } + if (defined(invoker.enable_errorprone)) { + enable_errorprone = invoker.enable_errorprone + } if (defined(invoker.java_files)) { java_files = invoker.java_files } @@ -841,6 +908,7 @@ template("java_binary") { testonly = invoker.testonly } + supports_android = false main_class = invoker.main_class } } @@ -919,6 +987,8 @@ template("junit_binary") { # ease the gyp->gn conversion and will be removed in the future. # # chromium_code: If true, extra analysis warning/errors will be enabled. +# enable_errorprone: If true, enables the errorprone compiler. +# # jar_excluded_patterns: List of patterns of .class files to exclude from the # final jar. # @@ -967,6 +1037,9 @@ template("java_library") { if (defined(invoker.deps)) { deps = invoker.deps } + if (defined(invoker.enable_errorprone)) { + enable_errorprone = invoker.enable_errorprone + } if (defined(invoker.jar_excluded_patterns)) { jar_excluded_patterns = invoker.jar_excluded_patterns } @@ -1007,6 +1080,7 @@ template("java_library") { # deps: Specifies the dependencies of this target. Java targets in this list # will be added to the javac classpath. # jar_path: Path to the prebuilt jar. +# jar_dep: Target that builds jar_path (optional). # proguard_preprocess: If true, proguard preprocessing will be run. This can # be used to remove unwanted parts of the library. # proguard_config: Path to the proguard config for preprocessing. @@ -1023,12 +1097,18 @@ template("java_prebuilt") { set_sources_assignment_filter([]) java_prebuilt_impl(target_name) { jar_path = invoker.jar_path + if (defined(invoker.jar_dep)) { + jar_dep = invoker.jar_dep + } if (defined(invoker.testonly)) { testonly = invoker.testonly } if (defined(invoker.deps)) { deps = invoker.deps } + if (defined(invoker.data_deps)) { + data_deps = invoker.data_deps + } if (defined(invoker.proguard_config)) { proguard_config = invoker.proguard_config } @@ -1058,6 +1138,8 @@ template("java_prebuilt") { # ease the gyp->gn conversion and will be removed in the future. # # chromium_code: If true, extra analysis warning/errors will be enabled. +# enable_errorprone: If true, enables the errorprone compiler. +# # jar_excluded_patterns: List of patterns of .class files to exclude from the # final jar. # @@ -1103,6 +1185,9 @@ template("android_library") { if (defined(invoker.deps)) { deps = invoker.deps } + if (defined(invoker.enable_errorprone)) { + enable_errorprone = invoker.enable_errorprone + } if (defined(invoker.jar_excluded_patterns)) { jar_excluded_patterns = invoker.jar_excluded_patterns } @@ -1201,6 +1286,9 @@ template("android_java_prebuilt") { if (defined(invoker.deps)) { deps = invoker.deps } + if (defined(invoker.data_deps)) { + data_deps = invoker.data_deps + } if (defined(invoker.proguard_config)) { proguard_config = invoker.proguard_config } @@ -1217,6 +1305,7 @@ template("android_java_prebuilt") { # # Variables # android_manifest: Path to AndroidManifest.xml. +# android_manifest_dep: Target that generates AndroidManifest (if applicable) # data_deps: List of dependencies needed at runtime. These will be built but # won't change the generated .apk in any way (in fact they may be built # after the .apk is). @@ -1348,15 +1437,22 @@ template("android_apk") { "Relocation packing requires use of the" + " Chromium linker.") } - _native_libs = process_file_template( - invoker.native_libs, - "$root_build_dir/lib.stripped/{{source_file_part}}") + if (is_component_build) { + _native_libs += [ "$root_out_dir/lib.stripped/libc++_shared.so" ] + _chromium_linker_dep += [ "//build/android:cpplib_stripped" ] + } + + # Allow native_libs to be in the form "foo.so" or "foo.cr.so" + _first_ext_removed = + process_file_template(invoker.native_libs, "{{source_name_part}}") + _native_libs += process_file_template( + _first_ext_removed, + "$root_build_dir/lib.stripped/{{source_name_part}}$android_product_extension") _native_libs_dir = base_path + "/libs" if (_use_chromium_linker) { - _native_libs += - [ "$root_build_dir/lib.stripped/libchromium_android_linker.so" ] + _native_libs += [ "$root_build_dir/lib.stripped/libchromium_android_linker$android_product_extension" ] } _enable_relocation_packing = false @@ -1365,13 +1461,22 @@ template("android_apk") { _enable_relocation_packing = true } - _native_lib_version_name = "" - if (defined(invoker.native_lib_version_name)) { - _native_lib_version_name = invoker.native_lib_version_name + _native_lib_version_rule = "" + if (defined(invoker.native_lib_version_rule)) { + _native_lib_version_rule = invoker.native_lib_version_rule + } + _native_lib_version_arg = "\"\"" + if (defined(invoker.native_lib_version_arg)) { + _native_lib_version_arg = invoker.native_lib_version_arg } } + _android_manifest_deps = [] + if (defined(invoker.android_manifest_dep)) { + _android_manifest_deps = [ invoker.android_manifest_dep ] + } _android_manifest = invoker.android_manifest + _rebased_build_config = rebase_path(_build_config, root_build_dir) _create_abi_split = defined(invoker.create_abi_split) && invoker.create_abi_split @@ -1389,7 +1494,7 @@ template("android_apk") { build_config = _build_config android_manifest = _android_manifest - deps = _chromium_linker_dep + deps = _chromium_linker_dep + _android_manifest_deps if (defined(invoker.deps)) { deps += invoker.deps } @@ -1419,9 +1524,7 @@ template("android_apk") { } build_config = _build_config - deps = [ - ":$build_config_target", - ] + deps = _android_manifest_deps + [ ":$build_config_target" ] if (defined(invoker.deps)) { deps += invoker.deps } @@ -1445,11 +1548,14 @@ template("android_apk") { deps = [ ":$build_config_target", ] + if (_native_lib_version_rule != "") { + deps += [ _native_lib_version_rule ] + } defines = [ "NATIVE_LIBRARIES_LIST=" + "@FileArg($_rebased_build_config:native:java_libraries_list)", - "NATIVE_LIBRARIES_VERSION_NUMBER=\"$_native_lib_version_name\"", + "NATIVE_LIBRARIES_VERSION_NUMBER=$_native_lib_version_arg", ] if (_use_chromium_linker) { defines += [ "ENABLE_CHROMIUM_LINKER" ] @@ -1470,9 +1576,7 @@ template("android_apk") { supports_android = true requires_android = true override_build_config = _build_config - deps = [ - ":$build_config_target", - ] + deps = _android_manifest_deps + [ ":$build_config_target" ] android_manifest = _android_manifest chromium_code = true @@ -1544,7 +1648,7 @@ template("android_apk") { if (_native_libs != []) { action("${_template_name}__prepare_native") { - script = "//build/android/gyp/pack_arm_relocations.py" + script = "//build/android/gyp/pack_relocations.py" packed_libraries_dir = "$_native_libs_dir/$android_app_abi" depfile = "$target_gen_dir/$target_name.d" outputs = [ @@ -1559,7 +1663,7 @@ template("android_apk") { skip_packing_list = [ "gdbserver", - "libchromium_android_linker.so", + "libchromium_android_linker$android_product_extension", ] enable_packing_arg = 0 @@ -1609,6 +1713,17 @@ template("android_apk") { dex_path = final_dex_path load_library_from_apk = _load_library_from_apk create_density_splits = _create_density_splits + if (defined(invoker.language_splits)) { + language_splits = invoker.language_splits + } + if (defined(invoker.extensions_to_not_compress)) { + extensions_to_not_compress = invoker.extensions_to_not_compress + } else { + # Allow icu data, v8 snapshots, and pak files to be loaded directly from + # the .apk. + # Note: These are actually suffix matches, not necessarily extensions. + extensions_to_not_compress = ".dat,.bin,.pak" + } version_code = _version_code version_name = _version_name @@ -1618,10 +1733,10 @@ template("android_apk") { keystore_password = _keystore_password # This target generates the input file _all_resources_zip_path. - deps = [ - ":$process_resources_target", - ":$final_dex_target_name", - ] + deps = _android_manifest_deps + [ + ":$process_resources_target", + ":$final_dex_target_name", + ] if (defined(invoker.deps)) { deps += invoker.deps } @@ -1650,6 +1765,7 @@ template("android_apk") { out_manifest = "$gen_dir/split-manifests/${android_app_abi}/AndroidManifest.xml" split_name = "abi_${android_app_abi}" + deps = _android_manifest_deps } _apk_rule = "${_template_name}__split_apk_abi_${android_app_abi}" @@ -1675,6 +1791,7 @@ template("android_apk") { native_libs_dir = _native_libs_dir deps = [ ":${_template_name}__prepare_native", + ":${_manifest_rule}", ] } } @@ -1705,6 +1822,9 @@ template("android_apk") { # srcjar_deps: List of srcjar dependencies. The .java files in the srcjars # will be added to java_files and be included in this apk. # apk_name: Name for final apk. +# support_apk_path: Path to a support apk. If present, the test runner script +# will install it on the device before running the instrumentation tests. +# Should be a path relative to the src root. # final_apk_path: Path to final built apk. Default is # $root_out_dir/apks/$apk_name.apk. Setting this will override apk_name. # native_libs: List paths of native libraries to include in this apk. If these @@ -1744,6 +1864,9 @@ template("instrumentation_test_apk") { if (defined(invoker.isolate_file)) { isolate_file = invoker.isolate_file } + if (defined(invoker.support_apk_path)) { + support_apk_path = invoker.support_apk_path + } } } @@ -1830,7 +1953,7 @@ template("unittest_apk") { if (defined(invoker.unittests_binary)) { unittests_binary = invoker.unittests_binary } else { - unittests_binary = "lib" + test_suite_name + ".so" + unittests_binary = "lib${test_suite_name}${android_product_extension}" } if (defined(invoker.apk_name)) { @@ -1856,6 +1979,7 @@ template("unittest_apk") { "//base:base_java", "//build/android/pylib/remote/device/dummy:remote_device_dummy_apk", "//testing/android/appurify_support:appurify_support_java", + "//testing/android/reporter:reporter_java", ] if (defined(invoker.deps)) { deps += invoker.deps @@ -1979,11 +2103,6 @@ template("create_native_executable_dist") { libraries_list = "${target_gen_dir}/${template_name}_library_dependencies.list" - # TODO(gyp) - #'dependencies': [ - #'<(DEPTH)/build/android/setup.gyp:copy_system_libraries', - #], - find_deps_target_name = "${template_name}__find_library_dependencies" copy_target_name = "${template_name}__copy_libraries_and_exe" @@ -2031,7 +2150,7 @@ template("create_native_executable_dist") { rebased_libraries_list = rebase_path(libraries_list, root_build_dir) args = [ "--files=$rebased_binaries_list", - "--files=@FileArg($rebased_libraries_list:libraries)", + "--files=@FileArg($rebased_libraries_list:lib_paths)", ] deps = [ diff --git a/build/config/chrome_build.gni b/build/config/chrome_build.gni index e2ff123543c61..c2132c4a1624c 100644 --- a/build/config/chrome_build.gni +++ b/build/config/chrome_build.gni @@ -6,17 +6,14 @@ declare_args() { # Selects the desired build flavor. Official builds get additional # processing to prepare for release. Normally you will want to develop and # test with this flag off. - # TODO(brettw) move here from BUILDCONFIG.gn when DEPS are updated. - #is_official_build = false + is_official_build = false # Select the desired branding flavor. False means normal Chromium branding, # true means official Google Chrome branding (requires extra Google-internal # resources). - # TODO(brettw) move here from BUILDCONFIG.gn when DEPS are updated. - #is_chrome_branded = false + is_chrome_branded = false # Break chrome.dll into multple pieces based on process type. Only available # on Windows. - # TODO(brettw) make this work. When it does, the declaration should be: is_multi_dll_chrome = is_win && !is_component_build } diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn index f7797958044ce..140e32936083c 100644 --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn @@ -13,6 +13,9 @@ if (current_cpu == "mipsel" || current_cpu == "mips64el") { if (is_posix) { import("//build/config/gcc/gcc_version.gni") } +if (is_win) { + import("//build/config/win/visual_studio_version.gni") +} import("//build/toolchain/ccache.gni") import("//build/config/sanitizers/sanitizers.gni") @@ -48,8 +51,8 @@ declare_args() { # with some utilities such as icecc and ccache. Requires gold and # gcc >= 4.8 or clang. # http://gcc.gnu.org/wiki/DebugFission - use_debug_fission = - !is_win && use_gold && linux_use_bundled_binutils && !use_ccache + use_debug_fission = is_debug && !is_win && use_gold && + linux_use_bundled_binutils && !use_ccache if (is_win) { # Whether the VS xtree header has been patched to disable warning 4702. If @@ -127,6 +130,14 @@ config("compiler") { } else { cflags += [ "-m64" ] } + if (exec_script("//build/win/use_ansi_codes.py", [], "trim string") == + "True") { + cflags += [ + # cmd.exe doesn't understand ANSI escape codes by default, + # so only enable them if something emulating them is around. + "-fansi-escape-codes", + ] + } } } else { # Common GCC compiler flags setup. @@ -405,13 +416,6 @@ config("compiler") { } else { cflags += [ "-funwind-tables" ] } - - if (is_clang && !is_nacl && !is_debug) { - # Non-unique section names appears to make linker dead stripping - # less effective. See http://crbug.com/483026#c20 - # TODO(hans): Remove this if resolved upstream. - cflags += [ "-funique-section-names" ] - } } # Linux/Android common flags setup. @@ -463,17 +467,7 @@ config("compiler") { if (!is_asan && !is_msan && !is_lsan && !is_tsan) { # TODO(brettw) common.gypi has this only for target toolset. - if (current_cpu == "x64") { - # --icf=safe disables much more folding on x86_64 than elsewhere, see - # http://crbug.com/492177. Turning it on saves over 12 MB of binary - # size, but it seems to regress cold startup time by over a second - # (see http://crbug.com/492809). - # TODO(thakis): Check if disabling ICF would inmprove android cold start - # times by several seconds too. - ldflags += [ "-Wl,--icf=safe" ] - } else { - ldflags += [ "-Wl,--icf=all" ] - } + ldflags += [ "-Wl,--icf=all" ] } # TODO(thestig): Make this flag work with GN. @@ -657,8 +651,6 @@ config("runtime_library") { # arm-linux-androideabi-4.4.3 toolchain (circa Gingerbread) will exhibit # strange errors. The include ordering here is important; change with # caution. - android_libcpp_root = "$android_ndk_root/sources/cxx-stl/llvm-libc++" - cflags += [ "-isystem" + rebase_path("$android_libcpp_root/libcxx/include", root_build_dir), @@ -671,13 +663,6 @@ config("runtime_library") { ] lib_dirs += [ "$android_libcpp_root/libs/$android_app_abi" ] - - if (component_mode == "shared_library") { - android_libcpp_library = "c++_shared" - } else { - android_libcpp_library = "c++_static" - } - libs += [ "$android_libcpp_library" ] if (current_cpu == "mipsel") { @@ -767,6 +752,12 @@ if (is_win) { # prevent it. "/wd4503", + # Warning C4589 says: "Constructor of abstract class ignores + # initializer for virtual base class." Disable this warning because it + # is flaky in VS 2015 RTM. It triggers on compiler generated + # copy-constructors in some cases. + "/wd4589", + # C4611: interaction between 'function' and C++ object destruction is # non-portable # This warning is unavoidable when using e.g. setjmp/longjmp. MSDN @@ -803,40 +794,14 @@ if (is_win) { # Keep this in sync with the similar block in build/common.gypi if (is_clang) { default_warning_flags += [ - # TODO(hans): Make this list shorter eventually. - "-Qunused-arguments", - "-Wno-c++11-compat-deprecated-writable-strings", - "-Wno-deprecated-declarations", - "-Wno-empty-body", - "-Wno-enum-conversion", - "-Wno-extra-tokens", - "-Wno-ignored-attributes", - "-Wno-incompatible-pointer-types", - "-Wno-int-to-void-pointer-cast", - "-Wno-invalid-noreturn", - "-Wno-logical-op-parentheses", - "-Wno-microsoft", - "-Wno-missing-braces", - "-Wno-missing-declarations", - "-Wno-msvc-include", - "-Wno-null-dereference", - "-Wno-overloaded-virtual", - "-Wno-parentheses", - "-Wno-pointer-sign", - "-Wno-reorder", - "-Wno-return-type-c-linkage", - "-Wno-self-assign", - "-Wno-sometimes-uninitialized", - "-Wno-switch", - "-Wno-tautological-compare", - "-Wno-unknown-pragmas", - "-Wno-unsequenced", - "-Wno-unused-function", - "-Wno-unused-private-field", - "-Wno-unused-value", - "-Wno-unused-variable", + # TODO(hans): Make this list shorter eventually, http://crbug.com/504657 + "-Qunused-arguments", # http://crbug.com/504658 + "-Wno-microsoft", # http://crbug.com/505296 + "-Wno-switch", # http://crbug.com/505308 + "-Wno-unknown-pragmas", # http://crbug.com/505314 + "-Wno-unused-function", # http://crbug.com/505316 + "-Wno-unused-value", # http://crbug.com/505318 "-Wno-unused-local-typedef", # http://crbug.com/411648 - "-Wno-inconsistent-missing-override", #http://crbug.com/428099 ] } } else { @@ -943,8 +908,11 @@ if (is_clang) { if (!is_nacl) { # Flags NaCl does not recognize. default_warning_flags += [ - # TODO(hans): Get this cleaned up. + # TODO(hans): Get this cleaned up, http://crbug.com/428099 "-Wno-inconsistent-missing-override", + + # TODO(thakis): Enable this, crbug.com/507717 + "-Wno-shift-negative-value", ] } } @@ -1016,6 +984,18 @@ config("no_chromium_code") { cflags += [ "-Wno-unused-result" ] } + if (is_clang) { + cflags += [ + # TODO(mgiuca): Move this suppression into individual third-party + # libraries as required. http://crbug.com/505301. + "-Wno-overloaded-virtual", + + # Lots of third-party libraries have unused variables. Instead of + # suppressing them individually, we just blanket suppress them here. + "-Wno-unused-variable", + ] + } + if (is_linux || is_android) { cflags += [ # Don't warn about printf format problems. This is off by default in gcc @@ -1088,12 +1068,11 @@ config("no_size_t_to_int_warning") { # configs += [ "//build/config/compiler/optimize_max" ] # Shared settings for both "optimize" and "optimize_max" configs. +# IMPORTANT: On Windows "/O1" and "/O2" must go before the common flags. if (is_win) { common_optimize_on_cflags = [ - "/O2", - "/Ob2", # both explicit and auto inlining. - "/Oy-", # disable omitting frame pointers, must be after /o2. - "/Os", # favor size over speed. + "/Ob2", # Both explicit and auto inlining. + "/Oy-", # Disable omitting frame pointers, must be after /O2. ] if (!is_asan) { common_optimize_on_cflags += [ @@ -1159,15 +1138,16 @@ if (is_win) { # Default "optimization on" config. On Windows, this favors size over speed. config("optimize") { - cflags = common_optimize_on_cflags - ldflags = common_optimize_on_ldflags if (is_win) { - cflags += [ "/Os" ] # favor size over speed. + # Favor size over speed, /O1 must be before the common flags. The GYP + # build also specifies /Os and /GF but these are implied by /O1. + cflags = [ "/O1" ] + common_optimize_on_cflags + [ "/Oi" ] } else if (is_android || is_ios) { - cflags += [ "-Os" ] # Favor size over speed. + cflags = [ "-Os" ] + common_optimize_on_cflags # Favor size over speed. } else { - cflags += [ "-O2" ] + cflags = [ "-O2" ] + common_optimize_on_cflags } + ldflags = common_optimize_on_ldflags } # Turn off optimizations. @@ -1199,11 +1179,11 @@ config("no_optimize") { # optimization and link-time code generation which is very expensive and should # be used sparingly. config("optimize_max") { - cflags = common_optimize_on_cflags ldflags = common_optimize_on_ldflags if (is_win) { - cflags -= [ "/Os" ] - cflags += [ "/Ot" ] # Favor speed over size. + # Favor speed over size, /O2 must be before the common flags. The GYP + # build also specifies /Ot, /Oi, and /GF, but these are implied by /O2. + cflags = [ "/O2" ] + common_optimize_on_cflags if (is_official_build) { # TODO(GYP): TODO(dpranke): Should these only be on in an official # build, or on all the time? For now we'll require official build so @@ -1220,7 +1200,7 @@ config("optimize_max") { ldflags += [ "/LTCG" ] } } else { - cflags += [ "-O2" ] + cflags = [ "-O2" ] + common_optimize_on_cflags } } diff --git a/build/config/crypto.gni b/build/config/crypto.gni index 4d42a375bc71e..90a45eafee860 100644 --- a/build/config/crypto.gni +++ b/build/config/crypto.gni @@ -12,10 +12,9 @@ # to set up feature flags. declare_args() { - # Use OpenSSL instead of NSS. This is used for Android, Mac, NaCl untrusted - # code, and Windows, and is experimental in other cases (see - # http://crbug.com/62803). - use_openssl = is_android || is_mac || is_nacl || is_win + # Use OpenSSL instead of NSS. This is used for all platforms but iOS. (See + # http://crbug.com/338886). + use_openssl = !is_ios } # True when we're using OpenSSL for representing certificates. When targeting diff --git a/build/config/features.gni b/build/config/features.gni index f362777e92eb6..93b19dd1431ca 100644 --- a/build/config/features.gni +++ b/build/config/features.gni @@ -125,6 +125,9 @@ use_udev = is_linux # Enable the spell checker. enable_spellcheck = !is_android +# Use the operating system's spellchecker rather than hunspell. +use_platform_spellchecker = is_android || is_mac + enable_pepper_cdms = enable_plugins && (is_linux || is_mac || is_win) # Enable basic printing support and UI. @@ -165,7 +168,8 @@ win_pdf_metafile_for_printing = true # Whether we are using the rlz library or not. Platforms like Android send # rlz codes for searches but do not use the library. -enable_rlz = is_chrome_branded && (is_win || is_mac || is_ios || is_chromeos) +enable_rlz_support = is_win || is_mac || is_ios || is_chromeos +enable_rlz = is_chrome_branded && enable_rlz_support enable_settings_app = enable_app_list && !is_chromeos @@ -183,8 +187,6 @@ enable_chromevox_next = false # Use brlapi from brltty for braille display support. use_brlapi = is_chromeos -enable_media_router = !is_ios && !is_android - # Option controlling the use of GConf (the classic GNOME configuration # system). # TODO(GYP) also require !embedded to enable. @@ -197,3 +199,6 @@ enable_hangout_services_extension = false # Whether to back up data before sync. enable_pre_sync_backup = is_win || is_mac || (is_linux && !is_chromeos) + +# WebVR support disabled until platform implementations have been added +enable_webvr = false diff --git a/build/config/linux/BUILD.gn b/build/config/linux/BUILD.gn index 3d65937dd42dd..202fd731897a8 100644 --- a/build/config/linux/BUILD.gn +++ b/build/config/linux/BUILD.gn @@ -35,25 +35,6 @@ config("sdk") { } } -pkg_config("atk") { - packages = [ "atk" ] - atk_lib_dir = exec_script(pkg_config_script, - [ - "--libdir", - "atk", - ], - "string") - defines = [ "ATK_LIB_DIR=\"$atk_lib_dir\"" ] -} - -# gn orders flags on a target before flags from configs. The default config -# adds -Wall, and these flags have to be after -Wall -- so they need to come -# from a config and can't be on the target directly. -config("atk_warnings") { - # glib uses the pre-c++11 typedef-as-static_assert hack. - cflags = [ "-Wno-unused-local-typedef" ] -} - config("fontconfig") { libs = [ "fontconfig" ] } diff --git a/build/config/sanitizers/BUILD.gn b/build/config/sanitizers/BUILD.gn index 023315f12bd45..899695127e83f 100644 --- a/build/config/sanitizers/BUILD.gn +++ b/build/config/sanitizers/BUILD.gn @@ -8,12 +8,9 @@ import("//build/config/sanitizers/sanitizers.gni") # shared_libraries. Unconditionally depend upon this target as it is empty if # |is_asan|, |is_lsan|, |is_tsan|, |is_msan| and |use_custom_libcxx| are false. group("deps") { - # TODO(vtl): Chromium has the following (but we don't have - # instrumented_libraries). - # deps = [ - # "//third_party/instrumented_libraries:deps", - # ] - deps = [] + deps = [ + "//third_party/instrumented_libraries:deps", + ] if (is_asan || is_lsan || is_tsan || is_msan) { public_configs = [ ":sanitizer_options_link_helper" ] deps += [ ":options_sources" ] diff --git a/build/config/sanitizers/sanitizers.gni b/build/config/sanitizers/sanitizers.gni index 0edc144285d30..a7b965824a714 100644 --- a/build/config/sanitizers/sanitizers.gni +++ b/build/config/sanitizers/sanitizers.gni @@ -6,9 +6,7 @@ declare_args() { # Use libc++ (buildtools/third_party/libc++ and # buildtools/third_party/libc++abi) instead of stdlibc++ as standard library. # This is intended to be used for instrumented builds. - # TODO(vtl): We don't use this, since building fails, for some reason. - use_custom_libcxx = false - # use_custom_libcxx = (is_asan && is_linux) || is_tsan || is_msan + use_custom_libcxx = (is_asan && is_linux) || is_tsan || is_msan # Track where uninitialized memory originates from. From fastest to slowest: # 0 - no tracking, 1 - track only the initial allocation site, 2 - track the diff --git a/build/config/sysroot.gni b/build/config/sysroot.gni index e5a9c2b20a1a2..ffd8921f859a6 100644 --- a/build/config/sysroot.gni +++ b/build/config/sysroot.gni @@ -36,10 +36,9 @@ if (current_toolchain == default_toolchain && target_sysroot != "") { # For official builds, use the sysroot checked into the internal source repo # so that the builds work on older versions of Linux. if (current_cpu == "x64") { - sysroot = - rebase_path("//chrome/installer/linux/debian_wheezy_amd64-sysroot") + sysroot = rebase_path("//build/linux/debian_wheezy_amd64-sysroot") } else if (current_cpu == "x86") { - sysroot = rebase_path("//chrome/installer/linux/debian_wheezy_i386-sysroot") + sysroot = rebase_path("//build/linux/debian_wheezy_i386-sysroot") } else { # Any other builds don't use a sysroot. sysroot = "" diff --git a/build/config/win/BUILD.gn b/build/config/win/BUILD.gn index 8b0910f9fd24f..261a1ac4defb6 100644 --- a/build/config/win/BUILD.gn +++ b/build/config/win/BUILD.gn @@ -103,8 +103,8 @@ if (current_cpu == "x64") { # 5.02 = Windows Server 2003. subsystem_version_suffix = ",5.02" } else { - # Don't specify a min version on x86. - subsystem_version_suffix = "" + # 5.01 = Windows XP. + subsystem_version_suffix = ",5.01" } config("console") { diff --git a/build/get_landmines.py b/build/get_landmines.py index 26b2565858e4e..873563da2aba6 100755 --- a/build/get_landmines.py +++ b/build/get_landmines.py @@ -34,7 +34,8 @@ def print_landmines(): builder() == 'ninja'): print 'Need to clobber winja goma due to backend cwd cache fix.' if platform() == 'android': - print 'Clobber because of unions.' + print 'Clobber: to handle new way of suppressing findbugs failures.' + print 'Clobber to fix gyp not rename package name (crbug.com/457038)' if platform() == 'win' and builder() == 'ninja': print 'Compile on cc_unittests fails due to symbols removed in r185063.' if platform() == 'linux' and builder() == 'ninja': @@ -72,7 +73,8 @@ def print_landmines(): print 'Remove NaCl toolchains from the output dir (crbug.com/456902)' if platform() == 'ios': print 'Clobber iOS to workaround Xcode deps bug (crbug.com/485435)' - print 'Clobber: https://github.com/domokit/mojo/issues/269' + if platform() == 'win': + print 'Clobber to delete stale generated files (crbug.com/510086)' def main(): diff --git a/build/get_sdk_extras_packages.py b/build/get_sdk_extras_packages.py index 6d870cc86f1b9..a90b8a8b4a4f2 100755 --- a/build/get_sdk_extras_packages.py +++ b/build/get_sdk_extras_packages.py @@ -13,9 +13,12 @@ def main(): with open(SDK_EXTRAS_JSON_FILE) as json_file: packages = json.load(json_file) + + out = [] for package in packages: - print package['package'].replace('_', ' ') + out.append(package['package_id']) + print ','.join(out) if __name__ == '__main__': sys.exit(main()) diff --git a/build/get_syzygy_binaries.py b/build/get_syzygy_binaries.py index 2577c7cb7fde7..1cab3fcf48dfd 100755 --- a/build/get_syzygy_binaries.py +++ b/build/get_syzygy_binaries.py @@ -5,7 +5,6 @@ """A utility script for downloading versioned Syzygy binaries.""" -import cStringIO import hashlib import errno import json @@ -17,15 +16,15 @@ import stat import sys import subprocess -import urllib2 +import tempfile +import time import zipfile _LOGGER = logging.getLogger(os.path.basename(__file__)) -# The URL where official builds are archived. -_SYZYGY_ARCHIVE_URL = ('https://syzygy-archive.commondatastorage.googleapis.com' - '/builds/official/%(revision)s') +# The relative path where official builds are archived in their GS bucket. +_SYZYGY_ARCHIVE_PATH = ('/builds/official/%(revision)s') # A JSON file containing the state of the download directory. If this file and # directory state do not agree, then the binaries will be downloaded and @@ -49,17 +48,6 @@ lambda x: x.filename.endswith('.dll.pdb'))] -def _Shell(*cmd, **kw): - """Runs |cmd|, returns the results from Popen(cmd).communicate().""" - _LOGGER.debug('Executing %s.', cmd) - prog = subprocess.Popen(cmd, shell=True, **kw) - - stdout, stderr = prog.communicate() - if prog.returncode != 0: - raise RuntimeError('Command "%s" returned %d.' % (cmd, prog.returncode)) - return (stdout, stderr) - - def _LoadState(output_dir): """Loads the contents of the state file for a given |output_dir|, returning None if it doesn't exist. @@ -248,12 +236,50 @@ def _CleanState(output_dir, state, dry_run=False): return deleted -def _Download(url): - """Downloads the given URL and returns the contents as a string.""" - response = urllib2.urlopen(url) - if response.code != 200: - raise RuntimeError('Failed to download "%s".' % url) - return response.read() +def _FindGsUtil(): + """Looks for depot_tools and returns the absolute path to gsutil.py.""" + for path in os.environ['PATH'].split(os.pathsep): + path = os.path.abspath(path) + git_cl = os.path.join(path, 'git_cl.py') + gs_util = os.path.join(path, 'gsutil.py') + if os.path.exists(git_cl) and os.path.exists(gs_util): + return gs_util + return None + + +def _GsUtil(*cmd): + """Runs the given command in gsutil with exponential backoff and retries.""" + gs_util = _FindGsUtil() + cmd = [sys.executable, gs_util] + list(cmd) + + retries = 3 + timeout = 4 # Seconds. + while True: + _LOGGER.debug('Running %s', cmd) + prog = subprocess.Popen(cmd, shell=False) + prog.communicate() + + # Stop retrying on success. + if prog.returncode == 0: + return + + # Raise a permanent failure if retries have been exhausted. + if retries == 0: + raise RuntimeError('Command "%s" returned %d.' % (cmd, prog.returncode)) + + _LOGGER.debug('Sleeping %d seconds and trying again.', timeout) + time.sleep(timeout) + retries -= 1 + timeout *= 2 + + +def _Download(resource): + """Downloads the given GS resource to a temporary file, returning its path.""" + tmp = tempfile.mkstemp(suffix='syzygy_archive') + os.close(tmp[0]) + url = 'gs://syzygy-archive' + resource + _GsUtil('cp', url, tmp[1]) + return tmp[1] def _InstallBinaries(options, deleted={}): @@ -261,7 +287,7 @@ def _InstallBinaries(options, deleted={}): already been cleaned, as it will refuse to overwrite existing files.""" contents = {} state = { 'revision': options.revision, 'contents': contents } - archive_url = _SYZYGY_ARCHIVE_URL % { 'revision': options.revision } + archive_path = _SYZYGY_ARCHIVE_PATH % { 'revision': options.revision } if options.resources: resources = [(resource, resource, '', None) for resource in options.resources] @@ -278,33 +304,37 @@ def _InstallBinaries(options, deleted={}): if not options.dry_run: os.makedirs(fulldir) - # Download the archive. - url = archive_url + '/' + base - _LOGGER.debug('Retrieving %s archive at "%s".', name, url) - data = _Download(url) + # Download and read the archive. + resource = archive_path + '/' + base + _LOGGER.debug('Retrieving %s archive at "%s".', name, resource) + path = _Download(resource) _LOGGER.debug('Unzipping %s archive.', name) - archive = zipfile.ZipFile(cStringIO.StringIO(data)) - for entry in archive.infolist(): - if not filt or filt(entry): - fullpath = os.path.normpath(os.path.join(fulldir, entry.filename)) - relpath = os.path.relpath(fullpath, options.output_dir) - if os.path.exists(fullpath): - # If in a dry-run take into account the fact that the file *would* - # have been deleted. - if options.dry_run and relpath in deleted: - pass - else: - raise Exception('Path already exists: %s' % fullpath) - - # Extract the file and update the state dictionary. - _LOGGER.debug('Extracting "%s".', fullpath) - if not options.dry_run: - archive.extract(entry.filename, fulldir) - md5 = _Md5(fullpath) - contents[relpath] = md5 - if sys.platform == 'cygwin': - os.chmod(fullpath, os.stat(fullpath).st_mode | stat.S_IXUSR) + with open(path, 'rb') as data: + archive = zipfile.ZipFile(data) + for entry in archive.infolist(): + if not filt or filt(entry): + fullpath = os.path.normpath(os.path.join(fulldir, entry.filename)) + relpath = os.path.relpath(fullpath, options.output_dir) + if os.path.exists(fullpath): + # If in a dry-run take into account the fact that the file *would* + # have been deleted. + if options.dry_run and relpath in deleted: + pass + else: + raise Exception('Path already exists: %s' % fullpath) + + # Extract the file and update the state dictionary. + _LOGGER.debug('Extracting "%s".', fullpath) + if not options.dry_run: + archive.extract(entry.filename, fulldir) + md5 = _Md5(fullpath) + contents[relpath] = md5 + if sys.platform == 'cygwin': + os.chmod(fullpath, os.stat(fullpath).st_mode | stat.S_IXUSR) + + _LOGGER.debug('Removing temporary file "%s".', path) + os.remove(path) return state @@ -316,6 +346,9 @@ def _ParseCommandLine(): help='If true then will simply list actions that would be performed.') option_parser.add_option('--force', action='store_true', default=False, help='Force an installation even if the binaries are up to date.') + option_parser.add_option('--no-cleanup', action='store_true', default=False, + help='Allow installation on non-Windows platforms, and skip the forced ' + 'cleanup step.') option_parser.add_option('--output-dir', type='string', help='The path where the binaries will be replaced. Existing binaries ' 'will only be overwritten if not up to date.') @@ -408,7 +441,10 @@ def main(): # wasn't gated on OS types, and those OSes downloaded and installed binaries. # This will cleanup orphaned files on those operating systems. if sys.platform not in ('win32', 'cygwin'): - return _RemoveOrphanedFiles(options) + if options.no_cleanup: + _LOGGER.debug('Skipping usual cleanup for non-Windows platforms.') + else: + return _RemoveOrphanedFiles(options) # Load the current installation state, and validate it against the # requested installation. diff --git a/build/gn_migration.gypi b/build/gn_migration.gypi index 0ce7b2eb5786a..2527b2e52a740 100644 --- a/build/gn_migration.gypi +++ b/build/gn_migration.gypi @@ -62,7 +62,6 @@ '../cloud_print/cloud_print.gyp:cloud_print_unittests', '../components/components.gyp:network_hints_browser', '../components/components.gyp:policy_templates', - '../components/components.gyp:webui_generator', '../components/components_tests.gyp:components_browsertests', '../components/components_tests.gyp:components_perftests', '../components/components_tests.gyp:components_unittests', @@ -473,6 +472,7 @@ 'dependencies': [ '../base/base.gyp:pe_image_test', '../chrome/chrome.gyp:crash_service', + '../chrome/chrome.gyp:setup_unittests', '../chrome_elf/chrome_elf.gyp:chrome_elf_unittests', '../chrome_elf/chrome_elf.gyp:dll_hash_main', '../components/components.gyp:wifi_test', @@ -529,30 +529,74 @@ '../components/components_tests.gyp:components_unittests_run', '../content/content_shell_and_tests.gyp:content_browsertests_run', '../content/content_shell_and_tests.gyp:content_unittests_run', - '../crypto/crypto.gyp:crypto_unittests_run', '../courgette/courgette.gyp:courgette_unittests_run', + '../crypto/crypto.gyp:crypto_unittests_run', + '../google_apis/gcm/gcm.gyp:gcm_unit_tests_run', '../gpu/gpu.gyp:gpu_unittests_run', + '../ipc/ipc.gyp:ipc_tests_run', '../media/cast/cast.gyp:cast_unittests_run', '../media/media.gyp:media_unittests_run', '../media/midi/midi.gyp:midi_unittests_run', '../net/net.gyp:net_unittests_run', + '../printing/printing.gyp:printing_unittests_run', + '../remoting/remoting.gyp:remoting_unittests_run', + '../skia/skia_tests.gyp:skia_unittests_run', '../sql/sql.gyp:sql_unittests_run', + '../sync/sync.gyp:sync_unit_tests_run', '../third_party/cacheinvalidation/cacheinvalidation.gyp:cacheinvalidation_unittests_run', + '../third_party/mojo/mojo_edk_tests.gyp:mojo_public_bindings_unittests_run', + '../tools/gn/gn.gyp:gn_unittests_run', '../ui/accessibility/accessibility.gyp:accessibility_unittests_run', '../ui/app_list/app_list.gyp:app_list_unittests_run', + '../ui/compositor/compositor.gyp:compositor_unittests_run', '../ui/events/events.gyp:events_unittests_run', + '../ui/gl/gl_tests.gyp:gl_unittests_run', '../ui/message_center/message_center.gyp:message_center_unittests_run', '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_unittests_run', + '../url/url.gyp:url_unittests_run', ], - }], - ['test_isolation_mode!="noop" and use_ash==1', { - 'dependencies': [ - '../ash/ash.gyp:ash_unittests_run', - ], - }], - ['test_isolation_mode!="noop" and OS=="linux"', { - 'dependencies': [ - '../sandbox/sandbox.gyp:sandbox_linux_unittests_run', + 'conditions': [ + ['OS=="linux"', { + 'dependencies': [ + '../sandbox/sandbox.gyp:sandbox_linux_unittests_run', + '../ui/display/display.gyp:display_unittests_run', + ], + }], + ['OS=="mac"', { + 'dependencies': [ + '../sandbox/sandbox.gyp:sandbox_mac_unittests_run', + ], + }], + ['OS=="win"', { + 'dependencies': [ + '../chrome/chrome.gyp:installer_util_unittests_run', + '../chrome/chrome.gyp:setup_unittests_run', + '../sandbox/sandbox.gyp:sbox_integration_tests', + '../sandbox/sandbox.gyp:sbox_unittests', + '../sandbox/sandbox.gyp:sbox_validation_tests', + ], + }], + ['use_ash==1', { + 'dependencies': [ + '../ash/ash.gyp:ash_unittests_run', + ], + }], + ['use_aura==1', { + 'dependencies': [ + '../ui/aura/aura.gyp:aura_unittests_run', + '../ui/wm/wm.gyp:wm_unittests_run', + ], + }], + ['enable_webrtc==1 or OS!="android"', { + 'dependencies': [ + '../jingle/jingle.gyp:jingle_unittests_run', + ], + }], + ['disable_nacl==0 and disable_nacl_untrusted==0', { + 'dependencies': [ + '../components/nacl.gyp:nacl_loader_unittests_run', + ] + }], ], }], ['use_openssl==1', { @@ -589,6 +633,7 @@ }], ['chromeos==1', { 'dependencies': [ + '../content/content_shell_and_tests.gyp:jpeg_decode_accelerator_unittest', '../content/content_shell_and_tests.gyp:video_encode_accelerator_unittest', ], }], @@ -606,7 +651,7 @@ 'dependencies': [ # TODO(GYP): Figure out which of these run on android/mac/win/ios/etc. '../net/net.gyp:net_docs', - '../remoting/app_remoting_test.gyp:ar_sample_test_driver', + '../remoting/remoting.gyp:ar_sample_test_driver', # TODO(GYP): in progress - see tfarina. '../third_party/webrtc/tools/tools.gyp:frame_analyzer', @@ -624,14 +669,13 @@ '../chrome/chrome.gyp:pack_policy_templates', '../chrome/chrome.gyp:sb_sigutil', '../chrome/chrome.gyp:setup', - '../chrome/chrome.gyp:setup_unittests', '../chrome/installer/mini_installer.gyp:mini_installer', '../chrome/tools/crash_service/caps/caps.gyp:caps', '../cloud_print/gcp20/prototype/gcp20_device.gyp:gcp20_device', '../cloud_print/gcp20/prototype/gcp20_device.gyp:gcp20_device_unittests', - '../cloud_print/service/service.gyp:cloud_print_service', - '../cloud_print/service/service.gyp:cloud_print_service_config', - '../cloud_print/service/service.gyp:cloud_print_service_setup', + '../cloud_print/service/win/service.gyp:cloud_print_service', + '../cloud_print/service/win/service.gyp:cloud_print_service_config', + '../cloud_print/service/win/service.gyp:cloud_print_service_setup', '../cloud_print/virtual_driver/win/install/virtual_driver_install.gyp:virtual_driver_setup', '../cloud_print/virtual_driver/win/virtual_driver.gyp:gcp_portmon', '../components/test_runner/test_runner.gyp:layout_test_helper', @@ -640,7 +684,7 @@ '../gpu/gpu.gyp:angle_perftests', '../net/net.gyp:net_docs', '../ppapi/ppapi_internal.gyp:ppapi_perftests', - '../remoting/app_remoting_test.gyp:ar_sample_test_driver', + '../remoting/remoting.gyp:ar_sample_test_driver', '../remoting/remoting.gyp:remoting_breakpad_tester', '../remoting/remoting.gyp:remoting_console', '../remoting/remoting.gyp:remoting_desktop', diff --git a/build/gyp_chromium_test.py.remove b/build/gyp_chromium_test.py similarity index 100% rename from build/gyp_chromium_test.py.remove rename to build/gyp_chromium_test.py diff --git a/build/host_jar.gypi b/build/host_jar.gypi index 9c35177872ce9..a47f6bbdd99dd 100644 --- a/build/host_jar.gypi +++ b/build/host_jar.gypi @@ -53,6 +53,8 @@ 'jar_path': '<(jar_dir)/<(jar_name)', 'main_class%': '', 'stamp': '<(intermediate_dir)/jar.stamp', + 'enable_errorprone%': '0', + 'errorprone_exe_path': '<(PRODUCT_DIR)/bin.java/chromium_errorprone', }, 'all_dependent_settings': { 'variables': { @@ -64,18 +66,25 @@ 'action_name': 'javac_<(_target_name)', 'message': 'Compiling <(_target_name) java sources', 'variables': { - 'extra_options': [], + 'extra_args': [], + 'extra_inputs': [], 'java_sources': [ '(main_class)'] - }] + 'extra_args': ['--main-class=>(main_class)'] + }], + ['enable_errorprone == 1', { + 'extra_inputs': [ + '<(errorprone_exe_path)', + ], + 'extra_args': [ '--use-errorprone-path=<(errorprone_exe_path)' ], + }], ], }, 'inputs': [ @@ -83,6 +92,7 @@ '<(DEPTH)/build/android/gyp/javac.py', '^@(java_sources)', '>@(input_jars_paths)', + '<@(extra_inputs)', ], 'outputs': [ '<(jar_path)', @@ -95,7 +105,7 @@ '--chromium-code=<(chromium_code)', '--stamp=<(stamp)', '--jar-path=<(jar_path)', - '<@(extra_options)', + '<@(extra_args)', '^@(java_sources)', ], }, @@ -125,7 +135,12 @@ ] } ] - }] + }], + ['enable_errorprone == 1', { + 'dependencies': [ + '<(DEPTH)/third_party/errorprone/errorprone.gyp:chromium_errorprone', + ], + }], ] } diff --git a/build/install-android-sdks.sh b/build/install-android-sdks.sh index 5c4edafec5b4a..1119b7d7fddee 100755 --- a/build/install-android-sdks.sh +++ b/build/install-android-sdks.sh @@ -12,14 +12,9 @@ echo 'checking for sdk packages install' cwd=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) # Get the SDK extras packages to install from the DEPS file 'sdkextras' hook. packages="$(python ${cwd}/get_sdk_extras_packages.py)" -for package in "${packages}"; do - pkg_id=$(${cwd}/../third_party/android_tools/sdk/tools/android list sdk | \ - grep -i "$package," | \ - awk '/^[ ]*[0-9]*- / {gsub("-",""); print $1}') - if [[ -n ${pkg_id} ]]; then - ${cwd}/../third_party/android_tools/sdk/tools/android update sdk --no-ui \ - --filter ${pkg_id} - fi -done +if [[ -n "${packages}" ]]; then + ${cwd}/../third_party/android_tools/sdk/tools/android update sdk --no-ui \ + --filter ${packages} +fi echo "install-android-sdks.sh complete." diff --git a/build/install-build-deps-mac.sh b/build/install-build-deps-mac.sh deleted file mode 100755 index 625ddf4a64823..0000000000000 --- a/build/install-build-deps-mac.sh +++ /dev/null @@ -1,64 +0,0 @@ -#!/bin/bash -e - -# Copyright (c) 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -# -# Script to install dependencies for developing Mojo on Mac OS X. - -XCODE_APP="/Applications/Xcode.app" -JDK_VERSION="1.7.0" - -echo - -INSTRUCTIONS="" - -if [ ! -d $XCODE_APP ]; then - INSTRUCTIONS="${INSTRUCTIONS}\n** Install the latest version of Xcode from the Mac App Store." -fi - -if [ -z $(which java) ] || ! java -version 2>&1 | grep -q ${JDK_VERSION}; then - temp=$( - echo "** Download the Java JDK (Java SE Development Kit) 7:" - echo " http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html" - ) - - INSTRUCTIONS="${INSTRUCTIONS}\n$temp" -fi - - -if [ -z $(which gclient) ] && [ ! -d $HOME/depot_tools ]; then - echo "*** Installing depot_tools in $HOME" - echo - cd $HOME - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git - - temp=$( - echo "** Add this to your .bash_profile or similar:" - echo " export PATH=\"\${HOME}/depot_tools:\${PATH}\"" - ) - - INSTRUCTIONS="${INSTRUCTIONS}\n$temp" -fi - -if [ ! -z $(which brew) ]; then - brew install ant -elif [ ! -z $(which port) ]; then - sudo `which port` install apache-ant -else - INSTRUCTIONS="${INSTRUCTIONS}\n** Install homebrew (brew.sh) or macports (macports.org) and re-run this script." -fi - -sudo easy_install pip -sudo pip install requests - - -echo -echo "All done!" - -if [ ! -z "$INSTRUCTIONS" ]; then - echo - echo - echo "**** Follow these final instructions to get going." - echo $INSTRUCTIONS -fi diff --git a/build/install-build-deps.py b/build/install-build-deps.py new file mode 100755 index 0000000000000..7cc3760df7541 --- /dev/null +++ b/build/install-build-deps.py @@ -0,0 +1,430 @@ +#!/usr/bin/env python +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import argparse +import operator +import os +import platform +import re +import subprocess +import sys + + +SUPPORTED_UBUNTU_VERSIONS = ( + {'number': '12.04', 'codename': 'precise'}, + {'number': '14.04', 'codename': 'trusty'}, + {'number': '14.10', 'codename': 'utopic'}, + {'number': '15.04', 'codename': 'vivid'}, +) + + +# Packages needed for chromeos only. +_packages_chromeos_dev = ( + 'libbluetooth-dev', + 'libxkbcommon-dev', + 'realpath', +) + + +# Packages needed for development. +_packages_dev = ( + 'apache2.2-bin', + 'bison', + 'cdbs', + 'curl', + 'devscripts', + 'dpkg-dev', + 'elfutils', + 'fakeroot', + 'flex', + 'fonts-thai-tlwg', + 'g++', + 'git-core', + 'git-svn', + 'gperf', + 'language-pack-da', + 'language-pack-fr', + 'language-pack-he', + 'language-pack-zh-hant', + 'libapache2-mod-php5', + 'libasound2-dev', + 'libav-tools', + 'libbrlapi-dev', + 'libbz2-dev', + 'libcairo2-dev', + 'libcap-dev', + 'libcups2-dev', + 'libcurl4-gnutls-dev', + 'libdrm-dev', + 'libelf-dev', + 'libexif-dev', + 'libgconf2-dev', + 'libglib2.0-dev', + 'libglu1-mesa-dev', + 'libgnome-keyring-dev', + 'libgtk2.0-dev', + 'libkrb5-dev', + 'libnspr4-dev', + 'libnss3-dev', + 'libpam0g-dev', + 'libpci-dev', + 'libpulse-dev', + 'libsctp-dev', + 'libspeechd-dev', + 'libsqlite3-dev', + 'libssl-dev', + 'libudev-dev', + 'libwww-perl', + 'libxslt1-dev', + 'libxss-dev', + 'libxt-dev', + 'libxtst-dev', + 'openbox', + 'patch', + 'perl', + 'php5-cgi', + 'pkg-config', + 'python', + 'python-cherrypy3', + 'python-crypto', + 'python-dev', + 'python-numpy', + 'python-opencv', + 'python-openssl', + 'python-psutil', + 'python-yaml', + 'rpm', + 'ruby', + 'subversion', + 'ttf-dejavu-core', + 'ttf-indic-fonts', + 'ttf-kochi-gothic', + 'ttf-kochi-mincho', + 'wdiff', + 'xfonts-mathml', + 'zip', +) + + +# Run-time libraries required by chromeos only. +_packages_chromeos_lib = ( + 'libbz2-1.0', + 'libpulse0', +) + + +# Full list of required run-time libraries. +_packages_lib = ( + 'libasound2', + 'libatk1.0-0', + 'libc6', + 'libcairo2', + 'libcap2', + 'libcups2', + 'libexif12', + 'libexpat1', + 'libfontconfig1', + 'libfreetype6', + 'libglib2.0-0', + 'libgnome-keyring0', + 'libgtk2.0-0', + 'libpam0g', + 'libpango1.0-0', + 'libpci3', + 'libpcre3', + 'libpixman-1-0', + 'libpng12-0', + 'libspeechd2', + 'libsqlite3-0', + 'libstdc++6', + 'libx11-6', + 'libxau6', + 'libxcb1', + 'libxcomposite1', + 'libxcursor1', + 'libxdamage1', + 'libxdmcp6', + 'libxext6', + 'libxfixes3', + 'libxi6', + 'libxinerama1', + 'libxrandr2', + 'libxrender1', + 'libxtst6', + 'zlib1g', +) + + +# Debugging symbols for all of the run-time libraries. +_packages_dbg = ( + 'libatk1.0-dbg', + 'libc6-dbg', + 'libcairo2-dbg', + 'libfontconfig1-dbg', + 'libglib2.0-0-dbg', + 'libgtk2.0-0-dbg', + 'libpango1.0-0-dbg', + 'libpcre3-dbg', + 'libpixman-1-0-dbg', + 'libsqlite3-0-dbg', + 'libx11-6-dbg', + 'libxau6-dbg', + 'libxcb1-dbg', + 'libxcomposite1-dbg', + 'libxcursor1-dbg', + 'libxdamage1-dbg', + 'libxdmcp6-dbg', + 'libxext6-dbg', + 'libxfixes3-dbg', + 'libxi6-dbg', + 'libxinerama1-dbg', + 'libxrandr2-dbg', + 'libxrender1-dbg', + 'libxtst6-dbg', + 'zlib1g-dbg', +) + + +# 32-bit libraries needed e.g. to compile V8 snapshot for Android or armhf. +_packages_lib32 = ( + 'linux-libc-dev:i386', +) + + +# arm cross toolchain packages needed to build chrome on armhf. +_packages_arm = ( + 'g++-arm-linux-gnueabihf', + 'libc6-dev-armhf-cross', + 'linux-libc-dev-armhf-cross', +) + + +# Packages to build NaCl, its toolchains, and its ports. +_packages_naclports = ( + 'ant', + 'autoconf', + 'bison', + 'cmake', + 'gawk', + 'intltool', + 'xsltproc', + 'xutils-dev', +) +_packages_nacl = ( + 'g++-mingw-w64-i686', + 'lib32ncurses5-dev', + 'lib32z1-dev', + 'libasound2:i386', + 'libcap2:i386', + 'libelf-dev:i386', + 'libexif12:i386', + 'libfontconfig1:i386', + 'libgconf-2-4:i386', + 'libglib2.0-0:i386', + 'libgpm2:i386', + 'libgtk2.0-0:i386', + 'libncurses5:i386', + 'libnss3:i386', + 'libpango1.0-0:i386', + 'libssl1.0.0:i386', + 'libtinfo-dev', + 'libtinfo-dev:i386', + 'libtool', + 'libxcomposite1:i386', + 'libxcursor1:i386', + 'libxdamage1:i386', + 'libxi6:i386', + 'libxrandr2:i386', + 'libxss1:i386', + 'libxtst6:i386', + 'texinfo', + 'xvfb', +) + + +def is_userland_64_bit(): + return platform.architecture()[0] == '64bit' + + +def package_exists(pkg): + return pkg in subprocess.check_output(['apt-cache', 'pkgnames']).splitlines() + + +def lsb_release_short_codename(): + return subprocess.check_output( + ['lsb_release', '--codename', '--short']).strip() + + +def write_error(message): + sys.stderr.write('ERROR: %s\n' % message) + sys.stderr.flush() + + +def nonfatal_get_output(*popenargs, **kwargs): + process = subprocess.Popen( + stdout=subprocess.PIPE, stderr=subprocess.PIPE, *popenargs, **kwargs) + stdout, stderr = process.communicate() + retcode = process.poll() + return retcode, stdout, stderr + + +def compute_dynamic_package_lists(): + global _packages_arm + global _packages_dbg + global _packages_dev + global _packages_lib + global _packages_lib32 + global _packages_nacl + + if is_userland_64_bit(): + # 64-bit systems need a minimum set of 32-bit compat packages + # for the pre-built NaCl binaries. + _packages_dev += ( + 'lib32gcc1', + 'lib32stdc++6', + 'libc6-i386', + ) + + # When cross building for arm/Android on 64-bit systems the host binaries + # that are part of v8 need to be compiled with -m32 which means + # that basic multilib support is needed. + # gcc-multilib conflicts with the arm cross compiler (at least in trusty) + # but g++-X.Y-multilib gives us the 32-bit support that we need. Find out + # the appropriate value of X and Y by seeing what version the current + # distribution's g++-multilib package depends on. + output = subprocess.check_output(['apt-cache', 'depends', 'g++-multilib']) + multilib_package = re.search(r'g\+\+-[0-9.]+-multilib', output).group() + _packages_lib32 += (multilib_package,) + + lsb_codename = lsb_release_short_codename() + + # Find the proper version of libstdc++6-4.x-dbg. + if lsb_codename == 'precise': + _packages_dbg += ('libstdc++6-4.6-dbg',) + elif lsb_codename == 'trusty': + _packages_dbg += ('libstdc++6-4.8-dbg',) + else: + _packages_dbg += ('libstdc++6-4.9-dbg',) + + # Work around for dependency issue Ubuntu/Trusty: http://crbug.com/435056 . + if lsb_codename == 'trusty': + _packages_arm += ( + 'g++-4.8-multilib-arm-linux-gnueabihf', + 'gcc-4.8-multilib-arm-linux-gnueabihf', + ) + + # Find the proper version of libgbm-dev. We can't just install libgbm-dev as + # it depends on mesa, and only one version of mesa can exists on the system. + # Hence we must match the same version or this entire script will fail. + mesa_variant = '' + for variant in ('-lts-trusty', '-lts-utopic'): + rc, stdout, stderr = nonfatal_get_output( + ['dpkg-query', '-Wf\'{Status}\'', 'libgl1-mesa-glx' + variant]) + if 'ok installed' in output: + mesa_variant = variant + _packages_dev += ( + 'libgbm-dev' + mesa_variant, + 'libgl1-mesa-dev' + mesa_variant, + 'libgles2-mesa-dev' + mesa_variant, + 'mesa-common-dev' + mesa_variant, + ) + + if package_exists('ttf-mscorefonts-installer'): + _packages_dev += ('ttf-mscorefonts-installer',) + else: + _packages_dev += ('msttcorefonts',) + + if package_exists('libnspr4-dbg'): + _packages_dbg += ('libnspr4-dbg', 'libnss3-dbg') + _packages_lib += ('libnspr4', 'libnss3') + else: + _packages_dbg += ('libnspr4-0d-dbg', 'libnss3-1d-dbg') + _packages_lib += ('libnspr4-0d', 'libnss3-1d') + + if package_exists('libjpeg-dev'): + _packages_dev += ('libjpeg-dev',) + else: + _packages_dev += ('libjpeg62-dev',) + + if package_exists('libudev1'): + _packages_dev += ('libudev1',) + _packages_nacl += ('libudev1:i386',) + else: + _packages_dev += ('libudev0',) + _packages_nacl += ('libudev0:i386',) + + if package_exists('libbrlapi0.6'): + _packages_dev += ('libbrlapi0.6',) + else: + _packages_dev += ('libbrlapi0.5',) + + # Some packages are only needed if the distribution actually supports + # installing them. + if package_exists('appmenu-gtk'): + _packages_lib += ('appmenu-gtk',) + + _packages_dev += _packages_chromeos_dev + _packages_lib += _packages_chromeos_lib + _packages_nacl += _packages_naclports + + +def quick_check(packages): + rc, stdout, stderr = nonfatal_get_output([ + 'dpkg-query', '-W', '-f', '${PackageSpec}:${Status}\n'] + list(packages)) + if rc == 0 and not stderr: + return 0 + print stderr + return 1 + + +def main(argv): + parser = argparse.ArgumentParser() + parser.add_argument('--quick-check', action='store_true', + help='quickly try to determine if dependencies are ' + 'installed (this avoids interactive prompts and ' + 'sudo commands so might not be 100% accurate)') + parser.add_argument('--unsupported', action='store_true', + help='attempt installation even on unsupported systems') + args = parser.parse_args(argv) + + lsb_codename = lsb_release_short_codename() + if not args.unsupported and not args.quick_check: + if lsb_codename not in map( + operator.itemgetter('codename'), SUPPORTED_UBUNTU_VERSIONS): + supported_ubuntus = ['%(number)s (%(codename)s)' % v + for v in SUPPORTED_UBUNTU_VERSIONS] + write_error('Only Ubuntu %s are currently supported.' % + ', '.join(supported_ubuntus)) + return 1 + + if platform.machine() not in ('i686', 'x86_64'): + write_error('Only x86 architectures are currently supported.') + return 1 + + if os.geteuid() != 0 and not args.quick_check: + print 'Running as non-root user.' + print 'You might have to enter your password one or more times' + print 'for \'sudo\'.' + print + + compute_dynamic_package_lists() + + packages = (_packages_dev + _packages_lib + _packages_dbg + _packages_lib32 + + _packages_arm + _packages_nacl) + def packages_key(pkg): + s = pkg.rsplit(':', 1) + if len(s) == 1: + return (s, '') + return s + packages = sorted(set(packages), key=packages_key) + + if args.quick_check: + return quick_check(packages) + + return 0 + + +if __name__ == '__main__': + sys.exit(main(sys.argv[1:])) diff --git a/build/install-chroot.sh b/build/install-chroot.sh index e2d558b76c4b3..99451ed7ea49e 100755 --- a/build/install-chroot.sh +++ b/build/install-chroot.sh @@ -223,7 +223,8 @@ target="${distname}${arch}" d|D) sudo rm -rf "/var/lib/chroot/${target}" \ "/usr/local/bin/${target%bit}" \ "/etc/schroot/mount-${target}" \ - "/etc/schroot/script-${target}" + "/etc/schroot/script-${target}" \ + "/etc/schroot/${target}" sudo sed -ni '/^[[]'"${target%bit}"']$/,${ :1;n;/^[[]/b2;b1;:2;p;n;b2};p' \ "/etc/schroot/schroot.conf" @@ -349,13 +350,41 @@ grep -qs ubuntu.com /usr/share/debootstrap/scripts/"${distname}" && if [ -z "${chroot_groups}" ]; then chroot_groups="${admin},$(id -gn)" fi -# Older versions of schroot wanted a "priority=" line, whereas recent -# versions deprecate "priority=" and warn if they see it. We don't have -# a good feature test, but scanning for the string "priority=" in the -# existing "schroot.conf" file is a good indication of what to do. -priority=$(grep -qs 'priority=' /etc/schroot/schroot.conf && + +if [ -d '/etc/schroot/default' ]; then + new_version=1 + fstab="/etc/schroot/${target}/fstab" +else + new_version=0 + fstab="/etc/schroot/mount-${target}" +fi + +if [ "$new_version" = "1" ]; then + sudo cp -ar /etc/schroot/default /etc/schroot/${target} + + sudo sh -c 'cat >>/etc/schroot/schroot.conf' <>${fstab}" +else + # Older versions of schroot wanted a "priority=" line, whereas recent + # versions deprecate "priority=" and warn if they see it. We don't have + # a good feature test, but scanning for the string "priority=" in the + # existing "schroot.conf" file is a good indication of what to do. + priority=$(grep -qs 'priority=' /etc/schroot/schroot.conf && echo 'priority=3' || :) -sudo sh -c 'cat >>/etc/schroot/schroot.conf' <>/etc/schroot/schroot.conf' </etc/schroot/script-'"${target}" -sed '\,^/home[/[:space:]],s/\([,[:space:]]\)bind[[:space:]]/\1rbind /' \ - /etc/schroot/mount-defaults | - sudo sh -c 'cat > /etc/schroot/mount-'"${target}" + # Set up a list of mount points that is specific to this + # chroot environment. + sed '/^FSTAB=/s,"[^"]*","'"${fstab}"'",' \ + /etc/schroot/script-defaults | + sudo sh -c 'cat >/etc/schroot/script-'"${target}" + sed '\,^/home[/[:space:]],s/\([,[:space:]]\)bind[[:space:]]/\1rbind /' \ + /etc/schroot/mount-defaults | + sudo sh -c "cat > ${fstab}" +fi # Add the extra mount points that the user told us about [ -n "${bind_mounts}" -a "${bind_mounts}" != "NONE" ] && printf "${bind_mounts}" | - sudo sh -c 'cat >>/etc/schroot/mount-'"${target}" + sudo sh -c 'cat >>'"${fstab}" # If this system has a "/media" mountpoint, import it into the chroot # environment. Most modern distributions use this mount point to # automatically mount devices such as CDROMs, USB sticks, etc... if [ -d /media ] && - ! grep -qs '^/media' /etc/schroot/mount-"${target}"; then + ! grep -qs '^/media' "${fstab}"; then echo '/media /media none rw,rbind 0 0' | - sudo sh -c 'cat >>/etc/schroot/mount-'"${target}" + sudo sh -c 'cat >>'"${fstab}" fi # Share /dev/shm, /run and /run/shm. -grep -qs '^/dev/shm' /etc/schroot/mount-"${target}" || +grep -qs '^/dev/shm' "${fstab}" || echo '/dev/shm /dev/shm none rw,bind 0 0' | - sudo sh -c 'cat >>/etc/schroot/mount-'"${target}" + sudo sh -c 'cat >>'"${fstab}" if [ ! -d "/var/lib/chroot/${target}/run" ] && - ! grep -qs '^/run' /etc/schroot/mount-"${target}"; then + ! grep -qs '^/run' "${fstab}"; then echo '/run /run none rw,bind 0 0' | - sudo sh -c 'cat >>/etc/schroot/mount-'"${target}" + sudo sh -c 'cat >>'"${fstab}" fi -if ! grep -qs '^/run/shm' /etc/schroot/mount-"${target}"; then +if ! grep -qs '^/run/shm' "${fstab}"; then { [ -d /run ] && echo '/run/shm /run/shm none rw,bind 0 0' || echo '/dev/shm /run/shm none rw,bind 0 0'; } | - sudo sh -c 'cat >>/etc/schroot/mount-'"${target}" + sudo sh -c 'cat >>'"${fstab}" fi # Set up a special directory that changes contents depending on the target @@ -412,7 +442,7 @@ fi d="$(readlink -f "${HOME}/chroot" 2>/dev/null || echo "${HOME}/chroot")" s="${d}/.${target}" echo "${s} ${d} none rw,bind 0 0" | - sudo sh -c 'cat >>/etc/schroot/mount-'"${target}" + sudo sh -c 'cat >>'"${target}" mkdir -p "${s}" # Install a helper script to launch commands in the chroot @@ -717,7 +747,7 @@ if [ -x "${script}" ]; then # installing the Chrome build depencies. This prevents the chroot # session from being closed. So, we always try to shut down any running # instance of dbus and rsyslog. - sudo /usr/local/bin/"${target%bit}" sh -c "${script} --no-lib32; + sudo /usr/local/bin/"${target%bit}" sh -c "${script}; rc=$?; /etc/init.d/cron stop >/dev/null 2>&1 || :; /etc/init.d/rsyslog stop >/dev/null 2>&1 || :; diff --git a/build/internal/release_impl_official.gypi b/build/internal/release_impl_official.gypi index d0729a97e5dc1..36d5d787e9b35 100644 --- a/build/internal/release_impl_official.gypi +++ b/build/internal/release_impl_official.gypi @@ -8,7 +8,6 @@ 'VCCLCompilerTool': { 'InlineFunctionExpansion': '2', 'EnableIntrinsicFunctions': 'true', - 'EnableFiberSafeOptimizations': 'true', 'OmitFramePointers': 'false', # The above is not sufficient (http://crbug.com/106711): it # simply eliminates an explicit "/Oy", but both /O2 and /Ox diff --git a/build/ios/grit_whitelist.txt b/build/ios/grit_whitelist.txt index 8fb4f0ec9045c..a976daf16b525 100644 --- a/build/ios/grit_whitelist.txt +++ b/build/ios/grit_whitelist.txt @@ -21,6 +21,7 @@ IDR_DEFAULT_FAVICON_64 IDR_DIR_HEADER_HTML IDR_DISTILLABLE_PAGE_SERIALIZED_MODEL IDR_DISTILLER_CSS +IDR_DISTILLER_IOS_CSS IDR_DISTILLER_JS IDR_DOM_DISTILLER_VIEWER_HTML IDR_DOM_DISTILLER_VIEWER_JS @@ -104,7 +105,6 @@ IDR_TRANSLATE_JS IDR_UBER_UTILS_JS IDR_WEBUI_CSS_TEXT_DEFAULTS IDR_WEBUI_I18N_TEMPLATE_JS -IDR_WEBUI_I18N_TEMPLATE_POLYMER_JS IDR_WEBUI_JSTEMPLATE_JS IDR_WEBUI_JS_LOAD_TIME_DATA IDS_ABOUT_MAC @@ -143,8 +143,6 @@ IDS_AUTOFILL_CARD_UNMASK_PROMPT_INSTRUCTIONS IDS_AUTOFILL_CARD_UNMASK_PROMPT_INSTRUCTIONS_AMEX IDS_AUTOFILL_CARD_UNMASK_PROMPT_INSTRUCTIONS_EXPIRED IDS_AUTOFILL_CARD_UNMASK_PROMPT_INSTRUCTIONS_EXPIRED_AMEX -IDS_AUTOFILL_CARD_UNMASK_PROMPT_TITLE -IDS_AUTOFILL_CARD_UNMASK_PROMPT_UPDATE_TITLE IDS_AUTOFILL_CC_AMEX IDS_AUTOFILL_CC_AMEX_SHORT IDS_AUTOFILL_CC_DINERS @@ -326,6 +324,7 @@ IDS_DOM_DISTILLER_JAVASCRIPT_DISABLED_CONTENT IDS_DOM_DISTILLER_QUALITY_ANSWER_NO IDS_DOM_DISTILLER_QUALITY_ANSWER_YES IDS_DOM_DISTILLER_QUALITY_QUESTION +IDS_DOM_DISTILLER_VIEWER_CLOSE_READER_VIEW IDS_DOM_DISTILLER_VIEWER_FAILED_TO_FIND_ARTICLE_CONTENT IDS_DOM_DISTILLER_VIEWER_FAILED_TO_FIND_ARTICLE_TITLE IDS_DOM_DISTILLER_VIEWER_LOADING_STRING @@ -536,12 +535,12 @@ IDS_FLAGS_DISABLE_WEBGL_NAME IDS_FLAGS_DISABLE_WEBRTC_DESCRIPTION IDS_FLAGS_DISABLE_WEBRTC_NAME IDS_FLAGS_ENABLE +IDS_FLAGS_ENABLE_ACCELERATED_MJPEG_DECODE_DESCRIPTION +IDS_FLAGS_ENABLE_ACCELERATED_MJPEG_DECODE_NAME IDS_FLAGS_ENABLE_APPS_SHOW_ON_FIRST_PAINT_DESCRIPTION IDS_FLAGS_ENABLE_APPS_SHOW_ON_FIRST_PAINT_NAME IDS_FLAGS_ENABLE_CONTEXTUAL_SEARCH IDS_FLAGS_ENABLE_CONTEXTUAL_SEARCH_DESCRIPTION -IDS_FLAGS_ENABLE_DEFERRED_IMAGE_DECODING_DESCRIPTION -IDS_FLAGS_ENABLE_DEFERRED_IMAGE_DECODING_NAME IDS_FLAGS_ENABLE_DEVTOOLS_EXPERIMENTS_DESCRIPTION IDS_FLAGS_ENABLE_DEVTOOLS_EXPERIMENTS_NAME IDS_FLAGS_ENABLE_DOWNLOAD_RESUMPTION_DESCRIPTION @@ -820,9 +819,7 @@ IDS_PAGE_INFO_SECURITY_TAB_SECURE_IDENTITY_NO_CT IDS_PAGE_INFO_SECURITY_TAB_SSL_VERSION IDS_PAGE_INFO_SECURITY_TAB_UNABLE_TO_CHECK_REVOCATION IDS_PAGE_INFO_SECURITY_TAB_UNKNOWN_PARTY -IDS_PAGE_INFO_SECURITY_TAB_VISITED_BEFORE_TODAY IDS_PAGE_INFO_SECURITY_TAB_WEAK_ENCRYPTION_CONNECTION_TEXT -IDS_PAGE_INFO_SITE_INFO_TITLE IDS_PASSWORDS_EXCEPTIONS_TAB_TITLE IDS_PASSWORDS_SHOW_PASSWORDS_TAB_TITLE IDS_PASSWORD_MANAGER_BLACKLIST_BUTTON diff --git a/build/java.gypi b/build/java.gypi index cee70e5676005..73c550de071e3 100644 --- a/build/java.gypi +++ b/build/java.gypi @@ -79,8 +79,11 @@ 'never_lint%': 0, 'findbugs_stamp': '<(intermediate_dir)/findbugs.stamp', 'run_findbugs%': 0, + 'java_in_dir_suffix%': '/src', 'proguard_config%': '', 'proguard_preprocess%': '0', + 'enable_errorprone%': '0', + 'errorprone_exe_path': '<(PRODUCT_DIR)/bin.java/chromium_errorprone', 'variables': { 'variables': { 'proguard_preprocess%': 0, @@ -244,13 +247,28 @@ }, ], }], + ['enable_errorprone == 1', { + 'dependencies': [ + '<(DEPTH)/third_party/errorprone/errorprone.gyp:chromium_errorprone', + ], + }], ], 'actions': [ { 'action_name': 'javac_<(_target_name)', 'message': 'Compiling <(_target_name) java sources', 'variables': { - 'java_sources': ['>!@(find >(java_in_dir)/src >(additional_src_dirs) -name "*.java")'], + 'extra_args': [], + 'extra_inputs': [], + 'java_sources': ['>!@(find >(java_in_dir)>(java_in_dir_suffix) >(additional_src_dirs) -name "*.java")'], + 'conditions': [ + ['enable_errorprone == 1', { + 'extra_inputs': [ + '<(errorprone_exe_path)', + ], + 'extra_args': [ '--use-errorprone-path=<(errorprone_exe_path)' ], + }], + ], }, 'inputs': [ '<(DEPTH)/build/android/gyp/util/build_utils.py', @@ -258,6 +276,7 @@ '>@(java_sources)', '>@(input_jars_paths)', '>@(additional_input_paths)', + '<@(extra_inputs)', ], 'outputs': [ '<(compile_stamp)', @@ -265,6 +284,7 @@ ], 'action': [ 'python', '<(DEPTH)/build/android/gyp/javac.py', + '--bootclasspath=<(android_sdk_jar)', '--classpath=>(input_jars_paths)', '--src-gendirs=>(generated_src_dirs)', '--javac-includes=<(javac_includes)', @@ -273,6 +293,7 @@ '--jar-excluded-classes=<(jar_excluded_classes)', '--stamp=<(compile_stamp)', '>@(java_sources)', + '<@(extra_args)', ] }, { @@ -295,7 +316,7 @@ { 'variables': { 'src_dirs': [ - '<(java_in_dir)/src', + '<(java_in_dir)<(java_in_dir_suffix)', '>@(additional_src_dirs)', ], 'stamp_path': '<(lint_stamp)', diff --git a/build/java_apk.gypi b/build/java_apk.gypi index 976c90e4a57b4..ff837c38e71ec 100644 --- a/build/java_apk.gypi +++ b/build/java_apk.gypi @@ -31,8 +31,10 @@ # additional_bundled_libs - Additional libraries what will be stripped and # bundled in the apk. # asset_location - The directory where assets are located. -# create_density_splits - Whether to create density-based apk splits. Splits +# create_abi_split - Whether to create abi-based spilts. Splits # are supported only for minSdkVersion >= 21. +# create_density_splits - Whether to create density-based apk splits. +# language_splits - List of languages to create apk splits for. # generated_src_dirs - Same as additional_src_dirs except used for .java files # that are generated at build time. This should be set automatically by a # target's dependencies. The .java files in these directories are not @@ -70,6 +72,7 @@ 'tested_apk_dex_path%': '/', 'additional_input_paths': [], 'create_density_splits%': 0, + 'language_splits': [], 'input_jars_paths': [], 'library_dexed_jars_paths': [], 'additional_src_dirs': [], @@ -89,7 +92,9 @@ 'additional_res_packages': [], 'additional_bundled_libs%': [], 'is_test_apk%': 0, - 'extensions_to_not_compress%': '', + # Allow icu data, v8 snapshots, and pak files to be loaded directly from the .apk. + # Note: These are actually suffix matches, not necessarily extensions. + 'extensions_to_not_compress%': '.dat,.bin,.pak', 'resource_input_paths': [], 'intermediate_dir': '<(PRODUCT_DIR)/<(_target_name)', 'asset_location%': '<(intermediate_dir)/assets', @@ -115,7 +120,7 @@ 'instr_stamp': '<(intermediate_dir)/instr.stamp', 'jar_stamp': '<(intermediate_dir)/jar.stamp', 'obfuscate_stamp': '<(intermediate_dir)/obfuscate.stamp', - 'pack_arm_relocations_stamp': '<(intermediate_dir)/pack_arm_relocations.stamp', + 'pack_relocations_stamp': '<(intermediate_dir)/pack_relocations.stamp', 'strip_stamp': '<(intermediate_dir)/strip.stamp', 'stripped_libraries_dir': '<(intermediate_dir)/stripped_libraries', 'strip_additional_stamp': '<(intermediate_dir)/strip_additional.stamp', @@ -208,6 +213,8 @@ 'native_lib_placeholder_stamp': '<(apk_package_native_libs_dir)/<(android_app_abi)/native_lib_placeholder.stamp', 'native_lib_placeholders': [], 'main_apk_name': '<(apk_name)', + 'enable_errorprone%': '0', + 'errorprone_exe_path': '<(PRODUCT_DIR)/bin.java/chromium_errorprone', }, # Pass the jar path to the apk's "fake" jar target. This would be better as # direct_dependent_settings, but a variable set by a direct_dependent_settings @@ -250,6 +257,11 @@ '<(DEPTH)/base/base.gyp:chromium_android_linker', ], }], + ['enable_errorprone == 1', { + 'dependencies': [ + '<(DEPTH)/third_party/errorprone/errorprone.gyp:chromium_errorprone', + ], + }], ['native_lib_target != ""', { 'variables': { 'conditions': [ @@ -387,7 +399,7 @@ 'includes': ['../build/android/insert_chromium_version.gypi'], }, { - 'action_name': 'pack_arm_relocations', + 'action_name': 'pack_relocations', 'variables': { 'conditions': [ ['use_chromium_linker == 1 and use_relocation_packer == 1 and profiling != 1', { @@ -405,9 +417,9 @@ 'input_paths': [ '<(version_stamp)' ], - 'stamp': '<(pack_arm_relocations_stamp)', + 'stamp': '<(pack_relocations_stamp)', }, - 'includes': ['../build/android/pack_arm_relocations.gypi'], + 'includes': ['../build/android/pack_relocations.gypi'], }, { 'variables': { @@ -509,7 +521,7 @@ 'inputs': [ '<(ordered_libraries_file)', '<(strip_additional_stamp)', - '<(pack_arm_relocations_stamp)', + '<(pack_relocations_stamp)', ], 'output_apk_path': '<(unsigned_standalone_apk_path)', 'libraries_top_dir%': '<(libraries_top_dir)', @@ -526,7 +538,7 @@ 'libraries_source_dir': '<(apk_package_native_libs_dir)/<(android_app_abi)', 'package_input_paths': [ '<(strip_additional_stamp)', - '<(pack_arm_relocations_stamp)', + '<(pack_relocations_stamp)', ], }, }], @@ -581,6 +593,7 @@ 'asset_location': '', 'android_manifest_path': '<(split_android_manifest_path)', 'create_density_splits': 0, + 'language_splits=': [], }, 'includes': [ 'android/package_resources_action.gypi' ], }, @@ -663,15 +676,25 @@ '<(final_apk_path_no_extension)-density-hdpi.apk', '<(final_apk_path_no_extension)-density-xhdpi.apk', '<(final_apk_path_no_extension)-density-xxhdpi.apk', + '<(final_apk_path_no_extension)-density-xxxhdpi.apk', '<(final_apk_path_no_extension)-density-tvdpi.apk', ], 'action': [ '--split-apk-path=<(final_apk_path_no_extension)-density-hdpi.apk', '--split-apk-path=<(final_apk_path_no_extension)-density-xhdpi.apk', '--split-apk-path=<(final_apk_path_no_extension)-density-xxhdpi.apk', + '--split-apk-path=<(final_apk_path_no_extension)-density-xxxhdpi.apk', '--split-apk-path=<(final_apk_path_no_extension)-density-tvdpi.apk', ], }], + ['language_splits != []', { + 'inputs': [ + "@(generated_src_dirs)', @@ -807,7 +832,14 @@ # targets use the same java_in_dir and both use java_apk.gypi or # both use java.gypi.) 'java_sources': ['>!@(find >(java_in_dir)>(java_in_dir_suffix) >(additional_src_dirs) -name "*.java" # apk)'], - + 'conditions': [ + ['enable_errorprone == 1', { + 'extra_inputs': [ + '<(errorprone_exe_path)', + ], + 'extra_args': [ '--use-errorprone-path=<(errorprone_exe_path)' ], + }], + ], }, 'inputs': [ '<(DEPTH)/build/android/gyp/util/build_utils.py', @@ -815,6 +847,7 @@ '>@(java_sources)', '>@(input_jars_paths)', '<(codegen_stamp)', + '<@(extra_inputs)', ], 'conditions': [ ['native_lib_target != ""', { @@ -827,6 +860,7 @@ ], 'action': [ 'python', '<(DEPTH)/build/android/gyp/javac.py', + '--bootclasspath=<(android_sdk_jar)', '--classpath=>(input_jars_paths) <(android_sdk_jar)', '--src-gendirs=>(gen_src_dirs)', '--javac-includes=<(javac_includes)', @@ -834,6 +868,7 @@ '--jar-path=<(javac_jar_path)', '--jar-excluded-classes=<(jar_excluded_classes)', '--stamp=<(compile_stamp)', + '<@(extra_args)', '>@(java_sources)', ], }, diff --git a/build/json_to_struct.gypi b/build/json_to_struct.gypi index 57271c8bcda34..09c8e3e4574d5 100644 --- a/build/json_to_struct.gypi +++ b/build/json_to_struct.gypi @@ -10,7 +10,8 @@ # cc_dir: path to generated files # Functions and namespaces can be excluded by setting "nocompile" to true. 'struct_gen_dir': '<(DEPTH)/tools/json_to_struct', - 'struct_gen': '<(struct_gen_dir)/json_to_struct.py', + 'struct_gen%': '<(struct_gen_dir)/json_to_struct.py', + 'output_filename%': '<(RULE_INPUT_ROOT)', }, 'rules': [ { @@ -18,14 +19,15 @@ 'rule_name': 'genstaticinit', 'extension': 'json', 'inputs': [ + '<(struct_gen)', '<(struct_gen_dir)/element_generator.py', '<(struct_gen_dir)/json_to_struct.py', '<(struct_gen_dir)/struct_generator.py', '<(schema_file)', ], 'outputs': [ - '<(SHARED_INTERMEDIATE_DIR)/<(cc_dir)/<(RULE_INPUT_ROOT).cc', - '<(SHARED_INTERMEDIATE_DIR)/<(cc_dir)/<(RULE_INPUT_ROOT).h', + '<(SHARED_INTERMEDIATE_DIR)/<(cc_dir)/<(output_filename).cc', + '<(SHARED_INTERMEDIATE_DIR)/<(cc_dir)/<(output_filename).h', ], 'action': [ 'python', @@ -35,6 +37,7 @@ '--destdir=<(cc_dir)', '--namespace=<(namespace)', '--schema=<(schema_file)', + '--output=<(output_filename)', ], 'message': 'Generating C++ static initializers from <(RULE_INPUT_PATH)', 'process_outputs_as_sources': 1, diff --git a/build/landmines.py b/build/landmines.py index bac29823c3d73..0ea2b64058d6d 100755 --- a/build/landmines.py +++ b/build/landmines.py @@ -18,11 +18,11 @@ import logging import optparse import os -import shutil import sys import subprocess import time +import clobber import landmine_utils @@ -55,79 +55,6 @@ def get_build_dir(build_tool, is_iphone=False): return os.path.abspath(ret) -def extract_gn_build_commands(build_ninja_file): - """Extracts from a build.ninja the commands to run GN. - - The commands to run GN are the gn rule and build.ninja build step at the - top of the build.ninja file. We want to keep these when deleting GN builds - since we want to preserve the command-line flags to GN. - - On error, returns the empty string.""" - result = "" - with open(build_ninja_file, 'r') as f: - # Read until the second blank line. The first thing GN writes to the file - # is the "rule gn" and the second is the section for "build build.ninja", - # separated by blank lines. - num_blank_lines = 0 - while num_blank_lines < 2: - line = f.readline() - if len(line) == 0: - return '' # Unexpected EOF. - result += line - if line[0] == '\n': - num_blank_lines = num_blank_lines + 1 - return result - -def delete_build_dir(build_dir): - # GN writes a build.ninja.d file. Note that not all GN builds have args.gn. - build_ninja_d_file = os.path.join(build_dir, 'build.ninja.d') - if not os.path.exists(build_ninja_d_file): - shutil.rmtree(build_dir) - return - - # GN builds aren't automatically regenerated when you sync. To avoid - # messing with the GN workflow, erase everything but the args file, and - # write a dummy build.ninja file that will automatically rerun GN the next - # time Ninja is run. - build_ninja_file = os.path.join(build_dir, 'build.ninja') - build_commands = extract_gn_build_commands(build_ninja_file) - - try: - gn_args_file = os.path.join(build_dir, 'args.gn') - with open(gn_args_file, 'r') as f: - args_contents = f.read() - except IOError: - args_contents = '' - - shutil.rmtree(build_dir) - - # Put back the args file (if any). - os.mkdir(build_dir) - if args_contents != '': - with open(gn_args_file, 'w') as f: - f.write(args_contents) - - # Write the build.ninja file sufficiently to regenerate itself. - with open(os.path.join(build_dir, 'build.ninja'), 'w') as f: - if build_commands != '': - f.write(build_commands) - else: - # Couldn't parse the build.ninja file, write a default thing. - f.write('''rule gn -command = gn -q gen //out/%s/ -description = Regenerating ninja files - -build build.ninja: gn -generator = 1 -depfile = build.ninja.d -''' % (os.path.split(build_dir)[1])) - - # Write a .d file for the build which references a nonexistant file. This - # will make Ninja always mark the build as dirty. - with open(build_ninja_d_file, 'w') as f: - f.write('build.ninja: nonexistant_file.gn\n') - - def clobber_if_necessary(new_landmines): """Does the work of setting, planting, and triggering landmines.""" out_dir = get_build_dir(landmine_utils.builder()) @@ -149,14 +76,7 @@ def clobber_if_necessary(new_landmines): sys.stdout.write('Clobbering due to:\n') sys.stdout.writelines(diff) - # Clobber contents of build directory but not directory itself: some - # checkouts have the build directory mounted. - for f in os.listdir(out_dir): - path = os.path.join(out_dir, f) - if os.path.isfile(path): - os.unlink(path) - elif os.path.isdir(path): - delete_build_dir(path) + clobber.clobber(out_dir) # Save current set of landmines for next time. with open(landmines_path, 'w') as f: diff --git a/build/linux/OWNERS b/build/linux/OWNERS new file mode 100644 index 0000000000000..4a60b79d48458 --- /dev/null +++ b/build/linux/OWNERS @@ -0,0 +1,3 @@ +mmoss@chromium.org +phajdan.jr@chromium.org +thestig@chromium.org diff --git a/build/linux/dump_app_syms b/build/linux/dump_app_syms deleted file mode 100755 index cbeb676271205..0000000000000 --- a/build/linux/dump_app_syms +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/sh - -# Copyright (c) 2010 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -# -# Helper script to run dump_syms on Chrome Linux executables and strip -# them if needed. - -set -e - -usage() { - echo -n "$0 " >&2 - echo " " >&2 -} - - -if [ $# -ne 4 ]; then - usage - exit 1 -fi - -SCRIPTDIR="$(readlink -f "$(dirname "$0")")" -DUMPSYMS="$1" -STRIP_BINARY="$2" -INFILE="$3" -OUTFILE="$4" - -# Dump the symbols from the given binary. -if [ ! -e "$OUTFILE" -o "$INFILE" -nt "$OUTFILE" ]; then - "$DUMPSYMS" -r "$INFILE" > "$OUTFILE" -fi - -if [ "$STRIP_BINARY" != "0" ]; then - strip "$INFILE" -fi diff --git a/build/linux/dump_app_syms.py b/build/linux/dump_app_syms.py new file mode 100644 index 0000000000000..c18bff77694ae --- /dev/null +++ b/build/linux/dump_app_syms.py @@ -0,0 +1,29 @@ +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Helper script to run dump_syms on Chrome Linux executables and strip +# them if needed. + +import os +import subprocess +import sys + +if len(sys.argv) != 5: + print "dump_app_syms.py " + print " " + sys.exit(1) + +dumpsyms = sys.argv[1] +strip_binary = sys.argv[2] +infile = sys.argv[3] +outfile = sys.argv[4] + +# Dump only when the output file is out-of-date. +if not os.path.isfile(outfile) or \ + os.stat(outfile).st_mtime > os.stat(infile).st_mtime: + with open(outfile, 'w') as outfileobj: + subprocess.check_call([dumpsyms, '-r', infile], stdout=outfileobj) + +if strip_binary != '0': + subprocess.check_call(['strip', infile]) diff --git a/build/linux/sysroot_scripts/install-sysroot.py b/build/linux/sysroot_scripts/install-sysroot.py new file mode 100755 index 0000000000000..99fc2d6f459b4 --- /dev/null +++ b/build/linux/sysroot_scripts/install-sysroot.py @@ -0,0 +1,193 @@ +#!/usr/bin/env python +# Copyright (c) 2013 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Script to install a Debian Wheezy sysroot for making official Google Chrome +# Linux builds. +# The sysroot is needed to make Chrome work for Debian Wheezy. +# This script can be run manually but is more often run as part of gclient +# hooks. When run from hooks this script should be a no-op on non-linux +# platforms. + +# The sysroot image could be constructed from scratch based on the current +# state or Debian Wheezy but for consistency we currently use a pre-built root +# image. The image will normally need to be rebuilt every time chrome's build +# dependancies are changed. + +import hashlib +import platform +import optparse +import os +import re +import shutil +import subprocess +import sys + + +SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) +URL_PREFIX = 'http://storage.googleapis.com' +URL_PATH = 'chrome-linux-sysroot/toolchain' +REVISION_AMD64 = 'a2d45701cb21244b9514e420950ba6ba687fb655' +REVISION_ARM = 'a2d45701cb21244b9514e420950ba6ba687fb655' +REVISION_I386 = 'a2d45701cb21244b9514e420950ba6ba687fb655' +REVISION_MIPS = '7749d2957387abf225b6d45154c3ddad142148dc' +TARBALL_AMD64 = 'debian_wheezy_amd64_sysroot.tgz' +TARBALL_ARM = 'debian_wheezy_arm_sysroot.tgz' +TARBALL_I386 = 'debian_wheezy_i386_sysroot.tgz' +TARBALL_MIPS = 'debian_wheezy_mips_sysroot.tgz' +TARBALL_AMD64_SHA1SUM = '601216c0f980e798e7131635f3dd8171b3dcbcde' +TARBALL_ARM_SHA1SUM = '6289593b36616526562a4d85ae9c92b694b8ce7e' +TARBALL_I386_SHA1SUM = '0090e5a4b56ab9ffb5d557da6a520195ab59b446' +TARBALL_MIPS_SHA1SUM = '3b4d782a237db4aac185a638572a7747c1a21825' +SYSROOT_DIR_AMD64 = 'debian_wheezy_amd64-sysroot' +SYSROOT_DIR_ARM = 'debian_wheezy_arm-sysroot' +SYSROOT_DIR_I386 = 'debian_wheezy_i386-sysroot' +SYSROOT_DIR_MIPS = 'debian_wheezy_mips-sysroot' + +valid_archs = ('arm', 'i386', 'amd64', 'mips') + + +def GetSha1(filename): + sha1 = hashlib.sha1() + with open(filename, 'rb') as f: + while True: + # Read in 1mb chunks, so it doesn't all have to be loaded into memory. + chunk = f.read(1024*1024) + if not chunk: + break + sha1.update(chunk) + return sha1.hexdigest() + + +def DetectArch(gyp_defines): + # Check for optional target_arch and only install for that architecture. + # If target_arch is not specified, then only install for the host + # architecture. + if 'target_arch=x64' in gyp_defines: + return 'amd64' + elif 'target_arch=ia32' in gyp_defines: + return 'i386' + elif 'target_arch=arm' in gyp_defines: + return 'arm' + elif 'target_arch=mipsel' in gyp_defines: + return 'mips' + + # Figure out host arch using build/detect_host_arch.py and + # set target_arch to host arch + build_dir = os.path.dirname(os.path.dirname(os.path.join(SCRIPT_DIR))) + sys.path.append(build_dir) + import detect_host_arch + + detected_host_arch = detect_host_arch.HostArch() + if detected_host_arch == 'x64': + return 'amd64' + elif detected_host_arch == 'ia32': + return 'i386' + elif detected_host_arch == 'arm': + return 'arm' + elif detected_host_arch == 'mips': + return 'mips' + else: + print "Unknown host arch: %s" % detected_host_arch + + return None + + +def main(): + if options.running_as_hook and not sys.platform.startswith('linux'): + return 0 + + gyp_defines = os.environ.get('GYP_DEFINES', '') + + if options.arch: + target_arch = options.arch + else: + target_arch = DetectArch(gyp_defines) + if not target_arch: + print 'Unable to detect host architecture' + return 1 + + if options.running_as_hook and target_arch != 'arm' and target_arch != 'mips': + # When run from runhooks, only install the sysroot for an Official Chrome + # Linux build, except on ARM where we always use a sysroot. + skip_if_defined = ['branding=Chrome', 'buildtype=Official'] + skip_if_undefined = ['chromeos=1'] + for option in skip_if_defined: + if option not in gyp_defines: + return 0 + for option in skip_if_undefined: + if option in gyp_defines: + return 0 + + # The sysroot directory should match the one specified in build/common.gypi. + # TODO(thestig) Consider putting this else where to avoid having to recreate + # it on every build. + linux_dir = os.path.dirname(SCRIPT_DIR) + if target_arch == 'amd64': + sysroot = os.path.join(linux_dir, SYSROOT_DIR_AMD64) + tarball_filename = TARBALL_AMD64 + tarball_sha1sum = TARBALL_AMD64_SHA1SUM + revision = REVISION_AMD64 + elif target_arch == 'arm': + sysroot = os.path.join(linux_dir, SYSROOT_DIR_ARM) + tarball_filename = TARBALL_ARM + tarball_sha1sum = TARBALL_ARM_SHA1SUM + revision = REVISION_ARM + elif target_arch == 'i386': + sysroot = os.path.join(linux_dir, SYSROOT_DIR_I386) + tarball_filename = TARBALL_I386 + tarball_sha1sum = TARBALL_I386_SHA1SUM + revision = REVISION_I386 + elif target_arch == 'mips': + sysroot = os.path.join(linux_dir, SYSROOT_DIR_MIPS) + tarball_filename = TARBALL_MIPS + tarball_sha1sum = TARBALL_MIPS_SHA1SUM + revision = REVISION_MIPS + else: + print 'Unknown architecture: %s' % target_arch + assert(False) + + url = '%s/%s/%s/%s' % (URL_PREFIX, URL_PATH, revision, tarball_filename) + + stamp = os.path.join(sysroot, '.stamp') + if os.path.exists(stamp): + with open(stamp) as s: + if s.read() == url: + print 'Debian Wheezy %s root image already up-to-date: %s' % \ + (target_arch, sysroot) + return 0 + + print 'Installing Debian Wheezy %s root image: %s' % (target_arch, sysroot) + if os.path.isdir(sysroot): + shutil.rmtree(sysroot) + os.mkdir(sysroot) + tarball = os.path.join(sysroot, tarball_filename) + print 'Downloading %s' % url + sys.stdout.flush() + sys.stderr.flush() + subprocess.check_call(['curl', '--fail', '-L', url, '-o', tarball]) + sha1sum = GetSha1(tarball) + if sha1sum != tarball_sha1sum: + print 'Tarball sha1sum is wrong.' + print 'Expected %s, actual: %s' % (tarball_sha1sum, sha1sum) + return 1 + subprocess.check_call(['tar', 'xf', tarball, '-C', sysroot]) + os.remove(tarball) + + with open(stamp, 'w') as s: + s.write(url) + return 0 + + +if __name__ == '__main__': + parser = optparse.OptionParser('usage: %prog [OPTIONS]') + parser.add_option('--running-as-hook', action='store_true', + default=False, help='Used when running from gclient hooks.' + ' In this mode the sysroot will only ' + 'be installed for official Linux ' + 'builds or ARM Linux builds') + parser.add_option('--arch', type='choice', choices=valid_archs, + help='Sysroot architecture: %s' % ', '.join(valid_archs)) + options, _ = parser.parse_args() + sys.exit(main()) diff --git a/build/linux/sysroot_scripts/packagelist.trusty.arm b/build/linux/sysroot_scripts/packagelist.trusty.arm new file mode 100644 index 0000000000000..cd4b671f8b4c5 --- /dev/null +++ b/build/linux/sysroot_scripts/packagelist.trusty.arm @@ -0,0 +1,158 @@ +main/a/alsa-lib/libasound2_1.0.27.2-3ubuntu7_armhf.deb +main/a/alsa-lib/libasound2-dev_1.0.27.2-3ubuntu7_armhf.deb +main/a/atk1.0/libatk1.0-0_2.10.0-2ubuntu2_armhf.deb +main/a/atk1.0/libatk1.0-dev_2.10.0-2ubuntu2_armhf.deb +main/a/avahi/libavahi-client3_0.6.31-4ubuntu1_armhf.deb +main/a/avahi/libavahi-common3_0.6.31-4ubuntu1_armhf.deb +main/c/cairo/libcairo2_1.13.0~20140204-0ubuntu1_armhf.deb +main/c/cairo/libcairo2-dev_1.13.0~20140204-0ubuntu1_armhf.deb +main/c/cairo/libcairo-gobject2_1.13.0~20140204-0ubuntu1_armhf.deb +main/c/cairo/libcairo-script-interpreter2_1.13.0~20140204-0ubuntu1_armhf.deb +main/c/cups/libcups2_1.7.2-0ubuntu1_armhf.deb +main/c/cups/libcups2-dev_1.7.2-0ubuntu1_armhf.deb +main/d/dbus-glib/libdbus-glib-1-2_0.100.2-1_armhf.deb +main/d/dbus/libdbus-1-3_1.6.18-0ubuntu4_armhf.deb +main/d/dbus/libdbus-1-dev_1.6.18-0ubuntu4_armhf.deb +main/e/e2fsprogs/comerr-dev_2.1-1.42.9-3ubuntu1_armhf.deb +main/e/e2fsprogs/libcomerr2_1.42.9-3ubuntu1_armhf.deb +main/e/eglibc/libc6_2.19-0ubuntu6_armhf.deb +main/e/eglibc/libc6-dev_2.19-0ubuntu6_armhf.deb +main/e/elfutils/libelf1_0.158-0ubuntu5_armhf.deb +main/e/elfutils/libelf-dev_0.158-0ubuntu5_armhf.deb +main/e/expat/libexpat1_2.1.0-4ubuntu1_armhf.deb +main/e/expat/libexpat1-dev_2.1.0-4ubuntu1_armhf.deb +main/f/fontconfig/libfontconfig1_2.11.0-0ubuntu4_armhf.deb +main/f/fontconfig/libfontconfig1-dev_2.11.0-0ubuntu4_armhf.deb +main/f/freetype/libfreetype6_2.5.2-1ubuntu2_armhf.deb +main/f/freetype/libfreetype6-dev_2.5.2-1ubuntu2_armhf.deb +main/g/gcc-4.8/gcc-4.8_4.8.2-19ubuntu1_armhf.deb +main/g/gcc-4.8/libgomp1_4.8.2-19ubuntu1_armhf.deb +main/g/gcc-4.8/libstdc++-4.8-dev_4.8.2-19ubuntu1_armhf.deb +main/g/gcc-4.8/libstdc++6_4.8.2-19ubuntu1_armhf.deb +main/g/gccgo-4.9/libgcc1_4.9-20140406-0ubuntu1_armhf.deb +main/g/gconf/libgconf2-4_3.2.6-0ubuntu2_armhf.deb +main/g/gconf/libgconf-2-4_3.2.6-0ubuntu2_armhf.deb +main/g/gconf/libgconf2-dev_3.2.6-0ubuntu2_armhf.deb +main/g/gdk-pixbuf/libgdk-pixbuf2.0-0_2.30.7-0ubuntu1_armhf.deb +main/g/gdk-pixbuf/libgdk-pixbuf2.0-dev_2.30.7-0ubuntu1_armhf.deb +main/g/glib2.0/libglib2.0-0_2.40.0-2_armhf.deb +main/g/glib2.0/libglib2.0-dev_2.40.0-2_armhf.deb +main/g/gnutls26/libgnutls26_2.12.23-12ubuntu2_armhf.deb +main/g/gnutls26/libgnutls-dev_2.12.23-12ubuntu2_armhf.deb +main/g/gnutls26/libgnutls-openssl27_2.12.23-12ubuntu2_armhf.deb +main/g/gnutls26/libgnutlsxx27_2.12.23-12ubuntu2_armhf.deb +main/g/gtk+2.0/libgtk2.0-0_2.24.23-0ubuntu1_armhf.deb +main/g/gtk+2.0/libgtk2.0-dev_2.24.23-0ubuntu1_armhf.deb +main/k/keyutils/libkeyutils1_1.5.6-1_armhf.deb +main/k/krb5/krb5-multidev_1.12+dfsg-2ubuntu4_armhf.deb +main/k/krb5/libgssapi-krb5-2_1.12+dfsg-2ubuntu4_armhf.deb +main/k/krb5/libgssrpc4_1.12+dfsg-2ubuntu4_armhf.deb +main/k/krb5/libk5crypto3_1.12+dfsg-2ubuntu4_armhf.deb +main/k/krb5/libkadm5clnt-mit9_1.12+dfsg-2ubuntu4_armhf.deb +main/k/krb5/libkadm5srv-mit9_1.12+dfsg-2ubuntu4_armhf.deb +main/k/krb5/libkdb5-7_1.12+dfsg-2ubuntu4_armhf.deb +main/k/krb5/libkrb5-3_1.12+dfsg-2ubuntu4_armhf.deb +main/k/krb5/libkrb5-dev_1.12+dfsg-2ubuntu4_armhf.deb +main/k/krb5/libkrb5support0_1.12+dfsg-2ubuntu4_armhf.deb +main/libc/libcap2/libcap2_2.24-0ubuntu2_armhf.deb +main/libc/libcap2/libcap-dev_2.24-0ubuntu2_armhf.deb +main/libd/libdrm/libdrm2_2.4.52-1_armhf.deb +main/libe/libexif/libexif12_0.6.21-1ubuntu1_armhf.deb +main/libe/libexif/libexif-dev_0.6.21-1ubuntu1_armhf.deb +main/libf/libffi/libffi6_3.1~rc1+r3.0.13-12_armhf.deb +main/libg/libgcrypt11/libgcrypt11_1.5.3-2ubuntu4_armhf.deb +main/libg/libgcrypt11/libgcrypt11-dev_1.5.3-2ubuntu4_armhf.deb +main/libg/libgnome-keyring/libgnome-keyring0_3.8.0-2_armhf.deb +main/libg/libgnome-keyring/libgnome-keyring-dev_3.8.0-2_armhf.deb +main/libg/libgpg-error/libgpg-error0_1.12-0.2ubuntu1_armhf.deb +main/libg/libgpg-error/libgpg-error-dev_1.12-0.2ubuntu1_armhf.deb +main/libn/libnss-db/libnss-db_2.2.3pre1-5build3_armhf.deb +main/libp/libp11/libp11-2_0.2.8-3ubuntu1_armhf.deb +main/libp/libpng/libpng12-0_1.2.50-1ubuntu2_armhf.deb +main/libp/libpng/libpng12-dev_1.2.50-1ubuntu2_armhf.deb +main/libs/libselinux/libselinux1_2.2.2-1_armhf.deb +main/libt/libtasn1-6/libtasn1-6_3.4-3_armhf.deb +main/libx/libx11/libx11-6_1.6.2-1ubuntu2_armhf.deb +main/libx/libx11/libx11-dev_1.6.2-1ubuntu2_armhf.deb +main/libx/libx11/libx11-xcb1_1.6.2-1ubuntu2_armhf.deb +main/libx/libxau/libxau6_1.0.8-1_armhf.deb +main/libx/libxau/libxau-dev_1.0.8-1_armhf.deb +main/libx/libxcb/libxcb1_1.10-2ubuntu1_armhf.deb +main/libx/libxcb/libxcb1-dev_1.10-2ubuntu1_armhf.deb +main/libx/libxcb/libxcb-glx0_1.10-2ubuntu1_armhf.deb +main/libx/libxcb/libxcb-render0_1.10-2ubuntu1_armhf.deb +main/libx/libxcb/libxcb-render0-dev_1.10-2ubuntu1_armhf.deb +main/libx/libxcb/libxcb-shm0_1.10-2ubuntu1_armhf.deb +main/libx/libxcb/libxcb-shm0-dev_1.10-2ubuntu1_armhf.deb +main/libx/libxcomposite/libxcomposite1_0.4.4-1_armhf.deb +main/libx/libxcomposite/libxcomposite-dev_0.4.4-1_armhf.deb +main/libx/libxcursor/libxcursor1_1.1.14-1_armhf.deb +main/libx/libxcursor/libxcursor-dev_1.1.14-1_armhf.deb +main/libx/libxdamage/libxdamage1_1.1.4-1ubuntu1_armhf.deb +main/libx/libxdamage/libxdamage-dev_1.1.4-1ubuntu1_armhf.deb +main/libx/libxdmcp/libxdmcp6_1.1.1-1_armhf.deb +main/libx/libxext/libxext6_1.3.2-1_armhf.deb +main/libx/libxext/libxext-dev_1.3.2-1_armhf.deb +main/libx/libxfixes/libxfixes3_5.0.1-1ubuntu1_armhf.deb +main/libx/libxfixes/libxfixes-dev_5.0.1-1ubuntu1_armhf.deb +main/libx/libxi/libxi6_1.7.1.901-1ubuntu1_armhf.deb +main/libx/libxi/libxi-dev_1.7.1.901-1ubuntu1_armhf.deb +main/libx/libxinerama/libxinerama1_1.1.3-1_armhf.deb +main/libx/libxinerama/libxinerama-dev_1.1.3-1_armhf.deb +main/libx/libxrandr/libxrandr2_1.4.2-1_armhf.deb +main/libx/libxrandr/libxrandr-dev_1.4.2-1_armhf.deb +main/libx/libxrender/libxrender1_0.9.8-1_armhf.deb +main/libx/libxrender/libxrender-dev_0.9.8-1_armhf.deb +main/libx/libxss/libxss1_1.2.2-1_armhf.deb +main/libx/libxss/libxss-dev_1.2.2-1_armhf.deb +main/libx/libxt/libxt6_1.1.4-1_armhf.deb +main/libx/libxt/libxt-dev_1.1.4-1_armhf.deb +main/libx/libxtst/libxtst6_1.2.2-1_armhf.deb +main/libx/libxtst/libxtst-dev_1.2.2-1_armhf.deb +main/libx/libxxf86vm/libxxf86vm1_1.1.3-1_armhf.deb +main/l/linux/linux-libc-dev_3.13.0-24.46_armhf.deb +main/m/mesa/libgl1-mesa-dev_10.1.0-4ubuntu5_armhf.deb +main/m/mesa/libgl1-mesa-glx_10.1.0-4ubuntu5_armhf.deb +main/m/mesa/libglapi-mesa_10.1.0-4ubuntu5_armhf.deb +main/m/mesa/mesa-common-dev_10.1.0-4ubuntu5_armhf.deb +main/n/nspr/libnspr4_4.10.2-1ubuntu1_armhf.deb +main/n/nspr/libnspr4-dev_4.10.2-1ubuntu1_armhf.deb +main/n/nss/libnss3_3.15.4-1ubuntu7_armhf.deb +main/n/nss/libnss3-dev_3.15.4-1ubuntu7_armhf.deb +main/o/openssl/libssl1.0.0_1.0.1f-1ubuntu2_armhf.deb +main/o/openssl/libssl-dev_1.0.1f-1ubuntu2_armhf.deb +main/o/orbit2/liborbit2_2.14.19-0.3_armhf.deb +main/p/p11-kit/libp11-kit0_0.20.2-2ubuntu2_armhf.deb +main/p/pam/libpam0g_1.1.8-1ubuntu2_armhf.deb +main/p/pam/libpam0g-dev_1.1.8-1ubuntu2_armhf.deb +main/p/pango1.0/libpango-1.0-0_1.36.3-1ubuntu1_armhf.deb +main/p/pango1.0/libpango1.0-dev_1.36.3-1ubuntu1_armhf.deb +main/p/pango1.0/libpangocairo-1.0-0_1.36.3-1ubuntu1_armhf.deb +main/p/pango1.0/libpangoft2-1.0-0_1.36.3-1ubuntu1_armhf.deb +main/p/pango1.0/libpangoxft-1.0-0_1.36.3-1ubuntu1_armhf.deb +main/p/pciutils/libpci3_3.2.1-1ubuntu5_armhf.deb +main/p/pciutils/libpci-dev_3.2.1-1ubuntu5_armhf.deb +main/p/pcre3/libpcre3_8.31-2ubuntu2_armhf.deb +main/p/pcre3/libpcre3-dev_8.31-2ubuntu2_armhf.deb +main/p/pcre3/libpcrecpp0_8.31-2ubuntu2_armhf.deb +main/p/pixman/libpixman-1-0_0.30.2-2ubuntu1_armhf.deb +main/p/pixman/libpixman-1-dev_0.30.2-2ubuntu1_armhf.deb +main/p/pulseaudio/libpulse0_4.0-0ubuntu11_armhf.deb +main/p/pulseaudio/libpulse-dev_4.0-0ubuntu11_armhf.deb +main/p/pulseaudio/libpulse-mainloop-glib0_4.0-0ubuntu11_armhf.deb +main/s/speech-dispatcher/libspeechd2_0.8-5ubuntu1_armhf.deb +main/s/speech-dispatcher/libspeechd-dev_0.8-5ubuntu1_armhf.deb +main/s/speech-dispatcher/speech-dispatcher_0.8-5ubuntu1_armhf.deb +main/x/x11proto-composite/x11proto-composite-dev_0.4.2-2_all.deb +main/x/x11proto-core/x11proto-core-dev_7.0.24-1_all.deb +main/x/x11proto-damage/x11proto-damage-dev_1.2.1-2_all.deb +main/x/x11proto-fixes/x11proto-fixes-dev_5.0-2ubuntu2_all.deb +main/x/x11proto-input/x11proto-input-dev_2.3-1_all.deb +main/x/x11proto-kb/x11proto-kb-dev_1.0.6-2_all.deb +main/x/x11proto-randr/x11proto-randr-dev_1.4.0+git20120101.is.really.1.4.0-0ubuntu1_all.deb +main/x/x11proto-record/x11proto-record-dev_1.14.2-1_all.deb +main/x/x11proto-render/x11proto-render-dev_0.11.1-2_all.deb +main/x/x11proto-scrnsaver/x11proto-scrnsaver-dev_1.2.2-1_all.deb +main/x/x11proto-xext/x11proto-xext-dev_7.3.0-1_all.deb +main/z/zlib/zlib1g_1.2.8.dfsg-1ubuntu1_armhf.deb +main/z/zlib/zlib1g-dev_1.2.8.dfsg-1ubuntu1_armhf.deb diff --git a/build/linux/sysroot_scripts/packagelist.wheezy.amd64 b/build/linux/sysroot_scripts/packagelist.wheezy.amd64 new file mode 100644 index 0000000000000..ced7dfdb5ea97 --- /dev/null +++ b/build/linux/sysroot_scripts/packagelist.wheezy.amd64 @@ -0,0 +1,157 @@ +main/a/alsa-lib/libasound2_1.0.25-4_amd64.deb +main/a/alsa-lib/libasound2-dev_1.0.25-4_amd64.deb +main/a/atk1.0/libatk1.0-0_2.4.0-2_amd64.deb +main/a/atk1.0/libatk1.0-dev_2.4.0-2_amd64.deb +main/a/attr/libattr1_2.4.46-8_amd64.deb +main/a/avahi/libavahi-client3_0.6.31-2_amd64.deb +main/a/avahi/libavahi-common3_0.6.31-2_amd64.deb +main/c/cairo/libcairo2_1.12.2-3_amd64.deb +main/c/cairo/libcairo2-dev_1.12.2-3_amd64.deb +main/c/cairo/libcairo-gobject2_1.12.2-3_amd64.deb +main/c/cairo/libcairo-script-interpreter2_1.12.2-3_amd64.deb +main/c/cups/libcups2_1.5.3-5+deb7u4_amd64.deb +main/c/cups/libcups2-dev_1.5.3-5+deb7u4_amd64.deb +main/d/dbus-glib/libdbus-glib-1-2_0.100.2-1_amd64.deb +main/d/dbus/libdbus-1-3_1.6.8-1+deb7u5_amd64.deb +main/d/dbus/libdbus-1-dev_1.6.8-1+deb7u5_amd64.deb +main/e/e2fsprogs/comerr-dev_2.1-1.42.5-1.1_amd64.deb +main/e/e2fsprogs/libcomerr2_1.42.5-1.1_amd64.deb +main/e/eglibc/libc6_2.13-38+deb7u6_amd64.deb +main/e/eglibc/libc6-dev_2.13-38+deb7u6_amd64.deb +main/e/elfutils/libelf1_0.152-1+wheezy1_amd64.deb +main/e/elfutils/libelf-dev_0.152-1+wheezy1_amd64.deb +main/e/expat/libexpat1_2.1.0-1+deb7u1_amd64.deb +main/e/expat/libexpat1-dev_2.1.0-1+deb7u1_amd64.deb +main/f/fontconfig/libfontconfig1_2.9.0-7.1_amd64.deb +main/f/fontconfig/libfontconfig1-dev_2.9.0-7.1_amd64.deb +main/f/freetype/libfreetype6_2.4.9-1.1_amd64.deb +main/f/freetype/libfreetype6-dev_2.4.9-1.1_amd64.deb +main/g/gcc-4.6/gcc-4.6_4.6.3-14_amd64.deb +main/g/gcc-4.6/libstdc++6-4.6-dev_4.6.3-14_amd64.deb +main/g/gcc-4.7/libgcc1_4.7.2-5_amd64.deb +main/g/gcc-4.7/libgomp1_4.7.2-5_amd64.deb +main/g/gcc-4.7/libquadmath0_4.7.2-5_amd64.deb +main/g/gcc-4.7/libstdc++6_4.7.2-5_amd64.deb +main/g/gconf/libgconf-2-4_3.2.5-1+build1_amd64.deb +main/g/gconf/libgconf2-4_3.2.5-1+build1_amd64.deb +main/g/gconf/libgconf2-dev_3.2.5-1+build1_amd64.deb +main/g/gdk-pixbuf/libgdk-pixbuf2.0-0_2.26.1-1_amd64.deb +main/g/gdk-pixbuf/libgdk-pixbuf2.0-dev_2.26.1-1_amd64.deb +main/g/glib2.0/libglib2.0-0_2.33.12+really2.32.4-5_amd64.deb +main/g/glib2.0/libglib2.0-dev_2.33.12+really2.32.4-5_amd64.deb +main/g/gnutls26/libgnutls26_2.12.20-8+deb7u2_amd64.deb +main/g/gnutls26/libgnutls-dev_2.12.20-8+deb7u2_amd64.deb +main/g/gnutls26/libgnutls-openssl27_2.12.20-8+deb7u2_amd64.deb +main/g/gnutls26/libgnutlsxx27_2.12.20-8+deb7u2_amd64.deb +main/g/gtk+2.0/libgtk2.0-0_2.24.10-2_amd64.deb +main/g/gtk+2.0/libgtk2.0-dev_2.24.10-2_amd64.deb +main/k/keyutils/libkeyutils1_1.5.5-3+deb7u1_amd64.deb +main/k/krb5/krb5-multidev_1.10.1+dfsg-5+deb7u2_amd64.deb +main/k/krb5/libgssapi-krb5-2_1.10.1+dfsg-5+deb7u2_amd64.deb +main/k/krb5/libgssrpc4_1.10.1+dfsg-5+deb7u2_amd64.deb +main/k/krb5/libk5crypto3_1.10.1+dfsg-5+deb7u2_amd64.deb +main/k/krb5/libkadm5clnt-mit8_1.10.1+dfsg-5+deb7u2_amd64.deb +main/k/krb5/libkadm5srv-mit8_1.10.1+dfsg-5+deb7u2_amd64.deb +main/k/krb5/libkdb5-6_1.10.1+dfsg-5+deb7u2_amd64.deb +main/k/krb5/libkrb5-3_1.10.1+dfsg-5+deb7u2_amd64.deb +main/k/krb5/libkrb5-dev_1.10.1+dfsg-5+deb7u2_amd64.deb +main/k/krb5/libkrb5support0_1.10.1+dfsg-5+deb7u2_amd64.deb +main/libc/libcap2/libcap2_2.22-1.2_amd64.deb +main/libc/libcap2/libcap-dev_2.22-1.2_amd64.deb +main/libd/libdrm/libdrm2_2.4.40-1~deb7u2_amd64.deb +main/libe/libexif/libexif12_0.6.20-3_amd64.deb +main/libe/libexif/libexif-dev_0.6.20-3_amd64.deb +main/libf/libffi/libffi5_3.0.10-3_amd64.deb +main/libg/libgcrypt11/libgcrypt11_1.5.0-5+deb7u2_amd64.deb +main/libg/libgcrypt11/libgcrypt11-dev_1.5.0-5+deb7u2_amd64.deb +main/libg/libgnome-keyring/libgnome-keyring0_3.4.1-1_amd64.deb +main/libg/libgnome-keyring/libgnome-keyring-dev_3.4.1-1_amd64.deb +main/libg/libgpg-error/libgpg-error0_1.10-3.1_amd64.deb +main/libg/libgpg-error/libgpg-error-dev_1.10-3.1_amd64.deb +main/libn/libnss-db/libnss-db_2.2.3pre1-4_amd64.deb +main/libp/libp11/libp11-2_0.2.8-2_amd64.deb +main/libp/libpng/libpng12-0_1.2.49-1_amd64.deb +main/libp/libpng/libpng12-dev_1.2.49-1_amd64.deb +main/libs/libselinux/libselinux1_2.1.9-5_amd64.deb +main/libt/libtasn1-3/libtasn1-3_2.13-2+deb7u1_amd64.deb +main/libx/libx11/libx11-6_1.5.0-1+deb7u1_amd64.deb +main/libx/libx11/libx11-dev_1.5.0-1+deb7u1_amd64.deb +main/libx/libx11/libx11-xcb1_1.5.0-1+deb7u1_amd64.deb +main/libx/libxau/libxau6_1.0.7-1_amd64.deb +main/libx/libxau/libxau-dev_1.0.7-1_amd64.deb +main/libx/libxcb/libxcb1_1.8.1-2+deb7u1_amd64.deb +main/libx/libxcb/libxcb1-dev_1.8.1-2+deb7u1_amd64.deb +main/libx/libxcb/libxcb-glx0_1.8.1-2+deb7u1_amd64.deb +main/libx/libxcb/libxcb-render0_1.8.1-2+deb7u1_amd64.deb +main/libx/libxcb/libxcb-render0-dev_1.8.1-2+deb7u1_amd64.deb +main/libx/libxcb/libxcb-shm0_1.8.1-2+deb7u1_amd64.deb +main/libx/libxcb/libxcb-shm0-dev_1.8.1-2+deb7u1_amd64.deb +main/libx/libxcomposite/libxcomposite1_0.4.3-2_amd64.deb +main/libx/libxcomposite/libxcomposite-dev_0.4.3-2_amd64.deb +main/libx/libxcursor/libxcursor1_1.1.13-1+deb7u1_amd64.deb +main/libx/libxcursor/libxcursor-dev_1.1.13-1+deb7u1_amd64.deb +main/libx/libxdamage/libxdamage1_1.1.3-2_amd64.deb +main/libx/libxdamage/libxdamage-dev_1.1.3-2_amd64.deb +main/libx/libxdmcp/libxdmcp6_1.1.1-1_amd64.deb +main/libx/libxext/libxext6_1.3.1-2+deb7u1_amd64.deb +main/libx/libxext/libxext-dev_1.3.1-2+deb7u1_amd64.deb +main/libx/libxfixes/libxfixes3_5.0-4+deb7u1_amd64.deb +main/libx/libxfixes/libxfixes-dev_5.0-4+deb7u1_amd64.deb +main/libx/libxi/libxi6_1.6.1-1+deb7u1_amd64.deb +main/libx/libxi/libxi-dev_1.6.1-1+deb7u1_amd64.deb +main/libx/libxinerama/libxinerama1_1.1.2-1+deb7u1_amd64.deb +main/libx/libxinerama/libxinerama-dev_1.1.2-1+deb7u1_amd64.deb +main/libx/libxrandr/libxrandr2_1.3.2-2+deb7u1_amd64.deb +main/libx/libxrandr/libxrandr-dev_1.3.2-2+deb7u1_amd64.deb +main/libx/libxrender/libxrender1_0.9.7-1+deb7u1_amd64.deb +main/libx/libxrender/libxrender-dev_0.9.7-1+deb7u1_amd64.deb +main/libx/libxss/libxss1_1.2.2-1_amd64.deb +main/libx/libxss/libxss-dev_1.2.2-1_amd64.deb +main/libx/libxt/libxt6_1.1.3-1+deb7u1_amd64.deb +main/libx/libxt/libxt-dev_1.1.3-1+deb7u1_amd64.deb +main/libx/libxtst/libxtst6_1.2.1-1+deb7u1_amd64.deb +main/libx/libxtst/libxtst-dev_1.2.1-1+deb7u1_amd64.deb +main/libx/libxxf86vm/libxxf86vm1_1.1.2-1+deb7u1_amd64.deb +main/l/linux/linux-libc-dev_3.2.65-1_amd64.deb +main/m/mesa/libgl1-mesa-dev_8.0.5-4+deb7u2_amd64.deb +main/m/mesa/libgl1-mesa-glx_8.0.5-4+deb7u2_amd64.deb +main/m/mesa/libglapi-mesa_8.0.5-4+deb7u2_amd64.deb +main/m/mesa/mesa-common-dev_8.0.5-4+deb7u2_amd64.deb +main/n/nspr/libnspr4_4.9.2-1+deb7u2_amd64.deb +main/n/nspr/libnspr4-dev_4.9.2-1+deb7u2_amd64.deb +main/n/nss/libnss3_3.14.5-1+deb7u3_amd64.deb +main/n/nss/libnss3-dev_3.14.5-1+deb7u3_amd64.deb +main/o/openssl/libssl1.0.0_1.0.1e-2+deb7u13_amd64.deb +main/o/openssl/libssl-dev_1.0.1e-2+deb7u13_amd64.deb +main/o/orbit2/liborbit2_2.14.19-0.1_amd64.deb +main/p/p11-kit/libp11-kit0_0.12-3_amd64.deb +main/p/pam/libpam0g_1.1.3-7.1_amd64.deb +main/p/pam/libpam0g-dev_1.1.3-7.1_amd64.deb +main/p/pango1.0/libpango1.0-0_1.30.0-1_amd64.deb +main/p/pango1.0/libpango1.0-dev_1.30.0-1_amd64.deb +main/p/pciutils/libpci3_3.1.9-6_amd64.deb +main/p/pciutils/libpci-dev_3.1.9-6_amd64.deb +main/p/pcre3/libpcre3_8.30-5_amd64.deb +main/p/pcre3/libpcre3-dev_8.30-5_amd64.deb +main/p/pcre3/libpcrecpp0_8.30-5_amd64.deb +main/p/pixman/libpixman-1-0_0.26.0-4+deb7u1_amd64.deb +main/p/pixman/libpixman-1-dev_0.26.0-4+deb7u1_amd64.deb +main/p/pulseaudio/libpulse0_2.0-6.1_amd64.deb +main/p/pulseaudio/libpulse-dev_2.0-6.1_amd64.deb +main/p/pulseaudio/libpulse-mainloop-glib0_2.0-6.1_amd64.deb +main/s/speech-dispatcher/libspeechd2_0.7.1-6.2_amd64.deb +main/s/speech-dispatcher/libspeechd-dev_0.7.1-6.2_amd64.deb +main/s/speech-dispatcher/speech-dispatcher_0.7.1-6.2_amd64.deb +main/x/x11proto-composite/x11proto-composite-dev_0.4.2-2_all.deb +main/x/x11proto-core/x11proto-core-dev_7.0.23-1_all.deb +main/x/x11proto-damage/x11proto-damage-dev_1.2.1-2_all.deb +main/x/x11proto-fixes/x11proto-fixes-dev_5.0-2_all.deb +main/x/x11proto-input/x11proto-input-dev_2.2-1_all.deb +main/x/x11proto-kb/x11proto-kb-dev_1.0.6-2_all.deb +main/x/x11proto-randr/x11proto-randr-dev_1.3.2-2_all.deb +main/x/x11proto-record/x11proto-record-dev_1.14.2-1_all.deb +main/x/x11proto-render/x11proto-render-dev_0.11.1-2_all.deb +main/x/x11proto-scrnsaver/x11proto-scrnsaver-dev_1.2.2-1_all.deb +main/x/x11proto-xext/x11proto-xext-dev_7.2.1-1_all.deb +main/z/zlib/zlib1g_1.2.7.dfsg-13_amd64.deb +main/z/zlib/zlib1g-dev_1.2.7.dfsg-13_amd64.deb diff --git a/build/linux/sysroot_scripts/packagelist.wheezy.arm b/build/linux/sysroot_scripts/packagelist.wheezy.arm new file mode 100644 index 0000000000000..3d79cb37c6a20 --- /dev/null +++ b/build/linux/sysroot_scripts/packagelist.wheezy.arm @@ -0,0 +1,156 @@ +main/a/alsa-lib/libasound2_1.0.25-4_armhf.deb +main/a/alsa-lib/libasound2-dev_1.0.25-4_armhf.deb +main/a/atk1.0/libatk1.0-0_2.4.0-2_armhf.deb +main/a/atk1.0/libatk1.0-dev_2.4.0-2_armhf.deb +main/a/attr/libattr1_2.4.46-8_armhf.deb +main/a/avahi/libavahi-client3_0.6.31-2_armhf.deb +main/a/avahi/libavahi-common3_0.6.31-2_armhf.deb +main/c/cairo/libcairo2_1.12.2-3_armhf.deb +main/c/cairo/libcairo2-dev_1.12.2-3_armhf.deb +main/c/cairo/libcairo-gobject2_1.12.2-3_armhf.deb +main/c/cairo/libcairo-script-interpreter2_1.12.2-3_armhf.deb +main/c/cups/libcups2_1.5.3-5+deb7u4_armhf.deb +main/c/cups/libcups2-dev_1.5.3-5+deb7u4_armhf.deb +main/d/dbus-glib/libdbus-glib-1-2_0.100.2-1_armhf.deb +main/d/dbus/libdbus-1-3_1.6.8-1+deb7u5_armhf.deb +main/d/dbus/libdbus-1-dev_1.6.8-1+deb7u5_armhf.deb +main/e/e2fsprogs/comerr-dev_2.1-1.42.5-1.1_armhf.deb +main/e/e2fsprogs/libcomerr2_1.42.5-1.1_armhf.deb +main/e/eglibc/libc6_2.13-38+deb7u6_armhf.deb +main/e/eglibc/libc6-dev_2.13-38+deb7u6_armhf.deb +main/e/elfutils/libelf1_0.152-1+wheezy1_armhf.deb +main/e/elfutils/libelf-dev_0.152-1+wheezy1_armhf.deb +main/e/expat/libexpat1_2.1.0-1+deb7u1_armhf.deb +main/e/expat/libexpat1-dev_2.1.0-1+deb7u1_armhf.deb +main/f/fontconfig/libfontconfig1_2.9.0-7.1_armhf.deb +main/f/fontconfig/libfontconfig1-dev_2.9.0-7.1_armhf.deb +main/f/freetype/libfreetype6_2.4.9-1.1_armhf.deb +main/f/freetype/libfreetype6-dev_2.4.9-1.1_armhf.deb +main/g/gcc-4.6/gcc-4.6_4.6.3-14_armhf.deb +main/g/gcc-4.6/libstdc++6-4.6-dev_4.6.3-14_armhf.deb +main/g/gcc-4.7/libgcc1_4.7.2-5_armhf.deb +main/g/gcc-4.7/libgomp1_4.7.2-5_armhf.deb +main/g/gcc-4.7/libstdc++6_4.7.2-5_armhf.deb +main/g/gconf/libgconf2-4_3.2.5-1+build1_armhf.deb +main/g/gconf/libgconf-2-4_3.2.5-1+build1_armhf.deb +main/g/gconf/libgconf2-dev_3.2.5-1+build1_armhf.deb +main/g/gdk-pixbuf/libgdk-pixbuf2.0-0_2.26.1-1_armhf.deb +main/g/gdk-pixbuf/libgdk-pixbuf2.0-dev_2.26.1-1_armhf.deb +main/g/glib2.0/libglib2.0-0_2.33.12+really2.32.4-5_armhf.deb +main/g/glib2.0/libglib2.0-dev_2.33.12+really2.32.4-5_armhf.deb +main/g/gnutls26/libgnutls26_2.12.20-8+deb7u2_armhf.deb +main/g/gnutls26/libgnutls-dev_2.12.20-8+deb7u2_armhf.deb +main/g/gnutls26/libgnutls-openssl27_2.12.20-8+deb7u2_armhf.deb +main/g/gnutls26/libgnutlsxx27_2.12.20-8+deb7u2_armhf.deb +main/g/gtk+2.0/libgtk2.0-0_2.24.10-2_armhf.deb +main/g/gtk+2.0/libgtk2.0-dev_2.24.10-2_armhf.deb +main/k/keyutils/libkeyutils1_1.5.5-3+deb7u1_armhf.deb +main/k/krb5/krb5-multidev_1.10.1+dfsg-5+deb7u2_armhf.deb +main/k/krb5/libgssapi-krb5-2_1.10.1+dfsg-5+deb7u2_armhf.deb +main/k/krb5/libgssrpc4_1.10.1+dfsg-5+deb7u2_armhf.deb +main/k/krb5/libk5crypto3_1.10.1+dfsg-5+deb7u2_armhf.deb +main/k/krb5/libkadm5clnt-mit8_1.10.1+dfsg-5+deb7u2_armhf.deb +main/k/krb5/libkadm5srv-mit8_1.10.1+dfsg-5+deb7u2_armhf.deb +main/k/krb5/libkdb5-6_1.10.1+dfsg-5+deb7u2_armhf.deb +main/k/krb5/libkrb5-3_1.10.1+dfsg-5+deb7u2_armhf.deb +main/k/krb5/libkrb5-dev_1.10.1+dfsg-5+deb7u2_armhf.deb +main/k/krb5/libkrb5support0_1.10.1+dfsg-5+deb7u2_armhf.deb +main/libc/libcap2/libcap2_2.22-1.2_armhf.deb +main/libc/libcap2/libcap-dev_2.22-1.2_armhf.deb +main/libd/libdrm/libdrm2_2.4.40-1~deb7u2_armhf.deb +main/libe/libexif/libexif12_0.6.20-3_armhf.deb +main/libe/libexif/libexif-dev_0.6.20-3_armhf.deb +main/libf/libffi/libffi5_3.0.10-3+b1_armhf.deb +main/libg/libgcrypt11/libgcrypt11_1.5.0-5+deb7u2_armhf.deb +main/libg/libgcrypt11/libgcrypt11-dev_1.5.0-5+deb7u2_armhf.deb +main/libg/libgnome-keyring/libgnome-keyring0_3.4.1-1_armhf.deb +main/libg/libgnome-keyring/libgnome-keyring-dev_3.4.1-1_armhf.deb +main/libg/libgpg-error/libgpg-error0_1.10-3.1_armhf.deb +main/libg/libgpg-error/libgpg-error-dev_1.10-3.1_armhf.deb +main/libn/libnss-db/libnss-db_2.2.3pre1-4_armhf.deb +main/libp/libp11/libp11-2_0.2.8-2_armhf.deb +main/libp/libpng/libpng12-0_1.2.49-1_armhf.deb +main/libp/libpng/libpng12-dev_1.2.49-1_armhf.deb +main/libs/libselinux/libselinux1_2.1.9-5_armhf.deb +main/libt/libtasn1-3/libtasn1-3_2.13-2+deb7u1_armhf.deb +main/libx/libx11/libx11-6_1.5.0-1+deb7u1_armhf.deb +main/libx/libx11/libx11-dev_1.5.0-1+deb7u1_armhf.deb +main/libx/libx11/libx11-xcb1_1.5.0-1+deb7u1_armhf.deb +main/libx/libxau/libxau6_1.0.7-1_armhf.deb +main/libx/libxau/libxau-dev_1.0.7-1_armhf.deb +main/libx/libxcb/libxcb1_1.8.1-2+deb7u1_armhf.deb +main/libx/libxcb/libxcb1-dev_1.8.1-2+deb7u1_armhf.deb +main/libx/libxcb/libxcb-glx0_1.8.1-2+deb7u1_armhf.deb +main/libx/libxcb/libxcb-render0_1.8.1-2+deb7u1_armhf.deb +main/libx/libxcb/libxcb-render0-dev_1.8.1-2+deb7u1_armhf.deb +main/libx/libxcb/libxcb-shm0_1.8.1-2+deb7u1_armhf.deb +main/libx/libxcb/libxcb-shm0-dev_1.8.1-2+deb7u1_armhf.deb +main/libx/libxcomposite/libxcomposite1_0.4.3-2+b1_armhf.deb +main/libx/libxcomposite/libxcomposite-dev_0.4.3-2+b1_armhf.deb +main/libx/libxcursor/libxcursor1_1.1.13-1+deb7u1_armhf.deb +main/libx/libxcursor/libxcursor-dev_1.1.13-1+deb7u1_armhf.deb +main/libx/libxdamage/libxdamage1_1.1.3-2+b1_armhf.deb +main/libx/libxdamage/libxdamage-dev_1.1.3-2+b1_armhf.deb +main/libx/libxdmcp/libxdmcp6_1.1.1-1_armhf.deb +main/libx/libxext/libxext6_1.3.1-2+deb7u1_armhf.deb +main/libx/libxext/libxext-dev_1.3.1-2+deb7u1_armhf.deb +main/libx/libxfixes/libxfixes3_5.0-4+deb7u1_armhf.deb +main/libx/libxfixes/libxfixes-dev_5.0-4+deb7u1_armhf.deb +main/libx/libxi/libxi6_1.6.1-1+deb7u1_armhf.deb +main/libx/libxi/libxi-dev_1.6.1-1+deb7u1_armhf.deb +main/libx/libxinerama/libxinerama1_1.1.2-1+deb7u1_armhf.deb +main/libx/libxinerama/libxinerama-dev_1.1.2-1+deb7u1_armhf.deb +main/libx/libxrandr/libxrandr2_1.3.2-2+deb7u1_armhf.deb +main/libx/libxrandr/libxrandr-dev_1.3.2-2+deb7u1_armhf.deb +main/libx/libxrender/libxrender1_0.9.7-1+deb7u1_armhf.deb +main/libx/libxrender/libxrender-dev_0.9.7-1+deb7u1_armhf.deb +main/libx/libxss/libxss1_1.2.2-1_armhf.deb +main/libx/libxss/libxss-dev_1.2.2-1_armhf.deb +main/libx/libxt/libxt6_1.1.3-1+deb7u1_armhf.deb +main/libx/libxt/libxt-dev_1.1.3-1+deb7u1_armhf.deb +main/libx/libxtst/libxtst6_1.2.1-1+deb7u1_armhf.deb +main/libx/libxtst/libxtst-dev_1.2.1-1+deb7u1_armhf.deb +main/libx/libxxf86vm/libxxf86vm1_1.1.2-1+deb7u1_armhf.deb +main/l/linux/linux-libc-dev_3.2.65-1_armhf.deb +main/m/mesa/libgl1-mesa-dev_8.0.5-4+deb7u2_armhf.deb +main/m/mesa/libgl1-mesa-glx_8.0.5-4+deb7u2_armhf.deb +main/m/mesa/libglapi-mesa_8.0.5-4+deb7u2_armhf.deb +main/m/mesa/mesa-common-dev_8.0.5-4+deb7u2_armhf.deb +main/n/nspr/libnspr4_4.9.2-1+deb7u2_armhf.deb +main/n/nspr/libnspr4-dev_4.9.2-1+deb7u2_armhf.deb +main/n/nss/libnss3_3.14.5-1+deb7u3_armhf.deb +main/n/nss/libnss3-dev_3.14.5-1+deb7u3_armhf.deb +main/o/openssl/libssl1.0.0_1.0.1e-2+deb7u13_armhf.deb +main/o/openssl/libssl-dev_1.0.1e-2+deb7u13_armhf.deb +main/o/orbit2/liborbit2_2.14.19-0.1_armhf.deb +main/p/p11-kit/libp11-kit0_0.12-3_armhf.deb +main/p/pam/libpam0g_1.1.3-7.1_armhf.deb +main/p/pam/libpam0g-dev_1.1.3-7.1_armhf.deb +main/p/pango1.0/libpango1.0-0_1.30.0-1_armhf.deb +main/p/pango1.0/libpango1.0-dev_1.30.0-1_armhf.deb +main/p/pciutils/libpci3_3.1.9-6_armhf.deb +main/p/pciutils/libpci-dev_3.1.9-6_armhf.deb +main/p/pcre3/libpcre3_8.30-5_armhf.deb +main/p/pcre3/libpcre3-dev_8.30-5_armhf.deb +main/p/pcre3/libpcrecpp0_8.30-5_armhf.deb +main/p/pixman/libpixman-1-0_0.26.0-4+deb7u1_armhf.deb +main/p/pixman/libpixman-1-dev_0.26.0-4+deb7u1_armhf.deb +main/p/pulseaudio/libpulse0_2.0-6.1_armhf.deb +main/p/pulseaudio/libpulse-dev_2.0-6.1_armhf.deb +main/p/pulseaudio/libpulse-mainloop-glib0_2.0-6.1_armhf.deb +main/s/speech-dispatcher/libspeechd2_0.7.1-6.2_armhf.deb +main/s/speech-dispatcher/libspeechd-dev_0.7.1-6.2_armhf.deb +main/s/speech-dispatcher/speech-dispatcher_0.7.1-6.2_armhf.deb +main/x/x11proto-composite/x11proto-composite-dev_0.4.2-2_all.deb +main/x/x11proto-core/x11proto-core-dev_7.0.23-1_all.deb +main/x/x11proto-damage/x11proto-damage-dev_1.2.1-2_all.deb +main/x/x11proto-fixes/x11proto-fixes-dev_5.0-2_all.deb +main/x/x11proto-input/x11proto-input-dev_2.2-1_all.deb +main/x/x11proto-kb/x11proto-kb-dev_1.0.6-2_all.deb +main/x/x11proto-randr/x11proto-randr-dev_1.3.2-2_all.deb +main/x/x11proto-record/x11proto-record-dev_1.14.2-1_all.deb +main/x/x11proto-render/x11proto-render-dev_0.11.1-2_all.deb +main/x/x11proto-scrnsaver/x11proto-scrnsaver-dev_1.2.2-1_all.deb +main/x/x11proto-xext/x11proto-xext-dev_7.2.1-1_all.deb +main/z/zlib/zlib1g_1.2.7.dfsg-13_armhf.deb +main/z/zlib/zlib1g-dev_1.2.7.dfsg-13_armhf.deb diff --git a/build/linux/sysroot_scripts/packagelist.wheezy.i386 b/build/linux/sysroot_scripts/packagelist.wheezy.i386 new file mode 100644 index 0000000000000..1379fee4b87af --- /dev/null +++ b/build/linux/sysroot_scripts/packagelist.wheezy.i386 @@ -0,0 +1,157 @@ +main/a/alsa-lib/libasound2_1.0.25-4_i386.deb +main/a/alsa-lib/libasound2-dev_1.0.25-4_i386.deb +main/a/atk1.0/libatk1.0-0_2.4.0-2_i386.deb +main/a/atk1.0/libatk1.0-dev_2.4.0-2_i386.deb +main/a/attr/libattr1_2.4.46-8_i386.deb +main/a/avahi/libavahi-client3_0.6.31-2_i386.deb +main/a/avahi/libavahi-common3_0.6.31-2_i386.deb +main/c/cairo/libcairo2_1.12.2-3_i386.deb +main/c/cairo/libcairo2-dev_1.12.2-3_i386.deb +main/c/cairo/libcairo-gobject2_1.12.2-3_i386.deb +main/c/cairo/libcairo-script-interpreter2_1.12.2-3_i386.deb +main/c/cups/libcups2_1.5.3-5+deb7u4_i386.deb +main/c/cups/libcups2-dev_1.5.3-5+deb7u4_i386.deb +main/d/dbus-glib/libdbus-glib-1-2_0.100.2-1_i386.deb +main/d/dbus/libdbus-1-3_1.6.8-1+deb7u5_i386.deb +main/d/dbus/libdbus-1-dev_1.6.8-1+deb7u5_i386.deb +main/e/e2fsprogs/comerr-dev_2.1-1.42.5-1.1_i386.deb +main/e/e2fsprogs/libcomerr2_1.42.5-1.1_i386.deb +main/e/eglibc/libc6_2.13-38+deb7u6_i386.deb +main/e/eglibc/libc6-dev_2.13-38+deb7u6_i386.deb +main/e/elfutils/libelf1_0.152-1+wheezy1_i386.deb +main/e/elfutils/libelf-dev_0.152-1+wheezy1_i386.deb +main/e/expat/libexpat1_2.1.0-1+deb7u1_i386.deb +main/e/expat/libexpat1-dev_2.1.0-1+deb7u1_i386.deb +main/f/fontconfig/libfontconfig1_2.9.0-7.1_i386.deb +main/f/fontconfig/libfontconfig1-dev_2.9.0-7.1_i386.deb +main/f/freetype/libfreetype6_2.4.9-1.1_i386.deb +main/f/freetype/libfreetype6-dev_2.4.9-1.1_i386.deb +main/g/gcc-4.6/gcc-4.6_4.6.3-14_i386.deb +main/g/gcc-4.6/libstdc++6-4.6-dev_4.6.3-14_i386.deb +main/g/gcc-4.7/libgcc1_4.7.2-5_i386.deb +main/g/gcc-4.7/libgomp1_4.7.2-5_i386.deb +main/g/gcc-4.7/libquadmath0_4.7.2-5_i386.deb +main/g/gcc-4.7/libstdc++6_4.7.2-5_i386.deb +main/g/gconf/libgconf-2-4_3.2.5-1+build1_i386.deb +main/g/gconf/libgconf2-4_3.2.5-1+build1_i386.deb +main/g/gconf/libgconf2-dev_3.2.5-1+build1_i386.deb +main/g/gdk-pixbuf/libgdk-pixbuf2.0-0_2.26.1-1_i386.deb +main/g/gdk-pixbuf/libgdk-pixbuf2.0-dev_2.26.1-1_i386.deb +main/g/glib2.0/libglib2.0-0_2.33.12+really2.32.4-5_i386.deb +main/g/glib2.0/libglib2.0-dev_2.33.12+really2.32.4-5_i386.deb +main/g/gnutls26/libgnutls26_2.12.20-8+deb7u2_i386.deb +main/g/gnutls26/libgnutls-dev_2.12.20-8+deb7u2_i386.deb +main/g/gnutls26/libgnutls-openssl27_2.12.20-8+deb7u2_i386.deb +main/g/gnutls26/libgnutlsxx27_2.12.20-8+deb7u2_i386.deb +main/g/gtk+2.0/libgtk2.0-0_2.24.10-2_i386.deb +main/g/gtk+2.0/libgtk2.0-dev_2.24.10-2_i386.deb +main/k/keyutils/libkeyutils1_1.5.5-3+deb7u1_i386.deb +main/k/krb5/krb5-multidev_1.10.1+dfsg-5+deb7u2_i386.deb +main/k/krb5/libgssapi-krb5-2_1.10.1+dfsg-5+deb7u2_i386.deb +main/k/krb5/libgssrpc4_1.10.1+dfsg-5+deb7u2_i386.deb +main/k/krb5/libk5crypto3_1.10.1+dfsg-5+deb7u2_i386.deb +main/k/krb5/libkadm5clnt-mit8_1.10.1+dfsg-5+deb7u2_i386.deb +main/k/krb5/libkadm5srv-mit8_1.10.1+dfsg-5+deb7u2_i386.deb +main/k/krb5/libkdb5-6_1.10.1+dfsg-5+deb7u2_i386.deb +main/k/krb5/libkrb5-3_1.10.1+dfsg-5+deb7u2_i386.deb +main/k/krb5/libkrb5-dev_1.10.1+dfsg-5+deb7u2_i386.deb +main/k/krb5/libkrb5support0_1.10.1+dfsg-5+deb7u2_i386.deb +main/libc/libcap2/libcap2_2.22-1.2_i386.deb +main/libc/libcap2/libcap-dev_2.22-1.2_i386.deb +main/libd/libdrm/libdrm2_2.4.40-1~deb7u2_i386.deb +main/libe/libexif/libexif12_0.6.20-3_i386.deb +main/libe/libexif/libexif-dev_0.6.20-3_i386.deb +main/libf/libffi/libffi5_3.0.10-3_i386.deb +main/libg/libgcrypt11/libgcrypt11_1.5.0-5+deb7u2_i386.deb +main/libg/libgcrypt11/libgcrypt11-dev_1.5.0-5+deb7u2_i386.deb +main/libg/libgnome-keyring/libgnome-keyring0_3.4.1-1_i386.deb +main/libg/libgnome-keyring/libgnome-keyring-dev_3.4.1-1_i386.deb +main/libg/libgpg-error/libgpg-error0_1.10-3.1_i386.deb +main/libg/libgpg-error/libgpg-error-dev_1.10-3.1_i386.deb +main/libn/libnss-db/libnss-db_2.2.3pre1-4_i386.deb +main/libp/libp11/libp11-2_0.2.8-2_i386.deb +main/libp/libpng/libpng12-0_1.2.49-1_i386.deb +main/libp/libpng/libpng12-dev_1.2.49-1_i386.deb +main/libs/libselinux/libselinux1_2.1.9-5_i386.deb +main/libt/libtasn1-3/libtasn1-3_2.13-2+deb7u1_i386.deb +main/libx/libx11/libx11-6_1.5.0-1+deb7u1_i386.deb +main/libx/libx11/libx11-dev_1.5.0-1+deb7u1_i386.deb +main/libx/libx11/libx11-xcb1_1.5.0-1+deb7u1_i386.deb +main/libx/libxau/libxau6_1.0.7-1_i386.deb +main/libx/libxau/libxau-dev_1.0.7-1_i386.deb +main/libx/libxcb/libxcb1_1.8.1-2+deb7u1_i386.deb +main/libx/libxcb/libxcb1-dev_1.8.1-2+deb7u1_i386.deb +main/libx/libxcb/libxcb-glx0_1.8.1-2+deb7u1_i386.deb +main/libx/libxcb/libxcb-render0_1.8.1-2+deb7u1_i386.deb +main/libx/libxcb/libxcb-render0-dev_1.8.1-2+deb7u1_i386.deb +main/libx/libxcb/libxcb-shm0_1.8.1-2+deb7u1_i386.deb +main/libx/libxcb/libxcb-shm0-dev_1.8.1-2+deb7u1_i386.deb +main/libx/libxcomposite/libxcomposite1_0.4.3-2_i386.deb +main/libx/libxcomposite/libxcomposite-dev_0.4.3-2_i386.deb +main/libx/libxcursor/libxcursor1_1.1.13-1+deb7u1_i386.deb +main/libx/libxcursor/libxcursor-dev_1.1.13-1+deb7u1_i386.deb +main/libx/libxdamage/libxdamage1_1.1.3-2_i386.deb +main/libx/libxdamage/libxdamage-dev_1.1.3-2_i386.deb +main/libx/libxdmcp/libxdmcp6_1.1.1-1_i386.deb +main/libx/libxext/libxext6_1.3.1-2+deb7u1_i386.deb +main/libx/libxext/libxext-dev_1.3.1-2+deb7u1_i386.deb +main/libx/libxfixes/libxfixes3_5.0-4+deb7u1_i386.deb +main/libx/libxfixes/libxfixes-dev_5.0-4+deb7u1_i386.deb +main/libx/libxi/libxi6_1.6.1-1+deb7u1_i386.deb +main/libx/libxi/libxi-dev_1.6.1-1+deb7u1_i386.deb +main/libx/libxinerama/libxinerama1_1.1.2-1+deb7u1_i386.deb +main/libx/libxinerama/libxinerama-dev_1.1.2-1+deb7u1_i386.deb +main/libx/libxrandr/libxrandr2_1.3.2-2+deb7u1_i386.deb +main/libx/libxrandr/libxrandr-dev_1.3.2-2+deb7u1_i386.deb +main/libx/libxrender/libxrender1_0.9.7-1+deb7u1_i386.deb +main/libx/libxrender/libxrender-dev_0.9.7-1+deb7u1_i386.deb +main/libx/libxss/libxss1_1.2.2-1_i386.deb +main/libx/libxss/libxss-dev_1.2.2-1_i386.deb +main/libx/libxt/libxt6_1.1.3-1+deb7u1_i386.deb +main/libx/libxt/libxt-dev_1.1.3-1+deb7u1_i386.deb +main/libx/libxtst/libxtst6_1.2.1-1+deb7u1_i386.deb +main/libx/libxtst/libxtst-dev_1.2.1-1+deb7u1_i386.deb +main/libx/libxxf86vm/libxxf86vm1_1.1.2-1+deb7u1_i386.deb +main/l/linux/linux-libc-dev_3.2.65-1_i386.deb +main/m/mesa/libgl1-mesa-dev_8.0.5-4+deb7u2_i386.deb +main/m/mesa/libgl1-mesa-glx_8.0.5-4+deb7u2_i386.deb +main/m/mesa/libglapi-mesa_8.0.5-4+deb7u2_i386.deb +main/m/mesa/mesa-common-dev_8.0.5-4+deb7u2_i386.deb +main/n/nspr/libnspr4_4.9.2-1+deb7u2_i386.deb +main/n/nspr/libnspr4-dev_4.9.2-1+deb7u2_i386.deb +main/n/nss/libnss3_3.14.5-1+deb7u3_i386.deb +main/n/nss/libnss3-dev_3.14.5-1+deb7u3_i386.deb +main/o/openssl/libssl1.0.0_1.0.1e-2+deb7u13_i386.deb +main/o/openssl/libssl-dev_1.0.1e-2+deb7u13_i386.deb +main/o/orbit2/liborbit2_2.14.19-0.1_i386.deb +main/p/p11-kit/libp11-kit0_0.12-3_i386.deb +main/p/pam/libpam0g_1.1.3-7.1_i386.deb +main/p/pam/libpam0g-dev_1.1.3-7.1_i386.deb +main/p/pango1.0/libpango1.0-0_1.30.0-1_i386.deb +main/p/pango1.0/libpango1.0-dev_1.30.0-1_i386.deb +main/p/pciutils/libpci3_3.1.9-6_i386.deb +main/p/pciutils/libpci-dev_3.1.9-6_i386.deb +main/p/pcre3/libpcre3_8.30-5_i386.deb +main/p/pcre3/libpcre3-dev_8.30-5_i386.deb +main/p/pcre3/libpcrecpp0_8.30-5_i386.deb +main/p/pixman/libpixman-1-0_0.26.0-4+deb7u1_i386.deb +main/p/pixman/libpixman-1-dev_0.26.0-4+deb7u1_i386.deb +main/p/pulseaudio/libpulse0_2.0-6.1_i386.deb +main/p/pulseaudio/libpulse-dev_2.0-6.1_i386.deb +main/p/pulseaudio/libpulse-mainloop-glib0_2.0-6.1_i386.deb +main/s/speech-dispatcher/libspeechd2_0.7.1-6.2_i386.deb +main/s/speech-dispatcher/libspeechd-dev_0.7.1-6.2_i386.deb +main/s/speech-dispatcher/speech-dispatcher_0.7.1-6.2_i386.deb +main/x/x11proto-composite/x11proto-composite-dev_0.4.2-2_all.deb +main/x/x11proto-core/x11proto-core-dev_7.0.23-1_all.deb +main/x/x11proto-damage/x11proto-damage-dev_1.2.1-2_all.deb +main/x/x11proto-fixes/x11proto-fixes-dev_5.0-2_all.deb +main/x/x11proto-input/x11proto-input-dev_2.2-1_all.deb +main/x/x11proto-kb/x11proto-kb-dev_1.0.6-2_all.deb +main/x/x11proto-randr/x11proto-randr-dev_1.3.2-2_all.deb +main/x/x11proto-record/x11proto-record-dev_1.14.2-1_all.deb +main/x/x11proto-render/x11proto-render-dev_0.11.1-2_all.deb +main/x/x11proto-scrnsaver/x11proto-scrnsaver-dev_1.2.2-1_all.deb +main/x/x11proto-xext/x11proto-xext-dev_7.2.1-1_all.deb +main/z/zlib/zlib1g_1.2.7.dfsg-13_i386.deb +main/z/zlib/zlib1g-dev_1.2.7.dfsg-13_i386.deb diff --git a/build/linux/sysroot_scripts/sysroot-creator-test.sh b/build/linux/sysroot_scripts/sysroot-creator-test.sh new file mode 100755 index 0000000000000..b346bb70885c2 --- /dev/null +++ b/build/linux/sysroot_scripts/sysroot-creator-test.sh @@ -0,0 +1,23 @@ +#!/bin/sh +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Rudimentry test suite for sysroot-creator. + +SCRIPT_DIR=$(dirname $0) + +set -o errexit + +TestUpdateAllLists() { + echo "[ RUN ] TestUpdateAllLists" + "$SCRIPT_DIR/sysroot-creator-trusty.sh" UpdatePackageListsAmd64 + "$SCRIPT_DIR/sysroot-creator-trusty.sh" UpdatePackageListsI386 + "$SCRIPT_DIR/sysroot-creator-trusty.sh" UpdatePackageListsARM + "$SCRIPT_DIR/sysroot-creator-wheezy.sh" UpdatePackageListsAmd64 + "$SCRIPT_DIR/sysroot-creator-wheezy.sh" UpdatePackageListsI386 + "$SCRIPT_DIR/sysroot-creator-wheezy.sh" UpdatePackageListsARM + echo "[ OK ]" +} + +TestUpdateAllLists diff --git a/build/linux/sysroot_scripts/sysroot-creator-trusty.sh b/build/linux/sysroot_scripts/sysroot-creator-trusty.sh new file mode 100755 index 0000000000000..c0d82ec74a21d --- /dev/null +++ b/build/linux/sysroot_scripts/sysroot-creator-trusty.sh @@ -0,0 +1,182 @@ +#!/bin/sh +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +SCRIPT_DIR=$(dirname $0) + +DISTRO=ubuntu +DIST=trusty + +# This is where we get all the debian packages from. +APT_REPO=http://archive.ubuntu.com/ubuntu +APT_REPO_ARM=http://ports.ubuntu.com +REPO_BASEDIR="${APT_REPO}/dists/${DIST}" +KEYRING_FILE=/usr/share/keyrings/ubuntu-archive-keyring.gpg + +# Sysroot packages: these are the packages needed to build chrome. +# NOTE: When DEBIAN_PACKAGES is modified, the packagelist files must be updated +# by running this script in GeneratePackageList mode. +DEBIAN_PACKAGES="\ + comerr-dev \ + gcc-4.8 \ + krb5-multidev \ + libasound2 \ + libasound2-dev \ + libatk1.0-0 \ + libatk1.0-dev \ + libavahi-client3 \ + libavahi-common3 \ + libc6 \ + libc6-dev \ + libcairo2 \ + libcairo2-dev \ + libcairo-gobject2 \ + libcairo-script-interpreter2 \ + libcap-dev \ + libcap2 \ + libcomerr2 \ + libcups2 \ + libcups2-dev \ + libdbus-1-3 \ + libdbus-1-dev \ + libdbus-glib-1-2 \ + libdrm2 \ + libelf1 \ + libelf-dev \ + libexif12 \ + libexif-dev \ + libexpat1 \ + libexpat1-dev \ + libffi6 \ + libfontconfig1 \ + libfontconfig1-dev \ + libfreetype6 \ + libfreetype6-dev \ + libgcc1 \ + libgconf-2-4 \ + libgconf2-4 \ + libgconf2-dev \ + libgcrypt11 \ + libgcrypt11-dev \ + libgdk-pixbuf2.0-0 \ + libgdk-pixbuf2.0-dev \ + libgl1-mesa-dev \ + libgl1-mesa-glx \ + libglapi-mesa \ + libglib2.0-0 \ + libglib2.0-dev \ + libgnome-keyring0 \ + libgnome-keyring-dev \ + libgnutls26 \ + libgnutls-dev \ + libgnutls-openssl27 \ + libgnutlsxx27 \ + libgomp1 \ + libgpg-error0 \ + libgpg-error-dev \ + libgssapi-krb5-2 \ + libgssrpc4 \ + libgtk2.0-0 \ + libgtk2.0-dev \ + libk5crypto3 \ + libkadm5clnt-mit9 \ + libkadm5srv-mit9 \ + libkdb5-7 \ + libkeyutils1 \ + libkrb5-3 \ + libkrb5-dev \ + libkrb5support0 \ + libnspr4 \ + libnspr4-dev \ + libnss3 \ + libnss3-dev \ + libnss-db \ + liborbit2 \ + libp11-2 \ + libp11-kit0 \ + libpam0g \ + libpam0g-dev \ + libpango-1.0-0 \ + libpango1.0-dev \ + libpangocairo-1.0-0 \ + libpangoft2-1.0-0 \ + libpangoxft-1.0-0 \ + libpci3 \ + libpci-dev \ + libpcre3 \ + libpcre3-dev \ + libpcrecpp0 \ + libpixman-1-0 \ + libpixman-1-dev \ + libpng12-0 \ + libpng12-dev \ + libpulse0 \ + libpulse-dev \ + libpulse-mainloop-glib0 \ + libselinux1 \ + libspeechd2 \ + libspeechd-dev \ + libssl1.0.0 \ + libssl-dev \ + libstdc++6 \ + libstdc++-4.8-dev \ + libtasn1-6 \ + libx11-6 \ + libx11-dev \ + libx11-xcb1 \ + libxau6 \ + libxau-dev \ + libxcb1 \ + libxcb1-dev \ + libxcb-glx0 \ + libxcb-render0 \ + libxcb-render0-dev \ + libxcb-shm0 \ + libxcb-shm0-dev \ + libxcomposite1 \ + libxcomposite-dev \ + libxcursor1 \ + libxcursor-dev \ + libxdamage1 \ + libxdamage-dev \ + libxdmcp6 \ + libxext6 \ + libxext-dev \ + libxfixes3 \ + libxfixes-dev \ + libxi6 \ + libxi-dev \ + libxinerama1 \ + libxinerama-dev \ + libxrandr2 \ + libxrandr-dev \ + libxrender1 \ + libxrender-dev \ + libxss1 \ + libxss-dev \ + libxt6 \ + libxt-dev \ + libxtst6 \ + libxtst-dev \ + libxxf86vm1 \ + linux-libc-dev \ + mesa-common-dev \ + speech-dispatcher \ + x11proto-composite-dev \ + x11proto-core-dev \ + x11proto-damage-dev \ + x11proto-fixes-dev \ + x11proto-input-dev \ + x11proto-kb-dev \ + x11proto-randr-dev \ + x11proto-record-dev \ + x11proto-render-dev \ + x11proto-scrnsaver-dev \ + x11proto-xext-dev \ + zlib1g \ + zlib1g-dev" + +DEBIAN_PACKAGES_X86="libquadmath0" + +. ${SCRIPT_DIR}/sysroot-creator.sh diff --git a/build/linux/sysroot_scripts/sysroot-creator-wheezy.sh b/build/linux/sysroot_scripts/sysroot-creator-wheezy.sh new file mode 100755 index 0000000000000..9a4d1bf81cc3a --- /dev/null +++ b/build/linux/sysroot_scripts/sysroot-creator-wheezy.sh @@ -0,0 +1,177 @@ +#!/bin/sh +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +SCRIPT_DIR=$(dirname $0) + +DISTRO=debian +DIST=wheezy +APT_REPO=http://http.us.debian.org/debian +REPO_BASEDIR="${APT_REPO}/dists/${DIST}" +KEYRING_FILE=/usr/share/keyrings/debian-archive-keyring.gpg + +# Sysroot packages: these are the packages needed to build chrome. +# NOTE: When DEBIAN_PACKAGES is modified, the packagelist files must be updated +# by running this script in GeneratePackageList mode. +DEBIAN_PACKAGES="\ + comerr-dev \ + gcc-4.6 \ + krb5-multidev \ + libasound2 \ + libasound2-dev \ + libatk1.0-0 \ + libatk1.0-dev \ + libattr1 \ + libavahi-client3 \ + libavahi-common3 \ + libc6 \ + libc6-dev \ + libcairo2 \ + libcairo2-dev \ + libcairo-gobject2 \ + libcairo-script-interpreter2 \ + libcap-dev \ + libcap2 \ + libcomerr2 \ + libcups2 \ + libcups2-dev \ + libdbus-1-3 \ + libdbus-1-dev \ + libdbus-glib-1-2 \ + libdrm2 \ + libelf1 \ + libelf-dev \ + libexif12 \ + libexif-dev \ + libexpat1 \ + libexpat1-dev \ + libffi5 \ + libfontconfig1 \ + libfontconfig1-dev \ + libfreetype6 \ + libfreetype6-dev \ + libgcc1 \ + libgconf-2-4 \ + libgconf2-4 \ + libgconf2-dev \ + libgcrypt11 \ + libgcrypt11-dev \ + libgdk-pixbuf2.0-0 \ + libgdk-pixbuf2.0-dev \ + libgl1-mesa-dev \ + libgl1-mesa-glx \ + libglapi-mesa \ + libglib2.0-0 \ + libglib2.0-dev \ + libgnome-keyring0 \ + libgnome-keyring-dev \ + libgnutls26 \ + libgnutls-dev \ + libgnutls-openssl27 \ + libgnutlsxx27 \ + libgomp1 \ + libgpg-error0 \ + libgpg-error-dev \ + libgssapi-krb5-2 \ + libgssrpc4 \ + libgtk2.0-0 \ + libgtk2.0-dev \ + libk5crypto3 \ + libkadm5clnt-mit8 \ + libkadm5srv-mit8 \ + libkdb5-6 \ + libkeyutils1 \ + libkrb5-3 \ + libkrb5-dev \ + libkrb5support0 \ + libnspr4 \ + libnspr4-dev \ + libnss3 \ + libnss3-dev \ + libnss-db \ + liborbit2 \ + libp11-2 \ + libp11-kit0 \ + libpam0g \ + libpam0g-dev \ + libpango1.0-0 \ + libpango1.0-dev \ + libpci3 \ + libpci-dev \ + libpcre3 \ + libpcre3-dev \ + libpcrecpp0 \ + libpixman-1-0 \ + libpixman-1-dev \ + libpng12-0 \ + libpng12-dev \ + libpulse0 \ + libpulse-dev \ + libpulse-mainloop-glib0 \ + libselinux1 \ + libspeechd2 \ + libspeechd-dev \ + libssl1.0.0 \ + libssl-dev \ + libstdc++6 \ + libstdc++6-4.6-dev \ + libtasn1-3 \ + libx11-6 \ + libx11-dev \ + libx11-xcb1 \ + libxau6 \ + libxau-dev \ + libxcb1 \ + libxcb1-dev \ + libxcb-glx0 \ + libxcb-render0 \ + libxcb-render0-dev \ + libxcb-shm0 \ + libxcb-shm0-dev \ + libxcomposite1 \ + libxcomposite-dev \ + libxcursor1 \ + libxcursor-dev \ + libxdamage1 \ + libxdamage-dev \ + libxdmcp6 \ + libxext6 \ + libxext-dev \ + libxfixes3 \ + libxfixes-dev \ + libxi6 \ + libxi-dev \ + libxinerama1 \ + libxinerama-dev \ + libxrandr2 \ + libxrandr-dev \ + libxrender1 \ + libxrender-dev \ + libxss1 \ + libxss-dev \ + libxt6 \ + libxt-dev \ + libxtst6 \ + libxtst-dev \ + libxxf86vm1 \ + linux-libc-dev \ + mesa-common-dev \ + speech-dispatcher \ + x11proto-composite-dev \ + x11proto-core-dev \ + x11proto-damage-dev \ + x11proto-fixes-dev \ + x11proto-input-dev \ + x11proto-kb-dev \ + x11proto-randr-dev \ + x11proto-record-dev \ + x11proto-render-dev \ + x11proto-scrnsaver-dev \ + x11proto-xext-dev \ + zlib1g \ + zlib1g-dev" + +DEBIAN_PACKAGES_X86="libquadmath0" + +. ${SCRIPT_DIR}/sysroot-creator.sh diff --git a/build/linux/sysroot_scripts/sysroot-creator.sh b/build/linux/sysroot_scripts/sysroot-creator.sh new file mode 100644 index 0000000000000..822a5e8d9e17d --- /dev/null +++ b/build/linux/sysroot_scripts/sysroot-creator.sh @@ -0,0 +1,700 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# This script should not be run directly but sourced by the other +# scripts (e.g. sysroot-creator-trusty.sh). Its up to the parent scripts +# to define certain environment variables: e.g. +# DISTRO=ubuntu +# DIST=trusty +# APT_REPO=http://archive.ubuntu.com/ubuntu +# KEYRING_FILE=/usr/share/keyrings/ubuntu-archive-keyring.gpg +# DEBIAN_PACKAGES="gcc libz libssl" + +#@ This script builds a Debian sysroot images for building Google Chrome. +#@ +#@ Generally this script is invoked as: +#@ sysroot-creator-.sh * +#@ Available modes are shown below. +#@ +#@ List of modes: + +###################################################################### +# Config +###################################################################### + +set -o nounset +set -o errexit + +SCRIPT_DIR=$(cd $(dirname $0) && pwd) + +if [ -z "${DIST:-}" ]; then + echo "error: DIST not defined" + exit 1 +fi + +if [ -z "${APT_REPO:-}" ]; then + echo "error: APT_REPO not defined" + exit 1 +fi + +if [ -z "${KEYRING_FILE:-}" ]; then + echo "error: KEYRING_FILE not defined" + exit 1 +fi + +if [ -z "${DEBIAN_PACKAGES:-}" ]; then + echo "error: DEBIAN_PACKAGES not defined" + exit 1 +fi + +readonly REPO_BASEDIR="${APT_REPO}/dists/${DIST}" + +readonly REQUIRED_TOOLS="wget" + +###################################################################### +# Package Config +###################################################################### + +readonly RELEASE_FILE="Release" +readonly RELEASE_FILE_GPG="Release.gpg" +readonly RELEASE_LIST="${REPO_BASEDIR}/${RELEASE_FILE}" +readonly RELEASE_LIST_GPG="${REPO_BASEDIR}/${RELEASE_FILE_GPG}" +readonly PACKAGE_FILE_AMD64="main/binary-amd64/Packages.bz2" +readonly PACKAGE_FILE_I386="main/binary-i386/Packages.bz2" +readonly PACKAGE_FILE_ARM="main/binary-armhf/Packages.bz2" +readonly PACKAGE_FILE_MIPS="main/binary-mipsel/Packages.bz2" +readonly PACKAGE_LIST_AMD64="${REPO_BASEDIR}/${PACKAGE_FILE_AMD64}" +readonly PACKAGE_LIST_I386="${REPO_BASEDIR}/${PACKAGE_FILE_I386}" +readonly PACKAGE_LIST_ARM="${REPO_BASEDIR}/${PACKAGE_FILE_ARM}" +readonly PACKAGE_LIST_MIPS="${REPO_BASEDIR}/${PACKAGE_FILE_MIPS}" + +readonly DEBIAN_DEP_LIST_AMD64="packagelist.${DIST}.amd64" +readonly DEBIAN_DEP_LIST_I386="packagelist.${DIST}.i386" +readonly DEBIAN_DEP_LIST_ARM="packagelist.${DIST}.arm" +readonly DEBIAN_DEP_LIST_MIPS="packagelist.${DIST}.mipsel" + +###################################################################### +# Helper +###################################################################### + +Banner() { + echo "######################################################################" + echo $* + echo "######################################################################" +} + + +SubBanner() { + echo "----------------------------------------------------------------------" + echo $* + echo "----------------------------------------------------------------------" +} + + +Usage() { + egrep "^#@" "${BASH_SOURCE[0]}" | cut --bytes=3- +} + + +DownloadOrCopy() { + if [ -f "$2" ] ; then + echo "$2 already in place" + return + fi + + HTTP=0 + echo "$1" | grep -qs ^http:// && HTTP=1 + if [ "$HTTP" = "1" ]; then + SubBanner "downloading from $1 -> $2" + wget "$1" -O "${2}.partial" + mv "${2}.partial" $2 + else + SubBanner "copying from $1" + cp "$1" "$2" + fi +} + + +SetEnvironmentVariables() { + ARCH="" + echo $1 | grep -qs Amd64$ && ARCH=AMD64 + if [ -z "$ARCH" ]; then + echo $1 | grep -qs I386$ && ARCH=I386 + fi + if [ -z "$ARCH" ]; then + echo $1 | grep -qs Mips$ && ARCH=MIPS + fi + if [ -z "$ARCH" ]; then + echo $1 | grep -qs ARM$ && ARCH=ARM + fi + if [ -z "${ARCH}" ]; then + echo "ERROR: Unable to determine architecture based on: $1" + exit 1 + fi + ARCH_LOWER=$(echo $ARCH | tr '[:upper:]' '[:lower:]') +} + + +# some sanity checks to make sure this script is run from the right place +# with the right tools +SanityCheck() { + Banner "Sanity Checks" + + local chrome_dir=$(cd "${SCRIPT_DIR}/../../../.." && pwd) + BUILD_DIR="${chrome_dir}/out/sysroot-build/${DIST}" + mkdir -p ${BUILD_DIR} + echo "Using build directory: ${BUILD_DIR}" + + for tool in ${REQUIRED_TOOLS} ; do + if ! which ${tool} > /dev/null ; then + echo "Required binary $tool not found." + echo "Exiting." + exit 1 + fi + done + + # This is where the staging sysroot is. + INSTALL_ROOT="${BUILD_DIR}/${DIST}_${ARCH_LOWER}_staging" + TARBALL="${BUILD_DIR}/${DISTRO}_${DIST}_${ARCH_LOWER}_sysroot.tgz" + + if ! mkdir -p "${INSTALL_ROOT}" ; then + echo "ERROR: ${INSTALL_ROOT} can't be created." + exit 1 + fi +} + + +ChangeDirectory() { + # Change directory to where this script is. + cd ${SCRIPT_DIR} +} + + +ClearInstallDir() { + Banner "Clearing dirs in ${INSTALL_ROOT}" + rm -rf ${INSTALL_ROOT}/* +} + + +CreateTarBall() { + Banner "Creating tarball ${TARBALL}" + tar zcf ${TARBALL} -C ${INSTALL_ROOT} . +} + +ExtractPackageBz2() { + bzcat "$1" | egrep '^(Package:|Filename:|SHA256:) ' > "$2" +} + +GeneratePackageListAmd64() { + local output_file="$1" + local package_list="${BUILD_DIR}/Packages.${DIST}_amd64.bz2" + local tmp_package_list="${BUILD_DIR}/Packages.${DIST}_amd64" + DownloadOrCopy "${PACKAGE_LIST_AMD64}" "${package_list}" + VerifyPackageListing "${PACKAGE_FILE_AMD64}" "${package_list}" + ExtractPackageBz2 "$package_list" "$tmp_package_list" + GeneratePackageList "$tmp_package_list" "$output_file" "${DEBIAN_PACKAGES} + ${DEBIAN_PACKAGES_X86}" +} + +GeneratePackageListI386() { + local output_file="$1" + local package_list="${BUILD_DIR}/Packages.${DIST}_i386.bz2" + local tmp_package_list="${BUILD_DIR}/Packages.${DIST}_amd64" + DownloadOrCopy "${PACKAGE_LIST_I386}" "${package_list}" + VerifyPackageListing "${PACKAGE_FILE_I386}" "${package_list}" + ExtractPackageBz2 "$package_list" "$tmp_package_list" + GeneratePackageList "$tmp_package_list" "$output_file" "${DEBIAN_PACKAGES} + ${DEBIAN_PACKAGES_X86}" +} + +GeneratePackageListARM() { + local output_file="$1" + local package_list="${BUILD_DIR}/Packages.${DIST}_arm.bz2" + local tmp_package_list="${BUILD_DIR}/Packages.${DIST}_arm" + DownloadOrCopy "${PACKAGE_LIST_ARM}" "${package_list}" + VerifyPackageListing "${PACKAGE_FILE_ARM}" "${package_list}" + ExtractPackageBz2 "$package_list" "$tmp_package_list" + GeneratePackageList "$tmp_package_list" "$output_file" "${DEBIAN_PACKAGES}" +} + +GeneratePackageListMips() { + local output_file="$1" + local package_list="${BUILD_DIR}/Packages.${DIST}_mips.bz2" + local tmp_package_list="${BUILD_DIR}/Packages.${DIST}_mips" + DownloadOrCopy "${PACKAGE_LIST_MIPS}" "${package_list}" + VerifyPackageListing "${PACKAGE_FILE_MIPS}" "${package_list}" + ExtractPackageBz2 "$package_list" "$tmp_package_list" + GeneratePackageList "$tmp_package_list" "$output_file" "${DEBIAN_PACKAGES}" +} + +StripChecksumsFromPackageList() { + local package_file="$1" + sed -i 's/ [a-f0-9]\{64\}$//' "$package_file" +} + +VerifyPackageFilesMatch() { + local downloaded_package_file="$1" + local stored_package_file="$2" + diff -u "$downloaded_package_file" "$stored_package_file" + if [ "$?" -ne "0" ]; then + echo "ERROR: downloaded package files does not match $2." + echo "You may need to run UpdatePackageLists." + exit 1 + fi +} + +###################################################################### +# +###################################################################### + +HacksAndPatchesAmd64() { + Banner "Misc Hacks & Patches" + # these are linker scripts with absolute pathnames in them + # which we rewrite here + lscripts="${INSTALL_ROOT}/usr/lib/x86_64-linux-gnu/libpthread.so \ + ${INSTALL_ROOT}/usr/lib/x86_64-linux-gnu/libc.so" + + # Rewrite linker scripts + sed -i -e 's|/usr/lib/x86_64-linux-gnu/||g' ${lscripts} + sed -i -e 's|/lib/x86_64-linux-gnu/||g' ${lscripts} + + # This is for chrome's ./build/linux/pkg-config-wrapper + # which overwrites PKG_CONFIG_PATH internally + SubBanner "Package Configs Symlink" + mkdir -p ${INSTALL_ROOT}/usr/share + ln -s ../lib/x86_64-linux-gnu/pkgconfig ${INSTALL_ROOT}/usr/share/pkgconfig + + SubBanner "Adding an additional ld.conf include" + LD_SO_HACK_CONF="${INSTALL_ROOT}/etc/ld.so.conf.d/zz_hack.conf" + echo /usr/lib/gcc/x86_64-linux-gnu/4.6 > "$LD_SO_HACK_CONF" + echo /usr/lib >> "$LD_SO_HACK_CONF" +} + + +HacksAndPatchesI386() { + Banner "Misc Hacks & Patches" + # these are linker scripts with absolute pathnames in them + # which we rewrite here + lscripts="${INSTALL_ROOT}/usr/lib/i386-linux-gnu/libpthread.so \ + ${INSTALL_ROOT}/usr/lib/i386-linux-gnu/libc.so" + + # Rewrite linker scripts + sed -i -e 's|/usr/lib/i386-linux-gnu/||g' ${lscripts} + sed -i -e 's|/lib/i386-linux-gnu/||g' ${lscripts} + + # This is for chrome's ./build/linux/pkg-config-wrapper + # which overwrites PKG_CONFIG_PATH internally + SubBanner "Package Configs Symlink" + mkdir -p ${INSTALL_ROOT}/usr/share + ln -s ../lib/i386-linux-gnu/pkgconfig ${INSTALL_ROOT}/usr/share/pkgconfig + + SubBanner "Adding an additional ld.conf include" + LD_SO_HACK_CONF="${INSTALL_ROOT}/etc/ld.so.conf.d/zz_hack.conf" + echo /usr/lib/gcc/i486-linux-gnu/4.6 > "$LD_SO_HACK_CONF" + echo /usr/lib >> "$LD_SO_HACK_CONF" +} + + +HacksAndPatchesARM() { + Banner "Misc Hacks & Patches" + # these are linker scripts with absolute pathnames in them + # which we rewrite here + lscripts="${INSTALL_ROOT}/usr/lib/arm-linux-gnueabihf/libpthread.so \ + ${INSTALL_ROOT}/usr/lib/arm-linux-gnueabihf/libc.so" + + # Rewrite linker scripts + sed -i -e 's|/usr/lib/arm-linux-gnueabihf/||g' ${lscripts} + sed -i -e 's|/lib/arm-linux-gnueabihf/||g' ${lscripts} + + # This is for chrome's ./build/linux/pkg-config-wrapper + # which overwrites PKG_CONFIG_PATH internally + SubBanner "Package Configs Symlink" + mkdir -p ${INSTALL_ROOT}/usr/share + ln -s ../lib/arm-linux-gnueabihf/pkgconfig ${INSTALL_ROOT}/usr/share/pkgconfig +} + + +HacksAndPatchesMips() { + Banner "Misc Hacks & Patches" + # these are linker scripts with absolute pathnames in them + # which we rewrite here + lscripts="${INSTALL_ROOT}/usr/lib/mipsel-linux-gnu/libpthread.so \ + ${INSTALL_ROOT}/usr/lib/mipsel-linux-gnu/libc.so" + + # Rewrite linker scripts + sed -i -e 's|/usr/lib/mipsel-linux-gnu/||g' ${lscripts} + sed -i -e 's|/lib/mipsel-linux-gnu/||g' ${lscripts} + + # This is for chrome's ./build/linux/pkg-config-wrapper + # which overwrites PKG_CONFIG_PATH internally + SubBanner "Package Configs Symlink" + mkdir -p ${INSTALL_ROOT}/usr/share + ln -s ../lib/mipsel-linux-gnu/pkgconfig ${INSTALL_ROOT}/usr/share/pkgconfig +} + + +InstallIntoSysroot() { + Banner "Install Libs And Headers Into Jail" + + mkdir -p ${BUILD_DIR}/debian-packages + mkdir -p ${INSTALL_ROOT} + while (( "$#" )); do + local file="$1" + local package="${BUILD_DIR}/debian-packages/${file##*/}" + shift + local sha256sum="$1" + shift + if [ "${#sha256sum}" -ne "64" ]; then + echo "Bad sha256sum from package list" + exit 1 + fi + + Banner "Installing ${file}" + DownloadOrCopy ${APT_REPO}/pool/${file} ${package} + if [ ! -s "${package}" ] ; then + echo + echo "ERROR: bad package ${package}" + exit 1 + fi + echo "${sha256sum} ${package}" | sha256sum --quiet -c + + SubBanner "Extracting to ${INSTALL_ROOT}" + dpkg --fsys-tarfile ${package}\ + | tar -xf - --exclude=./usr/share -C ${INSTALL_ROOT} + done +} + + +CleanupJailSymlinks() { + Banner "Jail symlink cleanup" + + SAVEDPWD=$(pwd) + cd ${INSTALL_ROOT} + local libdirs="lib usr/lib" + if [ "${ARCH}" != "MIPS" ]; then + libdirs+=" lib64" + fi + find $libdirs -type l -printf '%p %l\n' | while read link target; do + # skip links with non-absolute paths + echo "${target}" | grep -qs ^/ || continue + echo "${link}: ${target}" + case "${link}" in + usr/lib/gcc/x86_64-linux-gnu/4.*/* | usr/lib/gcc/i486-linux-gnu/4.*/* | \ + usr/lib/gcc/arm-linux-gnueabihf/4.*/* | \ + usr/lib/gcc/mipsel-linux-gnu/4.*/*) + # Relativize the symlink. + ln -snfv "../../../../..${target}" "${link}" + ;; + usr/lib/x86_64-linux-gnu/* | usr/lib/i386-linux-gnu/* | \ + usr/lib/arm-linux-gnueabihf/* | usr/lib/mipsel-linux-gnu/* ) + # Relativize the symlink. + ln -snfv "../../..${target}" "${link}" + ;; + usr/lib/*) + # Relativize the symlink. + ln -snfv "../..${target}" "${link}" + ;; + lib64/* | lib/*) + # Relativize the symlink. + ln -snfv "..${target}" "${link}" + ;; + esac + done + + find $libdirs -type l -printf '%p %l\n' | while read link target; do + # Make sure we catch new bad links. + if [ ! -r "${link}" ]; then + echo "ERROR: FOUND BAD LINK ${link}" + ls -l ${link} + exit 1 + fi + done + cd "$SAVEDPWD" +} + +#@ +#@ BuildSysrootAmd64 +#@ +#@ Build everything and package it +BuildSysrootAmd64() { + ClearInstallDir + local package_file="$BUILD_DIR/package_with_sha256sum_amd64" + GeneratePackageListAmd64 "$package_file" + local files_and_sha256sums="$(cat ${package_file})" + StripChecksumsFromPackageList "$package_file" + VerifyPackageFilesMatch "$package_file" "$DEBIAN_DEP_LIST_AMD64" + InstallIntoSysroot ${files_and_sha256sums} + CleanupJailSymlinks + HacksAndPatchesAmd64 + CreateTarBall +} + +#@ +#@ BuildSysrootI386 +#@ +#@ Build everything and package it +BuildSysrootI386() { + ClearInstallDir + local package_file="$BUILD_DIR/package_with_sha256sum_i386" + GeneratePackageListI386 "$package_file" + local files_and_sha256sums="$(cat ${package_file})" + StripChecksumsFromPackageList "$package_file" + VerifyPackageFilesMatch "$package_file" "$DEBIAN_DEP_LIST_I386" + InstallIntoSysroot ${files_and_sha256sums} + CleanupJailSymlinks + HacksAndPatchesI386 + CreateTarBall +} + +#@ +#@ BuildSysrootARM +#@ +#@ Build everything and package it +BuildSysrootARM() { + ClearInstallDir + local package_file="$BUILD_DIR/package_with_sha256sum_arm" + GeneratePackageListARM "$package_file" + local files_and_sha256sums="$(cat ${package_file})" + StripChecksumsFromPackageList "$package_file" + VerifyPackageFilesMatch "$package_file" "$DEBIAN_DEP_LIST_ARM" + APT_REPO=${APR_REPO_ARM:=$APT_REPO} + InstallIntoSysroot ${files_and_sha256sums} + CleanupJailSymlinks + HacksAndPatchesARM + CreateTarBall +} + +#@ +#@ BuildSysrootMips +#@ +#@ Build everything and package it +BuildSysrootMips() { + ClearInstallDir + local package_file="$BUILD_DIR/package_with_sha256sum_arm" + GeneratePackageListMips "$package_file" + local files_and_sha256sums="$(cat ${package_file})" + StripChecksumsFromPackageList "$package_file" + VerifyPackageFilesMatch "$package_file" "$DEBIAN_DEP_LIST_MIPS" + APT_REPO=${APR_REPO_MIPS:=$APT_REPO} + InstallIntoSysroot ${files_and_sha256sums} + CleanupJailSymlinks + HacksAndPatchesMips + CreateTarBall +} + +#@ +#@ BuildSysrootAll +#@ +#@ Build sysroot images for all architectures +BuildSysrootAll() { + RunCommand BuildSysrootAmd64 + RunCommand BuildSysrootI386 + RunCommand BuildSysrootARM + RunCommand BuildSysrootMips +} + +UploadSysroot() { + local rev=$1 + if [ -z "${rev}" ]; then + echo "Please specify a revision to upload at." + exit 1 + fi + set -x + gsutil cp -a public-read "${TARBALL}" \ + "gs://chrome-linux-sysroot/toolchain/$rev/" + set +x +} + +#@ +#@ UploadSysrootAmd64 +#@ +UploadSysrootAmd64() { + UploadSysroot "$@" +} + +#@ +#@ UploadSysrootI386 +#@ +UploadSysrootI386() { + UploadSysroot "$@" +} + +#@ +#@ UploadSysrootARM +#@ +UploadSysrootARM() { + UploadSysroot "$@" +} + +#@ +#@ UploadSysrootMips +#@ +UploadSysrootMips() { + UploadSysroot "$@" +} + +#@ +#@ UploadSysrootAll +#@ +#@ Upload sysroot image for all architectures +UploadSysrootAll() { + RunCommand UploadSysrootAmd64 "$@" + RunCommand UploadSysrootI386 "$@" + RunCommand UploadSysrootARM "$@" + RunCommand UploadSysrootMips "$@" +} + +# +# CheckForDebianGPGKeyring +# +# Make sure the Debian GPG keys exist. Otherwise print a helpful message. +# +CheckForDebianGPGKeyring() { + if [ ! -e "$KEYRING_FILE" ]; then + echo "Debian GPG keys missing. Install the debian-archive-keyring package." + exit 1 + fi +} + +# +# VerifyPackageListing +# +# Verifies the downloaded Packages.bz2 file has the right checksums. +# +VerifyPackageListing() { + local file_path=$1 + local output_file=$2 + local release_file="${BUILD_DIR}/${RELEASE_FILE}" + local release_file_gpg="${BUILD_DIR}/${RELEASE_FILE_GPG}" + local tmp_keyring_file="${BUILD_DIR}/keyring.gpg" + + CheckForDebianGPGKeyring + + DownloadOrCopy ${RELEASE_LIST} ${release_file} + DownloadOrCopy ${RELEASE_LIST_GPG} ${release_file_gpg} + echo "Verifying: ${release_file} with ${release_file_gpg}" + cp "${KEYRING_FILE}" "${tmp_keyring_file}" + gpg --primary-keyring "${tmp_keyring_file}" --recv-keys 2B90D010 + gpgv --keyring "${tmp_keyring_file}" "${release_file_gpg}" "${release_file}" + + echo "Verifying: ${output_file}" + local checksums=$(grep ${file_path} ${release_file} | cut -d " " -f 2) + local sha256sum=$(echo ${checksums} | cut -d " " -f 3) + + if [ "${#sha256sum}" -ne "64" ]; then + echo "Bad sha256sum from ${RELEASE_LIST}" + exit 1 + fi + + echo "${sha256sum} ${output_file}" | sha256sum --quiet -c +} + +# +# GeneratePackageList +# +# Looks up package names in ${BUILD_DIR}/Packages and write list of URLs +# to output file. +# +GeneratePackageList() { + local input_file="$1" + local output_file="$2" + echo "Updating: ${output_file} from ${input_file}" + /bin/rm -f "${output_file}" + shift + shift + for pkg in $@ ; do + local pkg_full=$(grep -A 1 " ${pkg}\$" "$input_file" | \ + egrep -o "pool/.*") + if [ -z "${pkg_full}" ]; then + echo "ERROR: missing package: $pkg" + exit 1 + fi + local pkg_nopool=$(echo "$pkg_full" | sed "s/^pool\///") + local sha256sum=$(grep -A 4 " ${pkg}\$" "$input_file" | \ + grep ^SHA256: | sed 's/^SHA256: //') + if [ "${#sha256sum}" -ne "64" ]; then + echo "Bad sha256sum from Packages" + exit 1 + fi + echo $pkg_nopool $sha256sum >> "$output_file" + done + # sort -o does an in-place sort of this file + sort "$output_file" -o "$output_file" +} + +#@ +#@ UpdatePackageListsAmd64 +#@ +#@ Regenerate the package lists such that they contain an up-to-date +#@ list of URLs within the Debian archive. (For amd64) +UpdatePackageListsAmd64() { + GeneratePackageListAmd64 "$DEBIAN_DEP_LIST_AMD64" + StripChecksumsFromPackageList "$DEBIAN_DEP_LIST_AMD64" +} + +#@ +#@ UpdatePackageListsI386 +#@ +#@ Regenerate the package lists such that they contain an up-to-date +#@ list of URLs within the Debian archive. (For i386) +UpdatePackageListsI386() { + GeneratePackageListI386 "$DEBIAN_DEP_LIST_I386" + StripChecksumsFromPackageList "$DEBIAN_DEP_LIST_I386" +} + +#@ +#@ UpdatePackageListsARM +#@ +#@ Regenerate the package lists such that they contain an up-to-date +#@ list of URLs within the Debian archive. (For arm) +UpdatePackageListsARM() { + GeneratePackageListARM "$DEBIAN_DEP_LIST_ARM" + StripChecksumsFromPackageList "$DEBIAN_DEP_LIST_ARM" +} + +#@ +#@ UpdatePackageListsMips +#@ +#@ Regenerate the package lists such that they contain an up-to-date +#@ list of URLs within the Debian archive. (For arm) +UpdatePackageListsMips() { + GeneratePackageListMips "$DEBIAN_DEP_LIST_MIPS" + StripChecksumsFromPackageList "$DEBIAN_DEP_LIST_MIPS" +} + +#@ +#@ UpdatePackageListsAll +#@ +#@ Regenerate the package lists for all architectures. +UpdatePackageListsAll() { + RunCommand UpdatePackageListsAmd64 + RunCommand UpdatePackageListsI386 + RunCommand UpdatePackageListsARM + RunCommand UpdatePackageListsMips +} + +RunCommand() { + SetEnvironmentVariables "$1" + SanityCheck + "$@" +} + +if [ $# -eq 0 ] ; then + echo "ERROR: you must specify a mode on the commandline" + echo + Usage + exit 1 +elif [ "$(type -t $1)" != "function" ]; then + echo "ERROR: unknown function '$1'." >&2 + echo "For help, try:" + echo " $0 help" + exit 1 +else + ChangeDirectory + if echo $1 | grep -qs "All$"; then + "$@" + else + RunCommand "$@" + fi +fi diff --git a/build/linux/system.gyp b/build/linux/system.gyp index a1d6bf0a1bcdc..ab20951b9c91c 100644 --- a/build/linux/system.gyp +++ b/build/linux/system.gyp @@ -524,7 +524,7 @@ }, ], }], - ['ozone_platform_dri==1 or ozone_platform_drm==1 or ozone_platform_gbm==1', { + ['ozone_platform_drm==1 or ozone_platform_gbm==1', { 'targets': [ { 'target_name': 'libdrm', diff --git a/build/module_args/nacl.gni b/build/module_args/nacl.gni new file mode 100644 index 0000000000000..61e0768e13a37 --- /dev/null +++ b/build/module_args/nacl.gni @@ -0,0 +1,6 @@ +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Override nacl's build directory. +nacl_shared_build_dir = "//build" diff --git a/build/module_args/v8.gni b/build/module_args/v8.gni index aa2848c40b446..8b5204c68ec46 100644 --- a/build/module_args/v8.gni +++ b/build/module_args/v8.gni @@ -9,5 +9,5 @@ if (is_android) { # TODO(sky): nuke this. Temporary while sorting out http://crbug.com/465456. enable_correct_v8_arch = false -v8_use_external_startup_data = false +v8_use_external_startup_data = !(is_chromeos || is_win) v8_extra_library_files = [] diff --git a/build/sanitizers/lsan_suppressions.cc b/build/sanitizers/lsan_suppressions.cc index ac2defa11b7d8..e9a8b7eb47a43 100644 --- a/build/sanitizers/lsan_suppressions.cc +++ b/build/sanitizers/lsan_suppressions.cc @@ -97,6 +97,9 @@ char kLSanDefaultSuppressions[] = // http://crbug.com/356306 "leak:content::SetProcessTitleFromCommandLine\n" +// http://crbug.com/506433 +"leak:blink::ResourceFetcher::garbageCollectDocumentResources\n" + // PLEASE READ ABOVE BEFORE ADDING NEW SUPPRESSIONS. // End of suppressions. diff --git a/build/sanitizers/tsan_suppressions.cc b/build/sanitizers/tsan_suppressions.cc index ace60756629cd..fe64dd2c1d786 100644 --- a/build/sanitizers/tsan_suppressions.cc +++ b/build/sanitizers/tsan_suppressions.cc @@ -270,9 +270,6 @@ char kTSanDefaultSuppressions[] = "race:g_next_user_script_id\n" // http://crbug.com/389098 -"race:webrtc::RtpToNtpMs\n" -"race:webrtc::UpdateRtcpList\n" -"race:webrtc::RemoteNtpTimeEstimator::Estimate\n" "race:webrtc::voe::TransmitMixer::EnableStereoChannelSwapping\n" // http://crbug.com/397022 @@ -306,6 +303,8 @@ char kTSanDefaultSuppressions[] = // https://crbug.com/455665 "race:mojo::common::*::tick_clock\n" +"race:mojo::common::internal::NowTicks\n" +"race:tracked_objects::ThreadData::InitializeThreadContext\n" // https://crbug.com/459429 "race:randomnessPid\n" diff --git a/build/secondary/testing/gtest/BUILD.gn b/build/secondary/testing/gtest/BUILD.gn index a20a09d4db647..073faec56294f 100644 --- a/build/secondary/testing/gtest/BUILD.gn +++ b/build/secondary/testing/gtest/BUILD.gn @@ -111,6 +111,16 @@ static_library("gtest") { configs -= [ "//build/config/compiler:chromium_code" ] configs += [ "//build/config/compiler:no_chromium_code" ] + + config("gtest_warnings") { + if (is_win && is_clang) { + # The Mutex constructor initializer list in gtest-port.cc is incorrectly + # ordered. See + # https://groups.google.com/d/msg/googletestframework/S5uSV8L2TX8/U1FaTDa6J6sJ. + cflags = [ "-Wno-reorder" ] + } + } + configs += [ ":gtest_warnings" ] } source_set("gtest_main") { diff --git a/build/secondary/third_party/android_tools/BUILD.gn b/build/secondary/third_party/android_tools/BUILD.gn index dc934cb93e40b..df2368bfe21a4 100644 --- a/build/secondary/third_party/android_tools/BUILD.gn +++ b/build/secondary/third_party/android_tools/BUILD.gn @@ -28,6 +28,23 @@ android_java_prebuilt("uiautomator_java") { jar_path = "$android_sdk/uiautomator.jar" } +android_resources("android_support_design_resources") { + v14_skip = true + resource_dirs = [ "$android_sdk_root/extras/android/support/design/res" ] + deps = [ + ":android_support_v7_appcompat_resources", + ] + custom_package = "android.support.design" +} + +android_java_prebuilt("android_support_design_java") { + deps = [ + ":android_support_v7_appcompat_java", + ":android_support_design_resources", + ] + jar_path = "$android_sdk_root/extras/android/support/design/libs/android-support-design.jar" +} + android_java_prebuilt("android_support_v13_java") { jar_path = "$android_sdk_root/extras/android/support/v13/android-support-v13.jar" @@ -88,7 +105,33 @@ android_resources("google_play_services_default_resources") { android_java_prebuilt("google_play_services_default_java") { deps = [ ":android_support_v13_java", + ":android_support_v7_mediarouter_java", ":google_play_services_default_resources", ] + proguard_preprocess = true + proguard_config = "//third_party/android_tools/proguard.flags" + + # TODO(dgn) deps should not complain about having a custom action here + # Currently, there is no guarantee that the data_deps actions will complete before the current one runs + data_deps = [ ":check_sdk_extras_version" ] jar_path = "$android_sdk_root/extras/google/google_play_services/libproject/google-play-services_lib/libs/google-play-services.jar" } + +action("check_sdk_extras_version") { + script = "//build/check_sdk_extras_version.py" + args = [ + "--package-id", + "extra-google-google_play_services", + "--package-location", + rebase_path("$android_sdk_root/extras/google/google_play_services"), + "--stamp", + rebase_path("$target_gen_dir/checked_sdk_extras_version.stamp"), + ] + inputs = [ + "//build/android_sdk_extras.json", + "$android_sdk_root/extras/google/google_play_services/source.properties", + ] + outputs = [ + "$target_gen_dir/checked_sdk_extras_version.stamp", + ] +} diff --git a/build/secondary/third_party/cacheinvalidation/BUILD.gn b/build/secondary/third_party/cacheinvalidation/BUILD.gn deleted file mode 100644 index 17e4d1c4a1af4..0000000000000 --- a/build/secondary/third_party/cacheinvalidation/BUILD.gn +++ /dev/null @@ -1,146 +0,0 @@ -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//testing/test.gni") - -config("cacheinvalidation_config") { - include_dirs = [ - "overrides", - "src", - ] -} - -static_library("cacheinvalidation") { - sources = [ - "overrides/google/cacheinvalidation/deps/callback.h", - "overrides/google/cacheinvalidation/deps/gmock.h", - "overrides/google/cacheinvalidation/deps/googletest.h", - "overrides/google/cacheinvalidation/deps/logging.h", - "overrides/google/cacheinvalidation/deps/mutex.h", - "overrides/google/cacheinvalidation/deps/random.cc", - "overrides/google/cacheinvalidation/deps/random.h", - "overrides/google/cacheinvalidation/deps/scoped_ptr.h", - "overrides/google/cacheinvalidation/deps/sha1-digest-function.h", - "overrides/google/cacheinvalidation/deps/stl-namespace.h", - "overrides/google/cacheinvalidation/deps/string_util.h", - "overrides/google/cacheinvalidation/deps/time.h", - "src/google/cacheinvalidation/deps/digest-function.h", - "src/google/cacheinvalidation/impl/basic-system-resources.cc", - "src/google/cacheinvalidation/impl/basic-system-resources.h", - "src/google/cacheinvalidation/impl/checking-invalidation-listener.cc", - "src/google/cacheinvalidation/impl/checking-invalidation-listener.h", - "src/google/cacheinvalidation/impl/client-protocol-namespace-fix.h", - "src/google/cacheinvalidation/impl/constants.cc", - "src/google/cacheinvalidation/impl/constants.h", - "src/google/cacheinvalidation/impl/digest-store.h", - "src/google/cacheinvalidation/impl/exponential-backoff-delay-generator.cc", - "src/google/cacheinvalidation/impl/exponential-backoff-delay-generator.h", - "src/google/cacheinvalidation/impl/invalidation-client-core.cc", - "src/google/cacheinvalidation/impl/invalidation-client-core.h", - "src/google/cacheinvalidation/impl/invalidation-client-factory.cc", - "src/google/cacheinvalidation/impl/invalidation-client-impl.cc", - "src/google/cacheinvalidation/impl/invalidation-client-impl.h", - "src/google/cacheinvalidation/impl/invalidation-client-util.h", - "src/google/cacheinvalidation/impl/log-macro.h", - "src/google/cacheinvalidation/impl/object-id-digest-utils.cc", - "src/google/cacheinvalidation/impl/object-id-digest-utils.h", - "src/google/cacheinvalidation/impl/persistence-utils.cc", - "src/google/cacheinvalidation/impl/persistence-utils.h", - "src/google/cacheinvalidation/impl/proto-converter.cc", - "src/google/cacheinvalidation/impl/proto-converter.h", - "src/google/cacheinvalidation/impl/proto-helpers.cc", - "src/google/cacheinvalidation/impl/proto-helpers.h", - "src/google/cacheinvalidation/impl/protocol-handler.cc", - "src/google/cacheinvalidation/impl/protocol-handler.h", - "src/google/cacheinvalidation/impl/recurring-task.cc", - "src/google/cacheinvalidation/impl/recurring-task.h", - "src/google/cacheinvalidation/impl/registration-manager.cc", - "src/google/cacheinvalidation/impl/registration-manager.h", - "src/google/cacheinvalidation/impl/repeated-field-namespace-fix.h", - "src/google/cacheinvalidation/impl/run-state.h", - "src/google/cacheinvalidation/impl/safe-storage.cc", - "src/google/cacheinvalidation/impl/safe-storage.h", - "src/google/cacheinvalidation/impl/simple-registration-store.cc", - "src/google/cacheinvalidation/impl/simple-registration-store.h", - "src/google/cacheinvalidation/impl/smearer.h", - "src/google/cacheinvalidation/impl/statistics.cc", - "src/google/cacheinvalidation/impl/statistics.h", - "src/google/cacheinvalidation/impl/throttle.cc", - "src/google/cacheinvalidation/impl/throttle.h", - "src/google/cacheinvalidation/impl/ticl-message-validator.cc", - "src/google/cacheinvalidation/impl/ticl-message-validator.h", - "src/google/cacheinvalidation/include/invalidation-client-factory.h", - "src/google/cacheinvalidation/include/invalidation-client.h", - "src/google/cacheinvalidation/include/invalidation-listener.h", - "src/google/cacheinvalidation/include/system-resources.h", - "src/google/cacheinvalidation/include/types.h", - ] - - # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. - configs += [ "//build/config/compiler:no_size_t_to_int_warning" ] - public_configs = [ ":cacheinvalidation_config" ] - - public_deps = [ - "src/google/cacheinvalidation:cacheinvalidation_proto_cpp", - ] - - deps = [ - "//base", - ] -} - -test("cacheinvalidation_unittests") { - sources = [ - "src/google/cacheinvalidation/impl/invalidation-client-impl_test.cc", - "src/google/cacheinvalidation/impl/protocol-handler_test.cc", - "src/google/cacheinvalidation/impl/recurring-task_test.cc", - "src/google/cacheinvalidation/impl/throttle_test.cc", - "src/google/cacheinvalidation/test/deterministic-scheduler.cc", - "src/google/cacheinvalidation/test/deterministic-scheduler.h", - "src/google/cacheinvalidation/test/test-logger.cc", - "src/google/cacheinvalidation/test/test-logger.h", - "src/google/cacheinvalidation/test/test-utils.cc", - "src/google/cacheinvalidation/test/test-utils.h", - ] - - deps = [ - ":cacheinvalidation", - "src/google/cacheinvalidation:cacheinvalidation_proto_cpp", - "//base", - "//base/test:run_all_unittests", - "//testing/gmock", - "//testing/gtest", - ] -} - -# TODO(GYP) Test isolation stuff. -if (is_android) { - import("//build/config/android/rules.gni") - - # GYP: //third_party/cacheinvalidation/cacheinvalidation.gyp:cacheinvalidation_proto_java - proto_java_library("cacheinvalidation_proto_java") { - proto_path = "src/proto" - sources = [ - "$proto_path/android_channel.proto", - "$proto_path/android_listener.proto", - "$proto_path/android_service.proto", - "$proto_path/channel_common.proto", - "$proto_path/client.proto", - "$proto_path/client_protocol.proto", - "$proto_path/java_client.proto", - "$proto_path/types.proto", - ] - } - - # GYP: //third_party/cacheinvalidation/cacheinvalidation.gyp:cacheinvalidation_javalib - android_library("cacheinvalidation_javalib") { - deps = [ - ":cacheinvalidation_proto_java", - "//third_party/android_protobuf:protobuf_nano_javalib", - "//third_party/android_tools:android_gcm_java", - ] - - DEPRECATED_java_in_dir = "src/java" - } -} diff --git a/build/secondary/third_party/cacheinvalidation/src/google/cacheinvalidation/BUILD.gn b/build/secondary/third_party/cacheinvalidation/src/google/cacheinvalidation/BUILD.gn deleted file mode 100644 index 3bbb844eeaa48..0000000000000 --- a/build/secondary/third_party/cacheinvalidation/src/google/cacheinvalidation/BUILD.gn +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//third_party/protobuf/proto_library.gni") - -proto_library("cacheinvalidation_proto_cpp") { - # Depend on cacheinvalidation instead. - visibility = [ "//third_party/cacheinvalidation/*" ] - - sources = [ - "client.proto", - "client_gateway.proto", - "client_protocol.proto", - "client_test_internal.proto", - "types.proto", - ] - - if (!is_android) { - sources += [ - "android_channel.proto", - "channel_common.proto", - ] - } - - proto_out_dir = "google/cacheinvalidation" -} diff --git a/build/secondary/tools/grit/grit_rule.gni b/build/secondary/tools/grit/grit_rule.gni index 95a5e2e133270..bdf812f219dee 100644 --- a/build/secondary/tools/grit/grit_rule.gni +++ b/build/secondary/tools/grit/grit_rule.gni @@ -11,11 +11,10 @@ # Path to .grd file. # # outputs (required) -# List of outputs from grit, relative to the target_gen_dir. If supplied, -# a call to Grit to compute the outputs can be skipped which will make -# GN run faster. Grit will verify at build time that this list is correct -# and will fail if there is a mismatch between the outputs specified by -# the .grd file and the outputs list here. +# List of outputs from grit, relative to the target_gen_dir. Grit will +# verify at build time that this list is correct and will fail if there +# is a mismatch between the outputs specified by the .grd file and the +# outputs list here. # # To get this list, you can look in the .grd file for # 1: negative_patterns = pattern_groups[1].split(':') diff --git a/build/win/asan.gyp b/build/win/asan.gyp index c0d0c98f0b6e9..d938426e13694 100644 --- a/build/win/asan.gyp +++ b/build/win/asan.gyp @@ -19,7 +19,7 @@ 'destination': '<(PRODUCT_DIR)', 'files': [ # Path is relative to this GYP file. - '<(DEPTH)/<(make_clang_dir)/lib/clang/3.7.0/lib/windows/clang_rt.asan_dynamic-i386.dll', + '<(DEPTH)/<(make_clang_dir)/lib/clang/ +#include +#include + +#include "base/basictypes.h" +#include "base/strings/string_util.h" +#include "crypto/openssl_util.h" + +namespace crypto { + +Aead::Aead(AeadAlgorithm algorithm) : key_(nullptr) { + EnsureOpenSSLInit(); + switch (algorithm) { + case AES_128_CTR_HMAC_SHA256: + aead_ = EVP_aead_aes_128_ctr_hmac_sha256(); + break; + } +} + +Aead::~Aead() { +} + +void Aead::Init(const std::string* key) { + DCHECK(!key_); + DCHECK_EQ(KeyLength(), key->size()); + key_ = key; +} + +bool Aead::Seal(const base::StringPiece& plaintext, + const base::StringPiece& nonce, + const base::StringPiece& additional_data, + std::string* ciphertext) const { + DCHECK(key_); + DCHECK_EQ(NonceLength(), nonce.size()); + EVP_AEAD_CTX ctx; + + if (!EVP_AEAD_CTX_init(&ctx, aead_, + reinterpret_cast(key_->data()), + key_->size(), EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr)) { + return false; + } + + std::string result; + const size_t max_output_length = + EVP_AEAD_max_overhead(aead_) + plaintext.size(); + size_t output_length; + uint8* out_ptr = + reinterpret_cast(base::WriteInto(&result, max_output_length + 1)); + + if (!EVP_AEAD_CTX_seal( + &ctx, out_ptr, &output_length, max_output_length, + reinterpret_cast(nonce.data()), nonce.size(), + reinterpret_cast(plaintext.data()), plaintext.size(), + reinterpret_cast(additional_data.data()), + additional_data.size())) { + EVP_AEAD_CTX_cleanup(&ctx); + return false; + } + + DCHECK_LE(output_length, max_output_length); + result.resize(output_length); + + ciphertext->swap(result); + EVP_AEAD_CTX_cleanup(&ctx); + + return true; +} + +bool Aead::Open(const base::StringPiece& ciphertext, + const base::StringPiece& nonce, + const base::StringPiece& additional_data, + std::string* plaintext) const { + DCHECK(key_); + EVP_AEAD_CTX ctx; + + if (!EVP_AEAD_CTX_init(&ctx, aead_, + reinterpret_cast(key_->data()), + key_->size(), EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr)) { + return false; + } + + std::string result; + const size_t max_output_length = ciphertext.size(); + size_t output_length; + uint8* out_ptr = + reinterpret_cast(base::WriteInto(&result, max_output_length + 1)); + + if (!EVP_AEAD_CTX_open( + &ctx, out_ptr, &output_length, max_output_length, + reinterpret_cast(nonce.data()), nonce.size(), + reinterpret_cast(ciphertext.data()), ciphertext.size(), + reinterpret_cast(additional_data.data()), + additional_data.size())) { + EVP_AEAD_CTX_cleanup(&ctx); + return false; + } + + DCHECK_LE(output_length, max_output_length); + result.resize(output_length); + + plaintext->swap(result); + EVP_AEAD_CTX_cleanup(&ctx); + + return true; +} + +size_t Aead::KeyLength() const { + return EVP_AEAD_key_length(aead_); +} + +size_t Aead::NonceLength() const { + return EVP_AEAD_nonce_length(aead_); +} + +} // namespace + +#endif diff --git a/crypto/aead_openssl.h b/crypto/aead_openssl.h new file mode 100644 index 0000000000000..773cce1428686 --- /dev/null +++ b/crypto/aead_openssl.h @@ -0,0 +1,48 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CRYPTO_AEAD_H_ +#define CRYPTO_AEAD_H_ + +#include "base/strings/string_piece.h" +#include "crypto/crypto_export.h" + +struct evp_aead_st; + +namespace crypto { + +// This class exposes the AES-128-CTR-HMAC-SHA256 AEAD, currently only +// for OpenSSL builds. +class CRYPTO_EXPORT Aead { + public: + enum AeadAlgorithm { AES_128_CTR_HMAC_SHA256 }; + + explicit Aead(AeadAlgorithm algorithm); + + ~Aead(); + + void Init(const std::string* key); + + bool Seal(const base::StringPiece& plaintext, + const base::StringPiece& nonce, + const base::StringPiece& additional_data, + std::string* ciphertext) const; + + bool Open(const base::StringPiece& ciphertext, + const base::StringPiece& nonce, + const base::StringPiece& additional_data, + std::string* plaintext) const; + + size_t KeyLength() const; + + size_t NonceLength() const; + + private: + const std::string* key_; + const evp_aead_st* aead_; +}; + +} // namespace crypto + +#endif // CRYPTO_ENCRYPTOR_H_ diff --git a/crypto/aead_openssl_unittest.cc b/crypto/aead_openssl_unittest.cc new file mode 100644 index 0000000000000..446bca2cb02f3 --- /dev/null +++ b/crypto/aead_openssl_unittest.cc @@ -0,0 +1,54 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/aead_openssl.h" + +#include + +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +#if defined(USE_OPENSSL) + +TEST(AeadTest, SealOpen) { + crypto::Aead aead(crypto::Aead::AES_128_CTR_HMAC_SHA256); + std::string key(aead.KeyLength(), 0); + aead.Init(&key); + std::string nonce(aead.NonceLength(), 0); + std::string plaintext("this is the plaintext"); + std::string ad("this is the additional data"); + std::string ciphertext; + EXPECT_TRUE(aead.Seal(plaintext, nonce, ad, &ciphertext)); + EXPECT_LT(0U, ciphertext.size()); + + std::string decrypted; + EXPECT_TRUE(aead.Open(ciphertext, nonce, ad, &decrypted)); + + EXPECT_EQ(plaintext, decrypted); +} + +TEST(AeadTest, SealOpenWrongKey) { + crypto::Aead aead(crypto::Aead::AES_128_CTR_HMAC_SHA256); + std::string key(aead.KeyLength(), 0); + std::string wrong_key(aead.KeyLength(), 1); + aead.Init(&key); + crypto::Aead aead_wrong_key(crypto::Aead::AES_128_CTR_HMAC_SHA256); + aead_wrong_key.Init(&wrong_key); + + std::string nonce(aead.NonceLength(), 0); + std::string plaintext("this is the plaintext"); + std::string ad("this is the additional data"); + std::string ciphertext; + EXPECT_TRUE(aead.Seal(plaintext, nonce, ad, &ciphertext)); + EXPECT_LT(0U, ciphertext.size()); + + std::string decrypted; + EXPECT_FALSE(aead_wrong_key.Open(ciphertext, nonce, ad, &decrypted)); + EXPECT_EQ(0U, decrypted.size()); +} + +#endif + +} // namespace diff --git a/crypto/aes_128_gcm_helpers_nss.cc b/crypto/aes_128_gcm_helpers_nss.cc new file mode 100644 index 0000000000000..621f28b586f18 --- /dev/null +++ b/crypto/aes_128_gcm_helpers_nss.cc @@ -0,0 +1,374 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/aes_128_gcm_helpers_nss.h" + +#include +#include + +#include "base/lazy_instance.h" +#include "base/macros.h" +#include "crypto/ghash.h" +#include "crypto/scoped_nss_types.h" + +#if defined(USE_NSS_CERTS) +#include +#endif + +namespace crypto { +namespace { + +// Declaration of the prototype both PK11_Decrypt and PK11_Encrypt follow. +using PK11_TransformFunction = SECStatus(PK11SymKey* symKey, + CK_MECHANISM_TYPE mechanism, + SECItem* param, + unsigned char* out, + unsigned int* outLen, + unsigned int maxLen, + const unsigned char* data, + unsigned int dataLen); + +// On Linux, dynamically link against the system version of libnss3.so. In +// order to continue working on systems without up-to-date versions of NSS, +// lookup PK11_Decrypt and PK11_Encrypt with dlsym. +// +// GcmSupportChecker is a singleton which caches the results of runtime symbol +// resolution of these symbols. +class GcmSupportChecker { + public: + PK11_TransformFunction* pk11_decrypt_func() { return pk11_decrypt_func_; } + + PK11_TransformFunction* pk11_encrypt_func() { return pk11_encrypt_func_; } + + private: + friend struct base::DefaultLazyInstanceTraits; + + GcmSupportChecker() { +#if !defined(USE_NSS_CERTS) + // Using a bundled version of NSS that is guaranteed to have these symbols. + pk11_decrypt_func_ = PK11_Decrypt; + pk11_encrypt_func_ = PK11_Encrypt; +#else + // Using system NSS libraries and PCKS #11 modules, which may not have the + // necessary functions (PK11_Decrypt and PK11_Encrypt) or mechanism support + // (CKM_AES_GCM). + + // If PK11_Decrypt() and PK11_Encrypt() were successfully resolved, then NSS + // will support AES-GCM directly. This was introduced in NSS 3.15. + pk11_decrypt_func_ = reinterpret_cast( + dlsym(RTLD_DEFAULT, "PK11_Decrypt")); + pk11_encrypt_func_ = reinterpret_cast( + dlsym(RTLD_DEFAULT, "PK11_Encrypt")); +#endif + } + + ~GcmSupportChecker() {} + + // |pk11_decrypt_func_| stores the runtime symbol resolution of PK11_Decrypt. + PK11_TransformFunction* pk11_decrypt_func_; + + // |pk11_encrypt_func_| stores the runtime symbol resolution of PK11_Encrypt. + PK11_TransformFunction* pk11_encrypt_func_; + + DISALLOW_COPY_AND_ASSIGN(GcmSupportChecker); +}; + +base::LazyInstance::Leaky g_gcm_support_checker = + LAZY_INSTANCE_INITIALIZER; + +} // namespace + +// Calls PK11_Decrypt if it's available. Otherwise, emulates CKM_AES_GCM using +// CKM_AES_CTR and the GaloisHash class. +SECStatus PK11DecryptHelper(PK11SymKey* key, + CK_MECHANISM_TYPE mechanism, + SECItem* param, + unsigned char* out, + unsigned int* out_len, + unsigned int max_len, + const unsigned char* data, + unsigned int data_len) { + // If PK11_Decrypt() was successfully resolved or if bundled version of NSS is + // being used, then NSS will support AES-GCM directly. + PK11_TransformFunction* pk11_decrypt_func = + g_gcm_support_checker.Get().pk11_decrypt_func(); + + if (pk11_decrypt_func != nullptr) { + return pk11_decrypt_func(key, mechanism, param, out, out_len, max_len, data, + data_len); + } + + // Otherwise, the user has an older version of NSS. Regrettably, NSS 3.14.x + // has a bug in the AES GCM code + // (https://bugzilla.mozilla.org/show_bug.cgi?id=853285), as well as missing + // the PK11_Decrypt function + // (https://bugzilla.mozilla.org/show_bug.cgi?id=854063), both of which are + // resolved in NSS 3.15. + + CHECK_EQ(mechanism, static_cast(CKM_AES_GCM)); + CHECK_EQ(param->len, sizeof(CK_GCM_PARAMS)); + + const CK_GCM_PARAMS* gcm_params = + reinterpret_cast(param->data); + + const CK_ULONG auth_tag_size = gcm_params->ulTagBits / 8; + + if (gcm_params->ulIvLen != 12u) { + DVLOG(1) << "ulIvLen is not equal to 12"; + PORT_SetError(SEC_ERROR_INPUT_LEN); + return SECFailure; + } + + SECItem my_param = {siBuffer, nullptr, 0}; + + // Step 2. Let H = CIPH_K(128 '0' bits). + unsigned char ghash_key[16] = {0}; + crypto::ScopedPK11Context ctx( + PK11_CreateContextBySymKey(CKM_AES_ECB, CKA_ENCRYPT, key, &my_param)); + if (!ctx) { + DVLOG(1) << "PK11_CreateContextBySymKey failed"; + return SECFailure; + } + int output_len; + if (PK11_CipherOp(ctx.get(), ghash_key, &output_len, sizeof(ghash_key), + ghash_key, sizeof(ghash_key)) != SECSuccess) { + DVLOG(1) << "PK11_CipherOp failed"; + return SECFailure; + } + + if (PK11_Finalize(ctx.get()) != SECSuccess) { + DVLOG(1) << "PK11_Finalize failed"; + return SECFailure; + } + + if (output_len != sizeof(ghash_key)) { + DVLOG(1) << "Wrong output length"; + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return SECFailure; + } + + // Step 3. If len(IV)=96, then let J0 = IV || 31 '0' bits || 1. + CK_AES_CTR_PARAMS ctr_params = {0}; + ctr_params.ulCounterBits = 32; + memcpy(ctr_params.cb, gcm_params->pIv, gcm_params->ulIvLen); + ctr_params.cb[12] = 0; + ctr_params.cb[13] = 0; + ctr_params.cb[14] = 0; + ctr_params.cb[15] = 1; + + my_param.type = siBuffer; + my_param.data = reinterpret_cast(&ctr_params); + my_param.len = sizeof(ctr_params); + + ctx.reset( + PK11_CreateContextBySymKey(CKM_AES_CTR, CKA_ENCRYPT, key, &my_param)); + if (!ctx) { + DVLOG(1) << "PK11_CreateContextBySymKey failed"; + return SECFailure; + } + + // Step 6. Calculate the encryption mask of GCTR_K(J0, ...). + unsigned char tag_mask[16] = {0}; + if (PK11_CipherOp(ctx.get(), tag_mask, &output_len, sizeof(tag_mask), + tag_mask, sizeof(tag_mask)) != SECSuccess) { + DVLOG(1) << "PK11_CipherOp failed"; + return SECFailure; + } + if (output_len != sizeof(tag_mask)) { + DVLOG(1) << "Wrong output length"; + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return SECFailure; + } + + if (data_len < auth_tag_size) { + PORT_SetError(SEC_ERROR_INPUT_LEN); + return SECFailure; + } + + // The const_cast for |data| can be removed if system NSS libraries are + // NSS 3.14.1 or later (NSS bug + // https://bugzilla.mozilla.org/show_bug.cgi?id=808218). + if (PK11_CipherOp(ctx.get(), out, &output_len, max_len, + const_cast(data), + data_len - auth_tag_size) != SECSuccess) { + DVLOG(1) << "PK11_CipherOp failed"; + return SECFailure; + } + + if (PK11_Finalize(ctx.get()) != SECSuccess) { + DVLOG(1) << "PK11_Finalize failed"; + return SECFailure; + } + + if (static_cast(output_len) != data_len - auth_tag_size) { + DVLOG(1) << "Wrong output length"; + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return SECFailure; + } + + crypto::GaloisHash ghash(ghash_key); + ghash.UpdateAdditional(gcm_params->pAAD, gcm_params->ulAADLen); + ghash.UpdateCiphertext(data, output_len); + unsigned char auth_tag[auth_tag_size]; + ghash.Finish(auth_tag, auth_tag_size); + for (unsigned int i = 0; i < auth_tag_size; i++) { + auth_tag[i] ^= tag_mask[i]; + } + + if (NSS_SecureMemcmp(auth_tag, data + output_len, auth_tag_size) != 0) { + PORT_SetError(SEC_ERROR_BAD_DATA); + return SECFailure; + } + + *out_len = output_len; + return SECSuccess; +} + +// Calls PK11_Encrypt if it's available. Otherwise, emulates CKM_AES_GCM using +// CKM_AES_CTR and the GaloisHash class. +SECStatus PK11EncryptHelper(PK11SymKey* key, + CK_MECHANISM_TYPE mechanism, + SECItem* param, + unsigned char* out, + unsigned int* out_len, + unsigned int max_len, + const unsigned char* data, + unsigned int data_len) { + // If PK11_Encrypt() was successfully resolved or if bundled version of NSS is + // being used, then NSS will support AES-GCM directly. + PK11_TransformFunction* pk11_encrypt_func = + g_gcm_support_checker.Get().pk11_encrypt_func(); + + if (pk11_encrypt_func != nullptr) { + return pk11_encrypt_func(key, mechanism, param, out, out_len, max_len, data, + data_len); + } + + // Otherwise, the user has an older version of NSS. Regrettably, NSS 3.14.x + // has a bug in the AES GCM code + // (https://bugzilla.mozilla.org/show_bug.cgi?id=853285), as well as missing + // the PK11_Encrypt function + // (https://bugzilla.mozilla.org/show_bug.cgi?id=854063), both of which are + // resolved in NSS 3.15. + + CHECK_EQ(mechanism, static_cast(CKM_AES_GCM)); + CHECK_EQ(param->len, sizeof(CK_GCM_PARAMS)); + + const CK_GCM_PARAMS* gcm_params = + reinterpret_cast(param->data); + + const CK_ULONG auth_tag_size = gcm_params->ulTagBits / 8; + + if (max_len < auth_tag_size) { + DVLOG(1) << "max_len is less than kAuthTagSize"; + PORT_SetError(SEC_ERROR_OUTPUT_LEN); + return SECFailure; + } + + if (gcm_params->ulIvLen != 12u) { + DVLOG(1) << "ulIvLen is not equal to 12"; + PORT_SetError(SEC_ERROR_INPUT_LEN); + return SECFailure; + } + + SECItem my_param = {siBuffer, nullptr, 0}; + + // Step 1. Let H = CIPH_K(128 '0' bits). + unsigned char ghash_key[16] = {0}; + crypto::ScopedPK11Context ctx( + PK11_CreateContextBySymKey(CKM_AES_ECB, CKA_ENCRYPT, key, &my_param)); + if (!ctx) { + DVLOG(1) << "PK11_CreateContextBySymKey failed"; + return SECFailure; + } + int output_len; + if (PK11_CipherOp(ctx.get(), ghash_key, &output_len, sizeof(ghash_key), + ghash_key, sizeof(ghash_key)) != SECSuccess) { + DVLOG(1) << "PK11_CipherOp failed"; + return SECFailure; + } + + if (PK11_Finalize(ctx.get()) != SECSuccess) { + DVLOG(1) << "PK11_Finalize failed"; + return SECFailure; + } + + if (output_len != sizeof(ghash_key)) { + DVLOG(1) << "Wrong output length"; + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return SECFailure; + } + + // Step 2. If len(IV)=96, then let J0 = IV || 31 '0' bits || 1. + CK_AES_CTR_PARAMS ctr_params = {0}; + ctr_params.ulCounterBits = 32; + memcpy(ctr_params.cb, gcm_params->pIv, gcm_params->ulIvLen); + ctr_params.cb[12] = 0; + ctr_params.cb[13] = 0; + ctr_params.cb[14] = 0; + ctr_params.cb[15] = 1; + + my_param.type = siBuffer; + my_param.data = reinterpret_cast(&ctr_params); + my_param.len = sizeof(ctr_params); + + ctx.reset( + PK11_CreateContextBySymKey(CKM_AES_CTR, CKA_ENCRYPT, key, &my_param)); + if (!ctx) { + DVLOG(1) << "PK11_CreateContextBySymKey failed"; + return SECFailure; + } + + // Step 6. Calculate the encryption mask of GCTR_K(J0, ...). + unsigned char tag_mask[16] = {0}; + if (PK11_CipherOp(ctx.get(), tag_mask, &output_len, sizeof(tag_mask), + tag_mask, sizeof(tag_mask)) != SECSuccess) { + DVLOG(1) << "PK11_CipherOp failed"; + return SECFailure; + } + if (output_len != sizeof(tag_mask)) { + DVLOG(1) << "Wrong output length"; + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return SECFailure; + } + + // The const_cast for |data| can be removed if system NSS libraries are + // NSS 3.14.1 or later (NSS bug + // https://bugzilla.mozilla.org/show_bug.cgi?id=808218). + if (PK11_CipherOp(ctx.get(), out, &output_len, max_len, + const_cast(data), data_len) != SECSuccess) { + DVLOG(1) << "PK11_CipherOp failed"; + return SECFailure; + } + + if (PK11_Finalize(ctx.get()) != SECSuccess) { + DVLOG(1) << "PK11_Finalize failed"; + return SECFailure; + } + + if (static_cast(output_len) != data_len) { + DVLOG(1) << "Wrong output length"; + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return SECFailure; + } + + if ((max_len - auth_tag_size) < static_cast(output_len)) { + DVLOG(1) << "(max_len - kAuthTagSize) is less than output_len"; + PORT_SetError(SEC_ERROR_OUTPUT_LEN); + return SECFailure; + } + + crypto::GaloisHash ghash(ghash_key); + ghash.UpdateAdditional(gcm_params->pAAD, gcm_params->ulAADLen); + ghash.UpdateCiphertext(out, output_len); + ghash.Finish(out + output_len, auth_tag_size); + for (unsigned int i = 0; i < auth_tag_size; i++) { + out[output_len + i] ^= tag_mask[i]; + } + + *out_len = output_len + auth_tag_size; + return SECSuccess; +} + +} // namespace crypto diff --git a/crypto/aes_128_gcm_helpers_nss.h b/crypto/aes_128_gcm_helpers_nss.h new file mode 100644 index 0000000000000..dadc56e0f0d20 --- /dev/null +++ b/crypto/aes_128_gcm_helpers_nss.h @@ -0,0 +1,48 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CRYPTO_AES_128_GCM_HELPERS_NSS_H_ +#define CRYPTO_AES_128_GCM_HELPERS_NSS_H_ + +#include +#include + +#include "crypto/crypto_export.h" + +namespace crypto { + +// When using the CKM_AES_GCM mechanism, one must consider that the mechanism +// had a bug in NSS 3.14.x (https://bugzilla.mozilla.org/show_bug.cgi?id=853285) +// which also lacks the PK11_Decrypt and PK11_Encrypt functions. +// (https://bugzilla.mozilla.org/show_bug.cgi?id=854063) +// +// While both these bugs were resolved in NSS 3.15, certain builds of Chromium +// may still be loading older versions of NSS as the system libraries. These +// helper methods emulate support by using CKM_AES_CTR and the GaloisHash. + +// Helper function for using PK11_Decrypt. |mechanism| must be set to +// CKM_AES_GCM for this method. +CRYPTO_EXPORT SECStatus PK11DecryptHelper(PK11SymKey* key, + CK_MECHANISM_TYPE mechanism, + SECItem* param, + unsigned char* out, + unsigned int* out_len, + unsigned int max_len, + const unsigned char* data, + unsigned int data_len); + +// Helper function for using PK11_Encrypt. |mechanism| must be set to +// CKM_AES_GCM for this method. +CRYPTO_EXPORT SECStatus PK11EncryptHelper(PK11SymKey* key, + CK_MECHANISM_TYPE mechanism, + SECItem* param, + unsigned char* out, + unsigned int* out_len, + unsigned int max_len, + const unsigned char* data, + unsigned int data_len); + +} // namespace crypto + +#endif // CRYPTO_AES_128_GCM_HELPERS_NSS_H_ diff --git a/crypto/aes_128_gcm_helpers_nss_unittest.cc b/crypto/aes_128_gcm_helpers_nss_unittest.cc new file mode 100644 index 0000000000000..d741b2fe54d07 --- /dev/null +++ b/crypto/aes_128_gcm_helpers_nss_unittest.cc @@ -0,0 +1,580 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/aes_128_gcm_helpers_nss.h" + +#include +#include +#include + +#include "base/logging.h" +#include "base/rand_util.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" +#include "crypto/nss_util.h" +#include "crypto/random.h" +#include "crypto/scoped_nss_types.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace crypto { + +namespace { + +// The AES GCM test vectors come from the gcmDecrypt128.rsp and +// gcmEncryptExtIV128.rsp files downloaded from +// http://csrc.nist.gov/groups/STM/cavp/index.html on 2013-02-01. The test +// vectors in that file look like this: +// +// [Keylen = 128] +// [IVlen = 96] +// [PTlen = 0] +// [AADlen = 0] +// [Taglen = 128] +// +// Count = 0 +// Key = cf063a34d4a9a76c2c86787d3f96db71 +// IV = 113b9785971864c83b01c787 +// CT = +// AAD = +// Tag = 72ac8493e3a5228b5d130a69d2510e42 +// PT = +// +// Count = 1 +// Key = a49a5e26a2f8cb63d05546c2a62f5343 +// IV = 907763b19b9b4ab6bd4f0281 +// CT = +// AAD = +// Tag = a2be08210d8c470a8df6e8fbd79ec5cf +// FAIL +// +// ... +// +// These files are huge (2.6 MB and 2.8 MB), so this file contains just a +// selection of test vectors. + +// Describes a group of test vectors that all have a given key length, IV +// length, plaintext length, AAD length, and tag length. +struct TestGroupInfo { + size_t key_len; + size_t iv_len; + size_t input_len; + size_t aad_len; + size_t tag_len; +}; + +// Each test vector consists of six strings of lowercase hexadecimal digits. +// The strings may be empty (zero length). A test vector with a NULL |key| +// marks the end of an array of test vectors. +struct TestVector { + // Input: + const char* key; + const char* iv; + const char* input; + const char* aad; + const char* tag; + + // Expected output: + const char* output; // An empty string "" means decryption or encryption + // succeeded and the plaintext is zero-length. NULL means + // that the decryption or encryption failed. +}; + +const TestGroupInfo test_group_info[] = { + {128, 96, 0, 0, 128}, + {128, 96, 0, 128, 128}, + {128, 96, 128, 0, 128}, + {128, 96, 408, 160, 128}, + {128, 96, 408, 720, 128}, + {128, 96, 104, 0, 128}, +}; + +const TestVector decryption_test_group_0[] = { + {"cf063a34d4a9a76c2c86787d3f96db71", + "113b9785971864c83b01c787", + "", + "", + "72ac8493e3a5228b5d130a69d2510e42", + ""}, + { + "a49a5e26a2f8cb63d05546c2a62f5343", + "907763b19b9b4ab6bd4f0281", + "", + "", + "a2be08210d8c470a8df6e8fbd79ec5cf", + NULL // FAIL + }, + {NULL}}; + +const TestVector decryption_test_group_1[] = { + { + "d1f6af919cde85661208bdce0c27cb22", + "898c6929b435017bf031c3c5", + "", + "7c5faa40e636bbc91107e68010c92b9f", + "ae45f11777540a2caeb128be8092468a", + NULL // FAIL + }, + {"2370e320d4344208e0ff5683f243b213", + "04dbb82f044d30831c441228", + "", + "d43a8e5089eea0d026c03a85178b27da", + "2a049c049d25aa95969b451d93c31c6e", + ""}, + {NULL}}; + +const TestVector decryption_test_group_2[] = { + {"e98b72a9881a84ca6b76e0f43e68647a", + "8b23299fde174053f3d652ba", + "5a3c1cf1985dbb8bed818036fdd5ab42", + "", + "23c7ab0f952b7091cd324835043b5eb5", + "28286a321293253c3e0aa2704a278032"}, + {"33240636cd3236165f1a553b773e728e", + "17c4d61493ecdc8f31700b12", + "47bb7e23f7bdfe05a8091ac90e4f8b2e", + "", + "b723c70e931d9785f40fd4ab1d612dc9", + "95695a5b12f2870b9cc5fdc8f218a97d"}, + { + "5164df856f1e9cac04a79b808dc5be39", + "e76925d5355e0584ce871b2b", + "0216c899c88d6e32c958c7e553daa5bc", + "", + "a145319896329c96df291f64efbe0e3a", + NULL // FAIL + }, + {NULL}}; + +const TestVector decryption_test_group_3[] = { + {"af57f42c60c0fc5a09adb81ab86ca1c3", + "a2dc01871f37025dc0fc9a79", + "b9a535864f48ea7b6b1367914978f9bfa087d854bb0e269bed8d279d2eea1210e48947" + "338b22f9bad09093276a331e9c79c7f4", + "41dc38988945fcb44faf2ef72d0061289ef8efd8", + "4f71e72bde0018f555c5adcce062e005", + "3803a0727eeb0ade441e0ec107161ded2d425ec0d102f21f51bf2cf9947c7ec4aa7279" + "5b2f69b041596e8817d0a3c16f8fadeb"}, + {"ebc753e5422b377d3cb64b58ffa41b61", + "2e1821efaced9acf1f241c9b", + "069567190554e9ab2b50a4e1fbf9c147340a5025fdbd201929834eaf6532325899ccb9" + "f401823e04b05817243d2142a3589878", + "b9673412fd4f88ba0e920f46dd6438ff791d8eef", + "534d9234d2351cf30e565de47baece0b", + "39077edb35e9c5a4b1e4c2a6b9bb1fce77f00f5023af40333d6d699014c2bcf4209c18" + "353a18017f5b36bfc00b1f6dcb7ed485"}, + { + "52bdbbf9cf477f187ec010589cb39d58", + "d3be36d3393134951d324b31", + "700188da144fa692cf46e4a8499510a53d90903c967f7f13e8a1bd8151a74adc4fe63e" + "32b992760b3a5f99e9a47838867000a9", + "93c4fc6a4135f54d640b0c976bf755a06a292c33", + "8ca4e38aa3dfa6b1d0297021ccf3ea5f", + NULL // FAIL + }, + {NULL}}; + +const TestVector decryption_test_group_4[] = { + {"da2bb7d581493d692380c77105590201", + "44aa3e7856ca279d2eb020c6", + "9290d430c9e89c37f0446dbd620c9a6b34b1274aeb6f911f75867efcf95b6feda69f1a" + "f4ee16c761b3c9aeac3da03aa9889c88", + "4cd171b23bddb3a53cdf959d5c1710b481eb3785a90eb20a2345ee00d0bb7868c367ab" + "12e6f4dd1dee72af4eee1d197777d1d6499cc541f34edbf45cda6ef90b3c024f9272d7" + "2ec1909fb8fba7db88a4d6f7d3d925980f9f9f72", + "9e3ac938d3eb0cadd6f5c9e35d22ba38", + "9bbf4c1a2742f6ac80cb4e8a052e4a8f4f07c43602361355b717381edf9fabd4cb7e3a" + "d65dbd1378b196ac270588dd0621f642"}, + {"d74e4958717a9d5c0e235b76a926cae8", + "0b7471141e0c70b1995fd7b1", + "e701c57d2330bf066f9ff8cf3ca4343cafe4894651cd199bdaaa681ba486b4a65c5a22" + "b0f1420be29ea547d42c713bc6af66aa", + "4a42b7aae8c245c6f1598a395316e4b8484dbd6e64648d5e302021b1d3fa0a38f46e22" + "bd9c8080b863dc0016482538a8562a4bd0ba84edbe2697c76fd039527ac179ec5506cf" + "34a6039312774cedebf4961f3978b14a26509f96", + "e192c23cb036f0b31592989119eed55d", + "840d9fb95e32559fb3602e48590280a172ca36d9b49ab69510f5bd552bfab7a306f85f" + "f0a34bc305b88b804c60b90add594a17"}, + { + "1986310c725ac94ecfe6422e75fc3ee7", + "93ec4214fa8e6dc4e3afc775", + "b178ec72f85a311ac4168f42a4b2c23113fbea4b85f4b9dabb74e143eb1b8b0a361e02" + "43edfd365b90d5b325950df0ada058f9", + "e80b88e62c49c958b5e0b8b54f532d9ff6aa84c8a40132e93e55b59fc24e8decf28463" + "139f155d1e8ce4ee76aaeefcd245baa0fc519f83a5fb9ad9aa40c4b21126013f576c42" + "72c2cb136c8fd091cc4539877a5d1e72d607f960", + "8b347853f11d75e81e8a95010be81f17", + NULL // FAIL + }, + {NULL}}; + +const TestVector decryption_test_group_5[] = { + {"387218b246c1a8257748b56980e50c94", + "dd7e014198672be39f95b69d", + "cdba9e73eaf3d38eceb2b04a8d", + "", + "ecf90f4a47c9c626d6fb2c765d201556", + "48f5b426baca03064554cc2b30"}, + {"294de463721e359863887c820524b3d4", + "3338b35c9d57a5d28190e8c9", + "2f46634e74b8e4c89812ac83b9", + "", + "dabd506764e68b82a7e720aa18da0abe", + "46a2e55c8e264df211bd112685"}, + {"28ead7fd2179e0d12aa6d5d88c58c2dc", + "5055347f18b4d5add0ae5c41", + "142d8210c3fb84774cdbd0447a", + "", + "5fd321d9cdb01952dc85f034736c2a7d", + "3b95b981086ee73cc4d0cc1422"}, + { + "7d7b6c988137b8d470c57bf674a09c87", + "9edf2aa970d016ac962e1fd8", + "a85b66c3cb5eab91d5bdc8bc0e", + "", + "dc054efc01f3afd21d9c2484819f569a", + NULL // FAIL + }, + {NULL}}; + +const TestVector encryption_test_group_0[] = { + {"11754cd72aec309bf52f7687212e8957", + "3c819d9a9bed087615030b65", + "", + "", + "250327c674aaf477aef2675748cf6971", + ""}, + {"ca47248ac0b6f8372a97ac43508308ed", + "ffd2b598feabc9019262d2be", + "", + "", + "60d20404af527d248d893ae495707d1a", + ""}, + {NULL}}; + +const TestVector encryption_test_group_1[] = { + {"77be63708971c4e240d1cb79e8d77feb", + "e0e00f19fed7ba0136a797f3", + "", + "7a43ec1d9c0a5a78a0b16533a6213cab", + "209fcc8d3675ed938e9c7166709dd946", + ""}, + {"7680c5d3ca6154758e510f4d25b98820", + "f8f105f9c3df4965780321f8", + "", + "c94c410194c765e3dcc7964379758ed3", + "94dca8edfcf90bb74b153c8d48a17930", + ""}, + {NULL}}; + +const TestVector encryption_test_group_2[] = { + {"7fddb57453c241d03efbed3ac44e371c", + "ee283a3fc75575e33efd4887", + "d5de42b461646c255c87bd2962d3b9a2", + "", + "b36d1df9b9d5e596f83e8b7f52971cb3", + "2ccda4a5415cb91e135c2a0f78c9b2fd"}, + {"ab72c77b97cb5fe9a382d9fe81ffdbed", + "54cc7dc2c37ec006bcc6d1da", + "007c5e5b3e59df24a7c355584fc1518d", + "", + "2b4401346697138c7a4891ee59867d0c", + "0e1bde206a07a9c2c1b65300f8c64997"}, + {NULL}}; + +const TestVector encryption_test_group_3[] = { + {"fe47fcce5fc32665d2ae399e4eec72ba", + "5adb9609dbaeb58cbd6e7275", + "7c0e88c88899a779228465074797cd4c2e1498d259b54390b85e3eef1c02df60e743f1" + "b840382c4bccaf3bafb4ca8429bea063", + "88319d6e1d3ffa5f987199166c8a9b56c2aeba5a", + "291ef1982e4defedaa2249f898556b47", + "98f4826f05a265e6dd2be82db241c0fbbbf9ffb1c173aa83964b7cf539304373636525" + "3ddbc5db8778371495da76d269e5db3e"}, + {"ec0c2ba17aa95cd6afffe949da9cc3a8", + "296bce5b50b7d66096d627ef", + "b85b3753535b825cbe5f632c0b843c741351f18aa484281aebec2f45bb9eea2d79d987" + "b764b9611f6c0f8641843d5d58f3a242", + "f8d00f05d22bf68599bcdeb131292ad6e2df5d14", + "890147971946b627c40016da1ecf3e77", + "a7443d31c26bdf2a1c945e29ee4bd344a99cfaf3aa71f8b3f191f83c2adfc7a0716299" + "5506fde6309ffc19e716eddf1a828c5a"}, + {NULL}}; + +const TestVector encryption_test_group_4[] = { + {"2c1f21cf0f6fb3661943155c3e3d8492", + "23cb5ff362e22426984d1907", + "42f758836986954db44bf37c6ef5e4ac0adaf38f27252a1b82d02ea949c8a1a2dbc0d6" + "8b5615ba7c1220ff6510e259f06655d8", + "5d3624879d35e46849953e45a32a624d6a6c536ed9857c613b572b0333e701557a713e" + "3f010ecdf9a6bd6c9e3e44b065208645aff4aabee611b391528514170084ccf587177f" + "4488f33cfb5e979e42b6e1cfc0a60238982a7aec", + "57a3ee28136e94c74838997ae9823f3a", + "81824f0e0d523db30d3da369fdc0d60894c7a0a20646dd015073ad2732bd989b14a222" + "b6ad57af43e1895df9dca2a5344a62cc"}, + {"d9f7d2411091f947b4d6f1e2d1f0fb2e", + "e1934f5db57cc983e6b180e7", + "73ed042327f70fe9c572a61545eda8b2a0c6e1d6c291ef19248e973aee6c312012f490" + "c2c6f6166f4a59431e182663fcaea05a", + "0a8a18a7150e940c3d87b38e73baee9a5c049ee21795663e264b694a949822b639092d" + "0e67015e86363583fcf0ca645af9f43375f05fdb4ce84f411dcbca73c2220dea03a201" + "15d2e51398344b16bee1ed7c499b353d6c597af8", + "21b51ca862cb637cdd03b99a0f93b134", + "aaadbd5c92e9151ce3db7210b8714126b73e43436d242677afa50384f2149b831f1d57" + "3c7891c2a91fbc48db29967ec9542b23"}, + {NULL}}; + +const TestVector encryption_test_group_5[] = { + {"fe9bb47deb3a61e423c2231841cfd1fb", + "4d328eb776f500a2f7fb47aa", + "f1cc3818e421876bb6b8bbd6c9", + "", + "43fd4727fe5cdb4b5b42818dea7ef8c9", + "b88c5c1977b35b517b0aeae967"}, + {"6703df3701a7f54911ca72e24dca046a", + "12823ab601c350ea4bc2488c", + "793cd125b0b84a043e3ac67717", + "", + "38e6bcd29962e5f2c13626b85a877101", + "b2051c80014f42f08735a7b0cd"}, + {NULL}}; + +const TestVector* const decryption_test_group_array[] = { + decryption_test_group_0, + decryption_test_group_1, + decryption_test_group_2, + decryption_test_group_3, + decryption_test_group_4, + decryption_test_group_5, +}; + +const TestVector* const encryption_test_group_array[] = { + encryption_test_group_0, + encryption_test_group_1, + encryption_test_group_2, + encryption_test_group_3, + encryption_test_group_4, + encryption_test_group_5, +}; + +bool DecodeHexString(const base::StringPiece& hex, std::string* bytes) { + bytes->clear(); + if (hex.empty()) + return true; + std::vector v; + if (!base::HexStringToBytes(hex.as_string(), &v)) + return false; + if (!v.empty()) + bytes->assign(reinterpret_cast(&v[0]), v.size()); + return true; +} + +class Aes128GcmHelpersTest : public ::testing::Test { + public: + enum Mode { DECRYPT, ENCRYPT }; + + void SetUp() override { EnsureNSSInit(); } + + bool DecryptOrEncrypt(Mode mode, + const base::StringPiece& input, + const base::StringPiece& key, + const base::StringPiece& nonce, + const base::StringPiece& aad, + size_t auth_tag_size, + std::string* output) { + DCHECK(output); + + const CK_ATTRIBUTE_TYPE cka_mode = + mode == DECRYPT ? CKA_DECRYPT : CKA_ENCRYPT; + + SECItem key_item; + key_item.type = siBuffer; + key_item.data = const_cast( + reinterpret_cast(key.data())); + key_item.len = key.size(); + + crypto::ScopedPK11Slot slot(PK11_GetInternalSlot()); + DCHECK(slot); + + crypto::ScopedPK11SymKey aead_key( + PK11_ImportSymKey(slot.get(), CKM_AES_GCM, PK11_OriginUnwrap, cka_mode, + &key_item, nullptr)); + + CK_GCM_PARAMS gcm_params; + gcm_params.pIv = const_cast( + reinterpret_cast(nonce.data())); + gcm_params.ulIvLen = nonce.size(); + + gcm_params.pAAD = const_cast( + reinterpret_cast(aad.data())); + + gcm_params.ulAADLen = aad.size(); + + gcm_params.ulTagBits = auth_tag_size * 8; + + SECItem param; + param.type = siBuffer; + param.data = reinterpret_cast(&gcm_params); + param.len = sizeof(CK_GCM_PARAMS); + + size_t maximum_output_length = input.size(); + if (mode == ENCRYPT) + maximum_output_length += auth_tag_size; + + unsigned int output_length = 0; + unsigned char* raw_input = const_cast( + reinterpret_cast(input.data())); + unsigned char* raw_output = reinterpret_cast( + base::WriteInto(output, maximum_output_length + 1 /* null */)); + + PK11Helper_TransformFunction* transform_function = + mode == DECRYPT ? PK11DecryptHelper : PK11EncryptHelper; + + const SECStatus result = transform_function( + aead_key.get(), CKM_AES_GCM, ¶m, raw_output, &output_length, + maximum_output_length, raw_input, input.size()); + + if (result != SECSuccess) + return false; + + const size_t expected_output_length = mode == DECRYPT + ? input.size() - auth_tag_size + : input.size() + auth_tag_size; + + EXPECT_EQ(expected_output_length, output_length); + + output->resize(expected_output_length); + return true; + } + + private: + // The prototype of PK11_Decrypt and PK11_Encrypt. + using PK11Helper_TransformFunction = SECStatus(PK11SymKey* symKey, + CK_MECHANISM_TYPE mechanism, + SECItem* param, + unsigned char* out, + unsigned int* outLen, + unsigned int maxLen, + const unsigned char* data, + unsigned int dataLen); +}; + +} // namespace + +TEST_F(Aes128GcmHelpersTest, RoundTrip) { + const std::string message = "Hello, world!"; + + const size_t kKeySize = 16; + const size_t kNonceSize = 16; + + std::string key, nonce; + RandBytes(base::WriteInto(&key, kKeySize + 1), kKeySize); + RandBytes(base::WriteInto(&nonce, kNonceSize + 1), kNonceSize); + + // AEAD_AES_128_GCM is defined with a default authentication tag size of 16, + // but RFC 5282 extends this to authentication tag sizes of 8 and 12 as well. + size_t auth_tag_size = base::RandInt(2, 4) * 4; + + std::string encrypted; + ASSERT_TRUE(DecryptOrEncrypt(ENCRYPT, message, key, nonce, + base::StringPiece(), auth_tag_size, &encrypted)); + + std::string decrypted; + ASSERT_TRUE(DecryptOrEncrypt(DECRYPT, encrypted, key, nonce, + base::StringPiece(), auth_tag_size, &decrypted)); + + EXPECT_EQ(message, decrypted); +} + +TEST_F(Aes128GcmHelpersTest, DecryptionVectors) { + for (size_t i = 0; i < arraysize(decryption_test_group_array); i++) { + SCOPED_TRACE(i); + const TestVector* test_vectors = decryption_test_group_array[i]; + const TestGroupInfo& test_info = test_group_info[i]; + + for (size_t j = 0; test_vectors[j].key != nullptr; j++) { + // If not present then decryption is expected to fail. + bool has_output = test_vectors[j].output; + + // Decode the test vector. + std::string key, iv, input, aad, tag, expected_output; + ASSERT_TRUE(DecodeHexString(test_vectors[j].key, &key)); + ASSERT_TRUE(DecodeHexString(test_vectors[j].iv, &iv)); + ASSERT_TRUE(DecodeHexString(test_vectors[j].input, &input)); + ASSERT_TRUE(DecodeHexString(test_vectors[j].aad, &aad)); + ASSERT_TRUE(DecodeHexString(test_vectors[j].tag, &tag)); + if (has_output) + ASSERT_TRUE(DecodeHexString(test_vectors[j].output, &expected_output)); + + // The test vector's lengths should look sane. Note that the lengths + // in |test_info| are in bits. + EXPECT_EQ(test_info.key_len, key.length() * 8); + EXPECT_EQ(test_info.iv_len, iv.length() * 8); + EXPECT_EQ(test_info.input_len, input.length() * 8); + EXPECT_EQ(test_info.aad_len, aad.length() * 8); + EXPECT_EQ(test_info.tag_len, tag.length() * 8); + if (has_output) + EXPECT_EQ(test_info.input_len, expected_output.length() * 8); + + const std::string ciphertext = input + tag; + std::string output; + + if (!DecryptOrEncrypt(DECRYPT, ciphertext, key, iv, aad, tag.length(), + &output)) { + EXPECT_FALSE(has_output); + continue; + } + + EXPECT_TRUE(has_output); + EXPECT_EQ(expected_output, output); + } + } +} + +TEST_F(Aes128GcmHelpersTest, EncryptionVectors) { + for (size_t i = 0; i < arraysize(encryption_test_group_array); i++) { + SCOPED_TRACE(i); + const TestVector* test_vectors = encryption_test_group_array[i]; + const TestGroupInfo& test_info = test_group_info[i]; + + for (size_t j = 0; test_vectors[j].key != nullptr; j++) { + // If not present then decryption is expected to fail. + bool has_output = test_vectors[j].output; + + // Decode the test vector. + std::string key, iv, input, aad, tag, expected_output; + ASSERT_TRUE(DecodeHexString(test_vectors[j].key, &key)); + ASSERT_TRUE(DecodeHexString(test_vectors[j].iv, &iv)); + ASSERT_TRUE(DecodeHexString(test_vectors[j].input, &input)); + ASSERT_TRUE(DecodeHexString(test_vectors[j].aad, &aad)); + ASSERT_TRUE(DecodeHexString(test_vectors[j].tag, &tag)); + if (has_output) + ASSERT_TRUE(DecodeHexString(test_vectors[j].output, &expected_output)); + + // The test vector's lengths should look sane. Note that the lengths + // in |test_info| are in bits. + EXPECT_EQ(test_info.key_len, key.length() * 8); + EXPECT_EQ(test_info.iv_len, iv.length() * 8); + EXPECT_EQ(test_info.input_len, input.length() * 8); + EXPECT_EQ(test_info.aad_len, aad.length() * 8); + EXPECT_EQ(test_info.tag_len, tag.length() * 8); + if (has_output) + EXPECT_EQ(test_info.input_len, expected_output.length() * 8); + + std::string output; + + if (!DecryptOrEncrypt(ENCRYPT, input, key, iv, aad, tag.length(), + &output)) { + EXPECT_FALSE(has_output); + continue; + } + + const std::string expected_output_with_tag = expected_output + tag; + + EXPECT_TRUE(has_output); + EXPECT_EQ(expected_output_with_tag, output); + } + } +} + +} // namespace crypto diff --git a/crypto/apple_keychain.h b/crypto/apple_keychain.h new file mode 100644 index 0000000000000..840ccee8c2032 --- /dev/null +++ b/crypto/apple_keychain.h @@ -0,0 +1,108 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CRYPTO_KEYCHAIN_MAC_H_ +#define CRYPTO_KEYCHAIN_MAC_H_ + +#include + +#include "base/basictypes.h" +#include "crypto/crypto_export.h" + +#if defined (OS_IOS) +typedef void* SecKeychainRef; +typedef void* SecKeychainItemRef; +typedef void SecKeychainAttributeList; +#endif + +namespace crypto { + +// Wraps the KeychainServices API in a very thin layer, to allow it to be +// mocked out for testing. + +// See Keychain Services documentation for function documentation, as these call +// through directly to their Keychain Services equivalents (Foo -> +// SecKeychainFoo). The only exception is Free, which should be used for +// anything returned from this class that would normally be freed with +// CFRelease (to aid in testing). +class CRYPTO_EXPORT AppleKeychain { + public: + AppleKeychain(); + virtual ~AppleKeychain(); + + virtual OSStatus FindGenericPassword(CFTypeRef keychainOrArray, + UInt32 serviceNameLength, + const char* serviceName, + UInt32 accountNameLength, + const char* accountName, + UInt32* passwordLength, + void** passwordData, + SecKeychainItemRef* itemRef) const; + + virtual OSStatus ItemFreeContent(SecKeychainAttributeList* attrList, + void* data) const; + + virtual OSStatus AddGenericPassword(SecKeychainRef keychain, + UInt32 serviceNameLength, + const char* serviceName, + UInt32 accountNameLength, + const char* accountName, + UInt32 passwordLength, + const void* passwordData, + SecKeychainItemRef* itemRef) const; + +#if !defined(OS_IOS) + virtual OSStatus ItemCopyAttributesAndData( + SecKeychainItemRef itemRef, + SecKeychainAttributeInfo* info, + SecItemClass* itemClass, + SecKeychainAttributeList** attrList, + UInt32* length, + void** outData) const; + + virtual OSStatus ItemModifyAttributesAndData( + SecKeychainItemRef itemRef, + const SecKeychainAttributeList* attrList, + UInt32 length, + const void* data) const; + + virtual OSStatus ItemFreeAttributesAndData(SecKeychainAttributeList* attrList, + void* data) const; + + virtual OSStatus ItemDelete(SecKeychainItemRef itemRef) const; + + virtual OSStatus SearchCreateFromAttributes( + CFTypeRef keychainOrArray, + SecItemClass itemClass, + const SecKeychainAttributeList* attrList, + SecKeychainSearchRef* searchRef) const; + + virtual OSStatus SearchCopyNext(SecKeychainSearchRef searchRef, + SecKeychainItemRef* itemRef) const; + + virtual OSStatus AddInternetPassword(SecKeychainRef keychain, + UInt32 serverNameLength, + const char* serverName, + UInt32 securityDomainLength, + const char* securityDomain, + UInt32 accountNameLength, + const char* accountName, + UInt32 pathLength, const char* path, + UInt16 port, SecProtocolType protocol, + SecAuthenticationType authenticationType, + UInt32 passwordLength, + const void* passwordData, + SecKeychainItemRef* itemRef) const; + + // Calls CFRelease on the given ref, after checking that |ref| is non-NULL. + virtual void Free(CFTypeRef ref) const; +#endif // !defined(OS_IOS) + + private: + DISALLOW_COPY_AND_ASSIGN(AppleKeychain); +}; + +} // namespace crypto + +#endif // CRYPTO_KEYCHAIN_MAC_H_ diff --git a/crypto/apple_keychain_ios.mm b/crypto/apple_keychain_ios.mm new file mode 100644 index 0000000000000..74cf129ce1fd0 --- /dev/null +++ b/crypto/apple_keychain_ios.mm @@ -0,0 +1,196 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/apple_keychain.h" + +#import + +#include "base/mac/foundation_util.h" +#include "base/mac/scoped_cftyperef.h" +#include "base/mac/scoped_nsobject.h" + +namespace { + +enum KeychainAction { + kKeychainActionCreate, + kKeychainActionUpdate +}; + +// Creates a dictionary that can be used to query the keystore. +// Ownership follows the Create rule. +CFDictionaryRef CreateGenericPasswordQuery(UInt32 serviceNameLength, + const char* serviceName, + UInt32 accountNameLength, + const char* accountName) { + CFMutableDictionaryRef query = + CFDictionaryCreateMutable(NULL, + 5, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + // Type of element is generic password. + CFDictionarySetValue(query, kSecClass, kSecClassGenericPassword); + + // Set the service name. + base::scoped_nsobject service_name_ns( + [[NSString alloc] initWithBytes:serviceName + length:serviceNameLength + encoding:NSUTF8StringEncoding]); + CFDictionarySetValue(query, kSecAttrService, + base::mac::NSToCFCast(service_name_ns)); + + // Set the account name. + base::scoped_nsobject account_name_ns( + [[NSString alloc] initWithBytes:accountName + length:accountNameLength + encoding:NSUTF8StringEncoding]); + CFDictionarySetValue(query, kSecAttrAccount, + base::mac::NSToCFCast(account_name_ns)); + + // Use the proper search constants, return only the data of the first match. + CFDictionarySetValue(query, kSecMatchLimit, kSecMatchLimitOne); + CFDictionarySetValue(query, kSecReturnData, kCFBooleanTrue); + return query; +} + +// Creates a dictionary conatining the data to save into the keychain. +// Ownership follows the Create rule. +CFDictionaryRef CreateKeychainData(UInt32 serviceNameLength, + const char* serviceName, + UInt32 accountNameLength, + const char* accountName, + UInt32 passwordLength, + const void* passwordData, + KeychainAction action) { + CFMutableDictionaryRef keychain_data = + CFDictionaryCreateMutable(NULL, + 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + // Set the password. + NSData* password = [NSData dataWithBytes:passwordData length:passwordLength]; + CFDictionarySetValue(keychain_data, kSecValueData, + base::mac::NSToCFCast(password)); + + // If this is not a creation, no structural information is needed. + if (action != kKeychainActionCreate) + return keychain_data; + + // Set the type of the data. + CFDictionarySetValue(keychain_data, kSecClass, kSecClassGenericPassword); + + // Only allow access when the device has been unlocked. + CFDictionarySetValue(keychain_data, + kSecAttrAccessible, + kSecAttrAccessibleWhenUnlocked); + + // Set the service name. + base::scoped_nsobject service_name_ns( + [[NSString alloc] initWithBytes:serviceName + length:serviceNameLength + encoding:NSUTF8StringEncoding]); + CFDictionarySetValue(keychain_data, kSecAttrService, + base::mac::NSToCFCast(service_name_ns)); + + // Set the account name. + base::scoped_nsobject account_name_ns( + [[NSString alloc] initWithBytes:accountName + length:accountNameLength + encoding:NSUTF8StringEncoding]); + CFDictionarySetValue(keychain_data, kSecAttrAccount, + base::mac::NSToCFCast(account_name_ns)); + + return keychain_data; +} + +} // namespace + +namespace crypto { + +AppleKeychain::AppleKeychain() {} + +AppleKeychain::~AppleKeychain() {} + +OSStatus AppleKeychain::ItemFreeContent(SecKeychainAttributeList* attrList, + void* data) const { + free(data); + return noErr; +} + +OSStatus AppleKeychain::AddGenericPassword(SecKeychainRef keychain, + UInt32 serviceNameLength, + const char* serviceName, + UInt32 accountNameLength, + const char* accountName, + UInt32 passwordLength, + const void* passwordData, + SecKeychainItemRef* itemRef) const { + base::ScopedCFTypeRef query(CreateGenericPasswordQuery( + serviceNameLength, serviceName, accountNameLength, accountName)); + // Check that there is not already a password. + OSStatus status = SecItemCopyMatching(query, NULL); + if (status == errSecItemNotFound) { + // A new entry must be created. + base::ScopedCFTypeRef keychain_data( + CreateKeychainData(serviceNameLength, + serviceName, + accountNameLength, + accountName, + passwordLength, + passwordData, + kKeychainActionCreate)); + status = SecItemAdd(keychain_data, NULL); + } else if (status == noErr) { + // The entry must be updated. + base::ScopedCFTypeRef keychain_data( + CreateKeychainData(serviceNameLength, + serviceName, + accountNameLength, + accountName, + passwordLength, + passwordData, + kKeychainActionUpdate)); + status = SecItemUpdate(query, keychain_data); + } + + return status; +} + +OSStatus AppleKeychain::FindGenericPassword(CFTypeRef keychainOrArray, + UInt32 serviceNameLength, + const char* serviceName, + UInt32 accountNameLength, + const char* accountName, + UInt32* passwordLength, + void** passwordData, + SecKeychainItemRef* itemRef) const { + DCHECK((passwordData && passwordLength) || + (!passwordData && !passwordLength)); + base::ScopedCFTypeRef query(CreateGenericPasswordQuery( + serviceNameLength, serviceName, accountNameLength, accountName)); + + // Get the keychain item containing the password. + CFTypeRef resultRef = NULL; + OSStatus status = SecItemCopyMatching(query, &resultRef); + base::ScopedCFTypeRef result(resultRef); + + if (status != noErr) { + if (passwordData) { + *passwordData = NULL; + *passwordLength = 0; + } + return status; + } + + if (passwordData) { + CFDataRef data = base::mac::CFCast(result); + NSUInteger length = CFDataGetLength(data); + *passwordData = malloc(length * sizeof(UInt8)); + CFDataGetBytes(data, CFRangeMake(0, length), (UInt8*)*passwordData); + *passwordLength = length; + } + return status; +} + +} // namespace crypto diff --git a/crypto/apple_keychain_mac.mm b/crypto/apple_keychain_mac.mm new file mode 100644 index 0000000000000..240c32067bcf1 --- /dev/null +++ b/crypto/apple_keychain_mac.mm @@ -0,0 +1,144 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/apple_keychain.h" + +#import + +#include "base/synchronization/lock.h" +#include "crypto/mac_security_services_lock.h" + +namespace crypto { + +AppleKeychain::AppleKeychain() {} + +AppleKeychain::~AppleKeychain() {} + +OSStatus AppleKeychain::ItemCopyAttributesAndData( + SecKeychainItemRef itemRef, + SecKeychainAttributeInfo* info, + SecItemClass* itemClass, + SecKeychainAttributeList** attrList, + UInt32* length, + void** outData) const { + base::AutoLock lock(GetMacSecurityServicesLock()); + return SecKeychainItemCopyAttributesAndData(itemRef, info, itemClass, + attrList, length, outData); +} + +OSStatus AppleKeychain::ItemModifyAttributesAndData( + SecKeychainItemRef itemRef, + const SecKeychainAttributeList* attrList, + UInt32 length, + const void* data) const { + base::AutoLock lock(GetMacSecurityServicesLock()); + return SecKeychainItemModifyAttributesAndData(itemRef, attrList, length, + data); +} + +OSStatus AppleKeychain::ItemFreeAttributesAndData( + SecKeychainAttributeList* attrList, + void* data) const { + base::AutoLock lock(GetMacSecurityServicesLock()); + return SecKeychainItemFreeAttributesAndData(attrList, data); +} + +OSStatus AppleKeychain::ItemDelete(SecKeychainItemRef itemRef) const { + base::AutoLock lock(GetMacSecurityServicesLock()); + return SecKeychainItemDelete(itemRef); +} + +OSStatus AppleKeychain::SearchCreateFromAttributes( + CFTypeRef keychainOrArray, + SecItemClass itemClass, + const SecKeychainAttributeList* attrList, + SecKeychainSearchRef* searchRef) const { + base::AutoLock lock(GetMacSecurityServicesLock()); + return SecKeychainSearchCreateFromAttributes(keychainOrArray, itemClass, + attrList, searchRef); +} + +OSStatus AppleKeychain::SearchCopyNext(SecKeychainSearchRef searchRef, + SecKeychainItemRef* itemRef) const { + base::AutoLock lock(GetMacSecurityServicesLock()); + return SecKeychainSearchCopyNext(searchRef, itemRef); +} + +OSStatus AppleKeychain::AddInternetPassword( + SecKeychainRef keychain, + UInt32 serverNameLength, + const char* serverName, + UInt32 securityDomainLength, + const char* securityDomain, + UInt32 accountNameLength, + const char* accountName, + UInt32 pathLength, + const char* path, + UInt16 port, + SecProtocolType protocol, + SecAuthenticationType authenticationType, + UInt32 passwordLength, + const void* passwordData, + SecKeychainItemRef* itemRef) const { + base::AutoLock lock(GetMacSecurityServicesLock()); + return SecKeychainAddInternetPassword(keychain, + serverNameLength, serverName, + securityDomainLength, securityDomain, + accountNameLength, accountName, + pathLength, path, + port, protocol, authenticationType, + passwordLength, passwordData, + itemRef); +} + +OSStatus AppleKeychain::FindGenericPassword(CFTypeRef keychainOrArray, + UInt32 serviceNameLength, + const char* serviceName, + UInt32 accountNameLength, + const char* accountName, + UInt32* passwordLength, + void** passwordData, + SecKeychainItemRef* itemRef) const { + base::AutoLock lock(GetMacSecurityServicesLock()); + return SecKeychainFindGenericPassword(keychainOrArray, + serviceNameLength, + serviceName, + accountNameLength, + accountName, + passwordLength, + passwordData, + itemRef); +} + +OSStatus AppleKeychain::ItemFreeContent(SecKeychainAttributeList* attrList, + void* data) const { + base::AutoLock lock(GetMacSecurityServicesLock()); + return SecKeychainItemFreeContent(attrList, data); +} + +OSStatus AppleKeychain::AddGenericPassword(SecKeychainRef keychain, + UInt32 serviceNameLength, + const char* serviceName, + UInt32 accountNameLength, + const char* accountName, + UInt32 passwordLength, + const void* passwordData, + SecKeychainItemRef* itemRef) const { + base::AutoLock lock(GetMacSecurityServicesLock()); + return SecKeychainAddGenericPassword(keychain, + serviceNameLength, + serviceName, + accountNameLength, + accountName, + passwordLength, + passwordData, + itemRef); +} + +void AppleKeychain::Free(CFTypeRef ref) const { + if (ref) + CFRelease(ref); +} + +} // namespace crypto diff --git a/crypto/capi_util.cc b/crypto/capi_util.cc new file mode 100644 index 0000000000000..2cf10625ec34f --- /dev/null +++ b/crypto/capi_util.cc @@ -0,0 +1,57 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/capi_util.h" + +#include "base/basictypes.h" +#include "base/memory/singleton.h" +#include "base/synchronization/lock.h" + +namespace { + +class CAPIUtilSingleton { + public: + static CAPIUtilSingleton* GetInstance() { + return Singleton::get(); + } + + // Returns a lock to guard calls to CryptAcquireContext with + // CRYPT_DELETEKEYSET or CRYPT_NEWKEYSET. + base::Lock& acquire_context_lock() { + return acquire_context_lock_; + } + + private: + friend class Singleton; + friend struct DefaultSingletonTraits; + + CAPIUtilSingleton() {} + + base::Lock acquire_context_lock_; + + DISALLOW_COPY_AND_ASSIGN(CAPIUtilSingleton); +}; + +} // namespace + +namespace crypto { + +BOOL CryptAcquireContextLocked(HCRYPTPROV* prov, + LPCWSTR container, + LPCWSTR provider, + DWORD prov_type, + DWORD flags) { + base::AutoLock lock(CAPIUtilSingleton::GetInstance()->acquire_context_lock()); + return CryptAcquireContext(prov, container, provider, prov_type, flags); +} + +void* WINAPI CryptAlloc(size_t size) { + return malloc(size); +} + +void WINAPI CryptFree(void* p) { + free(p); +} + +} // namespace crypto diff --git a/crypto/capi_util.h b/crypto/capi_util.h new file mode 100644 index 0000000000000..9d43293e23121 --- /dev/null +++ b/crypto/capi_util.h @@ -0,0 +1,39 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CRYPTO_CAPI_UTIL_H_ +#define CRYPTO_CAPI_UTIL_H_ + +#include + +#include "crypto/crypto_export.h" +#include "crypto/wincrypt_shim.h" + +namespace crypto { + +// CryptAcquireContext when passed CRYPT_NEWKEYSET or CRYPT_DELETEKEYSET in +// flags is not thread-safe. For such calls, we create a global lock to +// synchronize it. +// +// From "Threading Issues with Cryptographic Service Providers", +// : +// +// "The CryptAcquireContext function is generally thread safe unless +// CRYPT_NEWKEYSET or CRYPT_DELETEKEYSET is specified in the dwFlags +// parameter." +CRYPTO_EXPORT BOOL CryptAcquireContextLocked(HCRYPTPROV* prov, + LPCWSTR container, + LPCWSTR provider, + DWORD prov_type, + DWORD flags); + +// Wrappers of malloc and free for CryptoAPI routines that need memory +// allocators, such as in CRYPT_DECODE_PARA. Such routines require WINAPI +// calling conventions. +CRYPTO_EXPORT void* WINAPI CryptAlloc(size_t size); +CRYPTO_EXPORT void WINAPI CryptFree(void* p); + +} // namespace crypto + +#endif // CRYPTO_CAPI_UTIL_H_ diff --git a/crypto/crypto.gyp b/crypto/crypto.gyp new file mode 100644 index 0000000000000..6327ce76dd24b --- /dev/null +++ b/crypto/crypto.gyp @@ -0,0 +1,335 @@ +# Copyright (c) 2012 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'variables': { + 'chromium_code': 1, + }, + 'includes': [ + 'crypto.gypi', + ], + 'targets': [ + { + 'target_name': 'crypto', + 'type': '<(component)', + 'product_name': 'crcrypto', # Avoid colliding with OpenSSL's libcrypto + 'dependencies': [ + '../base/base.gyp:base', + '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations', + ], + 'defines': [ + 'CRYPTO_IMPLEMENTATION', + ], + 'conditions': [ + [ 'os_posix == 1 and OS != "mac" and OS != "ios" and OS != "android"', { + 'dependencies': [ + '../build/linux/system.gyp:ssl', + ], + 'export_dependent_settings': [ + '../build/linux/system.gyp:ssl', + ], + 'conditions': [ + [ 'chromeos==1', { + 'sources/': [ ['include', '_chromeos\\.cc$'] ] + }, + ], + ], + }, { # os_posix != 1 or OS == "mac" or OS == "ios" or OS == "android" + 'sources!': [ + 'hmac_win.cc', + 'symmetric_key_win.cc', + ], + }], + [ 'OS != "mac" and OS != "ios"', { + 'sources!': [ + 'apple_keychain.h', + 'mock_apple_keychain.cc', + 'mock_apple_keychain.h', + ], + }], + [ 'OS == "android"', { + 'dependencies': [ + '../build/android/ndk.gyp:cpu_features', + ], + }], + [ 'os_bsd==1', { + 'link_settings': { + 'libraries': [ + '-L/usr/local/lib -lexecinfo', + ], + }, + }, + ], + [ 'OS == "mac"', { + 'link_settings': { + 'libraries': [ + '$(SDKROOT)/System/Library/Frameworks/Security.framework', + ], + }, + }, { # OS != "mac" + 'sources!': [ + 'cssm_init.cc', + 'cssm_init.h', + 'mac_security_services_lock.cc', + 'mac_security_services_lock.h', + ], + }], + [ 'use_openssl == 0 and (OS == "mac" or OS == "ios" or OS == "win")', { + 'dependencies': [ + '../third_party/nss/nss.gyp:nspr', + '../third_party/nss/nss.gyp:nss', + ], + 'export_dependent_settings': [ + '../third_party/nss/nss.gyp:nspr', + '../third_party/nss/nss.gyp:nss', + ], + }], + [ 'OS != "win"', { + 'sources!': [ + 'capi_util.h', + 'capi_util.cc', + ], + }], + [ 'OS == "win"', { + 'msvs_disabled_warnings': [ + 4267, # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. + 4018, + ], + }], + [ 'use_openssl==1', { + 'dependencies': [ + '../third_party/boringssl/boringssl.gyp:boringssl', + ], + # TODO(joth): Use a glob to match exclude patterns once the + # OpenSSL file set is complete. + 'sources!': [ + 'aes_128_gcm_helpers_nss.cc', + 'aes_128_gcm_helpers_nss.h', + 'ec_private_key_nss.cc', + 'ec_signature_creator_nss.cc', + 'encryptor_nss.cc', + 'hmac_nss.cc', + 'rsa_private_key_nss.cc', + 'secure_hash_default.cc', + 'signature_creator_nss.cc', + 'signature_verifier_nss.cc', + 'symmetric_key_nss.cc', + 'third_party/nss/chromium-blapi.h', + 'third_party/nss/chromium-blapit.h', + 'third_party/nss/chromium-nss.h', + 'third_party/nss/chromium-prtypes.h', + 'third_party/nss/chromium-sha256.h', + 'third_party/nss/pk11akey.cc', + 'third_party/nss/rsawrapr.c', + 'third_party/nss/secsign.cc', + 'third_party/nss/sha512.cc', + ], + }, { + 'sources!': [ + 'aead_openssl.cc', + 'aead_openssl.h', + 'ec_private_key_openssl.cc', + 'ec_signature_creator_openssl.cc', + 'encryptor_openssl.cc', + 'hmac_openssl.cc', + 'openssl_bio_string.cc', + 'openssl_bio_string.h', + 'openssl_util.cc', + 'openssl_util.h', + 'rsa_private_key_openssl.cc', + 'secure_hash_openssl.cc', + 'signature_creator_openssl.cc', + 'signature_verifier_openssl.cc', + 'symmetric_key_openssl.cc', + ], + },], + [ 'use_openssl==1 and use_nss_certs==0', { + # Some files are built when NSS is used at all, either for the + # internal crypto library or the platform certificate library. + 'sources!': [ + 'nss_key_util.cc', + 'nss_key_util.h', + 'nss_util.cc', + 'nss_util.h', + 'nss_util_internal.h', + ], + },], + ], + 'sources': [ + '<@(crypto_sources)', + ], + }, + { + 'target_name': 'crypto_unittests', + 'type': 'executable', + 'sources': [ + 'aead_openssl_unittest.cc', + 'aes_128_gcm_helpers_nss_unittest.cc', + 'curve25519_unittest.cc', + 'ec_private_key_unittest.cc', + 'ec_signature_creator_unittest.cc', + 'encryptor_unittest.cc', + 'ghash_unittest.cc', + 'hkdf_unittest.cc', + 'hmac_unittest.cc', + 'nss_key_util_unittest.cc', + 'nss_util_unittest.cc', + 'openssl_bio_string_unittest.cc', + 'p224_unittest.cc', + 'p224_spake_unittest.cc', + 'random_unittest.cc', + 'rsa_private_key_unittest.cc', + 'secure_hash_unittest.cc', + 'sha2_unittest.cc', + 'signature_creator_unittest.cc', + 'signature_verifier_unittest.cc', + 'symmetric_key_unittest.cc', + ], + 'dependencies': [ + 'crypto', + 'crypto_test_support', + '../base/base.gyp:base', + '../base/base.gyp:run_all_unittests', + '../base/base.gyp:test_support_base', + '../testing/gmock.gyp:gmock', + '../testing/gtest.gyp:gtest', + ], + 'conditions': [ + [ 'use_nss_certs == 1', { + 'conditions': [ + [ 'use_allocator!="none"', { + 'dependencies': [ + '../base/allocator/allocator.gyp:allocator', + ], + }, + ], + ], + 'dependencies': [ + '../build/linux/system.gyp:ssl', + ], + }], + [ 'use_openssl == 1 and use_nss_certs == 0', { + # Some files are built when NSS is used at all, either for the + # internal crypto library or the platform certificate library. + 'sources!': [ + 'nss_key_util_unittest.cc', + 'nss_util_unittest.cc', + ], + }], + [ 'use_openssl == 0 and (OS == "mac" or OS == "ios" or OS == "win")', { + 'dependencies': [ + '../third_party/nss/nss.gyp:nspr', + ], + }], + [ 'OS == "win"', { + # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. + 'msvs_disabled_warnings': [4267, ], + }], + [ 'use_openssl==1', { + 'dependencies': [ + '../third_party/boringssl/boringssl.gyp:boringssl', + ], + 'sources!': [ + 'aes_128_gcm_helpers_nss_unittest.cc', + ], + }, { + 'sources!': [ + 'openssl_bio_string_unittest.cc', + ], + }], + ], + }, + ], + 'conditions': [ + ['OS == "win" and target_arch=="ia32"', { + 'targets': [ + { + 'target_name': 'crypto_nacl_win64', + # We do not want nacl_helper to depend on NSS because this would + # require including a 64-bit copy of NSS. Thus, use the native APIs + # for the helper. + 'type': '<(component)', + 'dependencies': [ + '../base/base.gyp:base_win64', + '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations_win64', + ], + 'sources': [ + '<@(nacl_win64_sources)', + ], + 'defines': [ + 'CRYPTO_IMPLEMENTATION', + '<@(nacl_win64_defines)', + ], + 'msvs_disabled_warnings': [ + 4018, + ], + 'configurations': { + 'Common_Base': { + 'msvs_target_platform': 'x64', + }, + }, + }, + ], + }], + ['use_nss_certs==1', { + 'targets': [ + { + 'target_name': 'crypto_test_support', + 'type': 'static_library', + 'dependencies': [ + '../base/base.gyp:base', + 'crypto', + ], + 'sources': [ + 'scoped_test_nss_db.cc', + 'scoped_test_nss_db.h', + 'scoped_test_nss_chromeos_user.cc', + 'scoped_test_nss_chromeos_user.h', + 'scoped_test_system_nss_key_slot.cc', + 'scoped_test_system_nss_key_slot.h', + ], + 'conditions': [ + ['use_nss_certs==0', { + 'sources!': [ + 'scoped_test_nss_db.cc', + 'scoped_test_nss_db.h', + ], + }], + [ 'chromeos==0', { + 'sources!': [ + 'scoped_test_nss_chromeos_user.cc', + 'scoped_test_nss_chromeos_user.h', + 'scoped_test_system_nss_key_slot.cc', + 'scoped_test_system_nss_key_slot.h', + ], + }], + ], + } + ]}, { # use_nss_certs==0 + 'targets': [ + { + 'target_name': 'crypto_test_support', + 'type': 'none', + 'sources': [], + } + ]}], + ['test_isolation_mode != "noop"', { + 'targets': [ + { + 'target_name': 'crypto_unittests_run', + 'type': 'none', + 'dependencies': [ + 'crypto_unittests', + ], + 'includes': [ + '../build/isolate.gypi', + ], + 'sources': [ + 'crypto_unittests.isolate', + ], + }, + ], + }], + ], +} diff --git a/crypto/crypto.gypi b/crypto/crypto.gypi new file mode 100644 index 0000000000000..71ffbecad1116 --- /dev/null +++ b/crypto/crypto.gypi @@ -0,0 +1,115 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'variables': { + # Put all transitive dependencies for Windows HMAC here. + # This is required so that we can build them for nacl win64. + 'variables': { + 'hmac_win64_related_sources': [ + 'hmac.cc', + 'hmac.h', + 'hmac_win.cc', + 'secure_util.cc', + 'secure_util.h', + 'symmetric_key.h', + 'symmetric_key_win.cc', + 'third_party/nss/chromium-blapi.h', + 'third_party/nss/chromium-blapit.h', + 'third_party/nss/chromium-prtypes.h', + 'third_party/nss/chromium-sha256.h', + 'third_party/nss/sha512.cc', + 'wincrypt_shim.h', + ], + }, + 'crypto_sources': [ + # NOTE: all transitive dependencies of HMAC on windows need + # to be placed in the source list above. + '<@(hmac_win64_related_sources)', + 'aead_openssl.cc', + 'aead_openssl.h', + 'aes_128_gcm_helpers_nss.cc', + 'aes_128_gcm_helpers_nss.h', + 'apple_keychain.h', + 'apple_keychain_ios.mm', + 'apple_keychain_mac.mm', + 'capi_util.cc', + 'capi_util.h', + 'crypto_export.h', + 'cssm_init.cc', + 'cssm_init.h', + 'curve25519.cc', + 'curve25519.h', + 'curve25519-donna.c', + 'ghash.cc', + 'ghash.h', + 'ec_private_key.h', + 'ec_private_key_nss.cc', + 'ec_private_key_openssl.cc', + 'ec_signature_creator.cc', + 'ec_signature_creator.h', + 'ec_signature_creator_impl.h', + 'ec_signature_creator_nss.cc', + 'ec_signature_creator_openssl.cc', + 'encryptor.cc', + 'encryptor.h', + 'encryptor_nss.cc', + 'encryptor_openssl.cc', + 'hkdf.cc', + 'hkdf.h', + 'hmac_nss.cc', + 'hmac_openssl.cc', + 'mac_security_services_lock.cc', + 'mac_security_services_lock.h', + 'mock_apple_keychain.cc', + 'mock_apple_keychain.h', + 'mock_apple_keychain_ios.cc', + 'mock_apple_keychain_mac.cc', + 'p224_spake.cc', + 'p224_spake.h', + 'nss_crypto_module_delegate.h', + 'nss_key_util.cc', + 'nss_key_util.h', + 'nss_util.cc', + 'nss_util.h', + 'nss_util_internal.h', + 'openssl_bio_string.cc', + 'openssl_bio_string.h', + 'openssl_util.cc', + 'openssl_util.h', + 'p224.cc', + 'p224.h', + 'random.h', + 'random.cc', + 'rsa_private_key.cc', + 'rsa_private_key.h', + 'rsa_private_key_nss.cc', + 'rsa_private_key_openssl.cc', + 'scoped_capi_types.h', + 'scoped_nss_types.h', + 'secure_hash.h', + 'secure_hash_default.cc', + 'secure_hash_openssl.cc', + 'sha2.cc', + 'sha2.h', + 'signature_creator.h', + 'signature_creator_nss.cc', + 'signature_creator_openssl.cc', + 'signature_verifier.h', + 'signature_verifier_nss.cc', + 'signature_verifier_openssl.cc', + 'symmetric_key_nss.cc', + 'symmetric_key_openssl.cc', + 'third_party/nss/chromium-nss.h', + 'third_party/nss/pk11akey.cc', + 'third_party/nss/rsawrapr.c', + 'third_party/nss/secsign.cc', + ], + 'nacl_win64_sources': [ + '<@(hmac_win64_related_sources)', + 'random.cc', + 'random.h', + ], + } +} diff --git a/crypto/crypto_nacl.gyp b/crypto/crypto_nacl.gyp new file mode 100644 index 0000000000000..255c42c51d317 --- /dev/null +++ b/crypto/crypto_nacl.gyp @@ -0,0 +1,46 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'variables': { + 'chromium_code': 1, + }, + 'includes': [ + '../native_client/build/untrusted.gypi', + 'crypto.gypi', + ], + 'targets': [ + { + 'target_name': 'crypto_nacl', + 'type': 'none', + 'variables': { + 'nacl_untrusted_build': 1, + 'nlib_target': 'libcrypto_nacl.a', + 'build_glibc': 0, + 'build_newlib': 0, + 'build_pnacl_newlib': 1, + }, + 'dependencies': [ + '../third_party/boringssl/boringssl_nacl.gyp:boringssl_nacl', + '../native_client_sdk/native_client_sdk_untrusted.gyp:nacl_io_untrusted', + ], + 'defines': [ + 'CRYPTO_IMPLEMENTATION', + ], + 'sources': [ + '<@(crypto_sources)', + ], + 'sources/': [ + ['exclude', '_nss\.(cc|h)$'], + ['exclude', '^(mock_)?apple_'], + ['exclude', '^capi_'], + ['exclude', '^cssm_'], + ['exclude', '^nss_'], + ['exclude', '^mac_'], + ['exclude', '^third_party/nss/'], + ['include', '^third_party/nss/sha512.cc'], + ], + }, + ], +} diff --git a/crypto/crypto_unittests.isolate b/crypto/crypto_unittests.isolate index 381a1c8b748c8..e09095c142bff 100644 --- a/crypto/crypto_unittests.isolate +++ b/crypto/crypto_unittests.isolate @@ -2,32 +2,18 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. { + 'variables': { + 'command': [ + '../testing/test_env.py', + '<(PRODUCT_DIR)/crypto_unittests<(EXECUTABLE_SUFFIX)', + '--brave-new-test-launcher', + '--test-launcher-bot-mode', + '--asan=<(asan)', + '--msan=<(msan)', + '--tsan=<(tsan)', + ], + }, 'conditions': [ - ['OS=="linux"', { - 'variables': { - 'command': [ - '../testing/xvfb.py', - '<(PRODUCT_DIR)', - '<(PRODUCT_DIR)/crypto_unittests<(EXECUTABLE_SUFFIX)', - '--brave-new-test-launcher', - '--test-launcher-bot-mode', - '--asan=<(asan)', - '--lsan=<(lsan)', - '--msan=<(msan)', - '--tsan=<(tsan)', - ], - 'files': [ - '../testing/xvfb.py', - ], - }, - }], - ['OS=="linux" and use_ozone==0', { - 'variables': { - 'files': [ - '<(PRODUCT_DIR)/xdisplaycheck<(EXECUTABLE_SUFFIX)', - ], - }, - }], ['OS=="linux" or OS=="mac" or OS=="win"', { 'variables': { 'files': [ @@ -37,20 +23,6 @@ 'read_only': 1, }, }], - ['OS=="mac" or OS=="win"', { - 'variables': { - 'command': [ - '../testing/test_env.py', - '<(PRODUCT_DIR)/crypto_unittests<(EXECUTABLE_SUFFIX)', - '--brave-new-test-launcher', - '--test-launcher-bot-mode', - '--asan=<(asan)', - '--lsan=<(lsan)', - '--msan=<(msan)', - '--tsan=<(tsan)', - ], - }, - }], ['OS=="mac" and asan==1 and fastbuild==0', { 'variables': { 'files': [ diff --git a/crypto/cssm_init.cc b/crypto/cssm_init.cc new file mode 100644 index 0000000000000..208309c351e3a --- /dev/null +++ b/crypto/cssm_init.cc @@ -0,0 +1,204 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/cssm_init.h" + +#include + +#include "base/logging.h" +#include "base/mac/scoped_cftyperef.h" +#include "base/memory/singleton.h" +#include "base/strings/sys_string_conversions.h" + +// When writing crypto code for Mac OS X, you may find the following +// documentation useful: +// - Common Security: CDSA and CSSM, Version 2 (with corrigenda) +// http://www.opengroup.org/security/cdsa.htm +// - Apple Cryptographic Service Provider Functional Specification +// - CryptoSample: http://developer.apple.com/SampleCode/CryptoSample/ + +namespace { + +void* CSSMMalloc(CSSM_SIZE size, void* alloc_ref) { + return malloc(size); +} + +void CSSMFree(void* mem_ptr, void* alloc_ref) { + free(mem_ptr); +} + +void* CSSMRealloc(void* ptr, CSSM_SIZE size, void* alloc_ref) { + return realloc(ptr, size); +} + +void* CSSMCalloc(uint32 num, CSSM_SIZE size, void* alloc_ref) { + return calloc(num, size); +} + +class CSSMInitSingleton { + public: + static CSSMInitSingleton* GetInstance() { + return Singleton >::get(); + } + + CSSM_CSP_HANDLE csp_handle() const { return csp_handle_; } + CSSM_CL_HANDLE cl_handle() const { return cl_handle_; } + CSSM_TP_HANDLE tp_handle() const { return tp_handle_; } + + private: + CSSMInitSingleton() + : inited_(false), csp_loaded_(false), cl_loaded_(false), + tp_loaded_(false), csp_handle_(CSSM_INVALID_HANDLE), + cl_handle_(CSSM_INVALID_HANDLE), tp_handle_(CSSM_INVALID_HANDLE) { + static CSSM_VERSION version = {2, 0}; + // TODO(wtc): what should our caller GUID be? + static const CSSM_GUID test_guid = { + 0xFADE, 0, 0, { 1, 2, 3, 4, 5, 6, 7, 0 } + }; + CSSM_RETURN crtn; + CSSM_PVC_MODE pvc_policy = CSSM_PVC_NONE; + crtn = CSSM_Init(&version, CSSM_PRIVILEGE_SCOPE_NONE, &test_guid, + CSSM_KEY_HIERARCHY_NONE, &pvc_policy, NULL); + if (crtn) { + NOTREACHED(); + return; + } + inited_ = true; + + crtn = CSSM_ModuleLoad(&gGuidAppleCSP, CSSM_KEY_HIERARCHY_NONE, NULL, NULL); + if (crtn) { + NOTREACHED(); + return; + } + csp_loaded_ = true; + crtn = CSSM_ModuleLoad( + &gGuidAppleX509CL, CSSM_KEY_HIERARCHY_NONE, NULL, NULL); + if (crtn) { + NOTREACHED(); + return; + } + cl_loaded_ = true; + crtn = CSSM_ModuleLoad( + &gGuidAppleX509TP, CSSM_KEY_HIERARCHY_NONE, NULL, NULL); + if (crtn) { + NOTREACHED(); + return; + } + tp_loaded_ = true; + + const CSSM_API_MEMORY_FUNCS cssmMemoryFunctions = { + CSSMMalloc, + CSSMFree, + CSSMRealloc, + CSSMCalloc, + NULL + }; + + crtn = CSSM_ModuleAttach(&gGuidAppleCSP, &version, &cssmMemoryFunctions, 0, + CSSM_SERVICE_CSP, 0, CSSM_KEY_HIERARCHY_NONE, + NULL, 0, NULL, &csp_handle_); + DCHECK_EQ(CSSM_OK, crtn); + crtn = CSSM_ModuleAttach(&gGuidAppleX509CL, &version, &cssmMemoryFunctions, + 0, CSSM_SERVICE_CL, 0, CSSM_KEY_HIERARCHY_NONE, + NULL, 0, NULL, &cl_handle_); + DCHECK_EQ(CSSM_OK, crtn); + crtn = CSSM_ModuleAttach(&gGuidAppleX509TP, &version, &cssmMemoryFunctions, + 0, CSSM_SERVICE_TP, 0, CSSM_KEY_HIERARCHY_NONE, + NULL, 0, NULL, &tp_handle_); + DCHECK_EQ(CSSM_OK, crtn); + } + + ~CSSMInitSingleton() { + CSSM_RETURN crtn; + if (csp_handle_) { + CSSM_RETURN crtn = CSSM_ModuleDetach(csp_handle_); + DCHECK_EQ(CSSM_OK, crtn); + } + if (cl_handle_) { + CSSM_RETURN crtn = CSSM_ModuleDetach(cl_handle_); + DCHECK_EQ(CSSM_OK, crtn); + } + if (tp_handle_) { + CSSM_RETURN crtn = CSSM_ModuleDetach(tp_handle_); + DCHECK_EQ(CSSM_OK, crtn); + } + if (csp_loaded_) { + crtn = CSSM_ModuleUnload(&gGuidAppleCSP, NULL, NULL); + DCHECK_EQ(CSSM_OK, crtn); + } + if (cl_loaded_) { + crtn = CSSM_ModuleUnload(&gGuidAppleX509CL, NULL, NULL); + DCHECK_EQ(CSSM_OK, crtn); + } + if (tp_loaded_) { + crtn = CSSM_ModuleUnload(&gGuidAppleX509TP, NULL, NULL); + DCHECK_EQ(CSSM_OK, crtn); + } + if (inited_) { + crtn = CSSM_Terminate(); + DCHECK_EQ(CSSM_OK, crtn); + } + } + + bool inited_; // True if CSSM_Init has been called successfully. + bool csp_loaded_; // True if gGuidAppleCSP has been loaded + bool cl_loaded_; // True if gGuidAppleX509CL has been loaded. + bool tp_loaded_; // True if gGuidAppleX509TP has been loaded. + CSSM_CSP_HANDLE csp_handle_; + CSSM_CL_HANDLE cl_handle_; + CSSM_TP_HANDLE tp_handle_; + + friend struct DefaultSingletonTraits; +}; + +} // namespace + +namespace crypto { + +void EnsureCSSMInit() { + CSSMInitSingleton::GetInstance(); +} + +CSSM_CSP_HANDLE GetSharedCSPHandle() { + return CSSMInitSingleton::GetInstance()->csp_handle(); +} + +CSSM_CL_HANDLE GetSharedCLHandle() { + return CSSMInitSingleton::GetInstance()->cl_handle(); +} + +CSSM_TP_HANDLE GetSharedTPHandle() { + return CSSMInitSingleton::GetInstance()->tp_handle(); +} + +void* CSSMMalloc(CSSM_SIZE size) { + return ::CSSMMalloc(size, NULL); +} + +void CSSMFree(void* ptr) { + ::CSSMFree(ptr, NULL); +} + +void LogCSSMError(const char* fn_name, CSSM_RETURN err) { + if (!err) + return; + base::ScopedCFTypeRef cfstr( + SecCopyErrorMessageString(err, NULL)); + LOG(ERROR) << fn_name << " returned " << err + << " (" << base::SysCFStringRefToUTF8(cfstr) << ")"; +} + +ScopedCSSMData::ScopedCSSMData() { + memset(&data_, 0, sizeof(data_)); +} + +ScopedCSSMData::~ScopedCSSMData() { + if (data_.Data) { + CSSMFree(data_.Data); + data_.Data = NULL; + } +} + +} // namespace crypto diff --git a/crypto/cssm_init.h b/crypto/cssm_init.h new file mode 100644 index 0000000000000..e711099ef08e6 --- /dev/null +++ b/crypto/cssm_init.h @@ -0,0 +1,60 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CRYPTO_CSSM_INIT_H_ +#define CRYPTO_CSSM_INIT_H_ + +#include + +#include "base/basictypes.h" +#include "crypto/crypto_export.h" + +namespace crypto { + +// Initialize CSSM if it isn't already initialized. This must be called before +// any other CSSM functions. This function is thread-safe, and CSSM will only +// ever be initialized once. CSSM will be properly shut down on program exit. +CRYPTO_EXPORT void EnsureCSSMInit(); + +// Returns the shared CSP handle used by CSSM functions. +CRYPTO_EXPORT CSSM_CSP_HANDLE GetSharedCSPHandle(); + +// Returns the shared CL handle used by CSSM functions. +CRYPTO_EXPORT CSSM_CL_HANDLE GetSharedCLHandle(); + +// Returns the shared TP handle used by CSSM functions. +CRYPTO_EXPORT CSSM_TP_HANDLE GetSharedTPHandle(); + +// Set of pointers to memory function wrappers that are required for CSSM +extern const CSSM_API_MEMORY_FUNCS kCssmMemoryFunctions; + +// Utility function to log an error message including the error name. +CRYPTO_EXPORT void LogCSSMError(const char *function_name, CSSM_RETURN err); + +// Utility functions to allocate and release CSSM memory. +void* CSSMMalloc(CSSM_SIZE size); +CRYPTO_EXPORT void CSSMFree(void* ptr); + +// Wrapper class for CSSM_DATA type. This should only be used when using the +// CL/TP/CSP handles from above, since that's the only time we're guaranteed (or +// supposed to be guaranteed) that our memory management functions will be used. +// Apple's Sec* APIs manage their own memory so it shouldn't be used for those. +// The constructor initializes data_ to zero and the destructor releases the +// data properly. +class ScopedCSSMData { + public: + ScopedCSSMData(); + ~ScopedCSSMData(); + operator CSSM_DATA*() { return &data_; } + CSSM_DATA* operator ->() { return &data_; } + + private: + CSSM_DATA data_; + + DISALLOW_COPY_AND_ASSIGN(ScopedCSSMData); +}; + +} // namespace crypto + +#endif // CRYPTO_CSSM_INIT_H_ diff --git a/crypto/curve25519-donna.c b/crypto/curve25519-donna.c new file mode 100644 index 0000000000000..f141ac028b0f7 --- /dev/null +++ b/crypto/curve25519-donna.c @@ -0,0 +1,592 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/* + * curve25519-donna: Curve25519 elliptic curve, public key function + * + * http://code.google.com/p/curve25519-donna/ + * + * Adam Langley + * + * Derived from public domain C code by Daniel J. Bernstein + * + * More information about curve25519 can be found here + * http://cr.yp.to/ecdh.html + * + * djb's sample implementation of curve25519 is written in a special assembly + * language called qhasm and uses the floating point registers. + * + * This is, almost, a clean room reimplementation from the curve25519 paper. It + * uses many of the tricks described therein. Only the crecip function is taken + * from the sample implementation. + */ + +#include +#include + +typedef uint8_t u8; +typedef int32_t s32; +typedef int64_t limb; + +/* Field element representation: + * + * Field elements are written as an array of signed, 64-bit limbs, least + * significant first. The value of the field element is: + * x[0] + 2^26·x[1] + x^51·x[2] + 2^102·x[3] + ... + * + * i.e. the limbs are 26, 25, 26, 25, ... bits wide. + */ + +/* Sum two numbers: output += in */ +static void fsum(limb *output, const limb *in) { + unsigned i; + for (i = 0; i < 10; i += 2) { + output[0+i] = (output[0+i] + in[0+i]); + output[1+i] = (output[1+i] + in[1+i]); + } +} + +/* Find the difference of two numbers: output = in - output + * (note the order of the arguments!) + */ +static void fdifference(limb *output, const limb *in) { + unsigned i; + for (i = 0; i < 10; ++i) { + output[i] = (in[i] - output[i]); + } +} + +/* Multiply a number my a scalar: output = in * scalar */ +static void fscalar_product(limb *output, const limb *in, const limb scalar) { + unsigned i; + for (i = 0; i < 10; ++i) { + output[i] = in[i] * scalar; + } +} + +/* Multiply two numbers: output = in2 * in + * + * output must be distinct to both inputs. The inputs are reduced coefficient + * form, the output is not. + */ +static void fproduct(limb *output, const limb *in2, const limb *in) { + output[0] = ((limb) ((s32) in2[0])) * ((s32) in[0]); + output[1] = ((limb) ((s32) in2[0])) * ((s32) in[1]) + + ((limb) ((s32) in2[1])) * ((s32) in[0]); + output[2] = 2 * ((limb) ((s32) in2[1])) * ((s32) in[1]) + + ((limb) ((s32) in2[0])) * ((s32) in[2]) + + ((limb) ((s32) in2[2])) * ((s32) in[0]); + output[3] = ((limb) ((s32) in2[1])) * ((s32) in[2]) + + ((limb) ((s32) in2[2])) * ((s32) in[1]) + + ((limb) ((s32) in2[0])) * ((s32) in[3]) + + ((limb) ((s32) in2[3])) * ((s32) in[0]); + output[4] = ((limb) ((s32) in2[2])) * ((s32) in[2]) + + 2 * (((limb) ((s32) in2[1])) * ((s32) in[3]) + + ((limb) ((s32) in2[3])) * ((s32) in[1])) + + ((limb) ((s32) in2[0])) * ((s32) in[4]) + + ((limb) ((s32) in2[4])) * ((s32) in[0]); + output[5] = ((limb) ((s32) in2[2])) * ((s32) in[3]) + + ((limb) ((s32) in2[3])) * ((s32) in[2]) + + ((limb) ((s32) in2[1])) * ((s32) in[4]) + + ((limb) ((s32) in2[4])) * ((s32) in[1]) + + ((limb) ((s32) in2[0])) * ((s32) in[5]) + + ((limb) ((s32) in2[5])) * ((s32) in[0]); + output[6] = 2 * (((limb) ((s32) in2[3])) * ((s32) in[3]) + + ((limb) ((s32) in2[1])) * ((s32) in[5]) + + ((limb) ((s32) in2[5])) * ((s32) in[1])) + + ((limb) ((s32) in2[2])) * ((s32) in[4]) + + ((limb) ((s32) in2[4])) * ((s32) in[2]) + + ((limb) ((s32) in2[0])) * ((s32) in[6]) + + ((limb) ((s32) in2[6])) * ((s32) in[0]); + output[7] = ((limb) ((s32) in2[3])) * ((s32) in[4]) + + ((limb) ((s32) in2[4])) * ((s32) in[3]) + + ((limb) ((s32) in2[2])) * ((s32) in[5]) + + ((limb) ((s32) in2[5])) * ((s32) in[2]) + + ((limb) ((s32) in2[1])) * ((s32) in[6]) + + ((limb) ((s32) in2[6])) * ((s32) in[1]) + + ((limb) ((s32) in2[0])) * ((s32) in[7]) + + ((limb) ((s32) in2[7])) * ((s32) in[0]); + output[8] = ((limb) ((s32) in2[4])) * ((s32) in[4]) + + 2 * (((limb) ((s32) in2[3])) * ((s32) in[5]) + + ((limb) ((s32) in2[5])) * ((s32) in[3]) + + ((limb) ((s32) in2[1])) * ((s32) in[7]) + + ((limb) ((s32) in2[7])) * ((s32) in[1])) + + ((limb) ((s32) in2[2])) * ((s32) in[6]) + + ((limb) ((s32) in2[6])) * ((s32) in[2]) + + ((limb) ((s32) in2[0])) * ((s32) in[8]) + + ((limb) ((s32) in2[8])) * ((s32) in[0]); + output[9] = ((limb) ((s32) in2[4])) * ((s32) in[5]) + + ((limb) ((s32) in2[5])) * ((s32) in[4]) + + ((limb) ((s32) in2[3])) * ((s32) in[6]) + + ((limb) ((s32) in2[6])) * ((s32) in[3]) + + ((limb) ((s32) in2[2])) * ((s32) in[7]) + + ((limb) ((s32) in2[7])) * ((s32) in[2]) + + ((limb) ((s32) in2[1])) * ((s32) in[8]) + + ((limb) ((s32) in2[8])) * ((s32) in[1]) + + ((limb) ((s32) in2[0])) * ((s32) in[9]) + + ((limb) ((s32) in2[9])) * ((s32) in[0]); + output[10] = 2 * (((limb) ((s32) in2[5])) * ((s32) in[5]) + + ((limb) ((s32) in2[3])) * ((s32) in[7]) + + ((limb) ((s32) in2[7])) * ((s32) in[3]) + + ((limb) ((s32) in2[1])) * ((s32) in[9]) + + ((limb) ((s32) in2[9])) * ((s32) in[1])) + + ((limb) ((s32) in2[4])) * ((s32) in[6]) + + ((limb) ((s32) in2[6])) * ((s32) in[4]) + + ((limb) ((s32) in2[2])) * ((s32) in[8]) + + ((limb) ((s32) in2[8])) * ((s32) in[2]); + output[11] = ((limb) ((s32) in2[5])) * ((s32) in[6]) + + ((limb) ((s32) in2[6])) * ((s32) in[5]) + + ((limb) ((s32) in2[4])) * ((s32) in[7]) + + ((limb) ((s32) in2[7])) * ((s32) in[4]) + + ((limb) ((s32) in2[3])) * ((s32) in[8]) + + ((limb) ((s32) in2[8])) * ((s32) in[3]) + + ((limb) ((s32) in2[2])) * ((s32) in[9]) + + ((limb) ((s32) in2[9])) * ((s32) in[2]); + output[12] = ((limb) ((s32) in2[6])) * ((s32) in[6]) + + 2 * (((limb) ((s32) in2[5])) * ((s32) in[7]) + + ((limb) ((s32) in2[7])) * ((s32) in[5]) + + ((limb) ((s32) in2[3])) * ((s32) in[9]) + + ((limb) ((s32) in2[9])) * ((s32) in[3])) + + ((limb) ((s32) in2[4])) * ((s32) in[8]) + + ((limb) ((s32) in2[8])) * ((s32) in[4]); + output[13] = ((limb) ((s32) in2[6])) * ((s32) in[7]) + + ((limb) ((s32) in2[7])) * ((s32) in[6]) + + ((limb) ((s32) in2[5])) * ((s32) in[8]) + + ((limb) ((s32) in2[8])) * ((s32) in[5]) + + ((limb) ((s32) in2[4])) * ((s32) in[9]) + + ((limb) ((s32) in2[9])) * ((s32) in[4]); + output[14] = 2 * (((limb) ((s32) in2[7])) * ((s32) in[7]) + + ((limb) ((s32) in2[5])) * ((s32) in[9]) + + ((limb) ((s32) in2[9])) * ((s32) in[5])) + + ((limb) ((s32) in2[6])) * ((s32) in[8]) + + ((limb) ((s32) in2[8])) * ((s32) in[6]); + output[15] = ((limb) ((s32) in2[7])) * ((s32) in[8]) + + ((limb) ((s32) in2[8])) * ((s32) in[7]) + + ((limb) ((s32) in2[6])) * ((s32) in[9]) + + ((limb) ((s32) in2[9])) * ((s32) in[6]); + output[16] = ((limb) ((s32) in2[8])) * ((s32) in[8]) + + 2 * (((limb) ((s32) in2[7])) * ((s32) in[9]) + + ((limb) ((s32) in2[9])) * ((s32) in[7])); + output[17] = ((limb) ((s32) in2[8])) * ((s32) in[9]) + + ((limb) ((s32) in2[9])) * ((s32) in[8]); + output[18] = 2 * ((limb) ((s32) in2[9])) * ((s32) in[9]); +} + +/* Reduce a long form to a short form by taking the input mod 2^255 - 19. */ +static void freduce_degree(limb *output) { + /* Each of these shifts and adds ends up multiplying the value by 19. */ + output[8] += output[18] << 4; + output[8] += output[18] << 1; + output[8] += output[18]; + output[7] += output[17] << 4; + output[7] += output[17] << 1; + output[7] += output[17]; + output[6] += output[16] << 4; + output[6] += output[16] << 1; + output[6] += output[16]; + output[5] += output[15] << 4; + output[5] += output[15] << 1; + output[5] += output[15]; + output[4] += output[14] << 4; + output[4] += output[14] << 1; + output[4] += output[14]; + output[3] += output[13] << 4; + output[3] += output[13] << 1; + output[3] += output[13]; + output[2] += output[12] << 4; + output[2] += output[12] << 1; + output[2] += output[12]; + output[1] += output[11] << 4; + output[1] += output[11] << 1; + output[1] += output[11]; + output[0] += output[10] << 4; + output[0] += output[10] << 1; + output[0] += output[10]; +} + +/* Reduce all coefficients of the short form input so that |x| < 2^26. + * + * On entry: |output[i]| < 2^62 + */ +static void freduce_coefficients(limb *output) { + unsigned i; + do { + output[10] = 0; + + for (i = 0; i < 10; i += 2) { + limb over = output[i] / 0x4000000l; + output[i+1] += over; + output[i] -= over * 0x4000000l; + + over = output[i+1] / 0x2000000; + output[i+2] += over; + output[i+1] -= over * 0x2000000; + } + output[0] += 19 * output[10]; + } while (output[10]); +} + +/* A helpful wrapper around fproduct: output = in * in2. + * + * output must be distinct to both inputs. The output is reduced degree and + * reduced coefficient. + */ +static void +fmul(limb *output, const limb *in, const limb *in2) { + limb t[19]; + fproduct(t, in, in2); + freduce_degree(t); + freduce_coefficients(t); + memcpy(output, t, sizeof(limb) * 10); +} + +static void fsquare_inner(limb *output, const limb *in) { + output[0] = ((limb) ((s32) in[0])) * ((s32) in[0]); + output[1] = 2 * ((limb) ((s32) in[0])) * ((s32) in[1]); + output[2] = 2 * (((limb) ((s32) in[1])) * ((s32) in[1]) + + ((limb) ((s32) in[0])) * ((s32) in[2])); + output[3] = 2 * (((limb) ((s32) in[1])) * ((s32) in[2]) + + ((limb) ((s32) in[0])) * ((s32) in[3])); + output[4] = ((limb) ((s32) in[2])) * ((s32) in[2]) + + 4 * ((limb) ((s32) in[1])) * ((s32) in[3]) + + 2 * ((limb) ((s32) in[0])) * ((s32) in[4]); + output[5] = 2 * (((limb) ((s32) in[2])) * ((s32) in[3]) + + ((limb) ((s32) in[1])) * ((s32) in[4]) + + ((limb) ((s32) in[0])) * ((s32) in[5])); + output[6] = 2 * (((limb) ((s32) in[3])) * ((s32) in[3]) + + ((limb) ((s32) in[2])) * ((s32) in[4]) + + ((limb) ((s32) in[0])) * ((s32) in[6]) + + 2 * ((limb) ((s32) in[1])) * ((s32) in[5])); + output[7] = 2 * (((limb) ((s32) in[3])) * ((s32) in[4]) + + ((limb) ((s32) in[2])) * ((s32) in[5]) + + ((limb) ((s32) in[1])) * ((s32) in[6]) + + ((limb) ((s32) in[0])) * ((s32) in[7])); + output[8] = ((limb) ((s32) in[4])) * ((s32) in[4]) + + 2 * (((limb) ((s32) in[2])) * ((s32) in[6]) + + ((limb) ((s32) in[0])) * ((s32) in[8]) + + 2 * (((limb) ((s32) in[1])) * ((s32) in[7]) + + ((limb) ((s32) in[3])) * ((s32) in[5]))); + output[9] = 2 * (((limb) ((s32) in[4])) * ((s32) in[5]) + + ((limb) ((s32) in[3])) * ((s32) in[6]) + + ((limb) ((s32) in[2])) * ((s32) in[7]) + + ((limb) ((s32) in[1])) * ((s32) in[8]) + + ((limb) ((s32) in[0])) * ((s32) in[9])); + output[10] = 2 * (((limb) ((s32) in[5])) * ((s32) in[5]) + + ((limb) ((s32) in[4])) * ((s32) in[6]) + + ((limb) ((s32) in[2])) * ((s32) in[8]) + + 2 * (((limb) ((s32) in[3])) * ((s32) in[7]) + + ((limb) ((s32) in[1])) * ((s32) in[9]))); + output[11] = 2 * (((limb) ((s32) in[5])) * ((s32) in[6]) + + ((limb) ((s32) in[4])) * ((s32) in[7]) + + ((limb) ((s32) in[3])) * ((s32) in[8]) + + ((limb) ((s32) in[2])) * ((s32) in[9])); + output[12] = ((limb) ((s32) in[6])) * ((s32) in[6]) + + 2 * (((limb) ((s32) in[4])) * ((s32) in[8]) + + 2 * (((limb) ((s32) in[5])) * ((s32) in[7]) + + ((limb) ((s32) in[3])) * ((s32) in[9]))); + output[13] = 2 * (((limb) ((s32) in[6])) * ((s32) in[7]) + + ((limb) ((s32) in[5])) * ((s32) in[8]) + + ((limb) ((s32) in[4])) * ((s32) in[9])); + output[14] = 2 * (((limb) ((s32) in[7])) * ((s32) in[7]) + + ((limb) ((s32) in[6])) * ((s32) in[8]) + + 2 * ((limb) ((s32) in[5])) * ((s32) in[9])); + output[15] = 2 * (((limb) ((s32) in[7])) * ((s32) in[8]) + + ((limb) ((s32) in[6])) * ((s32) in[9])); + output[16] = ((limb) ((s32) in[8])) * ((s32) in[8]) + + 4 * ((limb) ((s32) in[7])) * ((s32) in[9]); + output[17] = 2 * ((limb) ((s32) in[8])) * ((s32) in[9]); + output[18] = 2 * ((limb) ((s32) in[9])) * ((s32) in[9]); +} + +static void +fsquare(limb *output, const limb *in) { + limb t[19]; + fsquare_inner(t, in); + freduce_degree(t); + freduce_coefficients(t); + memcpy(output, t, sizeof(limb) * 10); +} + +/* Take a little-endian, 32-byte number and expand it into polynomial form */ +static void +fexpand(limb *output, const u8 *input) { +#define F(n,start,shift,mask) \ + output[n] = ((((limb) input[start + 0]) | \ + ((limb) input[start + 1]) << 8 | \ + ((limb) input[start + 2]) << 16 | \ + ((limb) input[start + 3]) << 24) >> shift) & mask; + F(0, 0, 0, 0x3ffffff); + F(1, 3, 2, 0x1ffffff); + F(2, 6, 3, 0x3ffffff); + F(3, 9, 5, 0x1ffffff); + F(4, 12, 6, 0x3ffffff); + F(5, 16, 0, 0x1ffffff); + F(6, 19, 1, 0x3ffffff); + F(7, 22, 3, 0x1ffffff); + F(8, 25, 4, 0x3ffffff); + F(9, 28, 6, 0x1ffffff); +#undef F +} + +/* Take a fully reduced polynomial form number and contract it into a + * little-endian, 32-byte array + */ +static void +fcontract(u8 *output, limb *input) { + int i; + + do { + for (i = 0; i < 9; ++i) { + if ((i & 1) == 1) { + while (input[i] < 0) { + input[i] += 0x2000000; + input[i + 1]--; + } + } else { + while (input[i] < 0) { + input[i] += 0x4000000; + input[i + 1]--; + } + } + } + while (input[9] < 0) { + input[9] += 0x2000000; + input[0] -= 19; + } + } while (input[0] < 0); + + input[1] <<= 2; + input[2] <<= 3; + input[3] <<= 5; + input[4] <<= 6; + input[6] <<= 1; + input[7] <<= 3; + input[8] <<= 4; + input[9] <<= 6; +#define F(i, s) \ + output[s+0] |= input[i] & 0xff; \ + output[s+1] = (input[i] >> 8) & 0xff; \ + output[s+2] = (input[i] >> 16) & 0xff; \ + output[s+3] = (input[i] >> 24) & 0xff; + output[0] = 0; + output[16] = 0; + F(0,0); + F(1,3); + F(2,6); + F(3,9); + F(4,12); + F(5,16); + F(6,19); + F(7,22); + F(8,25); + F(9,28); +#undef F +} + +/* Input: Q, Q', Q-Q' + * Output: 2Q, Q+Q' + * + * x2 z3: long form + * x3 z3: long form + * x z: short form, destroyed + * xprime zprime: short form, destroyed + * qmqp: short form, preserved + */ +static void fmonty(limb *x2, limb *z2, /* output 2Q */ + limb *x3, limb *z3, /* output Q + Q' */ + limb *x, limb *z, /* input Q */ + limb *xprime, limb *zprime, /* input Q' */ + const limb *qmqp /* input Q - Q' */) { + limb origx[10], origxprime[10], zzz[19], xx[19], zz[19], xxprime[19], + zzprime[19], zzzprime[19], xxxprime[19]; + + memcpy(origx, x, 10 * sizeof(limb)); + fsum(x, z); + fdifference(z, origx); // does x - z + + memcpy(origxprime, xprime, sizeof(limb) * 10); + fsum(xprime, zprime); + fdifference(zprime, origxprime); + fproduct(xxprime, xprime, z); + fproduct(zzprime, x, zprime); + freduce_degree(xxprime); + freduce_coefficients(xxprime); + freduce_degree(zzprime); + freduce_coefficients(zzprime); + memcpy(origxprime, xxprime, sizeof(limb) * 10); + fsum(xxprime, zzprime); + fdifference(zzprime, origxprime); + fsquare(xxxprime, xxprime); + fsquare(zzzprime, zzprime); + fproduct(zzprime, zzzprime, qmqp); + freduce_degree(zzprime); + freduce_coefficients(zzprime); + memcpy(x3, xxxprime, sizeof(limb) * 10); + memcpy(z3, zzprime, sizeof(limb) * 10); + + fsquare(xx, x); + fsquare(zz, z); + fproduct(x2, xx, zz); + freduce_degree(x2); + freduce_coefficients(x2); + fdifference(zz, xx); // does zz = xx - zz + memset(zzz + 10, 0, sizeof(limb) * 9); + fscalar_product(zzz, zz, 121665); + freduce_degree(zzz); + freduce_coefficients(zzz); + fsum(zzz, xx); + fproduct(z2, zz, zzz); + freduce_degree(z2); + freduce_coefficients(z2); +} + +/* Calculates nQ where Q is the x-coordinate of a point on the curve + * + * resultx/resultz: the x coordinate of the resulting curve point (short form) + * n: a little endian, 32-byte number + * q: a point of the curve (short form) + */ +static void +cmult(limb *resultx, limb *resultz, const u8 *n, const limb *q) { + limb a[19] = {0}, b[19] = {1}, c[19] = {1}, d[19] = {0}; + limb *nqpqx = a, *nqpqz = b, *nqx = c, *nqz = d, *t; + limb e[19] = {0}, f[19] = {1}, g[19] = {0}, h[19] = {1}; + limb *nqpqx2 = e, *nqpqz2 = f, *nqx2 = g, *nqz2 = h; + + unsigned i, j; + + memcpy(nqpqx, q, sizeof(limb) * 10); + + for (i = 0; i < 32; ++i) { + u8 byte = n[31 - i]; + for (j = 0; j < 8; ++j) { + if (byte & 0x80) { + fmonty(nqpqx2, nqpqz2, + nqx2, nqz2, + nqpqx, nqpqz, + nqx, nqz, + q); + } else { + fmonty(nqx2, nqz2, + nqpqx2, nqpqz2, + nqx, nqz, + nqpqx, nqpqz, + q); + } + + t = nqx; + nqx = nqx2; + nqx2 = t; + t = nqz; + nqz = nqz2; + nqz2 = t; + t = nqpqx; + nqpqx = nqpqx2; + nqpqx2 = t; + t = nqpqz; + nqpqz = nqpqz2; + nqpqz2 = t; + + byte <<= 1; + } + } + + memcpy(resultx, nqx, sizeof(limb) * 10); + memcpy(resultz, nqz, sizeof(limb) * 10); +} + +// ----------------------------------------------------------------------------- +// Shamelessly copied from djb's code +// ----------------------------------------------------------------------------- +static void +crecip(limb *out, const limb *z) { + limb z2[10]; + limb z9[10]; + limb z11[10]; + limb z2_5_0[10]; + limb z2_10_0[10]; + limb z2_20_0[10]; + limb z2_50_0[10]; + limb z2_100_0[10]; + limb t0[10]; + limb t1[10]; + int i; + + /* 2 */ fsquare(z2,z); + /* 4 */ fsquare(t1,z2); + /* 8 */ fsquare(t0,t1); + /* 9 */ fmul(z9,t0,z); + /* 11 */ fmul(z11,z9,z2); + /* 22 */ fsquare(t0,z11); + /* 2^5 - 2^0 = 31 */ fmul(z2_5_0,t0,z9); + + /* 2^6 - 2^1 */ fsquare(t0,z2_5_0); + /* 2^7 - 2^2 */ fsquare(t1,t0); + /* 2^8 - 2^3 */ fsquare(t0,t1); + /* 2^9 - 2^4 */ fsquare(t1,t0); + /* 2^10 - 2^5 */ fsquare(t0,t1); + /* 2^10 - 2^0 */ fmul(z2_10_0,t0,z2_5_0); + + /* 2^11 - 2^1 */ fsquare(t0,z2_10_0); + /* 2^12 - 2^2 */ fsquare(t1,t0); + /* 2^20 - 2^10 */ + for (i = 2;i < 10;i += 2) { fsquare(t0,t1); fsquare(t1,t0); } + /* 2^20 - 2^0 */ fmul(z2_20_0,t1,z2_10_0); + + /* 2^21 - 2^1 */ fsquare(t0,z2_20_0); + /* 2^22 - 2^2 */ fsquare(t1,t0); + /* 2^40 - 2^20 */ + for (i = 2;i < 20;i += 2) { fsquare(t0,t1); fsquare(t1,t0); } + /* 2^40 - 2^0 */ fmul(t0,t1,z2_20_0); + + /* 2^41 - 2^1 */ fsquare(t1,t0); + /* 2^42 - 2^2 */ fsquare(t0,t1); + /* 2^50 - 2^10 */ + for (i = 2;i < 10;i += 2) { fsquare(t1,t0); fsquare(t0,t1); } + /* 2^50 - 2^0 */ fmul(z2_50_0,t0,z2_10_0); + + /* 2^51 - 2^1 */ fsquare(t0,z2_50_0); + /* 2^52 - 2^2 */ fsquare(t1,t0); + /* 2^100 - 2^50 */ + for (i = 2;i < 50;i += 2) { fsquare(t0,t1); fsquare(t1,t0); } + /* 2^100 - 2^0 */ fmul(z2_100_0,t1,z2_50_0); + + /* 2^101 - 2^1 */ fsquare(t1,z2_100_0); + /* 2^102 - 2^2 */ fsquare(t0,t1); + /* 2^200 - 2^100 */ + for (i = 2;i < 100;i += 2) { fsquare(t1,t0); fsquare(t0,t1); } + /* 2^200 - 2^0 */ fmul(t1,t0,z2_100_0); + + /* 2^201 - 2^1 */ fsquare(t0,t1); + /* 2^202 - 2^2 */ fsquare(t1,t0); + /* 2^250 - 2^50 */ + for (i = 2;i < 50;i += 2) { fsquare(t0,t1); fsquare(t1,t0); } + /* 2^250 - 2^0 */ fmul(t0,t1,z2_50_0); + + /* 2^251 - 2^1 */ fsquare(t1,t0); + /* 2^252 - 2^2 */ fsquare(t0,t1); + /* 2^253 - 2^3 */ fsquare(t1,t0); + /* 2^254 - 2^4 */ fsquare(t0,t1); + /* 2^255 - 2^5 */ fsquare(t1,t0); + /* 2^255 - 21 */ fmul(out,t1,z11); +} + +int +curve25519_donna(u8 *mypublic, const u8 *secret, const u8 *basepoint) { + limb bp[10], x[10], z[10], zmone[10]; + uint8_t e[32]; + int i; + + for (i = 0; i < 32; ++i) e[i] = secret[i]; + e[0] &= 248; + e[31] &= 127; + e[31] |= 64; + + fexpand(bp, basepoint); + cmult(x, z, e, bp); + crecip(zmone, z); + fmul(z, x, zmone); + fcontract(mypublic, z); + return 0; +} diff --git a/crypto/curve25519.cc b/crypto/curve25519.cc new file mode 100644 index 0000000000000..3346df93a1ad7 --- /dev/null +++ b/crypto/curve25519.cc @@ -0,0 +1,36 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/curve25519.h" + +// Curve25519 is specified in terms of byte strings, not numbers, so all +// implementations take and return the same sequence of bits. So the byte +// order is implicitly specified as in, say, SHA1. +// +// Prototype for |curve25519_donna| function in +// third_party/curve25519-donna/curve25519-donna.c +extern "C" int curve25519_donna(uint8*, const uint8*, const uint8*); + +namespace crypto { + +namespace curve25519 { + +void ScalarMult(const uint8* private_key, + const uint8* peer_public_key, + uint8* shared_key) { + curve25519_donna(shared_key, private_key, peer_public_key); +} + +// kBasePoint is the base point (generator) of the elliptic curve group. +// It is little-endian version of '9' followed by 31 zeros. +// See "Computing public keys" section of http://cr.yp.to/ecdh.html. +static const unsigned char kBasePoint[32] = {9}; + +void ScalarBaseMult(const uint8* private_key, uint8* public_key) { + curve25519_donna(public_key, private_key, kBasePoint); +} + +} // namespace curve25519 + +} // namespace crypto diff --git a/crypto/curve25519.h b/crypto/curve25519.h new file mode 100644 index 0000000000000..ba24c92a8778e --- /dev/null +++ b/crypto/curve25519.h @@ -0,0 +1,48 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CRYPTO_CURVE25519_H +#define CRYPTO_CURVE25519_H + +#include "base/basictypes.h" +#include "crypto/crypto_export.h" + +namespace crypto { + +// Curve25519 implements the elliptic curve group known as Curve25519, as +// described in "Curve 25519: new Diffie-Hellman Speed Records", +// by D.J. Bernstein. Additional information is available at +// http://cr.yp.to/ecdh.html. +namespace curve25519 { + +// kBytes is the number of bytes in the result of the Diffie-Hellman operation, +// which is an element of GF(2^255-19). +static const size_t kBytes = 32; + +// kScalarBytes is the number of bytes in an element of the scalar field: +// GF(2^252 + 27742317777372353535851937790883648493). +static const size_t kScalarBytes = 32; + +// ScalarMult computes the |shared_key| from |private_key| and +// |peer_public_key|. This method is a wrapper for |curve25519_donna()|. It +// calls that function with |private_key| as |secret| and |peer_public_key| as +// basepoint. |private_key| should be of length |kScalarBytes| and +// |peer_public_key| should be of length |kBytes|. +// See "Computing shared secrets" section of/ http://cr.yp.to/ecdh.html. +CRYPTO_EXPORT void ScalarMult(const uint8* private_key, + const uint8* peer_public_key, + uint8* shared_key); + +// ScalarBaseMult computes the |public_key| from |private_key|. This method is a +// wrapper for |curve25519_donna()|. It calls that function with |private_key| +// as |secret| and |kBasePoint| as basepoint. |private_key| should be of length +// |kScalarBytes|. See "Computing public keys" section of +// http://cr.yp.to/ecdh.html. +CRYPTO_EXPORT void ScalarBaseMult(const uint8* private_key, uint8* public_key); + +} // namespace curve25519 + +} // namespace crypto + +#endif // CRYPTO_CURVE25519_H diff --git a/crypto/curve25519_unittest.cc b/crypto/curve25519_unittest.cc new file mode 100644 index 0000000000000..0ddc4224a615a --- /dev/null +++ b/crypto/curve25519_unittest.cc @@ -0,0 +1,44 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/curve25519.h" + +#include + +#include "crypto/random.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace crypto { + +// Test that the basic shared key exchange identity holds: that both parties end +// up with the same shared key. This test starts with a fixed private key for +// two parties: alice and bob. Runs ScalarBaseMult and ScalarMult to compute +// public key and shared key for alice and bob. It asserts that alice and bob +// have the same shared key. +TEST(Curve25519, SharedKeyIdentity) { + uint8 alice_private_key[curve25519::kScalarBytes] = {3}; + uint8 bob_private_key[curve25519::kScalarBytes] = {5}; + + // Get public key for alice and bob. + uint8 alice_public_key[curve25519::kBytes]; + curve25519::ScalarBaseMult(alice_private_key, alice_public_key); + + uint8 bob_public_key[curve25519::kBytes]; + curve25519::ScalarBaseMult(bob_private_key, bob_public_key); + + // Get the shared key for alice, by using alice's private key and bob's + // public key. + uint8 alice_shared_key[curve25519::kBytes]; + curve25519::ScalarMult(alice_private_key, bob_public_key, alice_shared_key); + + // Get the shared key for bob, by using bob's private key and alice's public + // key. + uint8 bob_shared_key[curve25519::kBytes]; + curve25519::ScalarMult(bob_private_key, alice_public_key, bob_shared_key); + + // Computed shared key of alice and bob should be the same. + ASSERT_EQ(0, memcmp(alice_shared_key, bob_shared_key, curve25519::kBytes)); +} + +} // namespace crypto diff --git a/crypto/ec_private_key.h b/crypto/ec_private_key.h new file mode 100644 index 0000000000000..87af838904ae6 --- /dev/null +++ b/crypto/ec_private_key.h @@ -0,0 +1,118 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CRYPTO_EC_PRIVATE_KEY_H_ +#define CRYPTO_EC_PRIVATE_KEY_H_ + +#include +#include + +#include "base/basictypes.h" +#include "build/build_config.h" +#include "crypto/crypto_export.h" + +#if defined(USE_OPENSSL) +// Forward declaration for openssl/*.h +typedef struct evp_pkey_st EVP_PKEY; +#else +// Forward declaration. +typedef struct CERTSubjectPublicKeyInfoStr CERTSubjectPublicKeyInfo; +typedef struct PK11SlotInfoStr PK11SlotInfo; +typedef struct SECKEYPrivateKeyStr SECKEYPrivateKey; +typedef struct SECKEYPublicKeyStr SECKEYPublicKey; +#endif + +namespace crypto { + +// Encapsulates an elliptic curve (EC) private key. Can be used to generate new +// keys, export keys to other formats, or to extract a public key. +// TODO(mattm): make this and RSAPrivateKey implement some PrivateKey interface. +// (The difference in types of key() and public_key() make this a little +// tricky.) +class CRYPTO_EXPORT ECPrivateKey { + public: + ~ECPrivateKey(); + + // Returns whether the system supports elliptic curve cryptography. + static bool IsSupported(); + + // Creates a new random instance. Can return NULL if initialization fails. + // The created key will use the NIST P-256 curve. + // TODO(mattm): Add a curve parameter. + static ECPrivateKey* Create(); + + // Creates a new instance by importing an existing key pair. + // The key pair is given as an ASN.1-encoded PKCS #8 EncryptedPrivateKeyInfo + // block and an X.509 SubjectPublicKeyInfo block. + // Returns NULL if initialization fails. + static ECPrivateKey* CreateFromEncryptedPrivateKeyInfo( + const std::string& password, + const std::vector& encrypted_private_key_info, + const std::vector& subject_public_key_info); + +#if !defined(USE_OPENSSL) + // Imports the key pair into |slot| and returns in |public_key| and |key|. + // Shortcut for code that needs to keep a reference directly to NSS types + // without having to create a ECPrivateKey object and make a copy of them. + // TODO(mattm): move this function to some NSS util file. + static bool ImportFromEncryptedPrivateKeyInfo( + PK11SlotInfo* slot, + const std::string& password, + const uint8* encrypted_private_key_info, + size_t encrypted_private_key_info_len, + CERTSubjectPublicKeyInfo* decoded_spki, + bool permanent, + bool sensitive, + SECKEYPrivateKey** key, + SECKEYPublicKey** public_key); +#endif + + // Returns a copy of the object. + ECPrivateKey* Copy() const; + +#if defined(USE_OPENSSL) + EVP_PKEY* key() { return key_; } +#else + SECKEYPrivateKey* key() { return key_; } + SECKEYPublicKey* public_key() { return public_key_; } +#endif + + // Exports the private key as an ASN.1-encoded PKCS #8 EncryptedPrivateKeyInfo + // block and the public key as an X.509 SubjectPublicKeyInfo block. + // The |password| and |iterations| are used as inputs to the key derivation + // function for generating the encryption key. PKCS #5 recommends a minimum + // of 1000 iterations, on modern systems a larger value may be preferrable. + bool ExportEncryptedPrivateKey(const std::string& password, + int iterations, + std::vector* output); + + // Exports the public key to an X.509 SubjectPublicKeyInfo block. + bool ExportPublicKey(std::vector* output); + + // Exports the public key as an EC point in the uncompressed point format. + bool ExportRawPublicKey(std::string* output); + + // Exports private key data for testing. The format of data stored into output + // doesn't matter other than that it is consistent for the same key. + bool ExportValue(std::vector* output); + bool ExportECParams(std::vector* output); + + private: + // Constructor is private. Use one of the Create*() methods above instead. + ECPrivateKey(); + +#if defined(USE_OPENSSL) + EVP_PKEY* key_; +#else + SECKEYPrivateKey* key_; + SECKEYPublicKey* public_key_; +#endif + + DISALLOW_COPY_AND_ASSIGN(ECPrivateKey); +}; + + +} // namespace crypto + +#endif // CRYPTO_EC_PRIVATE_KEY_H_ diff --git a/crypto/ec_private_key_nss.cc b/crypto/ec_private_key_nss.cc new file mode 100644 index 0000000000000..5092010c939b5 --- /dev/null +++ b/crypto/ec_private_key_nss.cc @@ -0,0 +1,357 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/ec_private_key.h" + +extern "C" { +// Work around NSS missing SEC_BEGIN_PROTOS in secmodt.h. This must come before +// other NSS headers. +#include +} + +#include +#include +#include +#include + +#include "base/lazy_instance.h" +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "crypto/nss_util.h" +#include "crypto/nss_util_internal.h" +#include "crypto/scoped_nss_types.h" +#include "crypto/third_party/nss/chromium-nss.h" + +namespace { + +PK11SlotInfo* GetTempKeySlot() { + return PK11_GetInternalSlot(); +} + +class EllipticCurveSupportChecker { + public: + EllipticCurveSupportChecker() { + // NOTE: we can do this check here only because we use the NSS internal + // slot. If we support other slots in the future, checking whether they + // support ECDSA may block NSS, and the value may also change as devices are + // inserted/removed, so we would need to re-check on every use. + crypto::EnsureNSSInit(); + crypto::ScopedPK11Slot slot(GetTempKeySlot()); + supported_ = PK11_DoesMechanism(slot.get(), CKM_EC_KEY_PAIR_GEN) && + PK11_DoesMechanism(slot.get(), CKM_ECDSA); + } + + bool Supported() { + return supported_; + } + + private: + bool supported_; +}; + +static base::LazyInstance::Leaky + g_elliptic_curve_supported = LAZY_INSTANCE_INITIALIZER; + +// Copied from rsa_private_key_nss.cc. +static bool ReadAttribute(SECKEYPrivateKey* key, + CK_ATTRIBUTE_TYPE type, + std::vector* output) { + SECItem item; + SECStatus rv; + rv = PK11_ReadRawAttribute(PK11_TypePrivKey, key, type, &item); + if (rv != SECSuccess) { + DLOG(ERROR) << "PK11_ReadRawAttribute: " << PORT_GetError(); + return false; + } + + output->assign(item.data, item.data + item.len); + SECITEM_FreeItem(&item, PR_FALSE); + return true; +} + +} // namespace + +namespace crypto { + +ECPrivateKey::~ECPrivateKey() { + if (key_) + SECKEY_DestroyPrivateKey(key_); + if (public_key_) + SECKEY_DestroyPublicKey(public_key_); +} + +// static +bool ECPrivateKey::IsSupported() { + return g_elliptic_curve_supported.Get().Supported(); +} + +// static +ECPrivateKey* ECPrivateKey::Create() { + EnsureNSSInit(); + + ScopedPK11Slot slot(GetTempKeySlot()); + if (!slot) + return nullptr; + + scoped_ptr result(new ECPrivateKey); + + SECOidData* oid_data = SECOID_FindOIDByTag(SEC_OID_SECG_EC_SECP256R1); + if (!oid_data) { + DLOG(ERROR) << "SECOID_FindOIDByTag: " << PORT_GetError(); + return nullptr; + } + + // SECKEYECParams is a SECItem containing the DER encoded ASN.1 ECParameters + // value. For a named curve, that is just the OBJECT IDENTIFIER of the curve. + // In addition to the oid data, the encoding requires one byte for the ASN.1 + // tag and one byte for the length (assuming the length is <= 127). + CHECK_LE(oid_data->oid.len, 127U); + std::vector parameters_buf(2 + oid_data->oid.len); + SECKEYECParams ec_parameters = { + siDEROID, ¶meters_buf[0], + static_cast(parameters_buf.size()) + }; + + ec_parameters.data[0] = SEC_ASN1_OBJECT_ID; + ec_parameters.data[1] = static_cast(oid_data->oid.len); + memcpy(ec_parameters.data + 2, oid_data->oid.data, oid_data->oid.len); + + result->key_ = PK11_GenerateKeyPair(slot.get(), + CKM_EC_KEY_PAIR_GEN, + &ec_parameters, + &result->public_key_, + PR_FALSE /* not permanent */, + PR_FALSE /* not sensitive */, + NULL); + if (!result->key_) { + DLOG(ERROR) << "PK11_GenerateKeyPair: " << PORT_GetError(); + return nullptr; + } + CHECK_EQ(ecKey, SECKEY_GetPublicKeyType(result->public_key_)); + + return result.release(); +} + +// static +ECPrivateKey* ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( + const std::string& password, + const std::vector& encrypted_private_key_info, + const std::vector& subject_public_key_info) { + EnsureNSSInit(); + + ScopedPK11Slot slot(GetTempKeySlot()); + if (!slot) + return nullptr; + + scoped_ptr result(new ECPrivateKey); + + SECItem encoded_spki = { + siBuffer, + const_cast(&subject_public_key_info[0]), + static_cast(subject_public_key_info.size()) + }; + CERTSubjectPublicKeyInfo* decoded_spki = SECKEY_DecodeDERSubjectPublicKeyInfo( + &encoded_spki); + if (!decoded_spki) { + DLOG(ERROR) << "SECKEY_DecodeDERSubjectPublicKeyInfo: " << PORT_GetError(); + return nullptr; + } + + bool success = ImportFromEncryptedPrivateKeyInfo( + slot.get(), + password, + &encrypted_private_key_info[0], + encrypted_private_key_info.size(), + decoded_spki, + false /* not permanent */, + false /* not sensitive */, + &result->key_, + &result->public_key_); + + SECKEY_DestroySubjectPublicKeyInfo(decoded_spki); + + if (success) { + CHECK_EQ(ecKey, SECKEY_GetPublicKeyType(result->public_key_)); + return result.release(); + } + + return nullptr; +} + +// static +bool ECPrivateKey::ImportFromEncryptedPrivateKeyInfo( + PK11SlotInfo* slot, + const std::string& password, + const uint8* encrypted_private_key_info, + size_t encrypted_private_key_info_len, + CERTSubjectPublicKeyInfo* decoded_spki, + bool permanent, + bool sensitive, + SECKEYPrivateKey** key, + SECKEYPublicKey** public_key) { + if (!slot) + return false; + + *public_key = SECKEY_ExtractPublicKey(decoded_spki); + + if (!*public_key) { + DLOG(ERROR) << "SECKEY_ExtractPublicKey: " << PORT_GetError(); + return false; + } + + if (SECKEY_GetPublicKeyType(*public_key) != ecKey) { + DLOG(ERROR) << "The public key is not an EC key"; + SECKEY_DestroyPublicKey(*public_key); + *public_key = NULL; + return false; + } + + SECItem encoded_epki = { + siBuffer, + const_cast(encrypted_private_key_info), + static_cast(encrypted_private_key_info_len) + }; + SECKEYEncryptedPrivateKeyInfo epki; + memset(&epki, 0, sizeof(epki)); + + ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); + + SECStatus rv = SEC_QuickDERDecodeItem( + arena.get(), + &epki, + SEC_ASN1_GET(SECKEY_EncryptedPrivateKeyInfoTemplate), + &encoded_epki); + if (rv != SECSuccess) { + DLOG(ERROR) << "SEC_QuickDERDecodeItem: " << PORT_GetError(); + SECKEY_DestroyPublicKey(*public_key); + *public_key = NULL; + return false; + } + + SECItem password_item = { + siBuffer, + reinterpret_cast(const_cast(password.data())), + static_cast(password.size()) + }; + + rv = ImportEncryptedECPrivateKeyInfoAndReturnKey( + slot, + &epki, + &password_item, + NULL, // nickname + &(*public_key)->u.ec.publicValue, + permanent, + sensitive, + key, + NULL); // wincx + if (rv != SECSuccess) { + DLOG(ERROR) << "ImportEncryptedECPrivateKeyInfoAndReturnKey: " + << PORT_GetError(); + SECKEY_DestroyPublicKey(*public_key); + *public_key = NULL; + return false; + } + + return true; +} + +ECPrivateKey* ECPrivateKey::Copy() const { + scoped_ptr copy(new ECPrivateKey); + if (key_) { + copy->key_ = SECKEY_CopyPrivateKey(key_); + if (!copy->key_) + return NULL; + } + if (public_key_) { + copy->public_key_ = SECKEY_CopyPublicKey(public_key_); + if (!copy->public_key_) + return NULL; + } + return copy.release(); +} + +bool ECPrivateKey::ExportEncryptedPrivateKey( + const std::string& password, + int iterations, + std::vector* output) { + // We export as an EncryptedPrivateKeyInfo bundle instead of a plain PKCS #8 + // PrivateKeyInfo because PK11_ImportDERPrivateKeyInfoAndReturnKey doesn't + // support EC keys. + // https://bugzilla.mozilla.org/show_bug.cgi?id=327773 + SECItem password_item = { + siBuffer, + reinterpret_cast(const_cast(password.data())), + static_cast(password.size()) + }; + + SECKEYEncryptedPrivateKeyInfo* encrypted = PK11_ExportEncryptedPrivKeyInfo( + NULL, // Slot, optional. + SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC, + &password_item, + key_, + iterations, + NULL); // wincx. + + if (!encrypted) { + DLOG(ERROR) << "PK11_ExportEncryptedPrivKeyInfo: " << PORT_GetError(); + return false; + } + + ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); + SECItem der_key = {siBuffer, NULL, 0}; + SECItem* encoded_item = SEC_ASN1EncodeItem( + arena.get(), + &der_key, + encrypted, + SEC_ASN1_GET(SECKEY_EncryptedPrivateKeyInfoTemplate)); + SECKEY_DestroyEncryptedPrivateKeyInfo(encrypted, PR_TRUE); + if (!encoded_item) { + DLOG(ERROR) << "SEC_ASN1EncodeItem: " << PORT_GetError(); + return false; + } + + output->assign(der_key.data, der_key.data + der_key.len); + + return true; +} + +bool ECPrivateKey::ExportPublicKey(std::vector* output) { + ScopedSECItem der_pubkey( + SECKEY_EncodeDERSubjectPublicKeyInfo(public_key_)); + if (!der_pubkey.get()) { + return false; + } + + output->assign(der_pubkey->data, der_pubkey->data + der_pubkey->len); + return true; +} + +bool ECPrivateKey::ExportRawPublicKey(std::string* output) { + // public_key_->u.ec.publicValue is an ANSI X9.62 public key which, for + // a P-256 key, is 0x04 (meaning uncompressed) followed by the x and y field + // elements as 32-byte, big-endian numbers. + static const unsigned int kExpectedKeyLength = 65; + + CHECK_EQ(ecKey, SECKEY_GetPublicKeyType(public_key_)); + const unsigned char* const data = public_key_->u.ec.publicValue.data; + const unsigned int len = public_key_->u.ec.publicValue.len; + if (len != kExpectedKeyLength || data[0] != 0x04) + return false; + + output->assign(reinterpret_cast(data + 1), + kExpectedKeyLength - 1); + return true; +} + +bool ECPrivateKey::ExportValue(std::vector* output) { + return ReadAttribute(key_, CKA_VALUE, output); +} + +bool ECPrivateKey::ExportECParams(std::vector* output) { + return ReadAttribute(key_, CKA_EC_PARAMS, output); +} + +ECPrivateKey::ECPrivateKey() : key_(NULL), public_key_(NULL) {} + +} // namespace crypto diff --git a/crypto/ec_private_key_openssl.cc b/crypto/ec_private_key_openssl.cc new file mode 100644 index 0000000000000..35403f39ce885 --- /dev/null +++ b/crypto/ec_private_key_openssl.cc @@ -0,0 +1,238 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/ec_private_key.h" + +#include +#include +#include +#include + +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "crypto/openssl_util.h" +#include "crypto/scoped_openssl_types.h" + +namespace crypto { + +namespace { + +// Function pointer definition, for injecting the required key export function +// into ExportKeyWithBio, below. |bio| is a temporary memory BIO object, and +// |key| is a handle to the input key object. Return 1 on success, 0 otherwise. +// NOTE: Used with OpenSSL functions, which do not comply with the Chromium +// style guide, hence the unusual parameter placement / types. +typedef int (*ExportBioFunction)(BIO* bio, const void* key); + +using ScopedPKCS8_PRIV_KEY_INFO = + ScopedOpenSSL; +using ScopedX509_SIG = ScopedOpenSSL; + +// Helper to export |key| into |output| via the specified ExportBioFunction. +bool ExportKeyWithBio(const void* key, + ExportBioFunction export_fn, + std::vector* output) { + if (!key) + return false; + + ScopedBIO bio(BIO_new(BIO_s_mem())); + if (!bio.get()) + return false; + + if (!export_fn(bio.get(), key)) + return false; + + char* data = NULL; + long len = BIO_get_mem_data(bio.get(), &data); + if (!data || len < 0) + return false; + + output->assign(data, data + len); + return true; +} + +// Function pointer definition, for injecting the required key export function +// into ExportKey below. |key| is a pointer to the input key object, +// and |data| is either NULL, or the address of an 'unsigned char*' pointer +// that points to the start of the output buffer. The function must return +// the number of bytes required to export the data, or -1 in case of error. +typedef int (*ExportDataFunction)(const void* key, unsigned char** data); + +// Helper to export |key| into |output| via the specified export function. +bool ExportKey(const void* key, + ExportDataFunction export_fn, + std::vector* output) { + if (!key) + return false; + + int data_len = export_fn(key, NULL); + if (data_len < 0) + return false; + + output->resize(static_cast(data_len)); + unsigned char* data = &(*output)[0]; + if (export_fn(key, &data) < 0) + return false; + + return true; +} + +} // namespace + +ECPrivateKey::~ECPrivateKey() { + if (key_) + EVP_PKEY_free(key_); +} + +ECPrivateKey* ECPrivateKey::Copy() const { + scoped_ptr copy(new ECPrivateKey); + if (key_) + copy->key_ = EVP_PKEY_up_ref(key_); + return copy.release(); +} + +// static +bool ECPrivateKey::IsSupported() { return true; } + +// static +ECPrivateKey* ECPrivateKey::Create() { + OpenSSLErrStackTracer err_tracer(FROM_HERE); + + ScopedEC_KEY ec_key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); + if (!ec_key.get() || !EC_KEY_generate_key(ec_key.get())) + return NULL; + + scoped_ptr result(new ECPrivateKey()); + result->key_ = EVP_PKEY_new(); + if (!result->key_ || !EVP_PKEY_set1_EC_KEY(result->key_, ec_key.get())) + return NULL; + + CHECK_EQ(EVP_PKEY_EC, EVP_PKEY_type(result->key_->type)); + return result.release(); +} + +// static +ECPrivateKey* ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( + const std::string& password, + const std::vector& encrypted_private_key_info, + const std::vector& subject_public_key_info) { + // NOTE: The |subject_public_key_info| can be ignored here, it is only + // useful for the NSS implementation (which uses the public key's SHA1 + // as a lookup key when storing the private one in its store). + if (encrypted_private_key_info.empty()) + return NULL; + + OpenSSLErrStackTracer err_tracer(FROM_HERE); + + const uint8_t* data = &encrypted_private_key_info[0]; + const uint8_t* ptr = data; + ScopedX509_SIG p8_encrypted( + d2i_X509_SIG(NULL, &ptr, encrypted_private_key_info.size())); + if (!p8_encrypted || ptr != data + encrypted_private_key_info.size()) + return NULL; + + ScopedPKCS8_PRIV_KEY_INFO p8_decrypted; + if (password.empty()) { + // Hack for reading keys generated by an older version of the OpenSSL + // code. OpenSSL used to use "\0\0" rather than the empty string because it + // would treat the password as an ASCII string to be converted to UCS-2 + // while NSS used a byte string. + p8_decrypted.reset(PKCS8_decrypt_pbe( + p8_encrypted.get(), reinterpret_cast("\0\0"), 2)); + } + if (!p8_decrypted) { + p8_decrypted.reset(PKCS8_decrypt_pbe( + p8_encrypted.get(), + reinterpret_cast(password.data()), + password.size())); + } + + if (!p8_decrypted) + return NULL; + + // Create a new EVP_PKEY for it. + scoped_ptr result(new ECPrivateKey); + result->key_ = EVP_PKCS82PKEY(p8_decrypted.get()); + if (!result->key_ || EVP_PKEY_type(result->key_->type) != EVP_PKEY_EC) + return NULL; + + return result.release(); +} + +bool ECPrivateKey::ExportEncryptedPrivateKey( + const std::string& password, + int iterations, + std::vector* output) { + OpenSSLErrStackTracer err_tracer(FROM_HERE); + // Convert into a PKCS#8 object. + ScopedPKCS8_PRIV_KEY_INFO pkcs8(EVP_PKEY2PKCS8(key_)); + if (!pkcs8.get()) + return false; + + // Encrypt the object. + // NOTE: NSS uses SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC + // so use NID_pbe_WithSHA1And3_Key_TripleDES_CBC which should be the OpenSSL + // equivalent. + ScopedX509_SIG encrypted(PKCS8_encrypt_pbe( + NID_pbe_WithSHA1And3_Key_TripleDES_CBC, + reinterpret_cast(password.data()), + password.size(), + NULL, + 0, + iterations, + pkcs8.get())); + if (!encrypted.get()) + return false; + + // Write it into |*output| + return ExportKeyWithBio(encrypted.get(), + reinterpret_cast(i2d_PKCS8_bio), + output); +} + +bool ECPrivateKey::ExportPublicKey(std::vector* output) { + OpenSSLErrStackTracer err_tracer(FROM_HERE); + return ExportKeyWithBio( + key_, reinterpret_cast(i2d_PUBKEY_bio), output); +} + +bool ECPrivateKey::ExportRawPublicKey(std::string* output) { + // i2d_PublicKey will produce an ANSI X9.62 public key which, for a P-256 + // key, is 0x04 (meaning uncompressed) followed by the x and y field + // elements as 32-byte, big-endian numbers. + static const int kExpectedKeyLength = 65; + + int len = i2d_PublicKey(key_, NULL); + if (len != kExpectedKeyLength) + return false; + + uint8 buf[kExpectedKeyLength]; + uint8* derp = buf; + len = i2d_PublicKey(key_, &derp); + if (len != kExpectedKeyLength) + return false; + + output->assign(reinterpret_cast(buf + 1), kExpectedKeyLength - 1); + return true; +} + +bool ECPrivateKey::ExportValue(std::vector* output) { + OpenSSLErrStackTracer err_tracer(FROM_HERE); + ScopedEC_KEY ec_key(EVP_PKEY_get1_EC_KEY(key_)); + return ExportKey(ec_key.get(), + reinterpret_cast(i2d_ECPrivateKey), + output); +} + +bool ECPrivateKey::ExportECParams(std::vector* output) { + OpenSSLErrStackTracer err_tracer(FROM_HERE); + ScopedEC_KEY ec_key(EVP_PKEY_get1_EC_KEY(key_)); + return ExportKey(ec_key.get(), + reinterpret_cast(i2d_ECParameters), + output); +} + +ECPrivateKey::ECPrivateKey() : key_(NULL) {} + +} // namespace crypto diff --git a/crypto/ec_private_key_unittest.cc b/crypto/ec_private_key_unittest.cc new file mode 100644 index 0000000000000..cfd08f2d92b57 --- /dev/null +++ b/crypto/ec_private_key_unittest.cc @@ -0,0 +1,294 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/ec_private_key.h" + +#include + +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "testing/gtest/include/gtest/gtest.h" + +// Generate random private keys. Export, then re-import. We should get +// back the same exact public key, and the private key should have the same +// value and elliptic curve params. +TEST(ECPrivateKeyUnitTest, InitRandomTest) { + const std::string password1; + const std::string password2 = "test"; + + scoped_ptr keypair1(crypto::ECPrivateKey::Create()); + scoped_ptr keypair2(crypto::ECPrivateKey::Create()); + ASSERT_TRUE(keypair1.get()); + ASSERT_TRUE(keypair2.get()); + + std::vector key1value; + std::vector key2value; + std::vector key1params; + std::vector key2params; + EXPECT_TRUE(keypair1->ExportValue(&key1value)); + EXPECT_TRUE(keypair2->ExportValue(&key2value)); + EXPECT_TRUE(keypair1->ExportECParams(&key1params)); + EXPECT_TRUE(keypair2->ExportECParams(&key2params)); + + std::vector privkey1; + std::vector privkey2; + std::vector pubkey1; + std::vector pubkey2; + std::string raw_pubkey1; + std::string raw_pubkey2; + ASSERT_TRUE(keypair1->ExportEncryptedPrivateKey(password1, 1, &privkey1)); + ASSERT_TRUE(keypair2->ExportEncryptedPrivateKey(password2, 1, &privkey2)); + EXPECT_TRUE(keypair1->ExportPublicKey(&pubkey1)); + EXPECT_TRUE(keypair2->ExportPublicKey(&pubkey2)); + EXPECT_TRUE(keypair1->ExportRawPublicKey(&raw_pubkey1)); + EXPECT_TRUE(keypair2->ExportRawPublicKey(&raw_pubkey2)); + + scoped_ptr keypair3( + crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( + password1, privkey1, pubkey1)); + scoped_ptr keypair4( + crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( + password2, privkey2, pubkey2)); + ASSERT_TRUE(keypair3.get()); + ASSERT_TRUE(keypair4.get()); + + std::vector key3value; + std::vector key4value; + std::vector key3params; + std::vector key4params; + EXPECT_TRUE(keypair3->ExportValue(&key3value)); + EXPECT_TRUE(keypair4->ExportValue(&key4value)); + EXPECT_TRUE(keypair3->ExportECParams(&key3params)); + EXPECT_TRUE(keypair4->ExportECParams(&key4params)); + + EXPECT_EQ(key1value, key3value); + EXPECT_EQ(key2value, key4value); + EXPECT_EQ(key1params, key3params); + EXPECT_EQ(key2params, key4params); + + std::vector pubkey3; + std::vector pubkey4; + std::string raw_pubkey3; + std::string raw_pubkey4; + EXPECT_TRUE(keypair3->ExportPublicKey(&pubkey3)); + EXPECT_TRUE(keypair4->ExportPublicKey(&pubkey4)); + EXPECT_TRUE(keypair3->ExportRawPublicKey(&raw_pubkey3)); + EXPECT_TRUE(keypair4->ExportRawPublicKey(&raw_pubkey4)); + + EXPECT_EQ(pubkey1, pubkey3); + EXPECT_EQ(pubkey2, pubkey4); + EXPECT_EQ(raw_pubkey1, raw_pubkey3); + EXPECT_EQ(raw_pubkey2, raw_pubkey4); +} + +TEST(ECPrivateKeyUnitTest, Copy) { + scoped_ptr keypair1(crypto::ECPrivateKey::Create()); + scoped_ptr keypair2(keypair1->Copy()); + ASSERT_TRUE(keypair1.get()); + ASSERT_TRUE(keypair2.get()); + + std::vector key1value; + std::vector key2value; + EXPECT_TRUE(keypair1->ExportValue(&key1value)); + EXPECT_TRUE(keypair2->ExportValue(&key2value)); + EXPECT_EQ(key1value, key2value); + + std::vector key1params; + std::vector key2params; + EXPECT_TRUE(keypair1->ExportECParams(&key1params)); + EXPECT_TRUE(keypair2->ExportECParams(&key2params)); + EXPECT_EQ(key1params, key2params); + + std::vector pubkey1; + std::vector pubkey2; + EXPECT_TRUE(keypair1->ExportPublicKey(&pubkey1)); + EXPECT_TRUE(keypair2->ExportPublicKey(&pubkey2)); + EXPECT_EQ(pubkey1, pubkey2); + + std::string raw_pubkey1; + std::string raw_pubkey2; + EXPECT_TRUE(keypair1->ExportRawPublicKey(&raw_pubkey1)); + EXPECT_TRUE(keypair2->ExportRawPublicKey(&raw_pubkey2)); + EXPECT_EQ(raw_pubkey1, raw_pubkey2); +} + +TEST(ECPrivateKeyUnitTest, BadPasswordTest) { + const std::string password1; + const std::string password2 = "test"; + + scoped_ptr keypair1( + crypto::ECPrivateKey::Create()); + ASSERT_TRUE(keypair1.get()); + + std::vector privkey1; + std::vector pubkey1; + ASSERT_TRUE(keypair1->ExportEncryptedPrivateKey( + password1, 1, &privkey1)); + ASSERT_TRUE(keypair1->ExportPublicKey(&pubkey1)); + + scoped_ptr keypair2( + crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( + password2, privkey1, pubkey1)); + ASSERT_FALSE(keypair2.get()); +} + +TEST(ECPrivateKeyUnitTest, LoadNSSKeyTest) { + static const unsigned char nss_key[] = { + 0x30, 0x81, 0xb8, 0x30, 0x23, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x0c, 0x01, 0x03, 0x30, 0x15, 0x04, 0x10, 0x3f, 0xac, 0xe9, + 0x38, 0xdb, 0x40, 0x6b, 0x26, 0x89, 0x09, 0x73, 0x18, 0x8d, 0x7f, 0x1c, + 0x82, 0x02, 0x01, 0x01, 0x04, 0x81, 0x90, 0x5e, 0x5e, 0x11, 0xef, 0xbb, + 0x7c, 0x4d, 0xec, 0xc0, 0xdc, 0xc7, 0x23, 0xd2, 0xc4, 0x77, 0xbc, 0xf4, + 0x5d, 0x59, 0x4c, 0x07, 0xc2, 0x8a, 0x26, 0xfa, 0x25, 0x1c, 0xaa, 0x42, + 0xed, 0xd0, 0xed, 0xbb, 0x5c, 0xe9, 0x13, 0x07, 0xaa, 0xdd, 0x52, 0x3c, + 0x65, 0x25, 0xbf, 0x94, 0x02, 0xaf, 0xd6, 0x97, 0xe9, 0x33, 0x00, 0x76, + 0x64, 0x4a, 0x73, 0xab, 0xfb, 0x99, 0x6e, 0x83, 0x12, 0x05, 0x86, 0x72, + 0x6c, 0xd5, 0xa4, 0xcf, 0xb1, 0xd5, 0x4d, 0x54, 0x87, 0x8b, 0x4b, 0x95, + 0x1d, 0xcd, 0xf3, 0xfe, 0xa8, 0xda, 0xe0, 0xb6, 0x72, 0x13, 0x3f, 0x2e, + 0x66, 0xe0, 0xb9, 0x2e, 0xfa, 0x69, 0x40, 0xbe, 0xd7, 0x67, 0x6e, 0x53, + 0x2b, 0x3f, 0x53, 0xe5, 0x39, 0x54, 0x77, 0xe1, 0x1d, 0xe6, 0x81, 0x92, + 0x58, 0x82, 0x14, 0xfb, 0x47, 0x85, 0x3c, 0xc3, 0xdf, 0xdd, 0xcc, 0x79, + 0x9f, 0x41, 0x83, 0x72, 0xf2, 0x0a, 0xe9, 0xe1, 0x2c, 0x12, 0xb0, 0xb0, + 0x0a, 0xb2, 0x1d, 0xca, 0x15, 0xb2, 0xca}; + static const unsigned char nss_pub_key[] = { + 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, + 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, + 0x42, 0x00, 0x04, 0x85, 0x92, 0x9e, 0x95, 0x5c, 0x6b, 0x9e, 0xd6, 0x1e, + 0xb8, 0x64, 0xea, 0xc2, 0xb3, 0xef, 0x18, 0xed, 0x3a, 0x5e, 0xc4, 0x5c, + 0x15, 0x37, 0x6a, 0xe9, 0xaa, 0x0b, 0x34, 0x03, 0xfd, 0xca, 0x83, 0x0f, + 0xd7, 0x5c, 0x5d, 0xc5, 0x53, 0x6e, 0xe5, 0xa9, 0x33, 0xd5, 0xcc, 0xab, + 0x53, 0x78, 0xdd, 0xd6, 0x12, 0x3a, 0x5e, 0xeb, 0xbf, 0xdf, 0x16, 0xd3, + 0x2c, 0x3b, 0xe8, 0xdb, 0x19, 0xfc, 0x5e}; + + scoped_ptr keypair_nss( + crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( + "", + std::vector(nss_key, nss_key + arraysize(nss_key)), + std::vector(nss_pub_key, + nss_pub_key + arraysize(nss_pub_key)))); + + EXPECT_TRUE(keypair_nss.get()); +} + +// Although the plan is to transition from OpenSSL to NSS, ensure NSS can import +// OpenSSL's format so that it is possible to rollback. +TEST(ECPrivateKeyUnitTest, LoadOpenSSLKeyTest) { + static const unsigned char openssl_key[] = { + 0x30, 0x81, 0xb0, 0x30, 0x1b, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x0c, 0x01, 0x03, 0x30, 0x0d, 0x04, 0x08, 0xb2, 0xfe, 0x68, + 0xc2, 0xea, 0x0f, 0x10, 0x9c, 0x02, 0x01, 0x01, 0x04, 0x81, 0x90, 0xe2, + 0xf6, 0x1c, 0xca, 0xad, 0x64, 0x30, 0xbf, 0x88, 0x04, 0x35, 0xe5, 0x0f, + 0x11, 0x49, 0x06, 0x01, 0x14, 0x33, 0x80, 0xa2, 0x78, 0x44, 0x5b, 0xaa, + 0x0d, 0xd7, 0x00, 0x36, 0x9d, 0x91, 0x97, 0x37, 0x20, 0x7b, 0x27, 0xc1, + 0xa0, 0xa2, 0x73, 0x06, 0x15, 0xdf, 0xc8, 0x13, 0x9b, 0xc9, 0x8c, 0x9c, + 0xce, 0x00, 0xd0, 0xc8, 0x42, 0xc1, 0xda, 0x2b, 0x07, 0x2b, 0x12, 0xa3, + 0xce, 0x10, 0x39, 0x7a, 0xf1, 0x55, 0x69, 0x8d, 0xa5, 0xc4, 0x2a, 0x00, + 0x0d, 0x94, 0xc6, 0xde, 0x6a, 0x3d, 0xb7, 0xe5, 0x6d, 0x59, 0x3e, 0x09, + 0xb5, 0xe3, 0x3e, 0xfc, 0x50, 0x56, 0xe9, 0x50, 0x42, 0x7c, 0xe7, 0xf0, + 0x19, 0xbd, 0x31, 0xa7, 0x85, 0x47, 0xb3, 0xe9, 0xb3, 0x50, 0x3c, 0xc9, + 0x32, 0x37, 0x1a, 0x93, 0x78, 0x48, 0x78, 0x82, 0xde, 0xad, 0x5c, 0xf2, + 0xcf, 0xf2, 0xbb, 0x2c, 0x44, 0x05, 0x7f, 0x4a, 0xf9, 0xb1, 0x2b, 0xdd, + 0x49, 0xf6, 0x7e, 0xd0, 0x42, 0xaa, 0x14, 0x3c, 0x24, 0x77, 0xb4}; + static const unsigned char openssl_pub_key[] = { + 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, + 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, + 0x42, 0x00, 0x04, 0xb9, 0xda, 0x0d, 0x71, 0x60, 0xb3, 0x63, 0x28, 0x22, + 0x67, 0xe7, 0xe0, 0xa3, 0xf8, 0x00, 0x8e, 0x4c, 0x89, 0xed, 0x31, 0x34, + 0xf6, 0xdb, 0xc4, 0xfe, 0x0b, 0x5d, 0xe1, 0x11, 0x39, 0x49, 0xa6, 0x50, + 0xa8, 0xe3, 0x4a, 0xc0, 0x40, 0x88, 0xb8, 0x38, 0x3f, 0x56, 0xfb, 0x33, + 0x8d, 0xd4, 0x64, 0x91, 0xd6, 0x15, 0x77, 0x42, 0x27, 0xc5, 0xaa, 0x44, + 0xff, 0xab, 0x4d, 0xb5, 0x7e, 0x25, 0x3d}; + + scoped_ptr keypair_openssl( + crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( + "", + std::vector(openssl_key, openssl_key + arraysize(openssl_key)), + std::vector(openssl_pub_key, + openssl_pub_key + arraysize(openssl_pub_key)))); + + EXPECT_TRUE(keypair_openssl.get()); +} + +// The Android code writes out Channel IDs differently from the NSS +// implementation; the empty password is converted to "\0\0". The OpenSSL port +// should support either. +#if defined(USE_OPENSSL) +TEST(ECPrivateKeyUnitTest, LoadOldOpenSSLKeyTest) { + static const unsigned char openssl_key[] = { + 0x30, 0x82, 0x01, 0xa1, 0x30, 0x1b, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x0c, 0x01, 0x03, 0x30, 0x0d, 0x04, 0x08, 0x86, 0xaa, + 0xd7, 0xdf, 0x3b, 0x91, 0x97, 0x60, 0x02, 0x01, 0x01, 0x04, 0x82, 0x01, + 0x80, 0xcb, 0x2a, 0x14, 0xaa, 0x4f, 0x38, 0x4c, 0xe1, 0x49, 0x00, 0xe2, + 0x1a, 0x3a, 0x75, 0x87, 0x7e, 0x3d, 0xea, 0x4d, 0x53, 0xd4, 0x46, 0x47, + 0x23, 0x8f, 0xa1, 0x72, 0x51, 0x92, 0x86, 0x8b, 0xeb, 0x53, 0xe6, 0x6a, + 0x0a, 0x6b, 0xb6, 0xa0, 0xdc, 0x0f, 0xdc, 0x20, 0xc3, 0x45, 0x85, 0xf1, + 0x95, 0x90, 0x5c, 0xf4, 0xfa, 0xee, 0x47, 0xaf, 0x35, 0xd0, 0xd0, 0xd3, + 0x14, 0xde, 0x0d, 0xca, 0x1b, 0xd3, 0xbb, 0x20, 0xec, 0x9d, 0x6a, 0xd4, + 0xc1, 0xce, 0x60, 0x81, 0xab, 0x0c, 0x72, 0x10, 0xfa, 0x28, 0x3c, 0xac, + 0x87, 0x7b, 0x82, 0x85, 0x00, 0xb8, 0x58, 0x9c, 0x07, 0xc4, 0x7d, 0xa9, + 0xc5, 0x94, 0x95, 0xf7, 0x23, 0x93, 0x3f, 0xed, 0xef, 0x92, 0x55, 0x25, + 0x74, 0xbb, 0xd3, 0xd1, 0x67, 0x3b, 0x3d, 0x5a, 0xfe, 0x84, 0xf8, 0x97, + 0x7d, 0x7c, 0x01, 0xc7, 0xd7, 0x0d, 0xf8, 0xc3, 0x6d, 0xd6, 0xf1, 0xaa, + 0x9d, 0x1f, 0x69, 0x97, 0x45, 0x06, 0xc4, 0x1c, 0x95, 0x3c, 0xe0, 0xef, + 0x11, 0xb2, 0xb3, 0x72, 0x91, 0x9e, 0x7d, 0x0f, 0x7f, 0xc8, 0xf6, 0x64, + 0x49, 0x5e, 0x3c, 0x53, 0x37, 0x79, 0x03, 0x1c, 0x3f, 0x29, 0x6c, 0x6b, + 0xea, 0x4c, 0x35, 0x9b, 0x6d, 0x1b, 0x59, 0x43, 0x4c, 0x14, 0x47, 0x2a, + 0x36, 0x39, 0x2a, 0xd8, 0x96, 0x90, 0xdc, 0xfc, 0xd2, 0xdd, 0x23, 0x0e, + 0x2c, 0xb3, 0x83, 0xf9, 0xf2, 0xe3, 0xe6, 0x99, 0x53, 0x57, 0x33, 0xc5, + 0x5f, 0xf9, 0xfd, 0x56, 0x0b, 0x32, 0xd4, 0xf3, 0x9d, 0x5b, 0x34, 0xe5, + 0x94, 0xbf, 0xb6, 0xc0, 0xce, 0xe1, 0x73, 0x5c, 0x02, 0x7a, 0x4c, 0xed, + 0xde, 0x23, 0x38, 0x89, 0x9f, 0xcd, 0x51, 0xf3, 0x90, 0x80, 0xd3, 0x4b, + 0x83, 0xd3, 0xee, 0xf2, 0x9e, 0x35, 0x91, 0xa5, 0xa3, 0xc0, 0x5c, 0xce, + 0xdb, 0xaa, 0x70, 0x1e, 0x1d, 0xc1, 0x44, 0xea, 0x3b, 0xa7, 0x5a, 0x11, + 0xd1, 0xf3, 0xf3, 0xd0, 0xf4, 0x5a, 0xc4, 0x99, 0xaf, 0x8d, 0xe2, 0xbc, + 0xa2, 0xb9, 0x3d, 0x86, 0x5e, 0xba, 0xa0, 0xdf, 0x78, 0x81, 0x7c, 0x54, + 0x31, 0xe3, 0x98, 0xb5, 0x46, 0xcb, 0x4d, 0x26, 0x4b, 0xf8, 0xac, 0x3a, + 0x54, 0x1b, 0x77, 0x5a, 0x18, 0xa5, 0x43, 0x0e, 0x14, 0xde, 0x7b, 0xb7, + 0x4e, 0x45, 0x99, 0x03, 0xd1, 0x3d, 0x18, 0xb2, 0x36, 0x00, 0x48, 0x07, + 0x72, 0xbb, 0x4f, 0x21, 0x25, 0x3e, 0xda, 0x25, 0x24, 0x5b, 0xc8, 0xa0, + 0x28, 0xd5, 0x9b, 0x96, 0x87, 0x07, 0x77, 0x84, 0xff, 0xd7, 0xac, 0x71, + 0xf6, 0x61, 0x63, 0x0b, 0xfb, 0x42, 0xfd, 0x52, 0xf4, 0xc4, 0x35, 0x0c, + 0xc2, 0xc1, 0x55, 0x22, 0x42, 0x2f, 0x13, 0x7d, 0x93, 0x27, 0xc8, 0x11, + 0x35, 0xc5, 0xe3, 0xc5, 0xaa, 0x15, 0x3c, 0xac, 0x30, 0xbc, 0x45, 0x16, + 0xed}; + static const unsigned char openssl_pub_key[] = { + 0x30, 0x82, 0x01, 0x4b, 0x30, 0x82, 0x01, 0x03, 0x06, 0x07, 0x2a, 0x86, + 0x48, 0xce, 0x3d, 0x02, 0x01, 0x30, 0x81, 0xf7, 0x02, 0x01, 0x01, 0x30, + 0x2c, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01, 0x01, 0x02, 0x21, + 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x30, 0x5b, 0x04, + 0x20, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x04, 0x20, 0x5a, + 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb, 0xbd, 0x55, 0x76, + 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53, 0xb0, 0xf6, 0x3b, + 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b, 0x03, 0x15, 0x00, 0xc4, 0x9d, + 0x36, 0x08, 0x86, 0xe7, 0x04, 0x93, 0x6a, 0x66, 0x78, 0xe1, 0x13, 0x9d, + 0x26, 0xb7, 0x81, 0x9f, 0x7e, 0x90, 0x04, 0x41, 0x04, 0x6b, 0x17, 0xd1, + 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5, 0x63, 0xa4, 0x40, + 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0, 0xf4, 0xa1, 0x39, + 0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, + 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, + 0x57, 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, + 0xf5, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc, 0xe6, 0xfa, 0xad, + 0xa7, 0x17, 0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc, 0x63, 0x25, 0x51, + 0x02, 0x01, 0x01, 0x03, 0x42, 0x00, 0x04, 0xde, 0x09, 0x08, 0x07, 0x03, + 0x2e, 0x8f, 0x37, 0x9a, 0xd5, 0xad, 0xe5, 0xc6, 0x9d, 0xd4, 0x63, 0xc7, + 0x4a, 0xe7, 0x20, 0xcb, 0x90, 0xa0, 0x1f, 0x18, 0x18, 0x72, 0xb5, 0x21, + 0x88, 0x38, 0xc0, 0xdb, 0xba, 0xf6, 0x99, 0xd8, 0xa5, 0x3b, 0x83, 0xe9, + 0xe3, 0xd5, 0x61, 0x99, 0x73, 0x42, 0xc6, 0x6c, 0xe8, 0x0a, 0x95, 0x40, + 0x41, 0x3b, 0x0d, 0x10, 0xa7, 0x4a, 0x93, 0xdb, 0x5a, 0xe7, 0xec}; + + scoped_ptr keypair_openssl( + crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( + "", + std::vector(openssl_key, openssl_key + arraysize(openssl_key)), + std::vector(openssl_pub_key, + openssl_pub_key + arraysize(openssl_pub_key)))); + + EXPECT_TRUE(keypair_openssl.get()); +} +#endif // defined(USE_OPENSSL) diff --git a/crypto/ec_signature_creator.cc b/crypto/ec_signature_creator.cc new file mode 100644 index 0000000000000..a6887bc117b7f --- /dev/null +++ b/crypto/ec_signature_creator.cc @@ -0,0 +1,34 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/ec_signature_creator.h" + +#include "base/logging.h" +#include "crypto/ec_signature_creator_impl.h" + +namespace crypto { + +namespace { + +ECSignatureCreatorFactory* g_factory_ = NULL; + +} // namespace + +// static +ECSignatureCreator* ECSignatureCreator::Create(ECPrivateKey* key) { + if (g_factory_) + return g_factory_->Create(key); + return new ECSignatureCreatorImpl(key); +} + +// static +void ECSignatureCreator::SetFactoryForTesting( + ECSignatureCreatorFactory* factory) { + // We should always clear the factory after each test to avoid + // use-after-free problems. + DCHECK(!g_factory_ || !factory); + g_factory_ = factory; +} + +} // namespace crypto diff --git a/crypto/ec_signature_creator.h b/crypto/ec_signature_creator.h new file mode 100644 index 0000000000000..16e64f5753cb8 --- /dev/null +++ b/crypto/ec_signature_creator.h @@ -0,0 +1,66 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CRYPTO_EC_SIGNATURE_CREATOR_H_ +#define CRYPTO_EC_SIGNATURE_CREATOR_H_ + +#include +#include + +#include "base/basictypes.h" +#include "crypto/crypto_export.h" + +namespace crypto { + +class ECPrivateKey; +class ECSignatureCreator; + +class CRYPTO_EXPORT ECSignatureCreatorFactory { + public: + virtual ~ECSignatureCreatorFactory() {} + + virtual ECSignatureCreator* Create(ECPrivateKey* key) = 0; +}; + +// Signs data using a bare private key (as opposed to a full certificate). +// We need this class because SignatureCreator is hardcoded to use +// RSAPrivateKey. +class CRYPTO_EXPORT ECSignatureCreator { + public: + virtual ~ECSignatureCreator() {} + + // Create an instance. The caller must ensure that the provided PrivateKey + // instance outlives the created ECSignatureCreator. + // TODO(rch): This is currently hard coded to use SHA256. Ideally, we should + // pass in the hash algorithm identifier. + static ECSignatureCreator* Create(ECPrivateKey* key); + + // Set a factory to make the Create function return non-standard + // ECSignatureCreator objects. Because the ECDSA algorithm involves + // randomness, this is useful for higher-level tests that want to have + // deterministic mocked output to compare. + static void SetFactoryForTesting(ECSignatureCreatorFactory* factory); + + // Signs |data_len| bytes from |data| and writes the results into + // |signature| as a DER encoded ECDSA-Sig-Value from RFC 3279. + // + // ECDSA-Sig-Value ::= SEQUENCE { + // r INTEGER, + // s INTEGER } + virtual bool Sign(const uint8* data, + int data_len, + std::vector* signature) = 0; + + // DecodeSignature converts from a DER encoded ECDSA-Sig-Value (as produced + // by Sign) to a `raw' ECDSA signature which consists of a pair of + // big-endian, zero-padded, 256-bit integers, r and s. On success it returns + // true and puts the raw signature into |out_raw_sig|. + // (Only P-256 signatures are supported.) + virtual bool DecodeSignature(const std::vector& signature, + std::vector* out_raw_sig) = 0; +}; + +} // namespace crypto + +#endif // CRYPTO_EC_SIGNATURE_CREATOR_H_ diff --git a/crypto/ec_signature_creator_impl.h b/crypto/ec_signature_creator_impl.h new file mode 100644 index 0000000000000..91a60a89963d7 --- /dev/null +++ b/crypto/ec_signature_creator_impl.h @@ -0,0 +1,34 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CRYPTO_EC_SIGNATURE_CREATOR_IMPL_H_ +#define CRYPTO_EC_SIGNATURE_CREATOR_IMPL_H_ + +#include "base/compiler_specific.h" +#include "crypto/ec_signature_creator.h" + +namespace crypto { + +class ECSignatureCreatorImpl : public ECSignatureCreator { + public: + explicit ECSignatureCreatorImpl(ECPrivateKey* key); + ~ECSignatureCreatorImpl() override; + + bool Sign(const uint8* data, + int data_len, + std::vector* signature) override; + + bool DecodeSignature(const std::vector& der_sig, + std::vector* out_raw_sig) override; + + private: + ECPrivateKey* key_; + size_t signature_len_; + + DISALLOW_COPY_AND_ASSIGN(ECSignatureCreatorImpl); +}; + +} // namespace crypto + +#endif // CRYPTO_EC_SIGNATURE_CREATOR_IMPL_H_ diff --git a/crypto/ec_signature_creator_nss.cc b/crypto/ec_signature_creator_nss.cc new file mode 100644 index 0000000000000..3e3626f449982 --- /dev/null +++ b/crypto/ec_signature_creator_nss.cc @@ -0,0 +1,114 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/ec_signature_creator_impl.h" + +#include +#include +#include +#include +#if defined(OS_POSIX) +#include +#endif + +#include "base/logging.h" +#include "crypto/ec_private_key.h" +#include "crypto/nss_util.h" +#include "crypto/scoped_nss_types.h" + +namespace crypto { + +namespace { + +SECStatus SignData(SECItem* result, + SECItem* input, + SECKEYPrivateKey* key, + HASH_HashType hash_type, + size_t* out_signature_len) { + if (key->keyType != ecKey) { + DLOG(FATAL) << "Should be using an EC key."; + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + // Hash the input. + std::vector hash_data(HASH_ResultLen(hash_type)); + SECStatus rv = HASH_HashBuf( + hash_type, &hash_data[0], input->data, input->len); + if (rv != SECSuccess) + return rv; + SECItem hash = {siBuffer, &hash_data[0], + static_cast(hash_data.size())}; + + // Compute signature of hash. + int signature_len = PK11_SignatureLen(key); + std::vector signature_data(signature_len); + SECItem sig = {siBuffer, &signature_data[0], + static_cast(signature_len)}; + rv = PK11_Sign(key, &sig, &hash); + if (rv != SECSuccess) + return rv; + + *out_signature_len = sig.len; + + // DER encode the signature. + return DSAU_EncodeDerSigWithLen(result, &sig, sig.len); +} + +} // namespace + +ECSignatureCreatorImpl::ECSignatureCreatorImpl(ECPrivateKey* key) + : key_(key), + signature_len_(0) { + EnsureNSSInit(); +} + +ECSignatureCreatorImpl::~ECSignatureCreatorImpl() {} + +bool ECSignatureCreatorImpl::Sign(const uint8* data, + int data_len, + std::vector* signature) { + // Data to be signed + SECItem secret; + secret.type = siBuffer; + secret.len = data_len; + secret.data = const_cast(data); + + // SECItem to receive the output buffer. + SECItem result; + result.type = siBuffer; + result.len = 0; + result.data = NULL; + + // Sign the secret data and save it to |result|. + SECStatus rv = + SignData(&result, &secret, key_->key(), HASH_AlgSHA256, &signature_len_); + if (rv != SECSuccess) { + DLOG(ERROR) << "DerSignData: " << PORT_GetError(); + return false; + } + + // Copy the signed data into the output vector. + signature->assign(result.data, result.data + result.len); + SECITEM_FreeItem(&result, PR_FALSE /* only free |result.data| */); + return true; +} + +bool ECSignatureCreatorImpl::DecodeSignature( + const std::vector& der_sig, + std::vector* out_raw_sig) { + SECItem der_sig_item; + der_sig_item.type = siBuffer; + der_sig_item.len = der_sig.size(); + der_sig_item.data = const_cast(&der_sig[0]); + + SECItem* raw_sig = DSAU_DecodeDerSigToLen(&der_sig_item, signature_len_); + if (!raw_sig) + return false; + out_raw_sig->assign(raw_sig->data, raw_sig->data + raw_sig->len); + SECITEM_FreeItem(raw_sig, PR_TRUE /* free SECItem structure itself. */); + return true; +} + +} // namespace crypto diff --git a/crypto/ec_signature_creator_openssl.cc b/crypto/ec_signature_creator_openssl.cc new file mode 100644 index 0000000000000..c422cef5f275a --- /dev/null +++ b/crypto/ec_signature_creator_openssl.cc @@ -0,0 +1,74 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/ec_signature_creator_impl.h" + +#include +#include +#include +#include +#include + +#include "base/logging.h" +#include "crypto/ec_private_key.h" +#include "crypto/openssl_util.h" +#include "crypto/scoped_openssl_types.h" + +namespace crypto { + +ECSignatureCreatorImpl::ECSignatureCreatorImpl(ECPrivateKey* key) + : key_(key), signature_len_(0) { + EnsureOpenSSLInit(); +} + +ECSignatureCreatorImpl::~ECSignatureCreatorImpl() {} + +bool ECSignatureCreatorImpl::Sign(const uint8* data, + int data_len, + std::vector* signature) { + OpenSSLErrStackTracer err_tracer(FROM_HERE); + ScopedEVP_MD_CTX ctx(EVP_MD_CTX_create()); + size_t sig_len = 0; + if (!ctx.get() || + !EVP_DigestSignInit(ctx.get(), NULL, EVP_sha256(), NULL, key_->key()) || + !EVP_DigestSignUpdate(ctx.get(), data, data_len) || + !EVP_DigestSignFinal(ctx.get(), NULL, &sig_len)) { + return false; + } + + signature->resize(sig_len); + if (!EVP_DigestSignFinal(ctx.get(), &signature->front(), &sig_len)) + return false; + + // NOTE: A call to EVP_DigestSignFinal() with a NULL second parameter returns + // a maximum allocation size, while the call without a NULL returns the real + // one, which may be smaller. + signature->resize(sig_len); + return true; +} + +bool ECSignatureCreatorImpl::DecodeSignature(const std::vector& der_sig, + std::vector* out_raw_sig) { + OpenSSLErrStackTracer err_tracer(FROM_HERE); + // Create ECDSA_SIG object from DER-encoded data. + const unsigned char* der_data = &der_sig.front(); + ScopedECDSA_SIG ecdsa_sig( + d2i_ECDSA_SIG(NULL, &der_data, static_cast(der_sig.size()))); + if (!ecdsa_sig.get()) + return false; + + // The result is made of two 32-byte vectors. + const size_t kMaxBytesPerBN = 32; + std::vector result(2 * kMaxBytesPerBN); + + if (!BN_bn2bin_padded(&result[0], kMaxBytesPerBN, ecdsa_sig->r) || + !BN_bn2bin_padded(&result[kMaxBytesPerBN], kMaxBytesPerBN, + ecdsa_sig->s)) { + return false; + } + out_raw_sig->swap(result); + return true; +} + +} // namespace crypto diff --git a/crypto/ec_signature_creator_unittest.cc b/crypto/ec_signature_creator_unittest.cc new file mode 100644 index 0000000000000..2a40cfe0c12a4 --- /dev/null +++ b/crypto/ec_signature_creator_unittest.cc @@ -0,0 +1,75 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/ec_signature_creator.h" + +#include +#include + +#include "base/memory/scoped_ptr.h" +#include "crypto/ec_private_key.h" +#include "crypto/signature_verifier.h" +#include "testing/gtest/include/gtest/gtest.h" + +// TODO(rch): Add some exported keys from each to +// test interop between NSS and OpenSSL. + +TEST(ECSignatureCreatorTest, BasicTest) { + // Do a verify round trip. + scoped_ptr key_original( + crypto::ECPrivateKey::Create()); + ASSERT_TRUE(key_original.get()); + + std::vector key_info; + ASSERT_TRUE( + key_original->ExportEncryptedPrivateKey(std::string(), 1000, &key_info)); + std::vector pubkey_info; + ASSERT_TRUE(key_original->ExportPublicKey(&pubkey_info)); + + scoped_ptr key( + crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( + std::string(), key_info, pubkey_info)); + ASSERT_TRUE(key.get()); + ASSERT_TRUE(key->key() != NULL); + + scoped_ptr signer( + crypto::ECSignatureCreator::Create(key.get())); + ASSERT_TRUE(signer.get()); + + std::string data("Hello, World!"); + std::vector signature; + ASSERT_TRUE(signer->Sign(reinterpret_cast(data.c_str()), + data.size(), + &signature)); + + std::vector public_key_info; + ASSERT_TRUE(key_original->ExportPublicKey(&public_key_info)); + + // This is the algorithm ID for ECDSA with SHA-256. Parameters are ABSENT. + // RFC 5758: + // ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { iso(1) member-body(2) + // us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 2 } + // ... + // When the ecdsa-with-SHA224, ecdsa-with-SHA256, ecdsa-with-SHA384, or + // ecdsa-with-SHA512 algorithm identifier appears in the algorithm field + // as an AlgorithmIdentifier, the encoding MUST omit the parameters + // field. That is, the AlgorithmIdentifier SHALL be a SEQUENCE of one + // component, the OID ecdsa-with-SHA224, ecdsa-with-SHA256, ecdsa-with- + // SHA384, or ecdsa-with-SHA512. + // See also RFC 5480, Appendix A. + const uint8 kECDSAWithSHA256AlgorithmID[] = { + 0x30, 0x0a, + 0x06, 0x08, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, + }; + crypto::SignatureVerifier verifier; + ASSERT_TRUE(verifier.VerifyInit( + kECDSAWithSHA256AlgorithmID, sizeof(kECDSAWithSHA256AlgorithmID), + &signature[0], signature.size(), + &public_key_info.front(), public_key_info.size())); + + verifier.VerifyUpdate(reinterpret_cast(data.c_str()), + data.size()); + ASSERT_TRUE(verifier.VerifyFinal()); +} diff --git a/crypto/encryptor.cc b/crypto/encryptor.cc new file mode 100644 index 0000000000000..a673f81c1781d --- /dev/null +++ b/crypto/encryptor.cc @@ -0,0 +1,97 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/encryptor.h" + +#include "base/logging.h" +#include "base/sys_byteorder.h" + +namespace crypto { + +///////////////////////////////////////////////////////////////////////////// +// Encyptor::Counter Implementation. +Encryptor::Counter::Counter(const base::StringPiece& counter) { + CHECK(sizeof(counter_) == counter.length()); + + memcpy(&counter_, counter.data(), sizeof(counter_)); +} + +Encryptor::Counter::~Counter() { +} + +bool Encryptor::Counter::Increment() { + uint64 low_num = base::NetToHost64(counter_.components64[1]); + uint64 new_low_num = low_num + 1; + counter_.components64[1] = base::HostToNet64(new_low_num); + + // If overflow occured then increment the most significant component. + if (new_low_num < low_num) { + counter_.components64[0] = + base::HostToNet64(base::NetToHost64(counter_.components64[0]) + 1); + } + + // TODO(hclam): Return false if counter value overflows. + return true; +} + +void Encryptor::Counter::Write(void* buf) { + uint8* buf_ptr = reinterpret_cast(buf); + memcpy(buf_ptr, &counter_, sizeof(counter_)); +} + +size_t Encryptor::Counter::GetLengthInBytes() const { + return sizeof(counter_); +} + +///////////////////////////////////////////////////////////////////////////// +// Partial Encryptor Implementation. + +bool Encryptor::SetCounter(const base::StringPiece& counter) { + if (mode_ != CTR) + return false; + if (counter.length() != 16u) + return false; + + counter_.reset(new Counter(counter)); + return true; +} + +bool Encryptor::GenerateCounterMask(size_t plaintext_len, + uint8* mask, + size_t* mask_len) { + DCHECK_EQ(CTR, mode_); + CHECK(mask); + CHECK(mask_len); + + const size_t kBlockLength = counter_->GetLengthInBytes(); + size_t blocks = (plaintext_len + kBlockLength - 1) / kBlockLength; + CHECK(blocks); + + *mask_len = blocks * kBlockLength; + + for (size_t i = 0; i < blocks; ++i) { + counter_->Write(mask); + mask += kBlockLength; + + bool ret = counter_->Increment(); + if (!ret) + return false; + } + return true; +} + +void Encryptor::MaskMessage(const void* plaintext, + size_t plaintext_len, + const void* mask, + void* ciphertext) const { + DCHECK_EQ(CTR, mode_); + const uint8* plaintext_ptr = reinterpret_cast(plaintext); + const uint8* mask_ptr = reinterpret_cast(mask); + uint8* ciphertext_ptr = reinterpret_cast(ciphertext); + + for (size_t i = 0; i < plaintext_len; ++i) + ciphertext_ptr[i] = plaintext_ptr[i] ^ mask_ptr[i]; +} + +} // namespace crypto diff --git a/crypto/encryptor.h b/crypto/encryptor.h new file mode 100644 index 0000000000000..8052a9fd5744f --- /dev/null +++ b/crypto/encryptor.h @@ -0,0 +1,138 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CRYPTO_ENCRYPTOR_H_ +#define CRYPTO_ENCRYPTOR_H_ + +#include + +#include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" +#include "base/strings/string_piece.h" +#include "build/build_config.h" +#include "crypto/crypto_export.h" + +#if defined(USE_NSS_CERTS) || \ + (!defined(USE_OPENSSL) && (defined(OS_WIN) || defined(OS_MACOSX))) +#include "crypto/scoped_nss_types.h" +#endif + +namespace crypto { + +class SymmetricKey; + +class CRYPTO_EXPORT Encryptor { + public: + enum Mode { + CBC, + CTR, + }; + + // This class implements a 128-bits counter to be used in AES-CTR encryption. + // Only 128-bits counter is supported in this class. + class CRYPTO_EXPORT Counter { + public: + explicit Counter(const base::StringPiece& counter); + ~Counter(); + + // Increment the counter value. + bool Increment(); + + // Write the content of the counter to |buf|. |buf| should have enough + // space for |GetLengthInBytes()|. + void Write(void* buf); + + // Return the length of this counter. + size_t GetLengthInBytes() const; + + private: + union { + uint32 components32[4]; + uint64 components64[2]; + } counter_; + }; + + Encryptor(); + virtual ~Encryptor(); + + // Initializes the encryptor using |key| and |iv|. Returns false if either the + // key or the initialization vector cannot be used. + // + // If |mode| is CBC, |iv| must not be empty; if it is CTR, then |iv| must be + // empty. + bool Init(SymmetricKey* key, Mode mode, const base::StringPiece& iv); + + // Encrypts |plaintext| into |ciphertext|. |plaintext| may only be empty if + // the mode is CBC. + bool Encrypt(const base::StringPiece& plaintext, std::string* ciphertext); + + // Decrypts |ciphertext| into |plaintext|. |ciphertext| must not be empty. + // + // WARNING: In CBC mode, Decrypt() returns false if it detects the padding + // in the decrypted plaintext is wrong. Padding errors can result from + // tampered ciphertext or a wrong decryption key. But successful decryption + // does not imply the authenticity of the data. The caller of Decrypt() + // must either authenticate the ciphertext before decrypting it, or take + // care to not report decryption failure. Otherwise it could inadvertently + // be used as a padding oracle to attack the cryptosystem. + bool Decrypt(const base::StringPiece& ciphertext, std::string* plaintext); + + // Sets the counter value when in CTR mode. Currently only 128-bits + // counter value is supported. + // + // Returns true only if update was successful. + bool SetCounter(const base::StringPiece& counter); + + // TODO(albertb): Support streaming encryption. + + private: + // Generates a mask using |counter_| to be used for encryption in CTR mode. + // Resulting mask will be written to |mask| with |mask_len| bytes. + // + // Make sure there's enough space in mask when calling this method. + // Reserve at least |plaintext_len| + 16 bytes for |mask|. + // + // The generated mask will always have at least |plaintext_len| bytes and + // will be a multiple of the counter length. + // + // This method is used only in CTR mode. + // + // Returns false if this call failed. + bool GenerateCounterMask(size_t plaintext_len, + uint8* mask, + size_t* mask_len); + + // Mask the |plaintext| message using |mask|. The output will be written to + // |ciphertext|. |ciphertext| must have at least |plaintext_len| bytes. + void MaskMessage(const void* plaintext, + size_t plaintext_len, + const void* mask, + void* ciphertext) const; + + SymmetricKey* key_; + Mode mode_; + scoped_ptr counter_; + +#if defined(USE_OPENSSL) + bool Crypt(bool do_encrypt, // Pass true to encrypt, false to decrypt. + const base::StringPiece& input, + std::string* output); + bool CryptCTR(bool do_encrypt, + const base::StringPiece& input, + std::string* output); + std::string iv_; +#elif defined(USE_NSS_CERTS) || defined(OS_WIN) || defined(OS_MACOSX) + bool Crypt(PK11Context* context, + const base::StringPiece& input, + std::string* output); + bool CryptCTR(PK11Context* context, + const base::StringPiece& input, + std::string* output); + ScopedSECItem param_; +#endif +}; + +} // namespace crypto + +#endif // CRYPTO_ENCRYPTOR_H_ diff --git a/crypto/encryptor_nss.cc b/crypto/encryptor_nss.cc new file mode 100644 index 0000000000000..ca5d5239a2a96 --- /dev/null +++ b/crypto/encryptor_nss.cc @@ -0,0 +1,202 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/encryptor.h" + +#include +#include + +#include "base/logging.h" +#include "crypto/nss_util.h" +#include "crypto/symmetric_key.h" + +namespace crypto { + +namespace { + +inline CK_MECHANISM_TYPE GetMechanism(Encryptor::Mode mode) { + switch (mode) { + case Encryptor::CBC: + return CKM_AES_CBC_PAD; + case Encryptor::CTR: + // AES-CTR encryption uses ECB encryptor as a building block since + // NSS doesn't support CTR encryption mode. + return CKM_AES_ECB; + default: + NOTREACHED() << "Unsupported mode of operation"; + break; + } + return static_cast(-1); +} + +} // namespace + +Encryptor::Encryptor() + : key_(NULL), + mode_(CBC) { + EnsureNSSInit(); +} + +Encryptor::~Encryptor() { +} + +bool Encryptor::Init(SymmetricKey* key, + Mode mode, + const base::StringPiece& iv) { + DCHECK(key); + DCHECK(CBC == mode || CTR == mode) << "Unsupported mode of operation"; + + key_ = key; + mode_ = mode; + + if (mode == CBC && iv.size() != AES_BLOCK_SIZE) + return false; + + switch (mode) { + case CBC: + SECItem iv_item; + iv_item.type = siBuffer; + iv_item.data = reinterpret_cast( + const_cast(iv.data())); + iv_item.len = iv.size(); + + param_.reset(PK11_ParamFromIV(GetMechanism(mode), &iv_item)); + break; + case CTR: + param_.reset(PK11_ParamFromIV(GetMechanism(mode), NULL)); + break; + } + + return param_ != NULL; +} + +bool Encryptor::Encrypt(const base::StringPiece& plaintext, + std::string* ciphertext) { + CHECK(!plaintext.empty() || (mode_ == CBC)); + ScopedPK11Context context(PK11_CreateContextBySymKey(GetMechanism(mode_), + CKA_ENCRYPT, + key_->key(), + param_.get())); + if (!context.get()) + return false; + + return (mode_ == CTR) ? + CryptCTR(context.get(), plaintext, ciphertext) : + Crypt(context.get(), plaintext, ciphertext); +} + +bool Encryptor::Decrypt(const base::StringPiece& ciphertext, + std::string* plaintext) { + CHECK(!ciphertext.empty()); + ScopedPK11Context context(PK11_CreateContextBySymKey( + GetMechanism(mode_), (mode_ == CTR ? CKA_ENCRYPT : CKA_DECRYPT), + key_->key(), param_.get())); + if (!context.get()) + return false; + + if (mode_ == CTR) + return CryptCTR(context.get(), ciphertext, plaintext); + + if (ciphertext.size() % AES_BLOCK_SIZE != 0) { + // Decryption will fail if the input is not a multiple of the block size. + // PK11_CipherOp has a bug where it will do an invalid memory access before + // the start of the input, so avoid calling it. (NSS bug 922780). + plaintext->clear(); + return false; + } + + return Crypt(context.get(), ciphertext, plaintext); +} + +bool Encryptor::Crypt(PK11Context* context, + const base::StringPiece& input, + std::string* output) { + size_t output_len = input.size() + AES_BLOCK_SIZE; + CHECK_GT(output_len, input.size()); + + output->resize(output_len); + uint8* output_data = + reinterpret_cast(const_cast(output->data())); + + int input_len = input.size(); + uint8* input_data = + reinterpret_cast(const_cast(input.data())); + + int op_len; + SECStatus rv = PK11_CipherOp(context, + output_data, + &op_len, + output_len, + input_data, + input_len); + + if (SECSuccess != rv) { + output->clear(); + return false; + } + + unsigned int digest_len; + rv = PK11_DigestFinal(context, + output_data + op_len, + &digest_len, + output_len - op_len); + if (SECSuccess != rv) { + output->clear(); + return false; + } + + output->resize(op_len + digest_len); + return true; +} + +bool Encryptor::CryptCTR(PK11Context* context, + const base::StringPiece& input, + std::string* output) { + if (!counter_.get()) { + LOG(ERROR) << "Counter value not set in CTR mode."; + return false; + } + + size_t output_len = ((input.size() + AES_BLOCK_SIZE - 1) / AES_BLOCK_SIZE) * + AES_BLOCK_SIZE; + CHECK_GE(output_len, input.size()); + output->resize(output_len); + uint8* output_data = + reinterpret_cast(const_cast(output->data())); + + size_t mask_len; + bool ret = GenerateCounterMask(input.size(), output_data, &mask_len); + if (!ret) + return false; + + CHECK_EQ(mask_len, output_len); + int op_len; + SECStatus rv = PK11_CipherOp(context, + output_data, + &op_len, + output_len, + output_data, + mask_len); + if (SECSuccess != rv) + return false; + CHECK_EQ(static_cast(mask_len), op_len); + + unsigned int digest_len; + rv = PK11_DigestFinal(context, + NULL, + &digest_len, + 0); + if (SECSuccess != rv) + return false; + CHECK(!digest_len); + + // Use |output_data| to mask |input|. + MaskMessage( + reinterpret_cast(const_cast(input.data())), + input.length(), output_data, output_data); + output->resize(input.length()); + return true; +} + +} // namespace crypto diff --git a/crypto/encryptor_openssl.cc b/crypto/encryptor_openssl.cc new file mode 100644 index 0000000000000..4f0e51137d76d --- /dev/null +++ b/crypto/encryptor_openssl.cc @@ -0,0 +1,177 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/encryptor.h" + +#include +#include + +#include "base/logging.h" +#include "base/strings/string_util.h" +#include "crypto/openssl_util.h" +#include "crypto/symmetric_key.h" + +namespace crypto { + +namespace { + +const EVP_CIPHER* GetCipherForKey(SymmetricKey* key) { + switch (key->key().length()) { + case 16: return EVP_aes_128_cbc(); + case 32: return EVP_aes_256_cbc(); + default: return NULL; + } +} + +// On destruction this class will cleanup the ctx, and also clear the OpenSSL +// ERR stack as a convenience. +class ScopedCipherCTX { + public: + explicit ScopedCipherCTX() { + EVP_CIPHER_CTX_init(&ctx_); + } + ~ScopedCipherCTX() { + EVP_CIPHER_CTX_cleanup(&ctx_); + ClearOpenSSLERRStack(FROM_HERE); + } + EVP_CIPHER_CTX* get() { return &ctx_; } + + private: + EVP_CIPHER_CTX ctx_; +}; + +} // namespace + +Encryptor::Encryptor() + : key_(NULL), + mode_(CBC) { +} + +Encryptor::~Encryptor() { +} + +bool Encryptor::Init(SymmetricKey* key, + Mode mode, + const base::StringPiece& iv) { + DCHECK(key); + DCHECK(mode == CBC || mode == CTR); + + EnsureOpenSSLInit(); + if (mode == CBC && iv.size() != AES_BLOCK_SIZE) + return false; + + if (GetCipherForKey(key) == NULL) + return false; + + key_ = key; + mode_ = mode; + iv.CopyToString(&iv_); + return true; +} + +bool Encryptor::Encrypt(const base::StringPiece& plaintext, + std::string* ciphertext) { + CHECK(!plaintext.empty() || (mode_ == CBC)); + return (mode_ == CTR) ? + CryptCTR(true, plaintext, ciphertext) : + Crypt(true, plaintext, ciphertext); +} + +bool Encryptor::Decrypt(const base::StringPiece& ciphertext, + std::string* plaintext) { + CHECK(!ciphertext.empty()); + return (mode_ == CTR) ? + CryptCTR(false, ciphertext, plaintext) : + Crypt(false, ciphertext, plaintext); +} + +bool Encryptor::Crypt(bool do_encrypt, + const base::StringPiece& input, + std::string* output) { + DCHECK(key_); // Must call Init() before En/De-crypt. + // Work on the result in a local variable, and then only transfer it to + // |output| on success to ensure no partial data is returned. + std::string result; + output->clear(); + + const EVP_CIPHER* cipher = GetCipherForKey(key_); + DCHECK(cipher); // Already handled in Init(); + + const std::string& key = key_->key(); + DCHECK_EQ(EVP_CIPHER_iv_length(cipher), iv_.length()); + DCHECK_EQ(EVP_CIPHER_key_length(cipher), key.length()); + + ScopedCipherCTX ctx; + if (!EVP_CipherInit_ex(ctx.get(), cipher, NULL, + reinterpret_cast(key.data()), + reinterpret_cast(iv_.data()), + do_encrypt)) + return false; + + // When encrypting, add another block size of space to allow for any padding. + const size_t output_size = input.size() + (do_encrypt ? iv_.size() : 0); + CHECK_GT(output_size, 0u); + CHECK_GT(output_size + 1, input.size()); + uint8* out_ptr = + reinterpret_cast(base::WriteInto(&result, output_size + 1)); + int out_len; + if (!EVP_CipherUpdate(ctx.get(), out_ptr, &out_len, + reinterpret_cast(input.data()), + input.length())) + return false; + + // Write out the final block plus padding (if any) to the end of the data + // just written. + int tail_len; + if (!EVP_CipherFinal_ex(ctx.get(), out_ptr + out_len, &tail_len)) + return false; + + out_len += tail_len; + DCHECK_LE(out_len, static_cast(output_size)); + result.resize(out_len); + + output->swap(result); + return true; +} + +bool Encryptor::CryptCTR(bool do_encrypt, + const base::StringPiece& input, + std::string* output) { + if (!counter_.get()) { + LOG(ERROR) << "Counter value not set in CTR mode."; + return false; + } + + AES_KEY aes_key; + if (AES_set_encrypt_key(reinterpret_cast(key_->key().data()), + key_->key().size() * 8, &aes_key) != 0) { + return false; + } + + const size_t out_size = input.size(); + CHECK_GT(out_size, 0u); + CHECK_GT(out_size + 1, input.size()); + + std::string result; + uint8* out_ptr = + reinterpret_cast(base::WriteInto(&result, out_size + 1)); + + uint8_t ivec[AES_BLOCK_SIZE] = { 0 }; + uint8_t ecount_buf[AES_BLOCK_SIZE] = { 0 }; + unsigned int block_offset = 0; + + counter_->Write(ivec); + + AES_ctr128_encrypt(reinterpret_cast(input.data()), out_ptr, + input.size(), &aes_key, ivec, ecount_buf, &block_offset); + + // AES_ctr128_encrypt() updates |ivec|. Update the |counter_| here. + SetCounter(base::StringPiece(reinterpret_cast(ivec), + AES_BLOCK_SIZE)); + + output->swap(result); + return true; +} + +} // namespace crypto diff --git a/crypto/encryptor_unittest.cc b/crypto/encryptor_unittest.cc new file mode 100644 index 0000000000000..79fe2cca1a675 --- /dev/null +++ b/crypto/encryptor_unittest.cc @@ -0,0 +1,531 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/encryptor.h" + +#include + +#include "base/memory/scoped_ptr.h" +#include "base/strings/string_number_conversions.h" +#include "crypto/symmetric_key.h" +#include "testing/gtest/include/gtest/gtest.h" + +TEST(EncryptorTest, EncryptDecrypt) { + scoped_ptr key( + crypto::SymmetricKey::DeriveKeyFromPassword( + crypto::SymmetricKey::AES, "password", "saltiest", 1000, 256)); + EXPECT_TRUE(key.get()); + + crypto::Encryptor encryptor; + // The IV must be exactly as long as the cipher block size. + std::string iv("the iv: 16 bytes"); + EXPECT_EQ(16U, iv.size()); + EXPECT_TRUE(encryptor.Init(key.get(), crypto::Encryptor::CBC, iv)); + + std::string plaintext("this is the plaintext"); + std::string ciphertext; + EXPECT_TRUE(encryptor.Encrypt(plaintext, &ciphertext)); + + EXPECT_LT(0U, ciphertext.size()); + + std::string decrypted; + EXPECT_TRUE(encryptor.Decrypt(ciphertext, &decrypted)); + + EXPECT_EQ(plaintext, decrypted); +} + +TEST(EncryptorTest, DecryptWrongKey) { + scoped_ptr key( + crypto::SymmetricKey::DeriveKeyFromPassword( + crypto::SymmetricKey::AES, "password", "saltiest", 1000, 256)); + EXPECT_TRUE(key.get()); + + // A wrong key that can be detected by implementations that validate every + // byte in the padding. + scoped_ptr wrong_key( + crypto::SymmetricKey::DeriveKeyFromPassword( + crypto::SymmetricKey::AES, "wrongword", "sweetest", 1000, 256)); + EXPECT_TRUE(wrong_key.get()); + + // A wrong key that can't be detected by any implementation. The password + // "wrongword;" would also work. + scoped_ptr wrong_key2( + crypto::SymmetricKey::DeriveKeyFromPassword( + crypto::SymmetricKey::AES, "wrongword+", "sweetest", 1000, 256)); + EXPECT_TRUE(wrong_key2.get()); + + // A wrong key that can be detected by all implementations. + scoped_ptr wrong_key3( + crypto::SymmetricKey::DeriveKeyFromPassword( + crypto::SymmetricKey::AES, "wrongwordx", "sweetest", 1000, 256)); + EXPECT_TRUE(wrong_key3.get()); + + crypto::Encryptor encryptor; + // The IV must be exactly as long as the cipher block size. + std::string iv("the iv: 16 bytes"); + EXPECT_EQ(16U, iv.size()); + EXPECT_TRUE(encryptor.Init(key.get(), crypto::Encryptor::CBC, iv)); + + std::string plaintext("this is the plaintext"); + std::string ciphertext; + EXPECT_TRUE(encryptor.Encrypt(plaintext, &ciphertext)); + + static const unsigned char expected_ciphertext[] = { + 0x7D, 0x67, 0x5B, 0x53, 0xE6, 0xD8, 0x0F, 0x27, + 0x74, 0xB1, 0x90, 0xFE, 0x6E, 0x58, 0x4A, 0xA0, + 0x0E, 0x35, 0xE3, 0x01, 0xC0, 0xFE, 0x9A, 0xD8, + 0x48, 0x1D, 0x42, 0xB0, 0xBA, 0x21, 0xB2, 0x0C + }; + + ASSERT_EQ(arraysize(expected_ciphertext), ciphertext.size()); + for (size_t i = 0; i < ciphertext.size(); ++i) { + ASSERT_EQ(expected_ciphertext[i], + static_cast(ciphertext[i])); + } + + std::string decrypted; + + // This wrong key causes the last padding byte to be 5, which is a valid + // padding length, and the second to last padding byte to be 137, which is + // invalid. If an implementation simply uses the last padding byte to + // determine the padding length without checking every padding byte, + // Encryptor::Decrypt() will still return true. This is the case for NSS + // (crbug.com/124434). +#if !defined(USE_NSS_CERTS) && !defined(OS_WIN) && !defined(OS_MACOSX) + crypto::Encryptor decryptor; + EXPECT_TRUE(decryptor.Init(wrong_key.get(), crypto::Encryptor::CBC, iv)); + EXPECT_FALSE(decryptor.Decrypt(ciphertext, &decrypted)); +#endif + + // This demonstrates that not all wrong keys can be detected by padding + // error. This wrong key causes the last padding byte to be 1, which is + // a valid padding block of length 1. + crypto::Encryptor decryptor2; + EXPECT_TRUE(decryptor2.Init(wrong_key2.get(), crypto::Encryptor::CBC, iv)); + EXPECT_TRUE(decryptor2.Decrypt(ciphertext, &decrypted)); + + // This wrong key causes the last padding byte to be 253, which should be + // rejected by all implementations. + crypto::Encryptor decryptor3; + EXPECT_TRUE(decryptor3.Init(wrong_key3.get(), crypto::Encryptor::CBC, iv)); + EXPECT_FALSE(decryptor3.Decrypt(ciphertext, &decrypted)); +} + +namespace { + +// From NIST SP 800-38a test cast: +// - F.5.1 CTR-AES128.Encrypt +// - F.5.6 CTR-AES256.Encrypt +// http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf +const unsigned char kAES128CTRKey[] = { + 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c +}; + +const unsigned char kAES256CTRKey[] = { + 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, + 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, + 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, + 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 +}; + +const unsigned char kAESCTRInitCounter[] = { + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff +}; + +const unsigned char kAESCTRPlaintext[] = { + // Block #1 + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + // Block #2 + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + // Block #3 + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, + 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + // Block #4 + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, + 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 +}; + +const unsigned char kAES128CTRCiphertext[] = { + // Block #1 + 0x87, 0x4d, 0x61, 0x91, 0xb6, 0x20, 0xe3, 0x26, + 0x1b, 0xef, 0x68, 0x64, 0x99, 0x0d, 0xb6, 0xce, + // Block #2 + 0x98, 0x06, 0xf6, 0x6b, 0x79, 0x70, 0xfd, 0xff, + 0x86, 0x17, 0x18, 0x7b, 0xb9, 0xff, 0xfd, 0xff, + // Block #3 + 0x5a, 0xe4, 0xdf, 0x3e, 0xdb, 0xd5, 0xd3, 0x5e, + 0x5b, 0x4f, 0x09, 0x02, 0x0d, 0xb0, 0x3e, 0xab, + // Block #4 + 0x1e, 0x03, 0x1d, 0xda, 0x2f, 0xbe, 0x03, 0xd1, + 0x79, 0x21, 0x70, 0xa0, 0xf3, 0x00, 0x9c, 0xee +}; + +const unsigned char kAES256CTRCiphertext[] = { + // Block #1 + 0x60, 0x1e, 0xc3, 0x13, 0x77, 0x57, 0x89, 0xa5, + 0xb7, 0xa7, 0xf5, 0x04, 0xbb, 0xf3, 0xd2, 0x28, + // Block #2 + 0xf4, 0x43, 0xe3, 0xca, 0x4d, 0x62, 0xb5, 0x9a, + 0xca, 0x84, 0xe9, 0x90, 0xca, 0xca, 0xf5, 0xc5, + // Block #3 + 0x2b, 0x09, 0x30, 0xda, 0xa2, 0x3d, 0xe9, 0x4c, + 0xe8, 0x70, 0x17, 0xba, 0x2d, 0x84, 0x98, 0x8d, + // Block #4 + 0xdf, 0xc9, 0xc5, 0x8d, 0xb6, 0x7a, 0xad, 0xa6, + 0x13, 0xc2, 0xdd, 0x08, 0x45, 0x79, 0x41, 0xa6 +}; + +void TestAESCTREncrypt( + const unsigned char* key, size_t key_size, + const unsigned char* init_counter, size_t init_counter_size, + const unsigned char* plaintext, size_t plaintext_size, + const unsigned char* ciphertext, size_t ciphertext_size) { + std::string key_str(reinterpret_cast(key), key_size); + scoped_ptr sym_key(crypto::SymmetricKey::Import( + crypto::SymmetricKey::AES, key_str)); + ASSERT_TRUE(sym_key.get()); + + crypto::Encryptor encryptor; + EXPECT_TRUE(encryptor.Init(sym_key.get(), crypto::Encryptor::CTR, "")); + + base::StringPiece init_counter_str( + reinterpret_cast(init_counter), init_counter_size); + base::StringPiece plaintext_str( + reinterpret_cast(plaintext), plaintext_size); + + EXPECT_TRUE(encryptor.SetCounter(init_counter_str)); + std::string encrypted; + EXPECT_TRUE(encryptor.Encrypt(plaintext_str, &encrypted)); + + EXPECT_EQ(ciphertext_size, encrypted.size()); + EXPECT_EQ(0, memcmp(encrypted.data(), ciphertext, encrypted.size())); + + std::string decrypted; + EXPECT_TRUE(encryptor.SetCounter(init_counter_str)); + EXPECT_TRUE(encryptor.Decrypt(encrypted, &decrypted)); + + EXPECT_EQ(plaintext_str, decrypted); +} + +void TestAESCTRMultipleDecrypt( + const unsigned char* key, size_t key_size, + const unsigned char* init_counter, size_t init_counter_size, + const unsigned char* plaintext, size_t plaintext_size, + const unsigned char* ciphertext, size_t ciphertext_size) { + std::string key_str(reinterpret_cast(key), key_size); + scoped_ptr sym_key(crypto::SymmetricKey::Import( + crypto::SymmetricKey::AES, key_str)); + ASSERT_TRUE(sym_key.get()); + + crypto::Encryptor encryptor; + EXPECT_TRUE(encryptor.Init(sym_key.get(), crypto::Encryptor::CTR, "")); + + // Counter is set only once. + EXPECT_TRUE(encryptor.SetCounter(base::StringPiece( + reinterpret_cast(init_counter), init_counter_size))); + + std::string ciphertext_str(reinterpret_cast(ciphertext), + ciphertext_size); + + int kTestDecryptSizes[] = { 32, 16, 8 }; + + int offset = 0; + for (size_t i = 0; i < arraysize(kTestDecryptSizes); ++i) { + std::string decrypted; + size_t len = kTestDecryptSizes[i]; + EXPECT_TRUE( + encryptor.Decrypt(ciphertext_str.substr(offset, len), &decrypted)); + EXPECT_EQ(len, decrypted.size()); + EXPECT_EQ(0, memcmp(decrypted.data(), plaintext + offset, len)); + offset += len; + } +} + +} // namespace + +TEST(EncryptorTest, EncryptAES128CTR) { + TestAESCTREncrypt( + kAES128CTRKey, arraysize(kAES128CTRKey), + kAESCTRInitCounter, arraysize(kAESCTRInitCounter), + kAESCTRPlaintext, arraysize(kAESCTRPlaintext), + kAES128CTRCiphertext, arraysize(kAES128CTRCiphertext)); +} + +TEST(EncryptorTest, EncryptAES256CTR) { + TestAESCTREncrypt( + kAES256CTRKey, arraysize(kAES256CTRKey), + kAESCTRInitCounter, arraysize(kAESCTRInitCounter), + kAESCTRPlaintext, arraysize(kAESCTRPlaintext), + kAES256CTRCiphertext, arraysize(kAES256CTRCiphertext)); +} + +TEST(EncryptorTest, EncryptAES128CTR_MultipleDecrypt) { + TestAESCTRMultipleDecrypt( + kAES128CTRKey, arraysize(kAES128CTRKey), + kAESCTRInitCounter, arraysize(kAESCTRInitCounter), + kAESCTRPlaintext, arraysize(kAESCTRPlaintext), + kAES128CTRCiphertext, arraysize(kAES128CTRCiphertext)); +} + +TEST(EncryptorTest, EncryptAES256CTR_MultipleDecrypt) { + TestAESCTRMultipleDecrypt( + kAES256CTRKey, arraysize(kAES256CTRKey), + kAESCTRInitCounter, arraysize(kAESCTRInitCounter), + kAESCTRPlaintext, arraysize(kAESCTRPlaintext), + kAES256CTRCiphertext, arraysize(kAES256CTRCiphertext)); +} + +TEST(EncryptorTest, EncryptDecryptCTR) { + scoped_ptr key( + crypto::SymmetricKey::GenerateRandomKey(crypto::SymmetricKey::AES, 128)); + + EXPECT_TRUE(key.get()); + const std::string kInitialCounter = "0000000000000000"; + + crypto::Encryptor encryptor; + EXPECT_TRUE(encryptor.Init(key.get(), crypto::Encryptor::CTR, "")); + EXPECT_TRUE(encryptor.SetCounter(kInitialCounter)); + + std::string plaintext("normal plaintext of random length"); + std::string ciphertext; + EXPECT_TRUE(encryptor.Encrypt(plaintext, &ciphertext)); + EXPECT_LT(0U, ciphertext.size()); + + std::string decrypted; + EXPECT_TRUE(encryptor.SetCounter(kInitialCounter)); + EXPECT_TRUE(encryptor.Decrypt(ciphertext, &decrypted)); + EXPECT_EQ(plaintext, decrypted); + + plaintext = "0123456789012345"; + EXPECT_TRUE(encryptor.SetCounter(kInitialCounter)); + EXPECT_TRUE(encryptor.Encrypt(plaintext, &ciphertext)); + EXPECT_LT(0U, ciphertext.size()); + + EXPECT_TRUE(encryptor.SetCounter(kInitialCounter)); + EXPECT_TRUE(encryptor.Decrypt(ciphertext, &decrypted)); + EXPECT_EQ(plaintext, decrypted); +} + +TEST(EncryptorTest, CTRCounter) { + const int kCounterSize = 16; + const unsigned char kTest1[] = + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + unsigned char buf[16]; + + // Increment 10 times. + crypto::Encryptor::Counter counter1( + std::string(reinterpret_cast(kTest1), kCounterSize)); + for (int i = 0; i < 10; ++i) + counter1.Increment(); + counter1.Write(buf); + EXPECT_EQ(0, memcmp(buf, kTest1, 15)); + EXPECT_TRUE(buf[15] == 10); + + // Check corner cases. + const unsigned char kTest2[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + }; + const unsigned char kExpect2[] = + {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}; + crypto::Encryptor::Counter counter2( + std::string(reinterpret_cast(kTest2), kCounterSize)); + counter2.Increment(); + counter2.Write(buf); + EXPECT_EQ(0, memcmp(buf, kExpect2, kCounterSize)); + + const unsigned char kTest3[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + }; + const unsigned char kExpect3[] = + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + crypto::Encryptor::Counter counter3( + std::string(reinterpret_cast(kTest3), kCounterSize)); + counter3.Increment(); + counter3.Write(buf); + EXPECT_EQ(0, memcmp(buf, kExpect3, kCounterSize)); +} + +// TODO(wtc): add more known-answer tests. Test vectors are available from +// http://www.ietf.org/rfc/rfc3602 +// http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf +// http://gladman.plushost.co.uk/oldsite/AES/index.php +// http://csrc.nist.gov/groups/STM/cavp/documents/aes/KAT_AES.zip + +// NIST SP 800-38A test vector F.2.5 CBC-AES256.Encrypt. +TEST(EncryptorTest, EncryptAES256CBC) { + // From NIST SP 800-38a test cast F.2.5 CBC-AES256.Encrypt. + static const unsigned char kRawKey[] = { + 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, + 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, + 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, + 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 + }; + static const unsigned char kRawIv[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f + }; + static const unsigned char kRawPlaintext[] = { + // Block #1 + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + // Block #2 + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + // Block #3 + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, + 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + // Block #4 + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, + 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10, + }; + static const unsigned char kRawCiphertext[] = { + // Block #1 + 0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba, + 0x77, 0x9e, 0xab, 0xfb, 0x5f, 0x7b, 0xfb, 0xd6, + // Block #2 + 0x9c, 0xfc, 0x4e, 0x96, 0x7e, 0xdb, 0x80, 0x8d, + 0x67, 0x9f, 0x77, 0x7b, 0xc6, 0x70, 0x2c, 0x7d, + // Block #3 + 0x39, 0xf2, 0x33, 0x69, 0xa9, 0xd9, 0xba, 0xcf, + 0xa5, 0x30, 0xe2, 0x63, 0x04, 0x23, 0x14, 0x61, + // Block #4 + 0xb2, 0xeb, 0x05, 0xe2, 0xc3, 0x9b, 0xe9, 0xfc, + 0xda, 0x6c, 0x19, 0x07, 0x8c, 0x6a, 0x9d, 0x1b, + // PKCS #5 padding, encrypted. + 0x3f, 0x46, 0x17, 0x96, 0xd6, 0xb0, 0xd6, 0xb2, + 0xe0, 0xc2, 0xa7, 0x2b, 0x4d, 0x80, 0xe6, 0x44 + }; + + std::string key(reinterpret_cast(kRawKey), sizeof(kRawKey)); + scoped_ptr sym_key(crypto::SymmetricKey::Import( + crypto::SymmetricKey::AES, key)); + ASSERT_TRUE(sym_key.get()); + + crypto::Encryptor encryptor; + // The IV must be exactly as long a the cipher block size. + std::string iv(reinterpret_cast(kRawIv), sizeof(kRawIv)); + EXPECT_EQ(16U, iv.size()); + EXPECT_TRUE(encryptor.Init(sym_key.get(), crypto::Encryptor::CBC, iv)); + + std::string plaintext(reinterpret_cast(kRawPlaintext), + sizeof(kRawPlaintext)); + std::string ciphertext; + EXPECT_TRUE(encryptor.Encrypt(plaintext, &ciphertext)); + + EXPECT_EQ(sizeof(kRawCiphertext), ciphertext.size()); + EXPECT_EQ(0, memcmp(ciphertext.data(), kRawCiphertext, ciphertext.size())); + + std::string decrypted; + EXPECT_TRUE(encryptor.Decrypt(ciphertext, &decrypted)); + + EXPECT_EQ(plaintext, decrypted); +} + +// Expected output derived from the NSS implementation. +TEST(EncryptorTest, EncryptAES128CBCRegression) { + std::string key = "128=SixteenBytes"; + std::string iv = "Sweet Sixteen IV"; + std::string plaintext = "Plain text with a g-clef U+1D11E \360\235\204\236"; + std::string expected_ciphertext_hex = + "D4A67A0BA33C30F207344D81D1E944BBE65587C3D7D9939A" + "C070C62B9C15A3EA312EA4AD1BC7929F4D3C16B03AD5ADA8"; + + scoped_ptr sym_key(crypto::SymmetricKey::Import( + crypto::SymmetricKey::AES, key)); + ASSERT_TRUE(sym_key.get()); + + crypto::Encryptor encryptor; + // The IV must be exactly as long a the cipher block size. + EXPECT_EQ(16U, iv.size()); + EXPECT_TRUE(encryptor.Init(sym_key.get(), crypto::Encryptor::CBC, iv)); + + std::string ciphertext; + EXPECT_TRUE(encryptor.Encrypt(plaintext, &ciphertext)); + EXPECT_EQ(expected_ciphertext_hex, base::HexEncode(ciphertext.data(), + ciphertext.size())); + + std::string decrypted; + EXPECT_TRUE(encryptor.Decrypt(ciphertext, &decrypted)); + EXPECT_EQ(plaintext, decrypted); +} + +// Symmetric keys with an unsupported size should be rejected. Whether they are +// rejected by SymmetricKey::Import or Encryptor::Init depends on the platform. +TEST(EncryptorTest, UnsupportedKeySize) { + std::string key = "7 = bad"; + std::string iv = "Sweet Sixteen IV"; + scoped_ptr sym_key(crypto::SymmetricKey::Import( + crypto::SymmetricKey::AES, key)); + if (!sym_key.get()) + return; + + crypto::Encryptor encryptor; + // The IV must be exactly as long as the cipher block size. + EXPECT_EQ(16U, iv.size()); + EXPECT_FALSE(encryptor.Init(sym_key.get(), crypto::Encryptor::CBC, iv)); +} + +TEST(EncryptorTest, UnsupportedIV) { + std::string key = "128=SixteenBytes"; + std::string iv = "OnlyForteen :("; + scoped_ptr sym_key(crypto::SymmetricKey::Import( + crypto::SymmetricKey::AES, key)); + ASSERT_TRUE(sym_key.get()); + + crypto::Encryptor encryptor; + EXPECT_FALSE(encryptor.Init(sym_key.get(), crypto::Encryptor::CBC, iv)); +} + +TEST(EncryptorTest, EmptyEncrypt) { + std::string key = "128=SixteenBytes"; + std::string iv = "Sweet Sixteen IV"; + std::string plaintext; + std::string expected_ciphertext_hex = "8518B8878D34E7185E300D0FCC426396"; + + scoped_ptr sym_key(crypto::SymmetricKey::Import( + crypto::SymmetricKey::AES, key)); + ASSERT_TRUE(sym_key.get()); + + crypto::Encryptor encryptor; + // The IV must be exactly as long a the cipher block size. + EXPECT_EQ(16U, iv.size()); + EXPECT_TRUE(encryptor.Init(sym_key.get(), crypto::Encryptor::CBC, iv)); + + std::string ciphertext; + EXPECT_TRUE(encryptor.Encrypt(plaintext, &ciphertext)); + EXPECT_EQ(expected_ciphertext_hex, base::HexEncode(ciphertext.data(), + ciphertext.size())); +} + +TEST(EncryptorTest, CipherTextNotMultipleOfBlockSize) { + std::string key = "128=SixteenBytes"; + std::string iv = "Sweet Sixteen IV"; + + scoped_ptr sym_key(crypto::SymmetricKey::Import( + crypto::SymmetricKey::AES, key)); + ASSERT_TRUE(sym_key.get()); + + crypto::Encryptor encryptor; + // The IV must be exactly as long a the cipher block size. + EXPECT_EQ(16U, iv.size()); + EXPECT_TRUE(encryptor.Init(sym_key.get(), crypto::Encryptor::CBC, iv)); + + // Use a separately allocated array to improve the odds of the memory tools + // catching invalid accesses. + // + // Otherwise when using std::string as the other tests do, accesses several + // bytes off the end of the buffer may fall inside the reservation of + // the string and not be detected. + scoped_ptr ciphertext(new char[1]); + + std::string plaintext; + EXPECT_FALSE( + encryptor.Decrypt(base::StringPiece(ciphertext.get(), 1), &plaintext)); +} diff --git a/crypto/ghash.cc b/crypto/ghash.cc new file mode 100644 index 0000000000000..1acd474cbc69a --- /dev/null +++ b/crypto/ghash.cc @@ -0,0 +1,259 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/ghash.h" + +#include + +#include "base/logging.h" +#include "base/sys_byteorder.h" + +namespace crypto { + +// GaloisHash is a polynomial authenticator that works in GF(2^128). +// +// Elements of the field are represented in `little-endian' order (which +// matches the description in the paper[1]), thus the most significant bit is +// the right-most bit. (This is backwards from the way that everybody else does +// it.) +// +// We store field elements in a pair of such `little-endian' uint64s. So the +// value one is represented by {low = 2**63, high = 0} and doubling a value +// involves a *right* shift. +// +// [1] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf + +namespace { + +// Get64 reads a 64-bit, big-endian number from |bytes|. +uint64 Get64(const uint8 bytes[8]) { + uint64 t; + memcpy(&t, bytes, sizeof(t)); + return base::NetToHost64(t); +} + +// Put64 writes |x| to |bytes| as a 64-bit, big-endian number. +void Put64(uint8 bytes[8], uint64 x) { + x = base::HostToNet64(x); + memcpy(bytes, &x, sizeof(x)); +} + +// Reverse reverses the order of the bits of 4-bit number in |i|. +int Reverse(int i) { + i = ((i << 2) & 0xc) | ((i >> 2) & 0x3); + i = ((i << 1) & 0xa) | ((i >> 1) & 0x5); + return i; +} + +} // namespace + +GaloisHash::GaloisHash(const uint8 key[16]) { + Reset(); + + // We precompute 16 multiples of |key|. However, when we do lookups into this + // table we'll be using bits from a field element and therefore the bits will + // be in the reverse order. So normally one would expect, say, 4*key to be in + // index 4 of the table but due to this bit ordering it will actually be in + // index 0010 (base 2) = 2. + FieldElement x = {Get64(key), Get64(key+8)}; + product_table_[0].low = 0; + product_table_[0].hi = 0; + product_table_[Reverse(1)] = x; + + for (int i = 0; i < 16; i += 2) { + product_table_[Reverse(i)] = Double(product_table_[Reverse(i/2)]); + product_table_[Reverse(i+1)] = Add(product_table_[Reverse(i)], x); + } +} + +void GaloisHash::Reset() { + state_ = kHashingAdditionalData; + additional_bytes_ = 0; + ciphertext_bytes_ = 0; + buf_used_ = 0; + y_.low = 0; + y_.hi = 0; +} + +void GaloisHash::UpdateAdditional(const uint8* data, size_t length) { + DCHECK_EQ(state_, kHashingAdditionalData); + additional_bytes_ += length; + Update(data, length); +} + +void GaloisHash::UpdateCiphertext(const uint8* data, size_t length) { + if (state_ == kHashingAdditionalData) { + // If there's any remaining additional data it's zero padded to the next + // full block. + if (buf_used_ > 0) { + memset(&buf_[buf_used_], 0, sizeof(buf_)-buf_used_); + UpdateBlocks(buf_, 1); + buf_used_ = 0; + } + state_ = kHashingCiphertext; + } + + DCHECK_EQ(state_, kHashingCiphertext); + ciphertext_bytes_ += length; + Update(data, length); +} + +void GaloisHash::Finish(void* output, size_t len) { + DCHECK(state_ != kComplete); + + if (buf_used_ > 0) { + // If there's any remaining data (additional data or ciphertext), it's zero + // padded to the next full block. + memset(&buf_[buf_used_], 0, sizeof(buf_)-buf_used_); + UpdateBlocks(buf_, 1); + buf_used_ = 0; + } + + state_ = kComplete; + + // The lengths of the additional data and ciphertext are included as the last + // block. The lengths are the number of bits. + y_.low ^= additional_bytes_*8; + y_.hi ^= ciphertext_bytes_*8; + MulAfterPrecomputation(product_table_, &y_); + + uint8 *result, result_tmp[16]; + if (len >= 16) { + result = reinterpret_cast(output); + } else { + result = result_tmp; + } + + Put64(result, y_.low); + Put64(result + 8, y_.hi); + + if (len < 16) + memcpy(output, result_tmp, len); +} + +// static +GaloisHash::FieldElement GaloisHash::Add( + const FieldElement& x, + const FieldElement& y) { + // Addition in a characteristic 2 field is just XOR. + FieldElement z = {x.low^y.low, x.hi^y.hi}; + return z; +} + +// static +GaloisHash::FieldElement GaloisHash::Double(const FieldElement& x) { + const bool msb_set = x.hi & 1; + + FieldElement xx; + // Because of the bit-ordering, doubling is actually a right shift. + xx.hi = x.hi >> 1; + xx.hi |= x.low << 63; + xx.low = x.low >> 1; + + // If the most-significant bit was set before shifting then it, conceptually, + // becomes a term of x^128. This is greater than the irreducible polynomial + // so the result has to be reduced. The irreducible polynomial is + // 1+x+x^2+x^7+x^128. We can subtract that to eliminate the term at x^128 + // which also means subtracting the other four terms. In characteristic 2 + // fields, subtraction == addition == XOR. + if (msb_set) + xx.low ^= 0xe100000000000000ULL; + + return xx; +} + +void GaloisHash::MulAfterPrecomputation(const FieldElement* table, + FieldElement* x) { + FieldElement z = {0, 0}; + + // In order to efficiently multiply, we use the precomputed table of i*key, + // for i in 0..15, to handle four bits at a time. We could obviously use + // larger tables for greater speedups but the next convenient table size is + // 4K, which is a little large. + // + // In other fields one would use bit positions spread out across the field in + // order to reduce the number of doublings required. However, in + // characteristic 2 fields, repeated doublings are exceptionally cheap and + // it's not worth spending more precomputation time to eliminate them. + for (unsigned i = 0; i < 2; i++) { + uint64 word; + if (i == 0) { + word = x->hi; + } else { + word = x->low; + } + + for (unsigned j = 0; j < 64; j += 4) { + Mul16(&z); + // the values in |table| are ordered for little-endian bit positions. See + // the comment in the constructor. + const FieldElement& t = table[word & 0xf]; + z.low ^= t.low; + z.hi ^= t.hi; + word >>= 4; + } + } + + *x = z; +} + +// kReductionTable allows for rapid multiplications by 16. A multiplication by +// 16 is a right shift by four bits, which results in four bits at 2**128. +// These terms have to be eliminated by dividing by the irreducible polynomial. +// In GHASH, the polynomial is such that all the terms occur in the +// least-significant 8 bits, save for the term at x^128. Therefore we can +// precompute the value to be added to the field element for each of the 16 bit +// patterns at 2**128 and the values fit within 12 bits. +static const uint16 kReductionTable[16] = { + 0x0000, 0x1c20, 0x3840, 0x2460, 0x7080, 0x6ca0, 0x48c0, 0x54e0, + 0xe100, 0xfd20, 0xd940, 0xc560, 0x9180, 0x8da0, 0xa9c0, 0xb5e0, +}; + +// static +void GaloisHash::Mul16(FieldElement* x) { + const unsigned msw = x->hi & 0xf; + x->hi >>= 4; + x->hi |= x->low << 60; + x->low >>= 4; + x->low ^= static_cast(kReductionTable[msw]) << 48; +} + +void GaloisHash::UpdateBlocks(const uint8* bytes, size_t num_blocks) { + for (size_t i = 0; i < num_blocks; i++) { + y_.low ^= Get64(bytes); + bytes += 8; + y_.hi ^= Get64(bytes); + bytes += 8; + MulAfterPrecomputation(product_table_, &y_); + } +} + +void GaloisHash::Update(const uint8* data, size_t length) { + if (buf_used_ > 0) { + const size_t n = std::min(length, sizeof(buf_) - buf_used_); + memcpy(&buf_[buf_used_], data, n); + buf_used_ += n; + length -= n; + data += n; + + if (buf_used_ == sizeof(buf_)) { + UpdateBlocks(buf_, 1); + buf_used_ = 0; + } + } + + if (length >= 16) { + const size_t n = length / 16; + UpdateBlocks(data, n); + length -= n*16; + data += n*16; + } + + if (length > 0) { + memcpy(buf_, data, length); + buf_used_ = length; + } +} + +} // namespace crypto diff --git a/crypto/ghash.h b/crypto/ghash.h new file mode 100644 index 0000000000000..6dc247be28e94 --- /dev/null +++ b/crypto/ghash.h @@ -0,0 +1,86 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/basictypes.h" +#include "crypto/crypto_export.h" + +namespace crypto { + +// GaloisHash implements the polynomial authenticator part of GCM as specified +// in http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf +// Specifically it implements the GHASH function, defined in section 2.3 of +// that document. +// +// In SP-800-38D, GHASH is defined differently and takes only a single data +// argument. But it is always called with an argument of a certain form: +// GHASH_H (A || 0^v || C || 0^u || [len(A)]_64 || [len(C)]_64) +// This mirrors how the gcm-revised-spec.pdf version of GHASH handles its two +// data arguments. The two GHASH functions therefore differ only in whether the +// data is formatted inside or outside of the function. +// +// WARNING: do not use this as a generic authenticator. Polynomial +// authenticators must be used in the correct manner and any use outside of GCM +// requires careful consideration. +// +// WARNING: this code is not constant time. However, in all likelihood, nor is +// the implementation of AES that is used. +class CRYPTO_EXPORT_PRIVATE GaloisHash { + public: + explicit GaloisHash(const uint8 key[16]); + + // Reset prepares to digest a fresh message with the same key. This is more + // efficient than creating a fresh object. + void Reset(); + + // UpdateAdditional hashes in `additional' data. This is data that is not + // encrypted, but is covered by the authenticator. All additional data must + // be written before any ciphertext is written. + void UpdateAdditional(const uint8* data, size_t length); + + // UpdateCiphertext hashes in ciphertext to be authenticated. + void UpdateCiphertext(const uint8* data, size_t length); + + // Finish completes the hash computation and writes at most |len| bytes of + // the result to |output|. + void Finish(void* output, size_t len); + + private: + enum State { + kHashingAdditionalData, + kHashingCiphertext, + kComplete, + }; + + struct FieldElement { + uint64 low, hi; + }; + + // Add returns |x|+|y|. + static FieldElement Add(const FieldElement& x, const FieldElement& y); + // Double returns 2*|x|. + static FieldElement Double(const FieldElement& x); + // MulAfterPrecomputation sets |x| = |x|*h where h is |table[1]| and + // table[i] = i*h for i=0..15. + static void MulAfterPrecomputation(const FieldElement* table, + FieldElement* x); + // Mul16 sets |x| = 16*|x|. + static void Mul16(FieldElement* x); + + // UpdateBlocks processes |num_blocks| 16-bytes blocks from |bytes|. + void UpdateBlocks(const uint8* bytes, size_t num_blocks); + // Update processes |length| bytes from |bytes| and calls UpdateBlocks on as + // much data as possible. It uses |buf_| to buffer any remaining data and + // always consumes all of |bytes|. + void Update(const uint8* bytes, size_t length); + + FieldElement y_; + State state_; + size_t additional_bytes_; + size_t ciphertext_bytes_; + uint8 buf_[16]; + size_t buf_used_; + FieldElement product_table_[16]; +}; + +} // namespace crypto diff --git a/crypto/ghash_unittest.cc b/crypto/ghash_unittest.cc new file mode 100644 index 0000000000000..5dd88ed5c8d2c --- /dev/null +++ b/crypto/ghash_unittest.cc @@ -0,0 +1,148 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include + +#include "crypto/ghash.h" + +#include "testing/gtest/include/gtest/gtest.h" + +namespace crypto { + +namespace { + +// Test vectors are taken from Appendix B of +// http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf + +static const uint8 kKey1[16] = { + 0x66, 0xe9, 0x4b, 0xd4, 0xef, 0x8a, 0x2c, 0x3b, + 0x88, 0x4c, 0xfa, 0x59, 0xca, 0x34, 0x2b, 0x2e, +}; + +static const uint8 kCiphertext2[] = { + 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92, + 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78, +}; + +static const uint8 kKey3[16] = { + 0xb8, 0x3b, 0x53, 0x37, 0x08, 0xbf, 0x53, 0x5d, + 0x0a, 0xa6, 0xe5, 0x29, 0x80, 0xd5, 0x3b, 0x78, +}; + +static const uint8 kCiphertext3[] = { + 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, + 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, + 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, + 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, + 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, + 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, + 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, + 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85, +}; + +static const uint8 kAdditional4[] = { + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xab, 0xad, 0xda, 0xd2, +}; + +struct TestCase { + const uint8* key; + const uint8* additional; + unsigned additional_length; + const uint8* ciphertext; + unsigned ciphertext_length; + const uint8 expected[16]; +}; + +static const TestCase kTestCases[] = { + { + kKey1, + NULL, + 0, + NULL, + 0, + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + }, + { + kKey1, + NULL, + 0, + kCiphertext2, + sizeof(kCiphertext2), + { + 0xf3, 0x8c, 0xbb, 0x1a, 0xd6, 0x92, 0x23, 0xdc, + 0xc3, 0x45, 0x7a, 0xe5, 0xb6, 0xb0, 0xf8, 0x85, + }, + }, + { + kKey3, + NULL, + 0, + kCiphertext3, + sizeof(kCiphertext3), + { + 0x7f, 0x1b, 0x32, 0xb8, 0x1b, 0x82, 0x0d, 0x02, + 0x61, 0x4f, 0x88, 0x95, 0xac, 0x1d, 0x4e, 0xac, + }, + }, + { + kKey3, + kAdditional4, + sizeof(kAdditional4), + kCiphertext3, + sizeof(kCiphertext3) - 4, + { + 0x69, 0x8e, 0x57, 0xf7, 0x0e, 0x6e, 0xcc, 0x7f, + 0xd9, 0x46, 0x3b, 0x72, 0x60, 0xa9, 0xae, 0x5f, + }, + }, +}; + +TEST(GaloisHash, TestCases) { + uint8 out[16]; + + for (size_t i = 0; i < arraysize(kTestCases); ++i) { + const TestCase& test = kTestCases[i]; + + GaloisHash hash(test.key); + if (test.additional_length) + hash.UpdateAdditional(test.additional, test.additional_length); + if (test.ciphertext_length) + hash.UpdateCiphertext(test.ciphertext, test.ciphertext_length); + hash.Finish(out, sizeof(out)); + EXPECT_TRUE(0 == memcmp(out, test.expected, 16)); + } +} + +TEST(GaloisHash, VaryLengths) { + uint8 out[16]; + + for (size_t chunk_size = 1; chunk_size < 16; chunk_size++) { + for (size_t i = 0; i < arraysize(kTestCases); ++i) { + const TestCase& test = kTestCases[i]; + + GaloisHash hash(test.key); + for (size_t i = 0; i < test.additional_length;) { + size_t n = std::min(test.additional_length - i, chunk_size); + hash.UpdateAdditional(test.additional + i, n); + i += n; + } + for (size_t i = 0; i < test.ciphertext_length;) { + size_t n = std::min(test.ciphertext_length - i, chunk_size); + hash.UpdateCiphertext(test.ciphertext + i, n); + i += n; + } + hash.Finish(out, sizeof(out)); + EXPECT_TRUE(0 == memcmp(out, test.expected, 16)); + } + } +} + +} // namespace + +} // namespace crypto diff --git a/crypto/hkdf.cc b/crypto/hkdf.cc new file mode 100644 index 0000000000000..82aae24679e45 --- /dev/null +++ b/crypto/hkdf.cc @@ -0,0 +1,107 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/hkdf.h" + +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "crypto/hmac.h" + +namespace crypto { + +const size_t kSHA256HashLength = 32; + +HKDF::HKDF(const base::StringPiece& secret, + const base::StringPiece& salt, + const base::StringPiece& info, + size_t key_bytes_to_generate, + size_t iv_bytes_to_generate, + size_t subkey_secret_bytes_to_generate) { + // https://tools.ietf.org/html/rfc5869#section-2.2 + base::StringPiece actual_salt = salt; + char zeros[kSHA256HashLength]; + if (actual_salt.empty()) { + // If salt is not given, HashLength zeros are used. + memset(zeros, 0, sizeof(zeros)); + actual_salt.set(zeros, sizeof(zeros)); + } + + // Perform the Extract step to transform the input key and + // salt into the pseudorandom key (PRK) used for Expand. + HMAC prk_hmac(HMAC::SHA256); + bool result = prk_hmac.Init(actual_salt); + DCHECK(result); + + // |prk| is a pseudorandom key (of kSHA256HashLength octets). + uint8 prk[kSHA256HashLength]; + DCHECK_EQ(sizeof(prk), prk_hmac.DigestLength()); + result = prk_hmac.Sign(secret, prk, sizeof(prk)); + DCHECK(result); + + // https://tools.ietf.org/html/rfc5869#section-2.3 + // Perform the Expand phase to turn the pseudorandom key + // and info into the output keying material. + const size_t material_length = 2 * key_bytes_to_generate + + 2 * iv_bytes_to_generate + + subkey_secret_bytes_to_generate; + const size_t n = (material_length + kSHA256HashLength-1) / + kSHA256HashLength; + DCHECK_LT(n, 256u); + + output_.resize(n * kSHA256HashLength); + base::StringPiece previous; + + scoped_ptr buf(new char[kSHA256HashLength + info.size() + 1]); + uint8 digest[kSHA256HashLength]; + + HMAC hmac(HMAC::SHA256); + result = hmac.Init(prk, sizeof(prk)); + DCHECK(result); + + for (size_t i = 0; i < n; i++) { + memcpy(buf.get(), previous.data(), previous.size()); + size_t j = previous.size(); + memcpy(buf.get() + j, info.data(), info.size()); + j += info.size(); + buf[j++] = static_cast(i + 1); + + result = hmac.Sign(base::StringPiece(buf.get(), j), digest, sizeof(digest)); + DCHECK(result); + + memcpy(&output_[i*sizeof(digest)], digest, sizeof(digest)); + previous = base::StringPiece(reinterpret_cast(digest), + sizeof(digest)); + } + + size_t j = 0; + // On Windows, when the size of output_ is zero, dereference of 0'th element + // results in a crash. C++11 solves this problem by adding a data() getter + // method to std::vector. + if (key_bytes_to_generate) { + client_write_key_ = base::StringPiece(reinterpret_cast(&output_[j]), + key_bytes_to_generate); + j += key_bytes_to_generate; + server_write_key_ = base::StringPiece(reinterpret_cast(&output_[j]), + key_bytes_to_generate); + j += key_bytes_to_generate; + } + + if (iv_bytes_to_generate) { + client_write_iv_ = base::StringPiece(reinterpret_cast(&output_[j]), + iv_bytes_to_generate); + j += iv_bytes_to_generate; + server_write_iv_ = base::StringPiece(reinterpret_cast(&output_[j]), + iv_bytes_to_generate); + j += iv_bytes_to_generate; + } + if (subkey_secret_bytes_to_generate) { + subkey_secret_ = base::StringPiece(reinterpret_cast(&output_[j]), + subkey_secret_bytes_to_generate); + } +} + +HKDF::~HKDF() { +} + +} // namespace crypto diff --git a/crypto/hkdf.h b/crypto/hkdf.h new file mode 100644 index 0000000000000..e91bccf5b4f38 --- /dev/null +++ b/crypto/hkdf.h @@ -0,0 +1,71 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CRYPTO_HKDF_H_ +#define CRYPTO_HKDF_H_ + +#include + +#include "base/basictypes.h" +#include "base/strings/string_piece.h" +#include "crypto/crypto_export.h" + +namespace crypto { + +// HKDF implements the key derivation function specified in RFC 5869 (using +// SHA-256) and outputs key material, as needed by QUIC. +// See https://tools.ietf.org/html/rfc5869 for details. +class CRYPTO_EXPORT HKDF { + public: + // |secret|: the input shared secret (or, from RFC 5869, the IKM). + // |salt|: an (optional) public salt / non-secret random value. While + // optional, callers are strongly recommended to provide a salt. There is no + // added security value in making this larger than the SHA-256 block size of + // 64 bytes. + // |info|: an (optional) label to distinguish different uses of HKDF. It is + // optional context and application specific information (can be a zero-length + // string). + // |key_bytes_to_generate|: the number of bytes of key material to generate + // for both client and server. + // |iv_bytes_to_generate|: the number of bytes of IV to generate for both + // client and server. + // |subkey_secret_bytes_to_generate|: the number of bytes of subkey secret to + // generate, shared between client and server. + HKDF(const base::StringPiece& secret, + const base::StringPiece& salt, + const base::StringPiece& info, + size_t key_bytes_to_generate, + size_t iv_bytes_to_generate, + size_t subkey_secret_bytes_to_generate); + ~HKDF(); + + base::StringPiece client_write_key() const { + return client_write_key_; + } + base::StringPiece client_write_iv() const { + return client_write_iv_; + } + base::StringPiece server_write_key() const { + return server_write_key_; + } + base::StringPiece server_write_iv() const { + return server_write_iv_; + } + base::StringPiece subkey_secret() const { + return subkey_secret_; + } + + private: + std::vector output_; + + base::StringPiece client_write_key_; + base::StringPiece server_write_key_; + base::StringPiece client_write_iv_; + base::StringPiece server_write_iv_; + base::StringPiece subkey_secret_; +}; + +} // namespace crypto + +#endif // CRYPTO_HKDF_H_ diff --git a/crypto/hkdf_unittest.cc b/crypto/hkdf_unittest.cc new file mode 100644 index 0000000000000..bcb19c5c10d18 --- /dev/null +++ b/crypto/hkdf_unittest.cc @@ -0,0 +1,94 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/hkdf.h" + +#include + +#include "base/strings/string_number_conversions.h" +#include "testing/gtest/include/gtest/gtest.h" + +using crypto::HKDF; + +namespace test { +namespace { + +struct HKDFTest { + const char* key_hex; + const char* salt_hex; + const char* info_hex; + const char* output_hex; +}; + +// These test cases are taken from +// https://tools.ietf.org/html/rfc5869#appendix-A. +static const HKDFTest kHKDFTests[] = {{ + "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", + "000102030405060708090a0b0c", + "f0f1f2f3f4f5f6f7f8f9", + "3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5" + "b887185865", + }, { + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021222324" + "25262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40414243444546474849" + "4a4b4c4d4e4f", + "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f8081828384" + "85868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9" + "aaabacadaeaf", + "b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4" + "d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9" + "fafbfcfdfeff", + "b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c59045a99ca" + "c7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71cc30c58179ec3e87c14c" + "01d5c1f3434f1d87", + }, { + "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", + "", + "", + "8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d201395fa" + "a4b61a96c8", + }, +}; + +TEST(HKDFTest, HKDF) { + for (size_t i = 0; i < arraysize(kHKDFTests); i++) { + const HKDFTest& test(kHKDFTests[i]); + SCOPED_TRACE(i); + + std::vector data; + ASSERT_TRUE(base::HexStringToBytes(test.key_hex, &data)); + const std::string key(reinterpret_cast(&data[0]), data.size()); + + data.clear(); + // |salt_hex| is optional and may be empty. + std::string salt(test.salt_hex); + if (!salt.empty()) { + ASSERT_TRUE(base::HexStringToBytes(salt, &data)); + salt.assign(reinterpret_cast(&data[0]), data.size()); + } + + data.clear(); + // |info_hex| is optional and may be empty. + std::string info(test.info_hex); + if (!info.empty()) { + ASSERT_TRUE(base::HexStringToBytes(info, &data)); + info.assign(reinterpret_cast(&data[0]), data.size()); + } + + data.clear(); + ASSERT_TRUE(base::HexStringToBytes(test.output_hex, &data)); + const std::string expected(reinterpret_cast(&data[0]), data.size()); + + // We set the key_length to the length of the expected output and then take + // the result from the first key, which is the client write key. + HKDF hkdf(key, salt, info, expected.size(), 0, 0); + + ASSERT_EQ(expected.size(), hkdf.client_write_key().size()); + EXPECT_EQ(0, memcmp(expected.data(), hkdf.client_write_key().data(), + expected.size())); + } +} + +} // namespace +} // namespace test diff --git a/crypto/hmac.cc b/crypto/hmac.cc new file mode 100644 index 0000000000000..c9a2b74d983ed --- /dev/null +++ b/crypto/hmac.cc @@ -0,0 +1,57 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/hmac.h" + +#include + +#include "base/logging.h" +#include "crypto/secure_util.h" +#include "crypto/symmetric_key.h" + +namespace crypto { + +bool HMAC::Init(SymmetricKey* key) { + std::string raw_key; + bool result = key->GetRawKey(&raw_key) && Init(raw_key); + // Zero out key copy. This might get optimized away, but one can hope. + // Using std::string to store key info at all is a larger problem. + std::fill(raw_key.begin(), raw_key.end(), 0); + return result; +} + +size_t HMAC::DigestLength() const { + switch (hash_alg_) { + case SHA1: + return 20; + case SHA256: + return 32; + default: + NOTREACHED(); + return 0; + } +} + +bool HMAC::Verify(const base::StringPiece& data, + const base::StringPiece& digest) const { + if (digest.size() != DigestLength()) + return false; + return VerifyTruncated(data, digest); +} + +bool HMAC::VerifyTruncated(const base::StringPiece& data, + const base::StringPiece& digest) const { + if (digest.empty()) + return false; + size_t digest_length = DigestLength(); + scoped_ptr computed_digest( + new unsigned char[digest_length]); + if (!Sign(data, computed_digest.get(), digest_length)) + return false; + + return SecureMemEqual(digest.data(), computed_digest.get(), + std::min(digest.size(), digest_length)); +} + +} // namespace crypto diff --git a/crypto/hmac.h b/crypto/hmac.h new file mode 100644 index 0000000000000..c7b22fa1bdff4 --- /dev/null +++ b/crypto/hmac.h @@ -0,0 +1,93 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Utility class for calculating the HMAC for a given message. We currently +// only support SHA1 for the hash algorithm, but this can be extended easily. + +#ifndef CRYPTO_HMAC_H_ +#define CRYPTO_HMAC_H_ + +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "base/memory/scoped_ptr.h" +#include "base/strings/string_piece.h" +#include "crypto/crypto_export.h" + +namespace crypto { + +// Simplify the interface and reduce includes by abstracting out the internals. +struct HMACPlatformData; +class SymmetricKey; + +class CRYPTO_EXPORT HMAC { + public: + // The set of supported hash functions. Extend as required. + enum HashAlgorithm { + SHA1, + SHA256, + }; + + explicit HMAC(HashAlgorithm hash_alg); + ~HMAC(); + + // Returns the length of digest that this HMAC will create. + size_t DigestLength() const; + + // TODO(abarth): Add a PreferredKeyLength() member function. + + // Initializes this instance using |key| of the length |key_length|. Call Init + // only once. It returns false on the second or later calls. + // + // NOTE: the US Federal crypto standard FIPS 198, Section 3 says: + // The size of the key, K, shall be equal to or greater than L/2, where L + // is the size of the hash function output. + // In FIPS 198-1 (and SP-800-107, which describes key size recommendations), + // this requirement is gone. But a system crypto library may still enforce + // this old requirement. If the key is shorter than this recommended value, + // Init() may fail. + bool Init(const unsigned char* key, size_t key_length) WARN_UNUSED_RESULT; + + // Initializes this instance using |key|. Call Init + // only once. It returns false on the second or later calls. + bool Init(SymmetricKey* key) WARN_UNUSED_RESULT; + + // Initializes this instance using |key|. Call Init only once. It returns + // false on the second or later calls. + bool Init(const base::StringPiece& key) WARN_UNUSED_RESULT { + return Init(reinterpret_cast(key.data()), + key.size()); + } + + // Calculates the HMAC for the message in |data| using the algorithm supplied + // to the constructor and the key supplied to the Init method. The HMAC is + // returned in |digest|, which has |digest_length| bytes of storage available. + bool Sign(const base::StringPiece& data, unsigned char* digest, + size_t digest_length) const WARN_UNUSED_RESULT; + + // Verifies that the HMAC for the message in |data| equals the HMAC provided + // in |digest|, using the algorithm supplied to the constructor and the key + // supplied to the Init method. Use of this method is strongly recommended + // over using Sign() with a manual comparison (such as memcmp), as such + // comparisons may result in side-channel disclosures, such as timing, that + // undermine the cryptographic integrity. |digest| must be exactly + // |DigestLength()| bytes long. + bool Verify(const base::StringPiece& data, + const base::StringPiece& digest) const WARN_UNUSED_RESULT; + + // Verifies a truncated HMAC, behaving identical to Verify(), except + // that |digest| is allowed to be smaller than |DigestLength()|. + bool VerifyTruncated( + const base::StringPiece& data, + const base::StringPiece& digest) const WARN_UNUSED_RESULT; + + private: + HashAlgorithm hash_alg_; + scoped_ptr plat_; + + DISALLOW_COPY_AND_ASSIGN(HMAC); +}; + +} // namespace crypto + +#endif // CRYPTO_HMAC_H_ diff --git a/crypto/hmac_nss.cc b/crypto/hmac_nss.cc new file mode 100644 index 0000000000000..e14282c916616 --- /dev/null +++ b/crypto/hmac_nss.cc @@ -0,0 +1,117 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/hmac.h" + +#include +#include + +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "crypto/nss_util.h" +#include "crypto/scoped_nss_types.h" + +namespace crypto { + +struct HMACPlatformData { + CK_MECHANISM_TYPE mechanism_; + ScopedPK11Slot slot_; + ScopedPK11SymKey sym_key_; +}; + +HMAC::HMAC(HashAlgorithm hash_alg) + : hash_alg_(hash_alg), plat_(new HMACPlatformData()) { + // Only SHA-1 and SHA-256 hash algorithms are supported. + switch (hash_alg_) { + case SHA1: + plat_->mechanism_ = CKM_SHA_1_HMAC; + break; + case SHA256: + plat_->mechanism_ = CKM_SHA256_HMAC; + break; + default: + NOTREACHED() << "Unsupported hash algorithm"; + break; + } +} + +HMAC::~HMAC() { +} + +bool HMAC::Init(const unsigned char *key, size_t key_length) { + EnsureNSSInit(); + + if (plat_->slot_.get()) { + // Init must not be called more than twice on the same HMAC object. + NOTREACHED(); + return false; + } + + plat_->slot_.reset(PK11_GetInternalSlot()); + if (!plat_->slot_.get()) { + NOTREACHED(); + return false; + } + + SECItem key_item; + key_item.type = siBuffer; + key_item.data = const_cast(key); // NSS API isn't const. + key_item.len = key_length; + + plat_->sym_key_.reset(PK11_ImportSymKey(plat_->slot_.get(), + plat_->mechanism_, + PK11_OriginUnwrap, + CKA_SIGN, + &key_item, + NULL)); + if (!plat_->sym_key_.get()) { + NOTREACHED(); + return false; + } + + return true; +} + +bool HMAC::Sign(const base::StringPiece& data, + unsigned char* digest, + size_t digest_length) const { + if (!plat_->sym_key_.get()) { + // Init has not been called before Sign. + NOTREACHED(); + return false; + } + + SECItem param = { siBuffer, NULL, 0 }; + ScopedPK11Context context(PK11_CreateContextBySymKey(plat_->mechanism_, + CKA_SIGN, + plat_->sym_key_.get(), + ¶m)); + if (!context.get()) { + NOTREACHED(); + return false; + } + + if (PK11_DigestBegin(context.get()) != SECSuccess) { + NOTREACHED(); + return false; + } + + if (PK11_DigestOp(context.get(), + reinterpret_cast(data.data()), + data.length()) != SECSuccess) { + NOTREACHED(); + return false; + } + + unsigned int len = 0; + if (PK11_DigestFinal(context.get(), + digest, &len, digest_length) != SECSuccess) { + NOTREACHED(); + return false; + } + + return true; +} + +} // namespace crypto diff --git a/crypto/hmac_openssl.cc b/crypto/hmac_openssl.cc new file mode 100644 index 0000000000000..ef20290e22320 --- /dev/null +++ b/crypto/hmac_openssl.cc @@ -0,0 +1,56 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/hmac.h" + +#include + +#include +#include + +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "base/stl_util.h" +#include "crypto/openssl_util.h" + +namespace crypto { + +struct HMACPlatformData { + std::vector key; +}; + +HMAC::HMAC(HashAlgorithm hash_alg) : hash_alg_(hash_alg) { + // Only SHA-1 and SHA-256 hash algorithms are supported now. + DCHECK(hash_alg_ == SHA1 || hash_alg_ == SHA256); +} + +bool HMAC::Init(const unsigned char* key, size_t key_length) { + // Init must not be called more than once on the same HMAC object. + DCHECK(!plat_); + plat_.reset(new HMACPlatformData()); + plat_->key.assign(key, key + key_length); + return true; +} + +HMAC::~HMAC() { + if (plat_) { + // Zero out key copy. + plat_->key.assign(plat_->key.size(), 0); + STLClearObject(&plat_->key); + } +} + +bool HMAC::Sign(const base::StringPiece& data, + unsigned char* digest, + size_t digest_length) const { + DCHECK(plat_); // Init must be called before Sign. + + ScopedOpenSSLSafeSizeBuffer result(digest, digest_length); + return !!::HMAC(hash_alg_ == SHA1 ? EVP_sha1() : EVP_sha256(), + vector_as_array(&plat_->key), plat_->key.size(), + reinterpret_cast(data.data()), + data.size(), result.safe_buffer(), NULL); +} + +} // namespace crypto diff --git a/crypto/hmac_unittest.cc b/crypto/hmac_unittest.cc new file mode 100644 index 0000000000000..91eccd68e231d --- /dev/null +++ b/crypto/hmac_unittest.cc @@ -0,0 +1,295 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include + +#include "crypto/hmac.h" +#include "testing/gtest/include/gtest/gtest.h" + +static const size_t kSHA1DigestSize = 20; +static const size_t kSHA256DigestSize = 32; + +static const char* kSimpleKey = + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"; +static const size_t kSimpleKeyLength = 80; + +static const struct { + const char *data; + const int data_len; + const char *digest; +} kSimpleHmacCases[] = { + { "Test Using Larger Than Block-Size Key - Hash Key First", 54, + "\xAA\x4A\xE5\xE1\x52\x72\xD0\x0E\x95\x70\x56\x37\xCE\x8A\x3B\x55" + "\xED\x40\x21\x12" }, + { "Test Using Larger Than Block-Size Key and Larger " + "Than One Block-Size Data", 73, + "\xE8\xE9\x9D\x0F\x45\x23\x7D\x78\x6D\x6B\xBA\xA7\x96\x5C\x78\x08" + "\xBB\xFF\x1A\x91" } +}; + +TEST(HMACTest, HmacSafeBrowsingResponseTest) { + const int kKeySize = 16; + + // Client key. + const unsigned char kClientKey[kKeySize] = + { 0xbf, 0xf6, 0x83, 0x4b, 0x3e, 0xa3, 0x23, 0xdd, + 0x96, 0x78, 0x70, 0x8e, 0xa1, 0x9d, 0x3b, 0x40 }; + + // Expected HMAC result using kMessage and kClientKey. + const unsigned char kReceivedHmac[kSHA1DigestSize] = + { 0xb9, 0x3c, 0xd6, 0xf0, 0x49, 0x47, 0xe2, 0x52, + 0x59, 0x7a, 0xbd, 0x1f, 0x2b, 0x4c, 0x83, 0xad, + 0x86, 0xd2, 0x48, 0x85 }; + + const char kMessage[] = +"n:1896\ni:goog-malware-shavar\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shav" +"ar_s_445-450\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_439-444\nu:s" +".ytimg.com/safebrowsing/rd/goog-malware-shavar_s_437\nu:s.ytimg.com/safebrowsi" +"ng/rd/goog-malware-shavar_s_436\nu:s.ytimg.com/safebrowsing/rd/goog-malware-sh" +"avar_s_433-435\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_431\nu:s.y" +"timg.com/safebrowsing/rd/goog-malware-shavar_s_430\nu:s.ytimg.com/safebrowsing" +"/rd/goog-malware-shavar_s_429\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shav" +"ar_s_428\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_426\nu:s.ytimg.c" +"om/safebrowsing/rd/goog-malware-shavar_s_424\nu:s.ytimg.com/safebrowsing/rd/go" +"og-malware-shavar_s_423\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_4" +"22\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_420\nu:s.ytimg.com/saf" +"ebrowsing/rd/goog-malware-shavar_s_419\nu:s.ytimg.com/safebrowsing/rd/goog-mal" +"ware-shavar_s_414\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_409-411" +"\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_405\nu:s.ytimg.com/safeb" +"rowsing/rd/goog-malware-shavar_s_404\nu:s.ytimg.com/safebrowsing/rd/goog-malwa" +"re-shavar_s_402\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_401\nu:s." +"ytimg.com/safebrowsing/rd/goog-malware-shavar_a_973-978\nu:s.ytimg.com/safebro" +"wsing/rd/goog-malware-shavar_a_937-972\nu:s.ytimg.com/safebrowsing/rd/goog-mal" +"ware-shavar_a_931-936\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_a_925" +"-930\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_a_919-924\ni:goog-phis" +"h-shavar\nu:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_2633\nu:s.ytimg.co" +"m/safebrowsing/rd/goog-phish-shavar_a_2632\nu:s.ytimg.com/safebrowsing/rd/goog" +"-phish-shavar_a_2629-2631\nu:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_2" +"626-2628\nu:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_2625\n"; + + std::string message_data(kMessage); + + crypto::HMAC hmac(crypto::HMAC::SHA1); + ASSERT_TRUE(hmac.Init(kClientKey, kKeySize)); + unsigned char calculated_hmac[kSHA1DigestSize]; + + EXPECT_TRUE(hmac.Sign(message_data, calculated_hmac, kSHA1DigestSize)); + EXPECT_EQ(0, memcmp(kReceivedHmac, calculated_hmac, kSHA1DigestSize)); +} + +// Test cases from RFC 2202 section 3 +TEST(HMACTest, RFC2202TestCases) { + const struct { + const char *key; + const int key_len; + const char *data; + const int data_len; + const char *digest; + } cases[] = { + { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B" + "\x0B\x0B\x0B\x0B", 20, + "Hi There", 8, + "\xB6\x17\x31\x86\x55\x05\x72\x64\xE2\x8B\xC0\xB6\xFB\x37\x8C\x8E" + "\xF1\x46\xBE\x00" }, + { "Jefe", 4, + "what do ya want for nothing?", 28, + "\xEF\xFC\xDF\x6A\xE5\xEB\x2F\xA2\xD2\x74\x16\xD5\xF1\x84\xDF\x9C" + "\x25\x9A\x7C\x79" }, + { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA", 20, + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD", 50, + "\x12\x5D\x73\x42\xB9\xAC\x11\xCD\x91\xA3\x9A\xF4\x8A\xA1\x7B\x4F" + "\x63\xF1\x75\xD3" }, + { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10" + "\x11\x12\x13\x14\x15\x16\x17\x18\x19", 25, + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD", 50, + "\x4C\x90\x07\xF4\x02\x62\x50\xC6\xBC\x84\x14\xF9\xBF\x50\xC8\x6C" + "\x2D\x72\x35\xDA" }, + { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C" + "\x0C\x0C\x0C\x0C", 20, + "Test With Truncation", 20, + "\x4C\x1A\x03\x42\x4B\x55\xE0\x7F\xE7\xF2\x7B\xE1\xD5\x8B\xB9\x32" + "\x4A\x9A\x5A\x04" }, + { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA", + 80, + "Test Using Larger Than Block-Size Key - Hash Key First", 54, + "\xAA\x4A\xE5\xE1\x52\x72\xD0\x0E\x95\x70\x56\x37\xCE\x8A\x3B\x55" + "\xED\x40\x21\x12" }, + { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA", + 80, + "Test Using Larger Than Block-Size Key and Larger " + "Than One Block-Size Data", 73, + "\xE8\xE9\x9D\x0F\x45\x23\x7D\x78\x6D\x6B\xBA\xA7\x96\x5C\x78\x08" + "\xBB\xFF\x1A\x91" } + }; + + for (size_t i = 0; i < arraysize(cases); ++i) { + crypto::HMAC hmac(crypto::HMAC::SHA1); + ASSERT_TRUE(hmac.Init(reinterpret_cast(cases[i].key), + cases[i].key_len)); + std::string data_string(cases[i].data, cases[i].data_len); + unsigned char digest[kSHA1DigestSize]; + EXPECT_TRUE(hmac.Sign(data_string, digest, kSHA1DigestSize)); + EXPECT_EQ(0, memcmp(cases[i].digest, digest, kSHA1DigestSize)); + } +} + +// TODO(wtc): add other test vectors from RFC 4231. +TEST(HMACTest, RFC4231TestCase6) { + unsigned char key[131]; + for (size_t i = 0; i < sizeof(key); ++i) + key[i] = 0xaa; + + std::string data = "Test Using Larger Than Block-Size Key - Hash Key First"; + ASSERT_EQ(54U, data.size()); + + static unsigned char kKnownHMACSHA256[] = { + 0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f, + 0x0d, 0x8a, 0x26, 0xaa, 0xcb, 0xf5, 0xb7, 0x7f, + 0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28, 0xc5, 0x14, + 0x05, 0x46, 0x04, 0x0f, 0x0e, 0xe3, 0x7f, 0x54 + }; + + crypto::HMAC hmac(crypto::HMAC::SHA256); + ASSERT_TRUE(hmac.Init(key, sizeof(key))); + unsigned char calculated_hmac[kSHA256DigestSize]; + + EXPECT_EQ(kSHA256DigestSize, hmac.DigestLength()); + EXPECT_TRUE(hmac.Sign(data, calculated_hmac, kSHA256DigestSize)); + EXPECT_EQ(0, memcmp(kKnownHMACSHA256, calculated_hmac, kSHA256DigestSize)); +} + +// Based on NSS's FIPS HMAC power-up self-test. +TEST(HMACTest, NSSFIPSPowerUpSelfTest) { + static const char kKnownMessage[] = + "The test message for the MD2, MD5, and SHA-1 hashing algorithms."; + + static const unsigned char kKnownSecretKey[] = { + 0x46, 0x69, 0x72, 0x65, 0x66, 0x6f, 0x78, 0x20, + 0x61, 0x6e, 0x64, 0x20, 0x54, 0x68, 0x75, 0x6e, + 0x64, 0x65, 0x72, 0x42, 0x69, 0x72, 0x64, 0x20, + 0x61, 0x72, 0x65, 0x20, 0x61, 0x77, 0x65, 0x73, + 0x6f, 0x6d, 0x65, 0x21, 0x00 + }; + + static const size_t kKnownSecretKeySize = sizeof(kKnownSecretKey); + + // HMAC-SHA-1 known answer (20 bytes). + static const unsigned char kKnownHMACSHA1[] = { + 0xd5, 0x85, 0xf6, 0x5b, 0x39, 0xfa, 0xb9, 0x05, + 0x3b, 0x57, 0x1d, 0x61, 0xe7, 0xb8, 0x84, 0x1e, + 0x5d, 0x0e, 0x1e, 0x11 + }; + + // HMAC-SHA-256 known answer (32 bytes). + static const unsigned char kKnownHMACSHA256[] = { + 0x05, 0x75, 0x9a, 0x9e, 0x70, 0x5e, 0xe7, 0x44, + 0xe2, 0x46, 0x4b, 0x92, 0x22, 0x14, 0x22, 0xe0, + 0x1b, 0x92, 0x8a, 0x0c, 0xfe, 0xf5, 0x49, 0xe9, + 0xa7, 0x1b, 0x56, 0x7d, 0x1d, 0x29, 0x40, 0x48 + }; + + std::string message_data(kKnownMessage); + + crypto::HMAC hmac(crypto::HMAC::SHA1); + ASSERT_TRUE(hmac.Init(kKnownSecretKey, kKnownSecretKeySize)); + unsigned char calculated_hmac[kSHA1DigestSize]; + + EXPECT_EQ(kSHA1DigestSize, hmac.DigestLength()); + EXPECT_TRUE(hmac.Sign(message_data, calculated_hmac, kSHA1DigestSize)); + EXPECT_EQ(0, memcmp(kKnownHMACSHA1, calculated_hmac, kSHA1DigestSize)); + EXPECT_TRUE(hmac.Verify( + message_data, + base::StringPiece(reinterpret_cast(kKnownHMACSHA1), + kSHA1DigestSize))); + EXPECT_TRUE(hmac.VerifyTruncated( + message_data, + base::StringPiece(reinterpret_cast(kKnownHMACSHA1), + kSHA1DigestSize / 2))); + + crypto::HMAC hmac2(crypto::HMAC::SHA256); + ASSERT_TRUE(hmac2.Init(kKnownSecretKey, kKnownSecretKeySize)); + unsigned char calculated_hmac2[kSHA256DigestSize]; + + EXPECT_TRUE(hmac2.Sign(message_data, calculated_hmac2, kSHA256DigestSize)); + EXPECT_EQ(0, memcmp(kKnownHMACSHA256, calculated_hmac2, kSHA256DigestSize)); +} + +TEST(HMACTest, HMACObjectReuse) { + crypto::HMAC hmac(crypto::HMAC::SHA1); + ASSERT_TRUE( + hmac.Init(reinterpret_cast(kSimpleKey), + kSimpleKeyLength)); + for (size_t i = 0; i < arraysize(kSimpleHmacCases); ++i) { + std::string data_string(kSimpleHmacCases[i].data, + kSimpleHmacCases[i].data_len); + unsigned char digest[kSHA1DigestSize]; + EXPECT_TRUE(hmac.Sign(data_string, digest, kSHA1DigestSize)); + EXPECT_EQ(0, memcmp(kSimpleHmacCases[i].digest, digest, kSHA1DigestSize)); + } +} + +TEST(HMACTest, Verify) { + crypto::HMAC hmac(crypto::HMAC::SHA1); + ASSERT_TRUE( + hmac.Init(reinterpret_cast(kSimpleKey), + kSimpleKeyLength)); + const char empty_digest[kSHA1DigestSize] = { 0 }; + for (size_t i = 0; i < arraysize(kSimpleHmacCases); ++i) { + // Expected results + EXPECT_TRUE(hmac.Verify( + base::StringPiece(kSimpleHmacCases[i].data, + kSimpleHmacCases[i].data_len), + base::StringPiece(kSimpleHmacCases[i].digest, + kSHA1DigestSize))); + // Mismatched size + EXPECT_FALSE(hmac.Verify( + base::StringPiece(kSimpleHmacCases[i].data, + kSimpleHmacCases[i].data_len), + base::StringPiece(kSimpleHmacCases[i].data, + kSimpleHmacCases[i].data_len))); + + // Expected size, mismatched data + EXPECT_FALSE(hmac.Verify( + base::StringPiece(kSimpleHmacCases[i].data, + kSimpleHmacCases[i].data_len), + base::StringPiece(empty_digest, kSHA1DigestSize))); + } +} + +TEST(HMACTest, EmptyKey) { + // Test vector from https://en.wikipedia.org/wiki/HMAC + const char* kExpectedDigest = + "\xFB\xDB\x1D\x1B\x18\xAA\x6C\x08\x32\x4B\x7D\x64\xB7\x1F\xB7\x63" + "\x70\x69\x0E\x1D"; + base::StringPiece data(""); + + crypto::HMAC hmac(crypto::HMAC::SHA1); + ASSERT_TRUE(hmac.Init(NULL, 0)); + + unsigned char digest[kSHA1DigestSize]; + EXPECT_TRUE(hmac.Sign(data, digest, kSHA1DigestSize)); + EXPECT_EQ(0, memcmp(kExpectedDigest, digest, kSHA1DigestSize)); + + EXPECT_TRUE(hmac.Verify( + data, base::StringPiece(kExpectedDigest, kSHA1DigestSize))); +} diff --git a/crypto/hmac_win.cc b/crypto/hmac_win.cc new file mode 100644 index 0000000000000..99b3a60d57efb --- /dev/null +++ b/crypto/hmac_win.cc @@ -0,0 +1,209 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/hmac.h" + +#include + +#include +#include + +#include "base/logging.h" +#include "crypto/scoped_capi_types.h" +#include "crypto/third_party/nss/chromium-blapi.h" +#include "crypto/third_party/nss/chromium-sha256.h" +#include "crypto/wincrypt_shim.h" + +namespace crypto { + +namespace { + +// Implementation of HMAC-SHA-256: +// +// SHA-256 is supported in Windows XP SP3 or later. We still need to support +// Windows XP SP2, so unfortunately we have to implement HMAC-SHA-256 here. + +enum { + SHA256_BLOCK_SIZE = 64 // Block size (in bytes) of the input to SHA-256. +}; + +// NSS doesn't accept size_t for text size, divide the data into smaller +// chunks as needed. +void Wrapped_SHA256_Update(SHA256Context* ctx, const unsigned char* text, + size_t text_len) { + const unsigned int kChunkSize = 1 << 30; + while (text_len > kChunkSize) { + SHA256_Update(ctx, text, kChunkSize); + text += kChunkSize; + text_len -= kChunkSize; + } + SHA256_Update(ctx, text, (unsigned int)text_len); +} + +// See FIPS 198: The Keyed-Hash Message Authentication Code (HMAC). +void ComputeHMACSHA256(const unsigned char* key, size_t key_len, + const unsigned char* text, size_t text_len, + unsigned char* output, size_t output_len) { + SHA256Context ctx; + + // Pre-process the key, if necessary. + unsigned char key0[SHA256_BLOCK_SIZE]; + if (key_len > SHA256_BLOCK_SIZE) { + SHA256_Begin(&ctx); + Wrapped_SHA256_Update(&ctx, key, key_len); + SHA256_End(&ctx, key0, NULL, SHA256_LENGTH); + memset(key0 + SHA256_LENGTH, 0, SHA256_BLOCK_SIZE - SHA256_LENGTH); + } else { + memcpy(key0, key, key_len); + if (key_len < SHA256_BLOCK_SIZE) + memset(key0 + key_len, 0, SHA256_BLOCK_SIZE - key_len); + } + + unsigned char padded_key[SHA256_BLOCK_SIZE]; + unsigned char inner_hash[SHA256_LENGTH]; + + // XOR key0 with ipad. + for (int i = 0; i < SHA256_BLOCK_SIZE; ++i) + padded_key[i] = key0[i] ^ 0x36; + + // Compute the inner hash. + SHA256_Begin(&ctx); + SHA256_Update(&ctx, padded_key, SHA256_BLOCK_SIZE); + Wrapped_SHA256_Update(&ctx, text, text_len); + SHA256_End(&ctx, inner_hash, NULL, SHA256_LENGTH); + + // XOR key0 with opad. + for (int i = 0; i < SHA256_BLOCK_SIZE; ++i) + padded_key[i] = key0[i] ^ 0x5c; + + // Compute the outer hash. + SHA256_Begin(&ctx); + SHA256_Update(&ctx, padded_key, SHA256_BLOCK_SIZE); + SHA256_Update(&ctx, inner_hash, SHA256_LENGTH); + SHA256_End(&ctx, output, NULL, (unsigned int) output_len); +} + +} // namespace + +struct HMACPlatformData { + ~HMACPlatformData() { + if (!raw_key_.empty()) { + SecureZeroMemory(&raw_key_[0], raw_key_.size()); + } + + // Destroy the key before releasing the provider. + key_.reset(); + } + + ScopedHCRYPTPROV provider_; + ScopedHCRYPTKEY key_; + + // For HMAC-SHA-256 only. + std::vector raw_key_; +}; + +HMAC::HMAC(HashAlgorithm hash_alg) + : hash_alg_(hash_alg), plat_(new HMACPlatformData()) { + // Only SHA-1 and SHA-256 hash algorithms are supported now. + DCHECK(hash_alg_ == SHA1 || hash_alg_ == SHA256); +} + +bool HMAC::Init(const unsigned char* key, size_t key_length) { + if (plat_->provider_ || plat_->key_ || !plat_->raw_key_.empty()) { + // Init must not be called more than once on the same HMAC object. + NOTREACHED(); + return false; + } + + if (hash_alg_ == SHA256) { + plat_->raw_key_.assign(key, key + key_length); + return true; + } + + if (!CryptAcquireContext(plat_->provider_.receive(), NULL, NULL, + PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { + NOTREACHED(); + return false; + } + + // This code doesn't work on Win2k because PLAINTEXTKEYBLOB and + // CRYPT_IPSEC_HMAC_KEY are not supported on Windows 2000. PLAINTEXTKEYBLOB + // allows the import of an unencrypted key. For Win2k support, a cubmbersome + // exponent-of-one key procedure must be used: + // http://support.microsoft.com/kb/228786/en-us + // CRYPT_IPSEC_HMAC_KEY allows keys longer than 16 bytes. + + struct KeyBlob { + BLOBHEADER header; + DWORD key_size; + BYTE key_data[1]; + }; + size_t key_blob_size = std::max(offsetof(KeyBlob, key_data) + key_length, + sizeof(KeyBlob)); + std::vector key_blob_storage = std::vector(key_blob_size); + KeyBlob* key_blob = reinterpret_cast(&key_blob_storage[0]); + key_blob->header.bType = PLAINTEXTKEYBLOB; + key_blob->header.bVersion = CUR_BLOB_VERSION; + key_blob->header.reserved = 0; + key_blob->header.aiKeyAlg = CALG_RC2; + key_blob->key_size = static_cast(key_length); + memcpy(key_blob->key_data, key, key_length); + + if (!CryptImportKey(plat_->provider_, &key_blob_storage[0], + (DWORD)key_blob_storage.size(), 0, + CRYPT_IPSEC_HMAC_KEY, plat_->key_.receive())) { + NOTREACHED(); + return false; + } + + // Destroy the copy of the key. + SecureZeroMemory(key_blob->key_data, key_length); + + return true; +} + +HMAC::~HMAC() { +} + +bool HMAC::Sign(const base::StringPiece& data, + unsigned char* digest, + size_t digest_length) const { + if (hash_alg_ == SHA256) { + if (plat_->raw_key_.empty()) + return false; + ComputeHMACSHA256(&plat_->raw_key_[0], plat_->raw_key_.size(), + reinterpret_cast(data.data()), + data.size(), digest, digest_length); + return true; + } + + if (!plat_->provider_ || !plat_->key_) + return false; + + if (hash_alg_ != SHA1) { + NOTREACHED(); + return false; + } + + ScopedHCRYPTHASH hash; + if (!CryptCreateHash(plat_->provider_, CALG_HMAC, plat_->key_, 0, + hash.receive())) + return false; + + HMAC_INFO hmac_info; + memset(&hmac_info, 0, sizeof(hmac_info)); + hmac_info.HashAlgid = CALG_SHA1; + if (!CryptSetHashParam(hash, HP_HMAC_INFO, + reinterpret_cast(&hmac_info), 0)) + return false; + + if (!CryptHashData(hash, reinterpret_cast(data.data()), + static_cast(data.size()), 0)) + return false; + + DWORD sha1_size = static_cast(digest_length); + return !!CryptGetHashParam(hash, HP_HASHVAL, digest, &sha1_size, 0); +} + +} // namespace crypto diff --git a/crypto/mac_security_services_lock.cc b/crypto/mac_security_services_lock.cc new file mode 100644 index 0000000000000..c0b8712089e9c --- /dev/null +++ b/crypto/mac_security_services_lock.cc @@ -0,0 +1,42 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/mac_security_services_lock.h" + +#include "base/memory/singleton.h" +#include "base/synchronization/lock.h" + +namespace { + +// This singleton pertains to Apple's wrappers over their own CSSM handles, +// as opposed to our own CSSM_CSP_HANDLE in cssm_init.cc. +class SecurityServicesSingleton { + public: + static SecurityServicesSingleton* GetInstance() { + return Singleton >::get(); + } + + base::Lock& lock() { return lock_; } + + private: + friend struct DefaultSingletonTraits; + + SecurityServicesSingleton() {} + ~SecurityServicesSingleton() {} + + base::Lock lock_; + + DISALLOW_COPY_AND_ASSIGN(SecurityServicesSingleton); +}; + +} // namespace + +namespace crypto { + +base::Lock& GetMacSecurityServicesLock() { + return SecurityServicesSingleton::GetInstance()->lock(); +} + +} // namespace crypto diff --git a/crypto/mac_security_services_lock.h b/crypto/mac_security_services_lock.h new file mode 100644 index 0000000000000..fe56c6f38e26b --- /dev/null +++ b/crypto/mac_security_services_lock.h @@ -0,0 +1,25 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CRYPTO_MAC_SECURITY_SERVICES_LOCK_H_ +#define CRYPTO_MAC_SECURITY_SERVICES_LOCK_H_ + +#include "crypto/crypto_export.h" + +namespace base { +class Lock; +} + +namespace crypto { + +// The Mac OS X certificate and key management wrappers over CSSM are not +// thread-safe. In particular, code that accesses the CSSM database is +// problematic. +// +// http://developer.apple.com/mac/library/documentation/Security/Reference/certifkeytrustservices/Reference/reference.html +CRYPTO_EXPORT base::Lock& GetMacSecurityServicesLock(); + +} // namespace crypto + +#endif // CRYPTO_MAC_SECURITY_SERVICES_LOCK_H_ diff --git a/crypto/mock_apple_keychain.cc b/crypto/mock_apple_keychain.cc new file mode 100644 index 0000000000000..a1faa65382a78 --- /dev/null +++ b/crypto/mock_apple_keychain.cc @@ -0,0 +1,84 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/logging.h" +#include "base/metrics/histogram.h" +#include "base/time/time.h" +#include "crypto/mock_apple_keychain.h" + +namespace { + +// Adds an entry to a local histogram to indicate that the Apple Keychain would +// have been accessed, if this class were not a mock of the Apple Keychain. +void IncrementKeychainAccessHistogram() { + // This local histogram is accessed by Telemetry to track the number of times + // the keychain is accessed, since keychain access is known to be synchronous + // and slow. + LOCAL_HISTOGRAM_BOOLEAN("OSX.Keychain.Access", true); +} + +} // namespace + +namespace crypto { + +OSStatus MockAppleKeychain::FindGenericPassword( + CFTypeRef keychainOrArray, + UInt32 serviceNameLength, + const char* serviceName, + UInt32 accountNameLength, + const char* accountName, + UInt32* passwordLength, + void** passwordData, + SecKeychainItemRef* itemRef) const { + IncrementKeychainAccessHistogram(); + + // When simulating |noErr|, return canned |passwordData| and + // |passwordLength|. Otherwise, just return given code. + if (find_generic_result_ == noErr) { + static const char kPassword[] = "my_password"; + DCHECK(passwordData); + // The function to free this data is mocked so the cast is fine. + *passwordData = const_cast(kPassword); + DCHECK(passwordLength); + *passwordLength = arraysize(kPassword); + password_data_count_++; + } + + return find_generic_result_; +} + +OSStatus MockAppleKeychain::ItemFreeContent(SecKeychainAttributeList* attrList, + void* data) const { + // No-op. + password_data_count_--; + return noErr; +} + +OSStatus MockAppleKeychain::AddGenericPassword( + SecKeychainRef keychain, + UInt32 serviceNameLength, + const char* serviceName, + UInt32 accountNameLength, + const char* accountName, + UInt32 passwordLength, + const void* passwordData, + SecKeychainItemRef* itemRef) const { + IncrementKeychainAccessHistogram(); + + called_add_generic_ = true; + + DCHECK_GT(passwordLength, 0U); + DCHECK(passwordData); + add_generic_password_ = + std::string(const_cast(static_cast(passwordData)), + passwordLength); + return noErr; +} + +std::string MockAppleKeychain::GetEncryptionPassword() const { + IncrementKeychainAccessHistogram(); + return "mock_password"; +} + +} // namespace crypto diff --git a/crypto/mock_apple_keychain.h b/crypto/mock_apple_keychain.h new file mode 100644 index 0000000000000..f73d3a6466ed2 --- /dev/null +++ b/crypto/mock_apple_keychain.h @@ -0,0 +1,256 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CRYPTO_MOCK_KEYCHAIN_MAC_H_ +#define CRYPTO_MOCK_KEYCHAIN_MAC_H_ + +#include + +#include +#include +#include +#include + +#include "base/compiler_specific.h" +#include "crypto/apple_keychain.h" + +namespace crypto { + +// Mock Keychain wrapper for testing code that interacts with the OS X +// Keychain. Implemented by storing SecKeychainAttributeList and +// KeychainPasswordData values in separate mutable containers and +// mapping them to integer keys. +// +// Note that "const" is pretty much meaningless for this class; the const-ness +// of AppleKeychain doesn't apply to the actual keychain data, so all of the +// Mock data is mutable; don't assume that it won't change over the life of +// tests. +class CRYPTO_EXPORT MockAppleKeychain : public AppleKeychain { + public: + MockAppleKeychain(); + ~MockAppleKeychain() override; + + // AppleKeychain implementation. + OSStatus FindGenericPassword(CFTypeRef keychainOrArray, + UInt32 serviceNameLength, + const char* serviceName, + UInt32 accountNameLength, + const char* accountName, + UInt32* passwordLength, + void** passwordData, + SecKeychainItemRef* itemRef) const override; + OSStatus ItemFreeContent(SecKeychainAttributeList* attrList, + void* data) const override; + OSStatus AddGenericPassword(SecKeychainRef keychain, + UInt32 serviceNameLength, + const char* serviceName, + UInt32 accountNameLength, + const char* accountName, + UInt32 passwordLength, + const void* passwordData, + SecKeychainItemRef* itemRef) const override; + + // Returns the password that OSCrypt uses to generate its encryption key. + std::string GetEncryptionPassword() const; + +#if !defined(OS_IOS) + OSStatus ItemCopyAttributesAndData(SecKeychainItemRef itemRef, + SecKeychainAttributeInfo* info, + SecItemClass* itemClass, + SecKeychainAttributeList** attrList, + UInt32* length, + void** outData) const override; + // Pass "fail_me" as the data to get errSecAuthFailed. + OSStatus ItemModifyAttributesAndData(SecKeychainItemRef itemRef, + const SecKeychainAttributeList* attrList, + UInt32 length, + const void* data) const override; + OSStatus ItemFreeAttributesAndData(SecKeychainAttributeList* attrList, + void* data) const override; + OSStatus ItemDelete(SecKeychainItemRef itemRef) const override; + OSStatus SearchCreateFromAttributes( + CFTypeRef keychainOrArray, + SecItemClass itemClass, + const SecKeychainAttributeList* attrList, + SecKeychainSearchRef* searchRef) const override; + OSStatus SearchCopyNext(SecKeychainSearchRef searchRef, + SecKeychainItemRef* itemRef) const override; + // Pass "some.domain.com" as the serverName to get errSecDuplicateItem. + OSStatus AddInternetPassword(SecKeychainRef keychain, + UInt32 serverNameLength, + const char* serverName, + UInt32 securityDomainLength, + const char* securityDomain, + UInt32 accountNameLength, + const char* accountName, + UInt32 pathLength, + const char* path, + UInt16 port, + SecProtocolType protocol, + SecAuthenticationType authenticationType, + UInt32 passwordLength, + const void* passwordData, + SecKeychainItemRef* itemRef) const override; + void Free(CFTypeRef ref) const override; + + // Return the counts of objects returned by Create/Copy functions but never + // Free'd as they should have been. + int UnfreedSearchCount() const; + int UnfreedKeychainItemCount() const; + int UnfreedAttributeDataCount() const; + + // Returns true if all items added with AddInternetPassword have a creator + // code set. + bool CreatorCodesSetForAddedItems() const; + + struct KeychainTestData { + const SecAuthenticationType auth_type; + const char* server; + const SecProtocolType protocol; + const char* path; + const UInt32 port; + const char* security_domain; + const char* creation_date; + const char* username; + const char* password; + const bool negative_item; + }; + // Adds a keychain item with the given info to the test set. + void AddTestItem(const KeychainTestData& item_data); + + void set_locked(bool locked) { locked_ = locked; } +#endif // !defined(OS_IOS) + + // |FindGenericPassword()| can return different results depending on user + // interaction with the system Keychain. For mocking purposes we allow the + // user of this class to specify the result code of the + // |FindGenericPassword()| call so we can simulate the result of different + // user interactions. + void set_find_generic_result(OSStatus result) { + find_generic_result_ = result; + } + + // Returns the true if |AddGenericPassword()| was called. + bool called_add_generic() const { return called_add_generic_; } + + // Returns the value of the password set when |AddGenericPassword()| was + // called. + std::string add_generic_password() const { return add_generic_password_; } + + // Returns the number of allocations - deallocations for password data. + int password_data_count() const { return password_data_count_; } + + private: + // Type used for the keys in the std::map(s) and MockAppleKeychain items. + typedef uintptr_t MockKeychainItemType; + + // Type of the map holding the mock keychain attributes. + typedef std::map + MockKeychainAttributesMap; + +#if !defined(OS_IOS) + // Returns true if the keychain already contains a password that matches the + // attributes provided. + bool AlreadyContainsInternetPassword( + UInt32 serverNameLength, + const char* serverName, + UInt32 securityDomainLength, + const char* securityDomain, + UInt32 accountNameLength, + const char* accountName, + UInt32 pathLength, + const char* path, + UInt16 port, + SecProtocolType protocol, + SecAuthenticationType authenticationType) const; + // Initializes storage for keychain data at |key|. + void InitializeKeychainData(MockKeychainItemType key) const; + // Sets the data and length of |tag| in the item-th test item. + void SetTestDataBytes( + MockKeychainItemType item, + UInt32 tag, + const void* data, + size_t length); + // Sets the data and length of |tag| in the item-th test item based on + // |value|. The null-terminator will not be included; the Keychain Services + // docs don't indicate whether it is or not, so clients should not assume + // that it will be. + void SetTestDataString(MockKeychainItemType item, + UInt32 tag, + const char* value); + // Sets the data of the corresponding attribute of the item-th test item to + // |value|. Assumes that the space has alread been allocated, and the length + // set. + void SetTestDataPort(MockKeychainItemType item, UInt32 value); + void SetTestDataProtocol(MockKeychainItemType item, SecProtocolType value); + void SetTestDataAuthType(MockKeychainItemType item, + SecAuthenticationType value); + void SetTestDataNegativeItem(MockKeychainItemType item, Boolean value); + void SetTestDataCreator(MockKeychainItemType item, OSType value); + // Sets the password data and length for the item-th test item. + void SetTestDataPasswordBytes(MockKeychainItemType item, + const void* data, + size_t length); + // Sets the password for the item-th test item. As with SetTestDataString, + // the data will not be null-terminated. + void SetTestDataPasswordString(MockKeychainItemType item, const char* value); + + // Returns the address of the attribute in attribute_list with tag |tag|. + static SecKeychainAttribute* AttributeWithTag( + const SecKeychainAttributeList& attribute_list, + UInt32 tag); + + static const SecKeychainSearchRef kDummySearchRef; + + // Simulates the state when the user refuses to unclock the Keychain. + // If true, reading and modifying a password value result in errSecAuthFailed. + bool locked_; + + typedef struct KeychainPasswordData { + KeychainPasswordData() : data(NULL), length(0) {} + void* data; + UInt32 length; + } KeychainPasswordData; + + // Mutable because the MockAppleKeychain API requires its internal keychain + // storage to be modifiable by users of this class. + mutable MockKeychainAttributesMap keychain_attr_list_; + mutable std::map keychain_data_; + mutable MockKeychainItemType next_item_key_; + + // Tracks the items that should be returned in subsequent calls to + // SearchCopyNext, based on the last call to SearchCreateFromAttributes. + // We can't handle multiple active searches, since we don't track the search + // ref we return, but we don't need to for our mocking. + mutable std::vector remaining_search_results_; + + // Track copies and releases to make sure they balance. Really these should + // be maps to track per item, but this should be good enough to catch + // real mistakes. + mutable int search_copy_count_; + mutable int keychain_item_copy_count_; + mutable int attribute_data_copy_count_; + + // Tracks which items (by key) were added with AddInternetPassword. + mutable std::set added_via_api_; +#endif // !defined(OS_IOS) + + // Result code for the |FindGenericPassword()| method. + OSStatus find_generic_result_; + + // Records whether |AddGenericPassword()| gets called. + mutable bool called_add_generic_; + + // Tracks the allocations and frees of password data in |FindGenericPassword| + // and |ItemFreeContent|. + mutable int password_data_count_; + + // Records the password being set when |AddGenericPassword()| gets called. + mutable std::string add_generic_password_; +}; + +} // namespace crypto + +#endif // CRYPTO_MOCK_KEYCHAIN_MAC_H_ diff --git a/crypto/mock_apple_keychain_ios.cc b/crypto/mock_apple_keychain_ios.cc new file mode 100644 index 0000000000000..9e8a164668536 --- /dev/null +++ b/crypto/mock_apple_keychain_ios.cc @@ -0,0 +1,20 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/logging.h" +#include "base/time/time.h" +#include "crypto/mock_apple_keychain.h" + +namespace crypto { + +MockAppleKeychain::MockAppleKeychain() + : find_generic_result_(noErr), + called_add_generic_(false), + password_data_count_(0) { +} + +MockAppleKeychain::~MockAppleKeychain() { +} + +} // namespace crypto diff --git a/crypto/mock_apple_keychain_mac.cc b/crypto/mock_apple_keychain_mac.cc new file mode 100644 index 0000000000000..5f33e5b209932 --- /dev/null +++ b/crypto/mock_apple_keychain_mac.cc @@ -0,0 +1,519 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/logging.h" +#include "base/time/time.h" +#include "crypto/mock_apple_keychain.h" + +namespace crypto { + +// static +const SecKeychainSearchRef MockAppleKeychain::kDummySearchRef = + reinterpret_cast(1000); + +MockAppleKeychain::MockAppleKeychain() + : locked_(false), + next_item_key_(0), + search_copy_count_(0), + keychain_item_copy_count_(0), + attribute_data_copy_count_(0), + find_generic_result_(noErr), + called_add_generic_(false), + password_data_count_(0) {} + +void MockAppleKeychain::InitializeKeychainData(MockKeychainItemType key) const { + UInt32 tags[] = { kSecAccountItemAttr, + kSecServerItemAttr, + kSecPortItemAttr, + kSecPathItemAttr, + kSecProtocolItemAttr, + kSecAuthenticationTypeItemAttr, + kSecSecurityDomainItemAttr, + kSecCreationDateItemAttr, + kSecNegativeItemAttr, + kSecCreatorItemAttr }; + keychain_attr_list_[key] = SecKeychainAttributeList(); + keychain_data_[key] = KeychainPasswordData(); + keychain_attr_list_[key].count = arraysize(tags); + keychain_attr_list_[key].attr = static_cast( + calloc(keychain_attr_list_[key].count, sizeof(SecKeychainAttribute))); + for (unsigned int i = 0; i < keychain_attr_list_[key].count; ++i) { + keychain_attr_list_[key].attr[i].tag = tags[i]; + size_t data_size = 0; + switch (tags[i]) { + case kSecPortItemAttr: + data_size = sizeof(UInt32); + break; + case kSecProtocolItemAttr: + data_size = sizeof(SecProtocolType); + break; + case kSecAuthenticationTypeItemAttr: + data_size = sizeof(SecAuthenticationType); + break; + case kSecNegativeItemAttr: + data_size = sizeof(Boolean); + break; + case kSecCreatorItemAttr: + data_size = sizeof(OSType); + break; + } + if (data_size > 0) { + keychain_attr_list_[key].attr[i].length = data_size; + keychain_attr_list_[key].attr[i].data = calloc(1, data_size); + } + } +} + +MockAppleKeychain::~MockAppleKeychain() { + for (MockKeychainAttributesMap::iterator it = keychain_attr_list_.begin(); + it != keychain_attr_list_.end(); + ++it) { + for (unsigned int i = 0; i < it->second.count; ++i) { + if (it->second.attr[i].data) + free(it->second.attr[i].data); + } + free(it->second.attr); + if (keychain_data_[it->first].data) + free(keychain_data_[it->first].data); + } + keychain_attr_list_.clear(); + keychain_data_.clear(); +} + +SecKeychainAttribute* MockAppleKeychain::AttributeWithTag( + const SecKeychainAttributeList& attribute_list, + UInt32 tag) { + int attribute_index = -1; + for (unsigned int i = 0; i < attribute_list.count; ++i) { + if (attribute_list.attr[i].tag == tag) { + attribute_index = i; + break; + } + } + if (attribute_index == -1) { + NOTREACHED() << "Unsupported attribute: " << tag; + return NULL; + } + return &(attribute_list.attr[attribute_index]); +} + +void MockAppleKeychain::SetTestDataBytes(MockKeychainItemType item, + UInt32 tag, + const void* data, + size_t length) { + SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[item], + tag); + attribute->length = length; + if (length > 0) { + if (attribute->data) + free(attribute->data); + attribute->data = malloc(length); + CHECK(attribute->data); + memcpy(attribute->data, data, length); + } else { + attribute->data = NULL; + } +} + +void MockAppleKeychain::SetTestDataString(MockKeychainItemType item, + UInt32 tag, + const char* value) { + SetTestDataBytes(item, tag, value, value ? strlen(value) : 0); +} + +void MockAppleKeychain::SetTestDataPort(MockKeychainItemType item, + UInt32 value) { + SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[item], + kSecPortItemAttr); + UInt32* data = static_cast(attribute->data); + *data = value; +} + +void MockAppleKeychain::SetTestDataProtocol(MockKeychainItemType item, + SecProtocolType value) { + SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[item], + kSecProtocolItemAttr); + SecProtocolType* data = static_cast(attribute->data); + *data = value; +} + +void MockAppleKeychain::SetTestDataAuthType(MockKeychainItemType item, + SecAuthenticationType value) { + SecKeychainAttribute* attribute = AttributeWithTag( + keychain_attr_list_[item], kSecAuthenticationTypeItemAttr); + SecAuthenticationType* data = static_cast( + attribute->data); + *data = value; +} + +void MockAppleKeychain::SetTestDataNegativeItem(MockKeychainItemType item, + Boolean value) { + SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[item], + kSecNegativeItemAttr); + Boolean* data = static_cast(attribute->data); + *data = value; +} + +void MockAppleKeychain::SetTestDataCreator(MockKeychainItemType item, + OSType value) { + SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[item], + kSecCreatorItemAttr); + OSType* data = static_cast(attribute->data); + *data = value; +} + +void MockAppleKeychain::SetTestDataPasswordBytes(MockKeychainItemType item, + const void* data, + size_t length) { + keychain_data_[item].length = length; + if (length > 0) { + if (keychain_data_[item].data) + free(keychain_data_[item].data); + keychain_data_[item].data = malloc(length); + memcpy(keychain_data_[item].data, data, length); + } else { + keychain_data_[item].data = NULL; + } +} + +void MockAppleKeychain::SetTestDataPasswordString(MockKeychainItemType item, + const char* value) { + SetTestDataPasswordBytes(item, value, value ? strlen(value) : 0); +} + +OSStatus MockAppleKeychain::ItemCopyAttributesAndData( + SecKeychainItemRef itemRef, + SecKeychainAttributeInfo* info, + SecItemClass* itemClass, + SecKeychainAttributeList** attrList, + UInt32* length, + void** outData) const { + DCHECK(itemRef); + MockKeychainItemType key = + reinterpret_cast(itemRef) - 1; + if (keychain_attr_list_.find(key) == keychain_attr_list_.end()) + return errSecInvalidItemRef; + + DCHECK(!itemClass); // itemClass not implemented in the Mock. + if (locked_ && outData) + return errSecAuthFailed; + + if (attrList) + *attrList = &(keychain_attr_list_[key]); + if (outData) { + *outData = keychain_data_[key].data; + DCHECK(length); + *length = keychain_data_[key].length; + } + + ++attribute_data_copy_count_; + return noErr; +} + +OSStatus MockAppleKeychain::ItemModifyAttributesAndData( + SecKeychainItemRef itemRef, + const SecKeychainAttributeList* attrList, + UInt32 length, + const void* data) const { + DCHECK(itemRef); + if (locked_) + return errSecAuthFailed; + const char* fail_trigger = "fail_me"; + if (length == strlen(fail_trigger) && + memcmp(data, fail_trigger, length) == 0) { + return errSecAuthFailed; + } + + MockKeychainItemType key = + reinterpret_cast(itemRef) - 1; + if (keychain_attr_list_.find(key) == keychain_attr_list_.end()) + return errSecInvalidItemRef; + + MockAppleKeychain* mutable_this = const_cast(this); + if (attrList) { + for (UInt32 change_attr = 0; change_attr < attrList->count; ++change_attr) { + if (attrList->attr[change_attr].tag == kSecCreatorItemAttr) { + void* data = attrList->attr[change_attr].data; + mutable_this->SetTestDataCreator(key, *(static_cast(data))); + } else { + NOTIMPLEMENTED(); + } + } + } + if (data) + mutable_this->SetTestDataPasswordBytes(key, data, length); + return noErr; +} + +OSStatus MockAppleKeychain::ItemFreeAttributesAndData( + SecKeychainAttributeList* attrList, + void* data) const { + --attribute_data_copy_count_; + return noErr; +} + +OSStatus MockAppleKeychain::ItemDelete(SecKeychainItemRef itemRef) const { + if (locked_) + return errSecAuthFailed; + MockKeychainItemType key = + reinterpret_cast(itemRef) - 1; + + for (unsigned int i = 0; i < keychain_attr_list_[key].count; ++i) { + if (keychain_attr_list_[key].attr[i].data) + free(keychain_attr_list_[key].attr[i].data); + } + free(keychain_attr_list_[key].attr); + if (keychain_data_[key].data) + free(keychain_data_[key].data); + + keychain_attr_list_.erase(key); + keychain_data_.erase(key); + added_via_api_.erase(key); + return noErr; +} + +OSStatus MockAppleKeychain::SearchCreateFromAttributes( + CFTypeRef keychainOrArray, + SecItemClass itemClass, + const SecKeychainAttributeList* attrList, + SecKeychainSearchRef* searchRef) const { + // Figure out which of our mock items matches, and set up the array we'll use + // to generate results out of SearchCopyNext. + remaining_search_results_.clear(); + for (MockKeychainAttributesMap::const_iterator it = + keychain_attr_list_.begin(); + it != keychain_attr_list_.end(); + ++it) { + bool mock_item_matches = true; + for (UInt32 search_attr = 0; search_attr < attrList->count; ++search_attr) { + SecKeychainAttribute* mock_attribute = + AttributeWithTag(it->second, attrList->attr[search_attr].tag); + if (mock_attribute->length != attrList->attr[search_attr].length || + memcmp(mock_attribute->data, attrList->attr[search_attr].data, + attrList->attr[search_attr].length) != 0) { + mock_item_matches = false; + break; + } + } + if (mock_item_matches) + remaining_search_results_.push_back(it->first); + } + + DCHECK(searchRef); + *searchRef = kDummySearchRef; + ++search_copy_count_; + return noErr; +} + +bool MockAppleKeychain::AlreadyContainsInternetPassword( + UInt32 serverNameLength, + const char* serverName, + UInt32 securityDomainLength, + const char* securityDomain, + UInt32 accountNameLength, + const char* accountName, + UInt32 pathLength, + const char* path, + UInt16 port, + SecProtocolType protocol, + SecAuthenticationType authenticationType) const { + for (MockKeychainAttributesMap::const_iterator it = + keychain_attr_list_.begin(); + it != keychain_attr_list_.end(); + ++it) { + SecKeychainAttribute* attribute; + attribute = AttributeWithTag(it->second, kSecServerItemAttr); + if ((attribute->length != serverNameLength) || + (attribute->data == NULL && *serverName != '\0') || + (attribute->data != NULL && *serverName == '\0') || + strncmp(serverName, + (const char*) attribute->data, + serverNameLength) != 0) { + continue; + } + attribute = AttributeWithTag(it->second, kSecSecurityDomainItemAttr); + if ((attribute->length != securityDomainLength) || + (attribute->data == NULL && *securityDomain != '\0') || + (attribute->data != NULL && *securityDomain == '\0') || + strncmp(securityDomain, + (const char*) attribute->data, + securityDomainLength) != 0) { + continue; + } + attribute = AttributeWithTag(it->second, kSecAccountItemAttr); + if ((attribute->length != accountNameLength) || + (attribute->data == NULL && *accountName != '\0') || + (attribute->data != NULL && *accountName == '\0') || + strncmp(accountName, + (const char*) attribute->data, + accountNameLength) != 0) { + continue; + } + attribute = AttributeWithTag(it->second, kSecPathItemAttr); + if ((attribute->length != pathLength) || + (attribute->data == NULL && *path != '\0') || + (attribute->data != NULL && *path == '\0') || + strncmp(path, + (const char*) attribute->data, + pathLength) != 0) { + continue; + } + attribute = AttributeWithTag(it->second, kSecPortItemAttr); + if ((attribute->data == NULL) || + (port != *(static_cast(attribute->data)))) { + continue; + } + attribute = AttributeWithTag(it->second, kSecProtocolItemAttr); + if ((attribute->data == NULL) || + (protocol != *(static_cast(attribute->data)))) { + continue; + } + attribute = AttributeWithTag(it->second, kSecAuthenticationTypeItemAttr); + if ((attribute->data == NULL) || + (authenticationType != + *(static_cast(attribute->data)))) { + continue; + } + // The keychain already has this item, since all fields other than the + // password match. + return true; + } + return false; +} + +OSStatus MockAppleKeychain::AddInternetPassword( + SecKeychainRef keychain, + UInt32 serverNameLength, + const char* serverName, + UInt32 securityDomainLength, + const char* securityDomain, + UInt32 accountNameLength, + const char* accountName, + UInt32 pathLength, + const char* path, + UInt16 port, + SecProtocolType protocol, + SecAuthenticationType authenticationType, + UInt32 passwordLength, + const void* passwordData, + SecKeychainItemRef* itemRef) const { + if (locked_) + return errSecAuthFailed; + + // Check for the magic duplicate item trigger. + if (strcmp(serverName, "some.domain.com") == 0) + return errSecDuplicateItem; + + // If the account already exists in the keychain, we don't add it. + if (AlreadyContainsInternetPassword(serverNameLength, serverName, + securityDomainLength, securityDomain, + accountNameLength, accountName, + pathLength, path, + port, protocol, + authenticationType)) { + return errSecDuplicateItem; + } + + // Pick the next unused slot. + MockKeychainItemType key = next_item_key_++; + + // Initialize keychain data storage at the target location. + InitializeKeychainData(key); + + MockAppleKeychain* mutable_this = const_cast(this); + mutable_this->SetTestDataBytes(key, kSecServerItemAttr, serverName, + serverNameLength); + mutable_this->SetTestDataBytes(key, kSecSecurityDomainItemAttr, + securityDomain, securityDomainLength); + mutable_this->SetTestDataBytes(key, kSecAccountItemAttr, accountName, + accountNameLength); + mutable_this->SetTestDataBytes(key, kSecPathItemAttr, path, pathLength); + mutable_this->SetTestDataPort(key, port); + mutable_this->SetTestDataProtocol(key, protocol); + mutable_this->SetTestDataAuthType(key, authenticationType); + mutable_this->SetTestDataPasswordBytes(key, passwordData, + passwordLength); + base::Time::Exploded exploded_time; + base::Time::Now().UTCExplode(&exploded_time); + char time_string[128]; + snprintf(time_string, sizeof(time_string), "%04d%02d%02d%02d%02d%02dZ", + exploded_time.year, exploded_time.month, exploded_time.day_of_month, + exploded_time.hour, exploded_time.minute, exploded_time.second); + mutable_this->SetTestDataString(key, kSecCreationDateItemAttr, time_string); + + added_via_api_.insert(key); + + if (itemRef) { + *itemRef = reinterpret_cast(key + 1); + ++keychain_item_copy_count_; + } + return noErr; +} + +OSStatus MockAppleKeychain::SearchCopyNext(SecKeychainSearchRef searchRef, + SecKeychainItemRef* itemRef) const { + if (remaining_search_results_.empty()) + return errSecItemNotFound; + MockKeychainItemType key = remaining_search_results_.front(); + remaining_search_results_.erase(remaining_search_results_.begin()); + *itemRef = reinterpret_cast(key + 1); + ++keychain_item_copy_count_; + return noErr; +} + +void MockAppleKeychain::Free(CFTypeRef ref) const { + if (!ref) + return; + + if (ref == kDummySearchRef) { + --search_copy_count_; + } else { + --keychain_item_copy_count_; + } +} + +int MockAppleKeychain::UnfreedSearchCount() const { + return search_copy_count_; +} + +int MockAppleKeychain::UnfreedKeychainItemCount() const { + return keychain_item_copy_count_; +} + +int MockAppleKeychain::UnfreedAttributeDataCount() const { + return attribute_data_copy_count_; +} + +bool MockAppleKeychain::CreatorCodesSetForAddedItems() const { + for (std::set::const_iterator + i = added_via_api_.begin(); + i != added_via_api_.end(); + ++i) { + SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[*i], + kSecCreatorItemAttr); + OSType* data = static_cast(attribute->data); + if (*data == 0) + return false; + } + return true; +} + +void MockAppleKeychain::AddTestItem(const KeychainTestData& item_data) { + MockKeychainItemType key = next_item_key_++; + + InitializeKeychainData(key); + SetTestDataAuthType(key, item_data.auth_type); + SetTestDataString(key, kSecServerItemAttr, item_data.server); + SetTestDataProtocol(key, item_data.protocol); + SetTestDataString(key, kSecPathItemAttr, item_data.path); + SetTestDataPort(key, item_data.port); + SetTestDataString(key, kSecSecurityDomainItemAttr, + item_data.security_domain); + SetTestDataString(key, kSecCreationDateItemAttr, item_data.creation_date); + SetTestDataString(key, kSecAccountItemAttr, item_data.username); + SetTestDataPasswordString(key, item_data.password); + SetTestDataNegativeItem(key, item_data.negative_item); +} + +} // namespace crypto diff --git a/crypto/nss_crypto_module_delegate.h b/crypto/nss_crypto_module_delegate.h new file mode 100644 index 0000000000000..6c1da68161dd5 --- /dev/null +++ b/crypto/nss_crypto_module_delegate.h @@ -0,0 +1,53 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CRYPTO_NSS_CRYPTO_MODULE_DELEGATE_H_ +#define CRYPTO_NSS_CRYPTO_MODULE_DELEGATE_H_ + +#include + +#include "base/callback_forward.h" +#include "crypto/scoped_nss_types.h" + +namespace crypto { + +// PK11_SetPasswordFunc is a global setting. An implementation of +// CryptoModuleBlockingPasswordDelegate should be passed using wincx() as the +// user data argument (|wincx|) to relevant NSS functions, which the global +// password handler will call to do the actual work. This delegate should only +// be used in NSS calls on worker threads due to the blocking nature. +class CryptoModuleBlockingPasswordDelegate { + public: + virtual ~CryptoModuleBlockingPasswordDelegate() {} + + // Return a value suitable for passing to the |wincx| argument of relevant NSS + // functions. This should be used instead of passing the object pointer + // directly to avoid accidentally casting a pointer to a subclass to void* and + // then casting back to a pointer of the base class + void* wincx() { return this; } + + // Requests a password to unlock |slot_name|. The interface is synchronous + // because NSS cannot issue an asynchronous request. |retry| is true if this + // is a request for the retry and we previously returned the wrong password. + // The implementation should set |*cancelled| to true if the user cancelled + // instead of entering a password, otherwise it should return the password the + // user entered. + virtual std::string RequestPassword(const std::string& slot_name, bool retry, + bool* cancelled) = 0; + +}; + +// Extends CryptoModuleBlockingPasswordDelegate with the ability to return a +// slot in which to act. (Eg, which slot to store a generated key in.) +class NSSCryptoModuleDelegate : public CryptoModuleBlockingPasswordDelegate { + public: + ~NSSCryptoModuleDelegate() override {} + + // Get the slot to store the generated key. + virtual ScopedPK11Slot RequestSlot() = 0; +}; + +} // namespace crypto + +#endif // CRYPTO_NSS_CRYPTO_MODULE_DELEGATE_H_ diff --git a/crypto/nss_key_util.cc b/crypto/nss_key_util.cc new file mode 100644 index 0000000000000..77435fba36175 --- /dev/null +++ b/crypto/nss_key_util.cc @@ -0,0 +1,163 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/nss_key_util.h" + +#include +#include +#include + +#include "base/logging.h" +#include "base/stl_util.h" +#include "crypto/nss_util.h" + +#if defined(USE_NSS_CERTS) +#include +#include "crypto/nss_util_internal.h" +#endif + +namespace crypto { + +namespace { + +#if defined(USE_NSS_CERTS) + +struct PublicKeyInfoDeleter { + inline void operator()(CERTSubjectPublicKeyInfo* spki) { + SECKEY_DestroySubjectPublicKeyInfo(spki); + } +}; + +typedef scoped_ptr + ScopedPublicKeyInfo; + +// Decodes |input| as a SubjectPublicKeyInfo and returns a SECItem containing +// the CKA_ID of that public key or nullptr on error. +ScopedSECItem MakeIDFromSPKI(const std::vector& input) { + // First, decode and save the public key. + SECItem key_der; + key_der.type = siBuffer; + key_der.data = const_cast(vector_as_array(&input)); + key_der.len = input.size(); + + ScopedPublicKeyInfo spki(SECKEY_DecodeDERSubjectPublicKeyInfo(&key_der)); + if (!spki) + return nullptr; + + ScopedSECKEYPublicKey result(SECKEY_ExtractPublicKey(spki.get())); + if (!result) + return nullptr; + + // See pk11_MakeIDFromPublicKey from NSS. For now, only RSA keys are + // supported. + if (SECKEY_GetPublicKeyType(result.get()) != rsaKey) + return nullptr; + + return ScopedSECItem(PK11_MakeIDFromPubKey(&result->u.rsa.modulus)); +} + +#endif // defined(USE_NSS_CERTS) + +} // namespace + +bool GenerateRSAKeyPairNSS(PK11SlotInfo* slot, + uint16_t num_bits, + bool permanent, + ScopedSECKEYPublicKey* public_key, + ScopedSECKEYPrivateKey* private_key) { + DCHECK(slot); + + PK11RSAGenParams param; + param.keySizeInBits = num_bits; + param.pe = 65537L; + SECKEYPublicKey* public_key_raw = nullptr; + private_key->reset(PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN, + ¶m, &public_key_raw, permanent, + permanent /* sensitive */, nullptr)); + if (!*private_key) + return false; + + public_key->reset(public_key_raw); + return true; +} + +ScopedSECKEYPrivateKey ImportNSSKeyFromPrivateKeyInfo( + PK11SlotInfo* slot, + const std::vector& input, + bool permanent) { + DCHECK(slot); + + ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); + DCHECK(arena); + + // Excess data is illegal, but NSS silently accepts it, so first ensure that + // |input| consists of a single ASN.1 element. + SECItem input_item; + input_item.data = const_cast(vector_as_array(&input)); + input_item.len = input.size(); + SECItem der_private_key_info; + SECStatus rv = + SEC_QuickDERDecodeItem(arena.get(), &der_private_key_info, + SEC_ASN1_GET(SEC_AnyTemplate), &input_item); + if (rv != SECSuccess) + return nullptr; + + // Allow the private key to be used for key unwrapping, data decryption, + // and signature generation. + const unsigned int key_usage = + KU_KEY_ENCIPHERMENT | KU_DATA_ENCIPHERMENT | KU_DIGITAL_SIGNATURE; + SECKEYPrivateKey* key_raw = nullptr; + rv = PK11_ImportDERPrivateKeyInfoAndReturnKey( + slot, &der_private_key_info, nullptr, nullptr, permanent, + permanent /* sensitive */, key_usage, &key_raw, nullptr); + if (rv != SECSuccess) + return nullptr; + return ScopedSECKEYPrivateKey(key_raw); +} + +#if defined(USE_NSS_CERTS) + +ScopedSECKEYPrivateKey FindNSSKeyFromPublicKeyInfo( + const std::vector& input) { + EnsureNSSInit(); + + ScopedSECItem cka_id(MakeIDFromSPKI(input)); + if (!cka_id) + return nullptr; + + // Search all slots in all modules for the key with the given ID. + AutoSECMODListReadLock auto_lock; + const SECMODModuleList* head = SECMOD_GetDefaultModuleList(); + for (const SECMODModuleList* item = head; item != nullptr; + item = item->next) { + int slot_count = item->module->loaded ? item->module->slotCount : 0; + for (int i = 0; i < slot_count; i++) { + // Look for the key in slot |i|. + ScopedSECKEYPrivateKey key( + PK11_FindKeyByKeyID(item->module->slots[i], cka_id.get(), nullptr)); + if (key) + return key.Pass(); + } + } + + // The key wasn't found in any module. + return nullptr; +} + +ScopedSECKEYPrivateKey FindNSSKeyFromPublicKeyInfoInSlot( + const std::vector& input, + PK11SlotInfo* slot) { + DCHECK(slot); + + ScopedSECItem cka_id(MakeIDFromSPKI(input)); + if (!cka_id) + return nullptr; + + return ScopedSECKEYPrivateKey( + PK11_FindKeyByKeyID(slot, cka_id.get(), nullptr)); +} + +#endif // defined(USE_NSS_CERTS) + +} // namespace crypto diff --git a/crypto/nss_key_util.h b/crypto/nss_key_util.h new file mode 100644 index 0000000000000..12b948d25bb2a --- /dev/null +++ b/crypto/nss_key_util.h @@ -0,0 +1,58 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CRYPTO_NSS_KEY_UTIL_H_ +#define CRYPTO_NSS_KEY_UTIL_H_ + +#include + +#include + +#include "build/build_config.h" +#include "crypto/crypto_export.h" +#include "crypto/scoped_nss_types.h" + +typedef struct PK11SlotInfoStr PK11SlotInfo; + +namespace crypto { + +// Generates a new RSA keypair of size |num_bits| in |slot|. Returns true on +// success and false on failure. If |permanent| is true, the resulting key is +// permanent and is not exportable in plaintext form. +CRYPTO_EXPORT bool GenerateRSAKeyPairNSS( + PK11SlotInfo* slot, + uint16_t num_bits, + bool permanent, + ScopedSECKEYPublicKey* out_public_key, + ScopedSECKEYPrivateKey* out_private_key); + +// Imports a private key from |input| into |slot|. |input| is interpreted as a +// DER-encoded PrivateKeyInfo block from PKCS #8. Returns nullptr on error. If +// |permanent| is true, the resulting key is permanent and is not exportable in +// plaintext form. +CRYPTO_EXPORT ScopedSECKEYPrivateKey +ImportNSSKeyFromPrivateKeyInfo(PK11SlotInfo* slot, + const std::vector& input, + bool permanent); + +#if defined(USE_NSS_CERTS) + +// Decodes |input| as a DER-encoded X.509 SubjectPublicKeyInfo and searches for +// the private key half in the key database. Returns the private key on success +// or nullptr on error. +CRYPTO_EXPORT ScopedSECKEYPrivateKey +FindNSSKeyFromPublicKeyInfo(const std::vector& input); + +// Decodes |input| as a DER-encoded X.509 SubjectPublicKeyInfo and searches for +// the private key half in the slot specified by |slot|. Returns the private key +// on success or nullptr on error. +CRYPTO_EXPORT ScopedSECKEYPrivateKey +FindNSSKeyFromPublicKeyInfoInSlot(const std::vector& input, + PK11SlotInfo* slot); + +#endif // defined(USE_NSS_CERTS) + +} // namespace crypto + +#endif // CRYPTO_NSS_KEY_UTIL_H_ diff --git a/crypto/nss_key_util_unittest.cc b/crypto/nss_key_util_unittest.cc new file mode 100644 index 0000000000000..ff4d55a146094 --- /dev/null +++ b/crypto/nss_key_util_unittest.cc @@ -0,0 +1,87 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/nss_key_util.h" + +#include +#include + +#include + +#include "crypto/nss_util.h" +#include "crypto/scoped_nss_types.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace crypto { + +class NSSKeyUtilTest : public testing::Test { + public: + void SetUp() override { + EnsureNSSInit(); + + internal_slot_.reset(PK11_GetInternalSlot()); + ASSERT_TRUE(internal_slot_); + } + + PK11SlotInfo* internal_slot() { return internal_slot_.get(); } + + private: + ScopedPK11Slot internal_slot_; +}; + +TEST_F(NSSKeyUtilTest, GenerateRSAKeyPairNSS) { + const int kKeySizeBits = 1024; + + ScopedSECKEYPublicKey public_key; + ScopedSECKEYPrivateKey private_key; + ASSERT_TRUE(GenerateRSAKeyPairNSS(internal_slot(), kKeySizeBits, + false /* not permanent */, &public_key, + &private_key)); + + EXPECT_EQ(rsaKey, SECKEY_GetPublicKeyType(public_key.get())); + EXPECT_EQ(rsaKey, SECKEY_GetPrivateKeyType(private_key.get())); + EXPECT_EQ((kKeySizeBits + 7) / 8, + PK11_GetPrivateModulusLen(private_key.get())); +} + +#if defined(USE_NSS_CERTS) +TEST_F(NSSKeyUtilTest, FindNSSKeyFromPublicKeyInfo) { + // Create an NSS keypair, which will put the keys in the user's NSSDB. + ScopedSECKEYPublicKey public_key; + ScopedSECKEYPrivateKey private_key; + ASSERT_TRUE(GenerateRSAKeyPairNSS(internal_slot(), 512, + false /* not permanent */, &public_key, + &private_key)); + + ScopedSECItem item(SECKEY_EncodeDERSubjectPublicKeyInfo(public_key.get())); + ASSERT_TRUE(item); + std::vector public_key_der(item->data, item->data + item->len); + + ScopedSECKEYPrivateKey private_key2 = + FindNSSKeyFromPublicKeyInfo(public_key_der); + ASSERT_TRUE(private_key2); + EXPECT_EQ(private_key->pkcs11ID, private_key2->pkcs11ID); +} + +TEST_F(NSSKeyUtilTest, FailedFindNSSKeyFromPublicKeyInfo) { + // Create an NSS keypair, which will put the keys in the user's NSSDB. + ScopedSECKEYPublicKey public_key; + ScopedSECKEYPrivateKey private_key; + ASSERT_TRUE(GenerateRSAKeyPairNSS(internal_slot(), 512, + false /* not permanent */, &public_key, + &private_key)); + + ScopedSECItem item(SECKEY_EncodeDERSubjectPublicKeyInfo(public_key.get())); + ASSERT_TRUE(item); + std::vector public_key_der(item->data, item->data + item->len); + + // Remove the keys from the DB, and make sure we can't find them again. + PK11_DestroyTokenObject(private_key->pkcs11Slot, private_key->pkcs11ID); + PK11_DestroyTokenObject(public_key->pkcs11Slot, public_key->pkcs11ID); + + EXPECT_FALSE(FindNSSKeyFromPublicKeyInfo(public_key_der)); +} +#endif // defined(USE_NSS_CERTS) + +} // namespace crypto diff --git a/crypto/nss_util.cc b/crypto/nss_util.cc new file mode 100644 index 0000000000000..125591c73f6b9 --- /dev/null +++ b/crypto/nss_util.cc @@ -0,0 +1,1131 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/nss_util.h" +#include "crypto/nss_util_internal.h" + +#include +#include +#include +#include +#include +#include +#include + +#if defined(OS_OPENBSD) +#include +#include +#endif + +#if defined(OS_CHROMEOS) +#include +#endif + +#include +#include + +#include "base/base_paths.h" +#include "base/bind.h" +#include "base/cpu.h" +#include "base/debug/alias.h" +#include "base/debug/stack_trace.h" +#include "base/environment.h" +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/lazy_instance.h" +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "base/message_loop/message_loop.h" +#include "base/native_library.h" +#include "base/path_service.h" +#include "base/stl_util.h" +#include "base/strings/stringprintf.h" +#include "base/threading/thread_checker.h" +#include "base/threading/thread_restrictions.h" +#include "base/threading/worker_pool.h" +#include "build/build_config.h" + +// USE_NSS_CERTS means NSS is used for certificates and platform integration. +// This requires additional support to manage the platform certificate and key +// stores. +#if defined(USE_NSS_CERTS) +#include "base/synchronization/lock.h" +#include "crypto/nss_crypto_module_delegate.h" +#endif // defined(USE_NSS_CERTS) + +namespace crypto { + +namespace { + +#if defined(OS_CHROMEOS) +const char kUserNSSDatabaseName[] = "UserNSSDB"; + +// Constants for loading the Chrome OS TPM-backed PKCS #11 library. +const char kChapsModuleName[] = "Chaps"; +const char kChapsPath[] = "libchaps.so"; + +// Fake certificate authority database used for testing. +static const base::FilePath::CharType kReadOnlyCertDB[] = + FILE_PATH_LITERAL("/etc/fake_root_ca/nssdb"); +#endif // defined(OS_CHROMEOS) + +std::string GetNSSErrorMessage() { + std::string result; + if (PR_GetErrorTextLength()) { + scoped_ptr error_text(new char[PR_GetErrorTextLength() + 1]); + PRInt32 copied = PR_GetErrorText(error_text.get()); + result = std::string(error_text.get(), copied); + } else { + result = base::StringPrintf("NSS error code: %d", PR_GetError()); + } + return result; +} + +#if defined(USE_NSS_CERTS) +#if !defined(OS_CHROMEOS) +base::FilePath GetDefaultConfigDirectory() { + base::FilePath dir; + PathService::Get(base::DIR_HOME, &dir); + if (dir.empty()) { + LOG(ERROR) << "Failed to get home directory."; + return dir; + } + dir = dir.AppendASCII(".pki").AppendASCII("nssdb"); + if (!base::CreateDirectory(dir)) { + LOG(ERROR) << "Failed to create " << dir.value() << " directory."; + dir.clear(); + } + DVLOG(2) << "DefaultConfigDirectory: " << dir.value(); + return dir; +} +#endif // !defined(IS_CHROMEOS) + +// On non-Chrome OS platforms, return the default config directory. On Chrome OS +// test images, return a read-only directory with fake root CA certs (which are +// used by the local Google Accounts server mock we use when testing our login +// code). On Chrome OS non-test images (where the read-only directory doesn't +// exist), return an empty path. +base::FilePath GetInitialConfigDirectory() { +#if defined(OS_CHROMEOS) + base::FilePath database_dir = base::FilePath(kReadOnlyCertDB); + if (!base::PathExists(database_dir)) + database_dir.clear(); + return database_dir; +#else + return GetDefaultConfigDirectory(); +#endif // defined(OS_CHROMEOS) +} + +// This callback for NSS forwards all requests to a caller-specified +// CryptoModuleBlockingPasswordDelegate object. +char* PKCS11PasswordFunc(PK11SlotInfo* slot, PRBool retry, void* arg) { + crypto::CryptoModuleBlockingPasswordDelegate* delegate = + reinterpret_cast(arg); + if (delegate) { + bool cancelled = false; + std::string password = delegate->RequestPassword(PK11_GetTokenName(slot), + retry != PR_FALSE, + &cancelled); + if (cancelled) + return NULL; + char* result = PORT_Strdup(password.c_str()); + password.replace(0, password.size(), password.size(), 0); + return result; + } + DLOG(ERROR) << "PK11 password requested with NULL arg"; + return NULL; +} + +// NSS creates a local cache of the sqlite database if it detects that the +// filesystem the database is on is much slower than the local disk. The +// detection doesn't work with the latest versions of sqlite, such as 3.6.22 +// (NSS bug https://bugzilla.mozilla.org/show_bug.cgi?id=578561). So we set +// the NSS environment variable NSS_SDB_USE_CACHE to "yes" to override NSS's +// detection when database_dir is on NFS. See http://crbug.com/48585. +// +// TODO(wtc): port this function to other USE_NSS_CERTS platforms. It is +// defined only for OS_LINUX and OS_OPENBSD simply because the statfs structure +// is OS-specific. +// +// Because this function sets an environment variable it must be run before we +// go multi-threaded. +void UseLocalCacheOfNSSDatabaseIfNFS(const base::FilePath& database_dir) { + bool db_on_nfs = false; +#if defined(OS_LINUX) + base::FileSystemType fs_type = base::FILE_SYSTEM_UNKNOWN; + if (base::GetFileSystemType(database_dir, &fs_type)) + db_on_nfs = (fs_type == base::FILE_SYSTEM_NFS); +#elif defined(OS_OPENBSD) + struct statfs buf; + if (statfs(database_dir.value().c_str(), &buf) == 0) + db_on_nfs = (strcmp(buf.f_fstypename, MOUNT_NFS) == 0); +#else + NOTIMPLEMENTED(); +#endif + + if (db_on_nfs) { + scoped_ptr env(base::Environment::Create()); + static const char kUseCacheEnvVar[] = "NSS_SDB_USE_CACHE"; + if (!env->HasVar(kUseCacheEnvVar)) + env->SetVar(kUseCacheEnvVar, "yes"); + } +} + +#endif // defined(USE_NSS_CERTS) + +// A singleton to initialize/deinitialize NSPR. +// Separate from the NSS singleton because we initialize NSPR on the UI thread. +// Now that we're leaking the singleton, we could merge back with the NSS +// singleton. +class NSPRInitSingleton { + private: + friend struct base::DefaultLazyInstanceTraits; + + NSPRInitSingleton() { + PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); + } + + // NOTE(willchan): We don't actually execute this code since we leak NSS to + // prevent non-joinable threads from using NSS after it's already been shut + // down. + ~NSPRInitSingleton() { + PL_ArenaFinish(); + PRStatus prstatus = PR_Cleanup(); + if (prstatus != PR_SUCCESS) + LOG(ERROR) << "PR_Cleanup failed; was NSPR initialized on wrong thread?"; + } +}; + +base::LazyInstance::Leaky + g_nspr_singleton = LAZY_INSTANCE_INITIALIZER; + +// Force a crash with error info on NSS_NoDB_Init failure. +void CrashOnNSSInitFailure() { + int nss_error = PR_GetError(); + int os_error = PR_GetOSError(); + base::debug::Alias(&nss_error); + base::debug::Alias(&os_error); + LOG(ERROR) << "Error initializing NSS without a persistent database: " + << GetNSSErrorMessage(); + LOG(FATAL) << "nss_error=" << nss_error << ", os_error=" << os_error; +} + +#if defined(OS_CHROMEOS) +class ChromeOSUserData { + public: + explicit ChromeOSUserData(ScopedPK11Slot public_slot) + : public_slot_(public_slot.Pass()), + private_slot_initialization_started_(false) {} + ~ChromeOSUserData() { + if (public_slot_) { + SECStatus status = SECMOD_CloseUserDB(public_slot_.get()); + if (status != SECSuccess) + PLOG(ERROR) << "SECMOD_CloseUserDB failed: " << PORT_GetError(); + } + } + + ScopedPK11Slot GetPublicSlot() { + return ScopedPK11Slot( + public_slot_ ? PK11_ReferenceSlot(public_slot_.get()) : NULL); + } + + ScopedPK11Slot GetPrivateSlot( + const base::Callback& callback) { + if (private_slot_) + return ScopedPK11Slot(PK11_ReferenceSlot(private_slot_.get())); + if (!callback.is_null()) + tpm_ready_callback_list_.push_back(callback); + return ScopedPK11Slot(); + } + + void SetPrivateSlot(ScopedPK11Slot private_slot) { + DCHECK(!private_slot_); + private_slot_ = private_slot.Pass(); + + SlotReadyCallbackList callback_list; + callback_list.swap(tpm_ready_callback_list_); + for (SlotReadyCallbackList::iterator i = callback_list.begin(); + i != callback_list.end(); + ++i) { + (*i).Run(ScopedPK11Slot(PK11_ReferenceSlot(private_slot_.get()))); + } + } + + bool private_slot_initialization_started() const { + return private_slot_initialization_started_; + } + + void set_private_slot_initialization_started() { + private_slot_initialization_started_ = true; + } + + private: + ScopedPK11Slot public_slot_; + ScopedPK11Slot private_slot_; + + bool private_slot_initialization_started_; + + typedef std::vector > + SlotReadyCallbackList; + SlotReadyCallbackList tpm_ready_callback_list_; +}; + +class ScopedChapsLoadFixup { + public: + ScopedChapsLoadFixup(); + ~ScopedChapsLoadFixup(); + + private: +#if defined(COMPONENT_BUILD) + void *chaps_handle_; +#endif +}; + +#if defined(COMPONENT_BUILD) + +ScopedChapsLoadFixup::ScopedChapsLoadFixup() { + // HACK: libchaps links the system protobuf and there are symbol conflicts + // with the bundled copy. Load chaps with RTLD_DEEPBIND to workaround. + chaps_handle_ = dlopen(kChapsPath, RTLD_LOCAL | RTLD_NOW | RTLD_DEEPBIND); +} + +ScopedChapsLoadFixup::~ScopedChapsLoadFixup() { + // LoadModule() will have taken a 2nd reference. + if (chaps_handle_) + dlclose(chaps_handle_); +} + +#else + +ScopedChapsLoadFixup::ScopedChapsLoadFixup() {} +ScopedChapsLoadFixup::~ScopedChapsLoadFixup() {} + +#endif // defined(COMPONENT_BUILD) +#endif // defined(OS_CHROMEOS) + +class NSSInitSingleton { + public: +#if defined(OS_CHROMEOS) + // Used with PostTaskAndReply to pass handles to worker thread and back. + struct TPMModuleAndSlot { + explicit TPMModuleAndSlot(SECMODModule* init_chaps_module) + : chaps_module(init_chaps_module) {} + SECMODModule* chaps_module; + crypto::ScopedPK11Slot tpm_slot; + }; + + ScopedPK11Slot OpenPersistentNSSDBForPath(const std::string& db_name, + const base::FilePath& path) { + DCHECK(thread_checker_.CalledOnValidThread()); + // NSS is allowed to do IO on the current thread since dispatching + // to a dedicated thread would still have the affect of blocking + // the current thread, due to NSS's internal locking requirements + base::ThreadRestrictions::ScopedAllowIO allow_io; + + base::FilePath nssdb_path = path.AppendASCII(".pki").AppendASCII("nssdb"); + if (!base::CreateDirectory(nssdb_path)) { + LOG(ERROR) << "Failed to create " << nssdb_path.value() << " directory."; + return ScopedPK11Slot(); + } + return OpenSoftwareNSSDB(nssdb_path, db_name); + } + + void EnableTPMTokenForNSS() { + DCHECK(thread_checker_.CalledOnValidThread()); + + // If this gets set, then we'll use the TPM for certs with + // private keys, otherwise we'll fall back to the software + // implementation. + tpm_token_enabled_for_nss_ = true; + } + + bool IsTPMTokenEnabledForNSS() { + DCHECK(thread_checker_.CalledOnValidThread()); + return tpm_token_enabled_for_nss_; + } + + void InitializeTPMTokenAndSystemSlot( + int system_slot_id, + const base::Callback& callback) { + DCHECK(thread_checker_.CalledOnValidThread()); + // Should not be called while there is already an initialization in + // progress. + DCHECK(!initializing_tpm_token_); + // If EnableTPMTokenForNSS hasn't been called, return false. + if (!tpm_token_enabled_for_nss_) { + base::MessageLoop::current()->PostTask(FROM_HERE, + base::Bind(callback, false)); + return; + } + + // If everything is already initialized, then return true. + // Note that only |tpm_slot_| is checked, since |chaps_module_| could be + // NULL in tests while |tpm_slot_| has been set to the test DB. + if (tpm_slot_) { + base::MessageLoop::current()->PostTask(FROM_HERE, + base::Bind(callback, true)); + return; + } + + // Note that a reference is not taken to chaps_module_. This is safe since + // NSSInitSingleton is Leaky, so the reference it holds is never released. + scoped_ptr tpm_args(new TPMModuleAndSlot(chaps_module_)); + TPMModuleAndSlot* tpm_args_ptr = tpm_args.get(); + if (base::WorkerPool::PostTaskAndReply( + FROM_HERE, + base::Bind(&NSSInitSingleton::InitializeTPMTokenOnWorkerThread, + system_slot_id, + tpm_args_ptr), + base::Bind(&NSSInitSingleton::OnInitializedTPMTokenAndSystemSlot, + base::Unretained(this), // NSSInitSingleton is leaky + callback, + base::Passed(&tpm_args)), + true /* task_is_slow */ + )) { + initializing_tpm_token_ = true; + } else { + base::MessageLoop::current()->PostTask(FROM_HERE, + base::Bind(callback, false)); + } + } + + static void InitializeTPMTokenOnWorkerThread(CK_SLOT_ID token_slot_id, + TPMModuleAndSlot* tpm_args) { + // This tries to load the Chaps module so NSS can talk to the hardware + // TPM. + if (!tpm_args->chaps_module) { + ScopedChapsLoadFixup chaps_loader; + + DVLOG(3) << "Loading chaps..."; + tpm_args->chaps_module = LoadModule( + kChapsModuleName, + kChapsPath, + // For more details on these parameters, see: + // https://developer.mozilla.org/en/PKCS11_Module_Specs + // slotFlags=[PublicCerts] -- Certificates and public keys can be + // read from this slot without requiring a call to C_Login. + // askpw=only -- Only authenticate to the token when necessary. + "NSS=\"slotParams=(0={slotFlags=[PublicCerts] askpw=only})\""); + } + if (tpm_args->chaps_module) { + tpm_args->tpm_slot = + GetTPMSlotForIdOnWorkerThread(tpm_args->chaps_module, token_slot_id); + } + } + + void OnInitializedTPMTokenAndSystemSlot( + const base::Callback& callback, + scoped_ptr tpm_args) { + DCHECK(thread_checker_.CalledOnValidThread()); + DVLOG(2) << "Loaded chaps: " << !!tpm_args->chaps_module + << ", got tpm slot: " << !!tpm_args->tpm_slot; + + chaps_module_ = tpm_args->chaps_module; + tpm_slot_ = tpm_args->tpm_slot.Pass(); + if (!chaps_module_ && test_system_slot_) { + // chromeos_unittests try to test the TPM initialization process. If we + // have a test DB open, pretend that it is the TPM slot. + tpm_slot_.reset(PK11_ReferenceSlot(test_system_slot_.get())); + } + initializing_tpm_token_ = false; + + if (tpm_slot_) + RunAndClearTPMReadyCallbackList(); + + callback.Run(!!tpm_slot_); + } + + void RunAndClearTPMReadyCallbackList() { + TPMReadyCallbackList callback_list; + callback_list.swap(tpm_ready_callback_list_); + for (TPMReadyCallbackList::iterator i = callback_list.begin(); + i != callback_list.end(); + ++i) { + i->Run(); + } + } + + bool IsTPMTokenReady(const base::Closure& callback) { + if (!callback.is_null()) { + // Cannot DCHECK in the general case yet, but since the callback is + // a new addition to the API, DCHECK to make sure at least the new uses + // don't regress. + DCHECK(thread_checker_.CalledOnValidThread()); + } else if (!thread_checker_.CalledOnValidThread()) { + // TODO(mattm): Change to DCHECK when callers have been fixed. + DVLOG(1) << "Called on wrong thread.\n" + << base::debug::StackTrace().ToString(); + } + + if (tpm_slot_) + return true; + + if (!callback.is_null()) + tpm_ready_callback_list_.push_back(callback); + + return false; + } + + // Note that CK_SLOT_ID is an unsigned long, but cryptohome gives us the slot + // id as an int. This should be safe since this is only used with chaps, which + // we also control. + static crypto::ScopedPK11Slot GetTPMSlotForIdOnWorkerThread( + SECMODModule* chaps_module, + CK_SLOT_ID slot_id) { + DCHECK(chaps_module); + + DVLOG(3) << "Poking chaps module."; + SECStatus rv = SECMOD_UpdateSlotList(chaps_module); + if (rv != SECSuccess) + PLOG(ERROR) << "SECMOD_UpdateSlotList failed: " << PORT_GetError(); + + PK11SlotInfo* slot = SECMOD_LookupSlot(chaps_module->moduleID, slot_id); + if (!slot) + LOG(ERROR) << "TPM slot " << slot_id << " not found."; + return crypto::ScopedPK11Slot(slot); + } + + bool InitializeNSSForChromeOSUser(const std::string& username_hash, + const base::FilePath& path) { + DCHECK(thread_checker_.CalledOnValidThread()); + if (chromeos_user_map_.find(username_hash) != chromeos_user_map_.end()) { + // This user already exists in our mapping. + DVLOG(2) << username_hash << " already initialized."; + return false; + } + + DVLOG(2) << "Opening NSS DB " << path.value(); + std::string db_name = base::StringPrintf( + "%s %s", kUserNSSDatabaseName, username_hash.c_str()); + ScopedPK11Slot public_slot(OpenPersistentNSSDBForPath(db_name, path)); + chromeos_user_map_[username_hash] = + new ChromeOSUserData(public_slot.Pass()); + return true; + } + + bool ShouldInitializeTPMForChromeOSUser(const std::string& username_hash) { + DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(chromeos_user_map_.find(username_hash) != chromeos_user_map_.end()); + + return !chromeos_user_map_[username_hash] + ->private_slot_initialization_started(); + } + + void WillInitializeTPMForChromeOSUser(const std::string& username_hash) { + DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(chromeos_user_map_.find(username_hash) != chromeos_user_map_.end()); + + chromeos_user_map_[username_hash] + ->set_private_slot_initialization_started(); + } + + void InitializeTPMForChromeOSUser(const std::string& username_hash, + CK_SLOT_ID slot_id) { + DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(chromeos_user_map_.find(username_hash) != chromeos_user_map_.end()); + DCHECK(chromeos_user_map_[username_hash]-> + private_slot_initialization_started()); + + if (!chaps_module_) + return; + + // Note that a reference is not taken to chaps_module_. This is safe since + // NSSInitSingleton is Leaky, so the reference it holds is never released. + scoped_ptr tpm_args(new TPMModuleAndSlot(chaps_module_)); + TPMModuleAndSlot* tpm_args_ptr = tpm_args.get(); + base::WorkerPool::PostTaskAndReply( + FROM_HERE, + base::Bind(&NSSInitSingleton::InitializeTPMTokenOnWorkerThread, + slot_id, + tpm_args_ptr), + base::Bind(&NSSInitSingleton::OnInitializedTPMForChromeOSUser, + base::Unretained(this), // NSSInitSingleton is leaky + username_hash, + base::Passed(&tpm_args)), + true /* task_is_slow */ + ); + } + + void OnInitializedTPMForChromeOSUser(const std::string& username_hash, + scoped_ptr tpm_args) { + DCHECK(thread_checker_.CalledOnValidThread()); + DVLOG(2) << "Got tpm slot for " << username_hash << " " + << !!tpm_args->tpm_slot; + chromeos_user_map_[username_hash]->SetPrivateSlot( + tpm_args->tpm_slot.Pass()); + } + + void InitializePrivateSoftwareSlotForChromeOSUser( + const std::string& username_hash) { + DCHECK(thread_checker_.CalledOnValidThread()); + VLOG(1) << "using software private slot for " << username_hash; + DCHECK(chromeos_user_map_.find(username_hash) != chromeos_user_map_.end()); + DCHECK(chromeos_user_map_[username_hash]-> + private_slot_initialization_started()); + + chromeos_user_map_[username_hash]->SetPrivateSlot( + chromeos_user_map_[username_hash]->GetPublicSlot()); + } + + ScopedPK11Slot GetPublicSlotForChromeOSUser( + const std::string& username_hash) { + DCHECK(thread_checker_.CalledOnValidThread()); + + if (username_hash.empty()) { + DVLOG(2) << "empty username_hash"; + return ScopedPK11Slot(); + } + + if (chromeos_user_map_.find(username_hash) == chromeos_user_map_.end()) { + LOG(ERROR) << username_hash << " not initialized."; + return ScopedPK11Slot(); + } + return chromeos_user_map_[username_hash]->GetPublicSlot(); + } + + ScopedPK11Slot GetPrivateSlotForChromeOSUser( + const std::string& username_hash, + const base::Callback& callback) { + DCHECK(thread_checker_.CalledOnValidThread()); + + if (username_hash.empty()) { + DVLOG(2) << "empty username_hash"; + if (!callback.is_null()) { + base::MessageLoop::current()->PostTask( + FROM_HERE, base::Bind(callback, base::Passed(ScopedPK11Slot()))); + } + return ScopedPK11Slot(); + } + + DCHECK(chromeos_user_map_.find(username_hash) != chromeos_user_map_.end()); + + return chromeos_user_map_[username_hash]->GetPrivateSlot(callback); + } + + void CloseChromeOSUserForTesting(const std::string& username_hash) { + DCHECK(thread_checker_.CalledOnValidThread()); + ChromeOSUserMap::iterator i = chromeos_user_map_.find(username_hash); + DCHECK(i != chromeos_user_map_.end()); + delete i->second; + chromeos_user_map_.erase(i); + } + + void SetSystemKeySlotForTesting(ScopedPK11Slot slot) { + // Ensure that a previous value of test_system_slot_ is not overwritten. + // Unsetting, i.e. setting a NULL, however is allowed. + DCHECK(!slot || !test_system_slot_); + test_system_slot_ = slot.Pass(); + if (test_system_slot_) { + tpm_slot_.reset(PK11_ReferenceSlot(test_system_slot_.get())); + RunAndClearTPMReadyCallbackList(); + } else { + tpm_slot_.reset(); + } + } +#endif // defined(OS_CHROMEOS) + +#if !defined(OS_CHROMEOS) + PK11SlotInfo* GetPersistentNSSKeySlot() { + // TODO(mattm): Change to DCHECK when callers have been fixed. + if (!thread_checker_.CalledOnValidThread()) { + DVLOG(1) << "Called on wrong thread.\n" + << base::debug::StackTrace().ToString(); + } + + return PK11_GetInternalKeySlot(); + } +#endif + +#if defined(OS_CHROMEOS) + void GetSystemNSSKeySlotCallback( + const base::Callback& callback) { + callback.Run(ScopedPK11Slot(PK11_ReferenceSlot(tpm_slot_.get()))); + } + + ScopedPK11Slot GetSystemNSSKeySlot( + const base::Callback& callback) { + DCHECK(thread_checker_.CalledOnValidThread()); + // TODO(mattm): chromeos::TPMTokenloader always calls + // InitializeTPMTokenAndSystemSlot with slot 0. If the system slot is + // disabled, tpm_slot_ will be the first user's slot instead. Can that be + // detected and return NULL instead? + + base::Closure wrapped_callback; + if (!callback.is_null()) { + wrapped_callback = + base::Bind(&NSSInitSingleton::GetSystemNSSKeySlotCallback, + base::Unretained(this) /* singleton is leaky */, + callback); + } + if (IsTPMTokenReady(wrapped_callback)) + return ScopedPK11Slot(PK11_ReferenceSlot(tpm_slot_.get())); + return ScopedPK11Slot(); + } +#endif + +#if defined(USE_NSS_CERTS) + base::Lock* write_lock() { + return &write_lock_; + } +#endif // defined(USE_NSS_CERTS) + + // This method is used to force NSS to be initialized without a DB. + // Call this method before NSSInitSingleton() is constructed. + static void ForceNoDBInit() { + force_nodb_init_ = true; + } + + private: + friend struct base::DefaultLazyInstanceTraits; + + NSSInitSingleton() + : tpm_token_enabled_for_nss_(false), + initializing_tpm_token_(false), + chaps_module_(NULL), + root_(NULL) { + // It's safe to construct on any thread, since LazyInstance will prevent any + // other threads from accessing until the constructor is done. + thread_checker_.DetachFromThread(); + + DisableAESNIIfNeeded(); + + EnsureNSPRInit(); + + // We *must* have NSS >= 3.14.3. + static_assert( + (NSS_VMAJOR == 3 && NSS_VMINOR == 14 && NSS_VPATCH >= 3) || + (NSS_VMAJOR == 3 && NSS_VMINOR > 14) || + (NSS_VMAJOR > 3), + "nss version check failed"); + // Also check the run-time NSS version. + // NSS_VersionCheck is a >= check, not strict equality. + if (!NSS_VersionCheck("3.14.3")) { + LOG(FATAL) << "NSS_VersionCheck(\"3.14.3\") failed. NSS >= 3.14.3 is " + "required. Please upgrade to the latest NSS, and if you " + "still get this error, contact your distribution " + "maintainer."; + } + + SECStatus status = SECFailure; + bool nodb_init = force_nodb_init_; + +#if !defined(USE_NSS_CERTS) + // Use the system certificate store, so initialize NSS without database. + nodb_init = true; +#endif + + if (nodb_init) { + status = NSS_NoDB_Init(NULL); + if (status != SECSuccess) { + CrashOnNSSInitFailure(); + return; + } +#if defined(OS_IOS) + root_ = InitDefaultRootCerts(); +#endif // defined(OS_IOS) + } else { +#if defined(USE_NSS_CERTS) + base::FilePath database_dir = GetInitialConfigDirectory(); + if (!database_dir.empty()) { + // This duplicates the work which should have been done in + // EarlySetupForNSSInit. However, this function is idempotent so + // there's no harm done. + UseLocalCacheOfNSSDatabaseIfNFS(database_dir); + + // Initialize with a persistent database (likely, ~/.pki/nssdb). + // Use "sql:" which can be shared by multiple processes safely. + std::string nss_config_dir = + base::StringPrintf("sql:%s", database_dir.value().c_str()); +#if defined(OS_CHROMEOS) + status = NSS_Init(nss_config_dir.c_str()); +#else + status = NSS_InitReadWrite(nss_config_dir.c_str()); +#endif + if (status != SECSuccess) { + LOG(ERROR) << "Error initializing NSS with a persistent " + "database (" << nss_config_dir + << "): " << GetNSSErrorMessage(); + } + } + if (status != SECSuccess) { + VLOG(1) << "Initializing NSS without a persistent database."; + status = NSS_NoDB_Init(NULL); + if (status != SECSuccess) { + CrashOnNSSInitFailure(); + return; + } + } + + PK11_SetPasswordFunc(PKCS11PasswordFunc); + + // If we haven't initialized the password for the NSS databases, + // initialize an empty-string password so that we don't need to + // log in. + PK11SlotInfo* slot = PK11_GetInternalKeySlot(); + if (slot) { + // PK11_InitPin may write to the keyDB, but no other thread can use NSS + // yet, so we don't need to lock. + if (PK11_NeedUserInit(slot)) + PK11_InitPin(slot, NULL, NULL); + PK11_FreeSlot(slot); + } + + root_ = InitDefaultRootCerts(); +#endif // defined(USE_NSS_CERTS) + } + + // Disable MD5 certificate signatures. (They are disabled by default in + // NSS 3.14.) + NSS_SetAlgorithmPolicy(SEC_OID_MD5, 0, NSS_USE_ALG_IN_CERT_SIGNATURE); + NSS_SetAlgorithmPolicy(SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION, + 0, NSS_USE_ALG_IN_CERT_SIGNATURE); + } + + // NOTE(willchan): We don't actually execute this code since we leak NSS to + // prevent non-joinable threads from using NSS after it's already been shut + // down. + ~NSSInitSingleton() { +#if defined(OS_CHROMEOS) + STLDeleteValues(&chromeos_user_map_); +#endif + tpm_slot_.reset(); + if (root_) { + SECMOD_UnloadUserModule(root_); + SECMOD_DestroyModule(root_); + root_ = NULL; + } + if (chaps_module_) { + SECMOD_UnloadUserModule(chaps_module_); + SECMOD_DestroyModule(chaps_module_); + chaps_module_ = NULL; + } + + SECStatus status = NSS_Shutdown(); + if (status != SECSuccess) { + // We VLOG(1) because this failure is relatively harmless (leaking, but + // we're shutting down anyway). + VLOG(1) << "NSS_Shutdown failed; see http://crbug.com/4609"; + } + } + +#if defined(USE_NSS_CERTS) || defined(OS_IOS) + // Load nss's built-in root certs. + SECMODModule* InitDefaultRootCerts() { + SECMODModule* root = LoadModule("Root Certs", "libnssckbi.so", NULL); + if (root) + return root; + + // Aw, snap. Can't find/load root cert shared library. + // This will make it hard to talk to anybody via https. + // TODO(mattm): Re-add the NOTREACHED here when crbug.com/310972 is fixed. + return NULL; + } + + // Load the given module for this NSS session. + static SECMODModule* LoadModule(const char* name, + const char* library_path, + const char* params) { + std::string modparams = base::StringPrintf( + "name=\"%s\" library=\"%s\" %s", + name, library_path, params ? params : ""); + + // Shouldn't need to const_cast here, but SECMOD doesn't properly + // declare input string arguments as const. Bug + // https://bugzilla.mozilla.org/show_bug.cgi?id=642546 was filed + // on NSS codebase to address this. + SECMODModule* module = SECMOD_LoadUserModule( + const_cast(modparams.c_str()), NULL, PR_FALSE); + if (!module) { + LOG(ERROR) << "Error loading " << name << " module into NSS: " + << GetNSSErrorMessage(); + return NULL; + } + if (!module->loaded) { + LOG(ERROR) << "After loading " << name << ", loaded==false: " + << GetNSSErrorMessage(); + SECMOD_DestroyModule(module); + return NULL; + } + return module; + } +#endif + + static void DisableAESNIIfNeeded() { + if (NSS_VersionCheck("3.15") && !NSS_VersionCheck("3.15.4")) { + // Some versions of NSS have a bug that causes AVX instructions to be + // used without testing whether XSAVE is enabled by the operating system. + // In order to work around this, we disable AES-NI in NSS when we find + // that |has_avx()| is false (which includes the XSAVE test). See + // https://bugzilla.mozilla.org/show_bug.cgi?id=940794 + base::CPU cpu; + + if (cpu.has_avx_hardware() && !cpu.has_avx()) { + scoped_ptr env(base::Environment::Create()); + env->SetVar("NSS_DISABLE_HW_AES", "1"); + } + } + } + + // If this is set to true NSS is forced to be initialized without a DB. + static bool force_nodb_init_; + + bool tpm_token_enabled_for_nss_; + bool initializing_tpm_token_; + typedef std::vector TPMReadyCallbackList; + TPMReadyCallbackList tpm_ready_callback_list_; + SECMODModule* chaps_module_; + crypto::ScopedPK11Slot tpm_slot_; + SECMODModule* root_; +#if defined(OS_CHROMEOS) + typedef std::map ChromeOSUserMap; + ChromeOSUserMap chromeos_user_map_; + ScopedPK11Slot test_system_slot_; +#endif +#if defined(USE_NSS_CERTS) + // TODO(davidben): When https://bugzilla.mozilla.org/show_bug.cgi?id=564011 + // is fixed, we will no longer need the lock. + base::Lock write_lock_; +#endif // defined(USE_NSS_CERTS) + + base::ThreadChecker thread_checker_; +}; + +// static +bool NSSInitSingleton::force_nodb_init_ = false; + +base::LazyInstance::Leaky + g_nss_singleton = LAZY_INSTANCE_INITIALIZER; +} // namespace + +#if defined(USE_NSS_CERTS) +ScopedPK11Slot OpenSoftwareNSSDB(const base::FilePath& path, + const std::string& description) { + const std::string modspec = + base::StringPrintf("configDir='sql:%s' tokenDescription='%s'", + path.value().c_str(), + description.c_str()); + PK11SlotInfo* db_slot = SECMOD_OpenUserDB(modspec.c_str()); + if (db_slot) { + if (PK11_NeedUserInit(db_slot)) + PK11_InitPin(db_slot, NULL, NULL); + } else { + LOG(ERROR) << "Error opening persistent database (" << modspec + << "): " << GetNSSErrorMessage(); + } + return ScopedPK11Slot(db_slot); +} + +void EarlySetupForNSSInit() { + base::FilePath database_dir = GetInitialConfigDirectory(); + if (!database_dir.empty()) + UseLocalCacheOfNSSDatabaseIfNFS(database_dir); +} +#endif + +void EnsureNSPRInit() { + g_nspr_singleton.Get(); +} + +void InitNSSSafely() { + // We might fork, but we haven't loaded any security modules. + DisableNSSForkCheck(); + // If we're sandboxed, we shouldn't be able to open user security modules, + // but it's more correct to tell NSS to not even try. + // Loading user security modules would have security implications. + ForceNSSNoDBInit(); + // Initialize NSS. + EnsureNSSInit(); +} + +void EnsureNSSInit() { + // Initializing SSL causes us to do blocking IO. + // Temporarily allow it until we fix + // http://code.google.com/p/chromium/issues/detail?id=59847 + base::ThreadRestrictions::ScopedAllowIO allow_io; + g_nss_singleton.Get(); +} + +void ForceNSSNoDBInit() { + NSSInitSingleton::ForceNoDBInit(); +} + +void DisableNSSForkCheck() { + scoped_ptr env(base::Environment::Create()); + env->SetVar("NSS_STRICT_NOFORK", "DISABLED"); +} + +void LoadNSSLibraries() { + // Some NSS libraries are linked dynamically so load them here. +#if defined(USE_NSS_CERTS) + // Try to search for multiple directories to load the libraries. + std::vector paths; + + // Use relative path to Search PATH for the library files. + paths.push_back(base::FilePath()); + + // For Debian derivatives NSS libraries are located here. + paths.push_back(base::FilePath("/usr/lib/nss")); + + // Ubuntu 11.10 (Oneiric) and Debian Wheezy place the libraries here. +#if defined(ARCH_CPU_X86_64) + paths.push_back(base::FilePath("/usr/lib/x86_64-linux-gnu/nss")); +#elif defined(ARCH_CPU_X86) + paths.push_back(base::FilePath("/usr/lib/i386-linux-gnu/nss")); +#elif defined(ARCH_CPU_ARMEL) +#if defined(__ARM_PCS_VFP) + paths.push_back(base::FilePath("/usr/lib/arm-linux-gnueabihf/nss")); +#else + paths.push_back(base::FilePath("/usr/lib/arm-linux-gnueabi/nss")); +#endif // defined(__ARM_PCS_VFP) +#elif defined(ARCH_CPU_MIPSEL) + paths.push_back(base::FilePath("/usr/lib/mipsel-linux-gnu/nss")); +#endif // defined(ARCH_CPU_X86_64) + + // A list of library files to load. + std::vector libs; + libs.push_back("libsoftokn3.so"); + libs.push_back("libfreebl3.so"); + + // For each combination of library file and path, check for existence and + // then load. + size_t loaded = 0; + for (size_t i = 0; i < libs.size(); ++i) { + for (size_t j = 0; j < paths.size(); ++j) { + base::FilePath path = paths[j].Append(libs[i]); + base::NativeLibrary lib = base::LoadNativeLibrary(path, NULL); + if (lib) { + ++loaded; + break; + } + } + } + + if (loaded == libs.size()) { + VLOG(3) << "NSS libraries loaded."; + } else { + LOG(ERROR) << "Failed to load NSS libraries."; + } +#endif // defined(USE_NSS_CERTS) +} + +bool CheckNSSVersion(const char* version) { + return !!NSS_VersionCheck(version); +} + +#if defined(USE_NSS_CERTS) +base::Lock* GetNSSWriteLock() { + return g_nss_singleton.Get().write_lock(); +} + +AutoNSSWriteLock::AutoNSSWriteLock() : lock_(GetNSSWriteLock()) { + // May be NULL if the lock is not needed in our version of NSS. + if (lock_) + lock_->Acquire(); +} + +AutoNSSWriteLock::~AutoNSSWriteLock() { + if (lock_) { + lock_->AssertAcquired(); + lock_->Release(); + } +} + +AutoSECMODListReadLock::AutoSECMODListReadLock() + : lock_(SECMOD_GetDefaultModuleListLock()) { + SECMOD_GetReadLock(lock_); + } + +AutoSECMODListReadLock::~AutoSECMODListReadLock() { + SECMOD_ReleaseReadLock(lock_); +} +#endif // defined(USE_NSS_CERTS) + +#if defined(OS_CHROMEOS) +ScopedPK11Slot GetSystemNSSKeySlot( + const base::Callback& callback) { + return g_nss_singleton.Get().GetSystemNSSKeySlot(callback); +} + +void SetSystemKeySlotForTesting(ScopedPK11Slot slot) { + g_nss_singleton.Get().SetSystemKeySlotForTesting(slot.Pass()); +} + +void EnableTPMTokenForNSS() { + g_nss_singleton.Get().EnableTPMTokenForNSS(); +} + +bool IsTPMTokenEnabledForNSS() { + return g_nss_singleton.Get().IsTPMTokenEnabledForNSS(); +} + +bool IsTPMTokenReady(const base::Closure& callback) { + return g_nss_singleton.Get().IsTPMTokenReady(callback); +} + +void InitializeTPMTokenAndSystemSlot( + int token_slot_id, + const base::Callback& callback) { + g_nss_singleton.Get().InitializeTPMTokenAndSystemSlot(token_slot_id, + callback); +} + +bool InitializeNSSForChromeOSUser(const std::string& username_hash, + const base::FilePath& path) { + return g_nss_singleton.Get().InitializeNSSForChromeOSUser(username_hash, + path); +} + +bool ShouldInitializeTPMForChromeOSUser(const std::string& username_hash) { + return g_nss_singleton.Get().ShouldInitializeTPMForChromeOSUser( + username_hash); +} + +void WillInitializeTPMForChromeOSUser(const std::string& username_hash) { + g_nss_singleton.Get().WillInitializeTPMForChromeOSUser(username_hash); +} + +void InitializeTPMForChromeOSUser( + const std::string& username_hash, + CK_SLOT_ID slot_id) { + g_nss_singleton.Get().InitializeTPMForChromeOSUser(username_hash, slot_id); +} + +void InitializePrivateSoftwareSlotForChromeOSUser( + const std::string& username_hash) { + g_nss_singleton.Get().InitializePrivateSoftwareSlotForChromeOSUser( + username_hash); +} + +ScopedPK11Slot GetPublicSlotForChromeOSUser(const std::string& username_hash) { + return g_nss_singleton.Get().GetPublicSlotForChromeOSUser(username_hash); +} + +ScopedPK11Slot GetPrivateSlotForChromeOSUser( + const std::string& username_hash, + const base::Callback& callback) { + return g_nss_singleton.Get().GetPrivateSlotForChromeOSUser(username_hash, + callback); +} + +void CloseChromeOSUserForTesting(const std::string& username_hash) { + g_nss_singleton.Get().CloseChromeOSUserForTesting(username_hash); +} +#endif // defined(OS_CHROMEOS) + +base::Time PRTimeToBaseTime(PRTime prtime) { + return base::Time::FromInternalValue( + prtime + base::Time::UnixEpoch().ToInternalValue()); +} + +PRTime BaseTimeToPRTime(base::Time time) { + return time.ToInternalValue() - base::Time::UnixEpoch().ToInternalValue(); +} + +#if !defined(OS_CHROMEOS) +PK11SlotInfo* GetPersistentNSSKeySlot() { + return g_nss_singleton.Get().GetPersistentNSSKeySlot(); +} +#endif + +} // namespace crypto diff --git a/crypto/nss_util.h b/crypto/nss_util.h new file mode 100644 index 0000000000000..1ca0de3e77759 --- /dev/null +++ b/crypto/nss_util.h @@ -0,0 +1,155 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CRYPTO_NSS_UTIL_H_ +#define CRYPTO_NSS_UTIL_H_ + +#include +#include "base/basictypes.h" +#include "base/callback.h" +#include "base/compiler_specific.h" +#include "crypto/crypto_export.h" + +namespace base { +class FilePath; +class Lock; +class Time; +} // namespace base + +// This file specifically doesn't depend on any NSS or NSPR headers because it +// is included by various (non-crypto) parts of chrome to call the +// initialization functions. +namespace crypto { + +#if defined(USE_NSS_CERTS) +// EarlySetupForNSSInit performs lightweight setup which must occur before the +// process goes multithreaded. This does not initialise NSS. For test, see +// EnsureNSSInit. +CRYPTO_EXPORT void EarlySetupForNSSInit(); +#endif + +// Initialize NRPR if it isn't already initialized. This function is +// thread-safe, and NSPR will only ever be initialized once. +CRYPTO_EXPORT void EnsureNSPRInit(); + +// Initialize NSS safely for strict sandboxing. This function tells NSS to not +// load user security modules, and makes sure NSS will have proper entropy in a +// restricted, sandboxed environment. +// +// As a defense in depth measure, this function should be called in a sandboxed +// environment. That way, in the event of a bug, NSS will still not be able to +// load security modules that could expose private data and keys. +// +// Make sure to get an LGTM from the Chrome Security Team if you use this. +CRYPTO_EXPORT void InitNSSSafely(); + +// Initialize NSS if it isn't already initialized. This must be called before +// any other NSS functions. This function is thread-safe, and NSS will only +// ever be initialized once. +CRYPTO_EXPORT void EnsureNSSInit(); + +// Call this before calling EnsureNSSInit() will force NSS to initialize +// without a persistent DB. This is used for the special case where access of +// persistent DB is prohibited. +// +// TODO(hclam): Isolate loading default root certs. +// +// NSS will be initialized without loading any user security modules, including +// the built-in root certificates module. User security modules need to be +// loaded manually after NSS initialization. +// +// If EnsureNSSInit() is called before then this function has no effect. +// +// Calling this method only has effect on Linux. +// +// WARNING: Use this with caution. +CRYPTO_EXPORT void ForceNSSNoDBInit(); + +// This method is used to disable checks in NSS when used in a forked process. +// NSS checks whether it is running a forked process to avoid problems when +// using user security modules in a forked process. However if we are sure +// there are no modules loaded before the process is forked then there is no +// harm disabling the check. +// +// This method must be called before EnsureNSSInit() to take effect. +// +// WARNING: Use this with caution. +CRYPTO_EXPORT void DisableNSSForkCheck(); + +// Load NSS library files. This function has no effect on Mac and Windows. +// This loads the necessary NSS library files so that NSS can be initialized +// after loading additional library files is disallowed, for example when the +// sandbox is active. +// +// Note that this does not load libnssckbi.so which contains the root +// certificates. +CRYPTO_EXPORT void LoadNSSLibraries(); + +// Check if the current NSS version is greater than or equals to |version|. +// A sample version string is "3.12.3". +bool CheckNSSVersion(const char* version); + +#if defined(OS_CHROMEOS) +// Indicates that NSS should use the Chaps library so that we +// can access the TPM through NSS. InitializeTPMTokenAndSystemSlot and +// InitializeTPMForChromeOSUser must still be called to load the slots. +CRYPTO_EXPORT void EnableTPMTokenForNSS(); + +// Returns true if EnableTPMTokenForNSS has been called. +CRYPTO_EXPORT bool IsTPMTokenEnabledForNSS(); + +// Returns true if the TPM is owned and PKCS#11 initialized with the +// user and security officer PINs, and has been enabled in NSS by +// calling EnableTPMForNSS, and Chaps has been successfully +// loaded into NSS. +// If |callback| is non-null and the function returns false, the |callback| will +// be run once the TPM is ready. |callback| will never be run if the function +// returns true. +CRYPTO_EXPORT bool IsTPMTokenReady(const base::Closure& callback) + WARN_UNUSED_RESULT; + +// Initialize the TPM token and system slot. The |callback| will run on the same +// thread with true if the token and slot were successfully loaded or were +// already initialized. |callback| will be passed false if loading failed. Once +// called, InitializeTPMTokenAndSystemSlot must not be called again until the +// |callback| has been run. +CRYPTO_EXPORT void InitializeTPMTokenAndSystemSlot( + int system_slot_id, + const base::Callback& callback); +#endif + +// Convert a NSS PRTime value into a base::Time object. +// We use a int64 instead of PRTime here to avoid depending on NSPR headers. +CRYPTO_EXPORT base::Time PRTimeToBaseTime(int64 prtime); + +// Convert a base::Time object into a PRTime value. +// We use a int64 instead of PRTime here to avoid depending on NSPR headers. +CRYPTO_EXPORT int64 BaseTimeToPRTime(base::Time time); + +#if defined(USE_NSS_CERTS) +// NSS has a bug which can cause a deadlock or stall in some cases when writing +// to the certDB and keyDB. It also has a bug which causes concurrent key pair +// generations to scribble over each other. To work around this, we synchronize +// writes to the NSS databases with a global lock. The lock is hidden beneath a +// function for easy disabling when the bug is fixed. Callers should allow for +// it to return NULL in the future. +// +// See https://bugzilla.mozilla.org/show_bug.cgi?id=564011 +base::Lock* GetNSSWriteLock(); + +// A helper class that acquires the NSS write Lock while the AutoNSSWriteLock +// is in scope. +class CRYPTO_EXPORT AutoNSSWriteLock { + public: + AutoNSSWriteLock(); + ~AutoNSSWriteLock(); + private: + base::Lock *lock_; + DISALLOW_COPY_AND_ASSIGN(AutoNSSWriteLock); +}; +#endif // defined(USE_NSS_CERTS) + +} // namespace crypto + +#endif // CRYPTO_NSS_UTIL_H_ diff --git a/crypto/nss_util_internal.h b/crypto/nss_util_internal.h new file mode 100644 index 0000000000000..f321343d95649 --- /dev/null +++ b/crypto/nss_util_internal.h @@ -0,0 +1,113 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CRYPTO_NSS_UTIL_INTERNAL_H_ +#define CRYPTO_NSS_UTIL_INTERNAL_H_ + +#include + +#include "base/callback.h" +#include "base/compiler_specific.h" +#include "crypto/crypto_export.h" +#include "crypto/scoped_nss_types.h" + +namespace base { +class FilePath; +} + +// These functions return a type defined in an NSS header, and so cannot be +// declared in nss_util.h. Hence, they are declared here. + +namespace crypto { + +// Opens an NSS software database in folder |path|, with the (potentially) +// user-visible description |description|. Returns the slot for the opened +// database, or NULL if the database could not be opened. +CRYPTO_EXPORT_PRIVATE ScopedPK11Slot + OpenSoftwareNSSDB(const base::FilePath& path, + const std::string& description); + +#if !defined(OS_CHROMEOS) +// Returns a reference to the default NSS key slot for storing persistent data. +// Caller must release returned reference with PK11_FreeSlot. +CRYPTO_EXPORT PK11SlotInfo* GetPersistentNSSKeySlot() WARN_UNUSED_RESULT; +#endif + +// A helper class that acquires the SECMOD list read lock while the +// AutoSECMODListReadLock is in scope. +class CRYPTO_EXPORT AutoSECMODListReadLock { + public: + AutoSECMODListReadLock(); + ~AutoSECMODListReadLock(); + + private: + SECMODListLock* lock_; + DISALLOW_COPY_AND_ASSIGN(AutoSECMODListReadLock); +}; + +#if defined(OS_CHROMEOS) +// Returns a reference to the system-wide TPM slot if it is loaded. If it is not +// loaded and |callback| is non-null, the |callback| will be run once the slot +// is loaded. +CRYPTO_EXPORT ScopedPK11Slot GetSystemNSSKeySlot( + const base::Callback& callback) WARN_UNUSED_RESULT; + +// Sets the test system slot to |slot|, which means that |slot| will be exposed +// through |GetSystemNSSKeySlot| and |IsTPMTokenReady| will return true. +// |InitializeTPMTokenAndSystemSlot|, which triggers the TPM initialization, +// does not have to be called if the test system slot is set. +// This must must not be called consecutively with a |slot| != NULL. If |slot| +// is NULL, the test system slot is unset. +CRYPTO_EXPORT_PRIVATE void SetSystemKeySlotForTesting(ScopedPK11Slot slot); + +// Prepare per-user NSS slot mapping. It is safe to call this function multiple +// times. Returns true if the user was added, or false if it already existed. +CRYPTO_EXPORT bool InitializeNSSForChromeOSUser( + const std::string& username_hash, + const base::FilePath& path); + +// Returns whether TPM for ChromeOS user still needs initialization. If +// true is returned, the caller can proceed to initialize TPM slot for the +// user, but should call |WillInitializeTPMForChromeOSUser| first. +// |InitializeNSSForChromeOSUser| must have been called first. +CRYPTO_EXPORT bool ShouldInitializeTPMForChromeOSUser( + const std::string& username_hash) WARN_UNUSED_RESULT; + +// Makes |ShouldInitializeTPMForChromeOSUser| start returning false. +// Should be called before starting TPM initialization for the user. +// Assumes |InitializeNSSForChromeOSUser| had already been called. +CRYPTO_EXPORT void WillInitializeTPMForChromeOSUser( + const std::string& username_hash); + +// Use TPM slot |slot_id| for user. InitializeNSSForChromeOSUser must have been +// called first. +CRYPTO_EXPORT void InitializeTPMForChromeOSUser( + const std::string& username_hash, + CK_SLOT_ID slot_id); + +// Use the software slot as the private slot for user. +// InitializeNSSForChromeOSUser must have been called first. +CRYPTO_EXPORT void InitializePrivateSoftwareSlotForChromeOSUser( + const std::string& username_hash); + +// Returns a reference to the public slot for user. +CRYPTO_EXPORT ScopedPK11Slot GetPublicSlotForChromeOSUser( + const std::string& username_hash) WARN_UNUSED_RESULT; + +// Returns the private slot for |username_hash| if it is loaded. If it is not +// loaded and |callback| is non-null, the |callback| will be run once the slot +// is loaded. +CRYPTO_EXPORT ScopedPK11Slot GetPrivateSlotForChromeOSUser( + const std::string& username_hash, + const base::Callback& callback) WARN_UNUSED_RESULT; + +// Closes the NSS DB for |username_hash| that was previously opened by the +// *Initialize*ForChromeOSUser functions. +CRYPTO_EXPORT_PRIVATE void CloseChromeOSUserForTesting( + const std::string& username_hash); +#endif // defined(OS_CHROMEOS) + +} // namespace crypto + +#endif // CRYPTO_NSS_UTIL_INTERNAL_H_ diff --git a/crypto/nss_util_unittest.cc b/crypto/nss_util_unittest.cc new file mode 100644 index 0000000000000..28591916d3f65 --- /dev/null +++ b/crypto/nss_util_unittest.cc @@ -0,0 +1,43 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/nss_util.h" + +#include + +#include "base/time/time.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace crypto { + +TEST(NSSUtilTest, PRTimeConversion) { + EXPECT_EQ(base::Time::UnixEpoch(), PRTimeToBaseTime(0)); + EXPECT_EQ(0, BaseTimeToPRTime(base::Time::UnixEpoch())); + + PRExplodedTime prxtime; + prxtime.tm_params.tp_gmt_offset = 0; + prxtime.tm_params.tp_dst_offset = 0; + base::Time::Exploded exploded; + exploded.year = prxtime.tm_year = 2011; + exploded.month = 12; + prxtime.tm_month = 11; + // PRExplodedTime::tm_wday is a smaller type than Exploded::day_of_week, so + // assigning the two in this order instead of the reverse avoids potential + // warnings about type downcasting. + exploded.day_of_week = prxtime.tm_wday = 0; // Should be unused. + exploded.day_of_month = prxtime.tm_mday = 10; + exploded.hour = prxtime.tm_hour = 2; + exploded.minute = prxtime.tm_min = 52; + exploded.second = prxtime.tm_sec = 19; + exploded.millisecond = 342; + prxtime.tm_usec = 342000; + + PRTime pr_time = PR_ImplodeTime(&prxtime); + base::Time base_time = base::Time::FromUTCExploded(exploded); + + EXPECT_EQ(base_time, PRTimeToBaseTime(pr_time)); + EXPECT_EQ(pr_time, BaseTimeToPRTime(base_time)); +} + +} // namespace crypto diff --git a/crypto/openssl_bio_string.cc b/crypto/openssl_bio_string.cc new file mode 100644 index 0000000000000..48805001ef664 --- /dev/null +++ b/crypto/openssl_bio_string.cc @@ -0,0 +1,77 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/openssl_bio_string.h" + +#include +#include + +namespace crypto { + +namespace { + +int bio_string_write(BIO* bio, const char* data, int len) { + reinterpret_cast(bio->ptr)->append(data, len); + return len; +} + +int bio_string_puts(BIO* bio, const char* data) { + // Note: unlike puts(), BIO_puts does not add a newline. + return bio_string_write(bio, data, strlen(data)); +} + +long bio_string_ctrl(BIO* bio, int cmd, long num, void* ptr) { + std::string* str = reinterpret_cast(bio->ptr); + switch (cmd) { + case BIO_CTRL_RESET: + str->clear(); + return 1; + case BIO_C_FILE_SEEK: + return -1; + case BIO_C_FILE_TELL: + return str->size(); + case BIO_CTRL_FLUSH: + return 1; + default: + return 0; + } +} + +int bio_string_new(BIO* bio) { + bio->ptr = NULL; + bio->init = 0; + return 1; +} + +int bio_string_free(BIO* bio) { + // The string is owned by the caller, so there's nothing to do here. + return bio != NULL; +} + +BIO_METHOD bio_string_methods = { + // TODO(mattm): Should add some type number too? (bio.h uses 1-24) + BIO_TYPE_SOURCE_SINK, + "bio_string", + bio_string_write, + NULL, /* read */ + bio_string_puts, + NULL, /* gets */ + bio_string_ctrl, + bio_string_new, + bio_string_free, + NULL, /* callback_ctrl */ +}; + +} // namespace + +BIO* BIO_new_string(std::string* out) { + BIO* bio = BIO_new(&bio_string_methods); + if (!bio) + return bio; + bio->ptr = out; + bio->init = 1; + return bio; +} + +} // namespace crypto diff --git a/crypto/openssl_bio_string.h b/crypto/openssl_bio_string.h new file mode 100644 index 0000000000000..ca46c12de8d8f --- /dev/null +++ b/crypto/openssl_bio_string.h @@ -0,0 +1,29 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CRYPTO_OPENSSL_BIO_STRING_H_ +#define CRYPTO_OPENSSL_BIO_STRING_H_ + +#include + +#include "crypto/crypto_export.h" + +// From +typedef struct bio_st BIO; + +namespace crypto { + +// Creates a new BIO that can be used with OpenSSL's various output functions, +// and which will write all output directly into |out|. This is primarily +// intended as a utility to reduce the amount of copying and separate +// allocations when performing extensive string modifications or streaming +// within OpenSSL. +// +// Note: |out| must remain valid for the duration of the BIO. +CRYPTO_EXPORT BIO* BIO_new_string(std::string* out); + +} // namespace crypto + +#endif // CRYPTO_OPENSSL_BIO_STRING_H_ + diff --git a/crypto/openssl_bio_string_unittest.cc b/crypto/openssl_bio_string_unittest.cc new file mode 100644 index 0000000000000..9dfa0e70f7332 --- /dev/null +++ b/crypto/openssl_bio_string_unittest.cc @@ -0,0 +1,63 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/openssl_bio_string.h" + +#include + +#include "crypto/scoped_openssl_types.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace crypto { + +TEST(OpenSSLBIOString, TestWrite) { + std::string s; + const std::string expected1("a one\nb 2\n"); + const std::string expected2("c d e f"); + const std::string expected3("g h i"); + { + ScopedBIO bio(BIO_new_string(&s)); + ASSERT_TRUE(bio.get()); + + EXPECT_EQ(static_cast(expected1.size()), + BIO_printf(bio.get(), "a %s\nb %i\n", "one", 2)); + EXPECT_EQ(expected1, s); + + EXPECT_EQ(1, BIO_flush(bio.get())); + EXPECT_EQ(expected1, s); + + EXPECT_EQ(static_cast(expected2.size()), + BIO_write(bio.get(), expected2.data(), expected2.size())); + EXPECT_EQ(expected1 + expected2, s); + + EXPECT_EQ(static_cast(expected3.size()), + BIO_puts(bio.get(), expected3.c_str())); + EXPECT_EQ(expected1 + expected2 + expected3, s); + } + EXPECT_EQ(expected1 + expected2 + expected3, s); +} + +TEST(OpenSSLBIOString, TestReset) { + std::string s; + const std::string expected1("a b c\n"); + const std::string expected2("d e f g\n"); + { + ScopedBIO bio(BIO_new_string(&s)); + ASSERT_TRUE(bio.get()); + + EXPECT_EQ(static_cast(expected1.size()), + BIO_write(bio.get(), expected1.data(), expected1.size())); + EXPECT_EQ(expected1, s); + + EXPECT_EQ(1, BIO_reset(bio.get())); + EXPECT_EQ(std::string(), s); + + EXPECT_EQ(static_cast(expected2.size()), + BIO_write(bio.get(), expected2.data(), expected2.size())); + EXPECT_EQ(expected2, s); + } + EXPECT_EQ(expected2, s); +} + +} // namespace crypto diff --git a/crypto/openssl_util.cc b/crypto/openssl_util.cc index 8ea12323a9272..d89857f3851d7 100644 --- a/crypto/openssl_util.cc +++ b/crypto/openssl_util.cc @@ -9,10 +9,8 @@ #include #include "base/logging.h" -#include "base/memory/scoped_vector.h" #include "base/memory/singleton.h" #include "base/strings/string_piece.h" -#include "base/synchronization/lock.h" #include "build/build_config.h" #if defined(OS_ANDROID) && defined(ARCH_CPU_ARMEL) @@ -24,11 +22,6 @@ namespace crypto { namespace { -void CurrentThreadId(CRYPTO_THREADID* id) { - CRYPTO_THREADID_set_numeric( - id, static_cast(base::PlatformThread::CurrentId())); -} - // Singleton for initializing and cleaning up the OpenSSL library. class OpenSSLInitSingleton { public: @@ -60,36 +53,10 @@ class OpenSSLInitSingleton { CRYPTO_set_NEON_functional(!cpu.has_broken_neon()); #endif - SSL_load_error_strings(); SSL_library_init(); - int num_locks = CRYPTO_num_locks(); - locks_.reserve(num_locks); - for (int i = 0; i < num_locks; ++i) - locks_.push_back(new base::Lock()); - CRYPTO_set_locking_callback(LockingCallback); - CRYPTO_THREADID_set_callback(CurrentThreadId); - } - - ~OpenSSLInitSingleton() { - CRYPTO_set_locking_callback(NULL); - EVP_cleanup(); - ERR_free_strings(); - } - - static void LockingCallback(int mode, int n, const char* file, int line) { - OpenSSLInitSingleton::GetInstance()->OnLockingCallback(mode, n, file, line); - } - - void OnLockingCallback(int mode, int n, const char* file, int line) { - CHECK_LT(static_cast(n), locks_.size()); - if (mode & CRYPTO_LOCK) - locks_[n]->Acquire(); - else - locks_[n]->Release(); } - // These locks are used and managed by OpenSSL via LockingCallback(). - ScopedVector locks_; + ~OpenSSLInitSingleton() {} DISALLOW_COPY_AND_ASSIGN(OpenSSLInitSingleton); }; @@ -116,7 +83,7 @@ void EnsureOpenSSLInit() { void ClearOpenSSLERRStack(const tracked_objects::Location& location) { if (logging::DEBUG_MODE && VLOG_IS_ON(1)) { - int error_num = ERR_peek_error(); + uint32_t error_num = ERR_peek_error(); if (error_num == 0) return; diff --git a/crypto/p224.cc b/crypto/p224.cc new file mode 100644 index 0000000000000..11946a9413c5b --- /dev/null +++ b/crypto/p224.cc @@ -0,0 +1,758 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This is an implementation of the P224 elliptic curve group. It's written to +// be short and simple rather than fast, although it's still constant-time. +// +// See http://www.imperialviolet.org/2010/12/04/ecc.html ([1]) for background. + +#include "crypto/p224.h" + +#include + +#include "base/sys_byteorder.h" + +namespace { + +using base::HostToNet32; +using base::NetToHost32; + +// Field element functions. +// +// The field that we're dealing with is ℤ/pℤ where p = 2**224 - 2**96 + 1. +// +// Field elements are represented by a FieldElement, which is a typedef to an +// array of 8 uint32's. The value of a FieldElement, a, is: +// a[0] + 2**28·a[1] + 2**56·a[1] + ... + 2**196·a[7] +// +// Using 28-bit limbs means that there's only 4 bits of headroom, which is less +// than we would really like. But it has the useful feature that we hit 2**224 +// exactly, making the reflections during a reduce much nicer. + +using crypto::p224::FieldElement; + +// kP is the P224 prime. +const FieldElement kP = { + 1, 0, 0, 268431360, + 268435455, 268435455, 268435455, 268435455, +}; + +void Contract(FieldElement* inout); + +// IsZero returns 0xffffffff if a == 0 mod p and 0 otherwise. +uint32 IsZero(const FieldElement& a) { + FieldElement minimal; + memcpy(&minimal, &a, sizeof(minimal)); + Contract(&minimal); + + uint32 is_zero = 0, is_p = 0; + for (unsigned i = 0; i < 8; i++) { + is_zero |= minimal[i]; + is_p |= minimal[i] - kP[i]; + } + + // If either is_zero or is_p is 0, then we should return 1. + is_zero |= is_zero >> 16; + is_zero |= is_zero >> 8; + is_zero |= is_zero >> 4; + is_zero |= is_zero >> 2; + is_zero |= is_zero >> 1; + + is_p |= is_p >> 16; + is_p |= is_p >> 8; + is_p |= is_p >> 4; + is_p |= is_p >> 2; + is_p |= is_p >> 1; + + // For is_zero and is_p, the LSB is 0 iff all the bits are zero. + is_zero &= is_p & 1; + is_zero = (~is_zero) << 31; + is_zero = static_cast(is_zero) >> 31; + return is_zero; +} + +// Add computes *out = a+b +// +// a[i] + b[i] < 2**32 +void Add(FieldElement* out, const FieldElement& a, const FieldElement& b) { + for (int i = 0; i < 8; i++) { + (*out)[i] = a[i] + b[i]; + } +} + +static const uint32 kTwo31p3 = (1u<<31) + (1u<<3); +static const uint32 kTwo31m3 = (1u<<31) - (1u<<3); +static const uint32 kTwo31m15m3 = (1u<<31) - (1u<<15) - (1u<<3); +// kZero31ModP is 0 mod p where bit 31 is set in all limbs so that we can +// subtract smaller amounts without underflow. See the section "Subtraction" in +// [1] for why. +static const FieldElement kZero31ModP = { + kTwo31p3, kTwo31m3, kTwo31m3, kTwo31m15m3, + kTwo31m3, kTwo31m3, kTwo31m3, kTwo31m3 +}; + +// Subtract computes *out = a-b +// +// a[i], b[i] < 2**30 +// out[i] < 2**32 +void Subtract(FieldElement* out, const FieldElement& a, const FieldElement& b) { + for (int i = 0; i < 8; i++) { + // See the section on "Subtraction" in [1] for details. + (*out)[i] = a[i] + kZero31ModP[i] - b[i]; + } +} + +static const uint64 kTwo63p35 = (1ull<<63) + (1ull<<35); +static const uint64 kTwo63m35 = (1ull<<63) - (1ull<<35); +static const uint64 kTwo63m35m19 = (1ull<<63) - (1ull<<35) - (1ull<<19); +// kZero63ModP is 0 mod p where bit 63 is set in all limbs. See the section +// "Subtraction" in [1] for why. +static const uint64 kZero63ModP[8] = { + kTwo63p35, kTwo63m35, kTwo63m35, kTwo63m35, + kTwo63m35m19, kTwo63m35, kTwo63m35, kTwo63m35, +}; + +static const uint32 kBottom28Bits = 0xfffffff; + +// LargeFieldElement also represents an element of the field. The limbs are +// still spaced 28-bits apart and in little-endian order. So the limbs are at +// 0, 28, 56, ..., 392 bits, each 64-bits wide. +typedef uint64 LargeFieldElement[15]; + +// ReduceLarge converts a LargeFieldElement to a FieldElement. +// +// in[i] < 2**62 + +// GCC 4.9 incorrectly vectorizes the first coefficient elimination loop, so +// disable that optimization via pragma. Don't use the pragma under Clang, since +// clang doesn't understand it. +// TODO(wez): Remove this when crbug.com/439566 is fixed. +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC optimize("no-tree-vectorize") +#endif + +void ReduceLarge(FieldElement* out, LargeFieldElement* inptr) { + LargeFieldElement& in(*inptr); + + for (int i = 0; i < 8; i++) { + in[i] += kZero63ModP[i]; + } + + // Eliminate the coefficients at 2**224 and greater while maintaining the + // same value mod p. + for (int i = 14; i >= 8; i--) { + in[i-8] -= in[i]; // reflection off the "+1" term of p. + in[i-5] += (in[i] & 0xffff) << 12; // part of the "-2**96" reflection. + in[i-4] += in[i] >> 16; // the rest of the "-2**96" reflection. + } + in[8] = 0; + // in[0..8] < 2**64 + + // As the values become small enough, we start to store them in |out| and use + // 32-bit operations. + for (int i = 1; i < 8; i++) { + in[i+1] += in[i] >> 28; + (*out)[i] = static_cast(in[i] & kBottom28Bits); + } + // Eliminate the term at 2*224 that we introduced while keeping the same + // value mod p. + in[0] -= in[8]; // reflection off the "+1" term of p. + (*out)[3] += static_cast(in[8] & 0xffff) << 12; // "-2**96" term + (*out)[4] += static_cast(in[8] >> 16); // rest of "-2**96" term + // in[0] < 2**64 + // out[3] < 2**29 + // out[4] < 2**29 + // out[1,2,5..7] < 2**28 + + (*out)[0] = static_cast(in[0] & kBottom28Bits); + (*out)[1] += static_cast((in[0] >> 28) & kBottom28Bits); + (*out)[2] += static_cast(in[0] >> 56); + // out[0] < 2**28 + // out[1..4] < 2**29 + // out[5..7] < 2**28 +} + +// TODO(wez): Remove this when crbug.com/439566 is fixed. +#if defined(__GNUC__) && !defined(__clang__) +// Reenable "tree-vectorize" optimization if it got disabled for ReduceLarge. +#pragma GCC reset_options +#endif + +// Mul computes *out = a*b +// +// a[i] < 2**29, b[i] < 2**30 (or vice versa) +// out[i] < 2**29 +void Mul(FieldElement* out, const FieldElement& a, const FieldElement& b) { + LargeFieldElement tmp; + memset(&tmp, 0, sizeof(tmp)); + + for (int i = 0; i < 8; i++) { + for (int j = 0; j < 8; j++) { + tmp[i+j] += static_cast(a[i]) * static_cast(b[j]); + } + } + + ReduceLarge(out, &tmp); +} + +// Square computes *out = a*a +// +// a[i] < 2**29 +// out[i] < 2**29 +void Square(FieldElement* out, const FieldElement& a) { + LargeFieldElement tmp; + memset(&tmp, 0, sizeof(tmp)); + + for (int i = 0; i < 8; i++) { + for (int j = 0; j <= i; j++) { + uint64 r = static_cast(a[i]) * static_cast(a[j]); + if (i == j) { + tmp[i+j] += r; + } else { + tmp[i+j] += r << 1; + } + } + } + + ReduceLarge(out, &tmp); +} + +// Reduce reduces the coefficients of in_out to smaller bounds. +// +// On entry: a[i] < 2**31 + 2**30 +// On exit: a[i] < 2**29 +void Reduce(FieldElement* in_out) { + FieldElement& a = *in_out; + + for (int i = 0; i < 7; i++) { + a[i+1] += a[i] >> 28; + a[i] &= kBottom28Bits; + } + uint32 top = a[7] >> 28; + a[7] &= kBottom28Bits; + + // top < 2**4 + // Constant-time: mask = (top != 0) ? 0xffffffff : 0 + uint32 mask = top; + mask |= mask >> 2; + mask |= mask >> 1; + mask <<= 31; + mask = static_cast(static_cast(mask) >> 31); + + // Eliminate top while maintaining the same value mod p. + a[0] -= top; + a[3] += top << 12; + + // We may have just made a[0] negative but, if we did, then we must + // have added something to a[3], thus it's > 2**12. Therefore we can + // carry down to a[0]. + a[3] -= 1 & mask; + a[2] += mask & ((1<<28) - 1); + a[1] += mask & ((1<<28) - 1); + a[0] += mask & (1<<28); +} + +// Invert calcuates *out = in**-1 by computing in**(2**224 - 2**96 - 1), i.e. +// Fermat's little theorem. +void Invert(FieldElement* out, const FieldElement& in) { + FieldElement f1, f2, f3, f4; + + Square(&f1, in); // 2 + Mul(&f1, f1, in); // 2**2 - 1 + Square(&f1, f1); // 2**3 - 2 + Mul(&f1, f1, in); // 2**3 - 1 + Square(&f2, f1); // 2**4 - 2 + Square(&f2, f2); // 2**5 - 4 + Square(&f2, f2); // 2**6 - 8 + Mul(&f1, f1, f2); // 2**6 - 1 + Square(&f2, f1); // 2**7 - 2 + for (int i = 0; i < 5; i++) { // 2**12 - 2**6 + Square(&f2, f2); + } + Mul(&f2, f2, f1); // 2**12 - 1 + Square(&f3, f2); // 2**13 - 2 + for (int i = 0; i < 11; i++) { // 2**24 - 2**12 + Square(&f3, f3); + } + Mul(&f2, f3, f2); // 2**24 - 1 + Square(&f3, f2); // 2**25 - 2 + for (int i = 0; i < 23; i++) { // 2**48 - 2**24 + Square(&f3, f3); + } + Mul(&f3, f3, f2); // 2**48 - 1 + Square(&f4, f3); // 2**49 - 2 + for (int i = 0; i < 47; i++) { // 2**96 - 2**48 + Square(&f4, f4); + } + Mul(&f3, f3, f4); // 2**96 - 1 + Square(&f4, f3); // 2**97 - 2 + for (int i = 0; i < 23; i++) { // 2**120 - 2**24 + Square(&f4, f4); + } + Mul(&f2, f4, f2); // 2**120 - 1 + for (int i = 0; i < 6; i++) { // 2**126 - 2**6 + Square(&f2, f2); + } + Mul(&f1, f1, f2); // 2**126 - 1 + Square(&f1, f1); // 2**127 - 2 + Mul(&f1, f1, in); // 2**127 - 1 + for (int i = 0; i < 97; i++) { // 2**224 - 2**97 + Square(&f1, f1); + } + Mul(out, f1, f3); // 2**224 - 2**96 - 1 +} + +// Contract converts a FieldElement to its minimal, distinguished form. +// +// On entry, in[i] < 2**29 +// On exit, in[i] < 2**28 +void Contract(FieldElement* inout) { + FieldElement& out = *inout; + + // Reduce the coefficients to < 2**28. + for (int i = 0; i < 7; i++) { + out[i+1] += out[i] >> 28; + out[i] &= kBottom28Bits; + } + uint32 top = out[7] >> 28; + out[7] &= kBottom28Bits; + + // Eliminate top while maintaining the same value mod p. + out[0] -= top; + out[3] += top << 12; + + // We may just have made out[0] negative. So we carry down. If we made + // out[0] negative then we know that out[3] is sufficiently positive + // because we just added to it. + for (int i = 0; i < 3; i++) { + uint32 mask = static_cast(static_cast(out[i]) >> 31); + out[i] += (1 << 28) & mask; + out[i+1] -= 1 & mask; + } + + // We might have pushed out[3] over 2**28 so we perform another, partial + // carry chain. + for (int i = 3; i < 7; i++) { + out[i+1] += out[i] >> 28; + out[i] &= kBottom28Bits; + } + top = out[7] >> 28; + out[7] &= kBottom28Bits; + + // Eliminate top while maintaining the same value mod p. + out[0] -= top; + out[3] += top << 12; + + // There are two cases to consider for out[3]: + // 1) The first time that we eliminated top, we didn't push out[3] over + // 2**28. In this case, the partial carry chain didn't change any values + // and top is zero. + // 2) We did push out[3] over 2**28 the first time that we eliminated top. + // The first value of top was in [0..16), therefore, prior to eliminating + // the first top, 0xfff1000 <= out[3] <= 0xfffffff. Therefore, after + // overflowing and being reduced by the second carry chain, out[3] <= + // 0xf000. Thus it cannot have overflowed when we eliminated top for the + // second time. + + // Again, we may just have made out[0] negative, so do the same carry down. + // As before, if we made out[0] negative then we know that out[3] is + // sufficiently positive. + for (int i = 0; i < 3; i++) { + uint32 mask = static_cast(static_cast(out[i]) >> 31); + out[i] += (1 << 28) & mask; + out[i+1] -= 1 & mask; + } + + // The value is < 2**224, but maybe greater than p. In order to reduce to a + // unique, minimal value we see if the value is >= p and, if so, subtract p. + + // First we build a mask from the top four limbs, which must all be + // equal to bottom28Bits if the whole value is >= p. If top_4_all_ones + // ends up with any zero bits in the bottom 28 bits, then this wasn't + // true. + uint32 top_4_all_ones = 0xffffffffu; + for (int i = 4; i < 8; i++) { + top_4_all_ones &= out[i]; + } + top_4_all_ones |= 0xf0000000; + // Now we replicate any zero bits to all the bits in top_4_all_ones. + top_4_all_ones &= top_4_all_ones >> 16; + top_4_all_ones &= top_4_all_ones >> 8; + top_4_all_ones &= top_4_all_ones >> 4; + top_4_all_ones &= top_4_all_ones >> 2; + top_4_all_ones &= top_4_all_ones >> 1; + top_4_all_ones = + static_cast(static_cast(top_4_all_ones << 31) >> 31); + + // Now we test whether the bottom three limbs are non-zero. + uint32 bottom_3_non_zero = out[0] | out[1] | out[2]; + bottom_3_non_zero |= bottom_3_non_zero >> 16; + bottom_3_non_zero |= bottom_3_non_zero >> 8; + bottom_3_non_zero |= bottom_3_non_zero >> 4; + bottom_3_non_zero |= bottom_3_non_zero >> 2; + bottom_3_non_zero |= bottom_3_non_zero >> 1; + bottom_3_non_zero = + static_cast(static_cast(bottom_3_non_zero) >> 31); + + // Everything depends on the value of out[3]. + // If it's > 0xffff000 and top_4_all_ones != 0 then the whole value is >= p + // If it's = 0xffff000 and top_4_all_ones != 0 and bottom_3_non_zero != 0, + // then the whole value is >= p + // If it's < 0xffff000, then the whole value is < p + uint32 n = out[3] - 0xffff000; + uint32 out_3_equal = n; + out_3_equal |= out_3_equal >> 16; + out_3_equal |= out_3_equal >> 8; + out_3_equal |= out_3_equal >> 4; + out_3_equal |= out_3_equal >> 2; + out_3_equal |= out_3_equal >> 1; + out_3_equal = + ~static_cast(static_cast(out_3_equal << 31) >> 31); + + // If out[3] > 0xffff000 then n's MSB will be zero. + uint32 out_3_gt = ~static_cast(static_cast(n << 31) >> 31); + + uint32 mask = top_4_all_ones & ((out_3_equal & bottom_3_non_zero) | out_3_gt); + out[0] -= 1 & mask; + out[3] -= 0xffff000 & mask; + out[4] -= 0xfffffff & mask; + out[5] -= 0xfffffff & mask; + out[6] -= 0xfffffff & mask; + out[7] -= 0xfffffff & mask; +} + + +// Group element functions. +// +// These functions deal with group elements. The group is an elliptic curve +// group with a = -3 defined in FIPS 186-3, section D.2.2. + +using crypto::p224::Point; + +// kB is parameter of the elliptic curve. +const FieldElement kB = { + 55967668, 11768882, 265861671, 185302395, + 39211076, 180311059, 84673715, 188764328, +}; + +void CopyConditional(Point* out, const Point& a, uint32 mask); +void DoubleJacobian(Point* out, const Point& a); + +// AddJacobian computes *out = a+b where a != b. +void AddJacobian(Point *out, + const Point& a, + const Point& b) { + // See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl + FieldElement z1z1, z2z2, u1, u2, s1, s2, h, i, j, r, v; + + uint32 z1_is_zero = IsZero(a.z); + uint32 z2_is_zero = IsZero(b.z); + + // Z1Z1 = Z1² + Square(&z1z1, a.z); + + // Z2Z2 = Z2² + Square(&z2z2, b.z); + + // U1 = X1*Z2Z2 + Mul(&u1, a.x, z2z2); + + // U2 = X2*Z1Z1 + Mul(&u2, b.x, z1z1); + + // S1 = Y1*Z2*Z2Z2 + Mul(&s1, b.z, z2z2); + Mul(&s1, a.y, s1); + + // S2 = Y2*Z1*Z1Z1 + Mul(&s2, a.z, z1z1); + Mul(&s2, b.y, s2); + + // H = U2-U1 + Subtract(&h, u2, u1); + Reduce(&h); + uint32 x_equal = IsZero(h); + + // I = (2*H)² + for (int k = 0; k < 8; k++) { + i[k] = h[k] << 1; + } + Reduce(&i); + Square(&i, i); + + // J = H*I + Mul(&j, h, i); + // r = 2*(S2-S1) + Subtract(&r, s2, s1); + Reduce(&r); + uint32 y_equal = IsZero(r); + + if (x_equal && y_equal && !z1_is_zero && !z2_is_zero) { + // The two input points are the same therefore we must use the dedicated + // doubling function as the slope of the line is undefined. + DoubleJacobian(out, a); + return; + } + + for (int k = 0; k < 8; k++) { + r[k] <<= 1; + } + Reduce(&r); + + // V = U1*I + Mul(&v, u1, i); + + // Z3 = ((Z1+Z2)²-Z1Z1-Z2Z2)*H + Add(&z1z1, z1z1, z2z2); + Add(&z2z2, a.z, b.z); + Reduce(&z2z2); + Square(&z2z2, z2z2); + Subtract(&out->z, z2z2, z1z1); + Reduce(&out->z); + Mul(&out->z, out->z, h); + + // X3 = r²-J-2*V + for (int k = 0; k < 8; k++) { + z1z1[k] = v[k] << 1; + } + Add(&z1z1, j, z1z1); + Reduce(&z1z1); + Square(&out->x, r); + Subtract(&out->x, out->x, z1z1); + Reduce(&out->x); + + // Y3 = r*(V-X3)-2*S1*J + for (int k = 0; k < 8; k++) { + s1[k] <<= 1; + } + Mul(&s1, s1, j); + Subtract(&z1z1, v, out->x); + Reduce(&z1z1); + Mul(&z1z1, z1z1, r); + Subtract(&out->y, z1z1, s1); + Reduce(&out->y); + + CopyConditional(out, a, z2_is_zero); + CopyConditional(out, b, z1_is_zero); +} + +// DoubleJacobian computes *out = a+a. +void DoubleJacobian(Point* out, const Point& a) { + // See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b + FieldElement delta, gamma, beta, alpha, t; + + Square(&delta, a.z); + Square(&gamma, a.y); + Mul(&beta, a.x, gamma); + + // alpha = 3*(X1-delta)*(X1+delta) + Add(&t, a.x, delta); + for (int i = 0; i < 8; i++) { + t[i] += t[i] << 1; + } + Reduce(&t); + Subtract(&alpha, a.x, delta); + Reduce(&alpha); + Mul(&alpha, alpha, t); + + // Z3 = (Y1+Z1)²-gamma-delta + Add(&out->z, a.y, a.z); + Reduce(&out->z); + Square(&out->z, out->z); + Subtract(&out->z, out->z, gamma); + Reduce(&out->z); + Subtract(&out->z, out->z, delta); + Reduce(&out->z); + + // X3 = alpha²-8*beta + for (int i = 0; i < 8; i++) { + delta[i] = beta[i] << 3; + } + Reduce(&delta); + Square(&out->x, alpha); + Subtract(&out->x, out->x, delta); + Reduce(&out->x); + + // Y3 = alpha*(4*beta-X3)-8*gamma² + for (int i = 0; i < 8; i++) { + beta[i] <<= 2; + } + Reduce(&beta); + Subtract(&beta, beta, out->x); + Reduce(&beta); + Square(&gamma, gamma); + for (int i = 0; i < 8; i++) { + gamma[i] <<= 3; + } + Reduce(&gamma); + Mul(&out->y, alpha, beta); + Subtract(&out->y, out->y, gamma); + Reduce(&out->y); +} + +// CopyConditional sets *out=a if mask is 0xffffffff. mask must be either 0 of +// 0xffffffff. +void CopyConditional(Point* out, + const Point& a, + uint32 mask) { + for (int i = 0; i < 8; i++) { + out->x[i] ^= mask & (a.x[i] ^ out->x[i]); + out->y[i] ^= mask & (a.y[i] ^ out->y[i]); + out->z[i] ^= mask & (a.z[i] ^ out->z[i]); + } +} + +// ScalarMult calculates *out = a*scalar where scalar is a big-endian number of +// length scalar_len and != 0. +void ScalarMult(Point* out, const Point& a, + const uint8* scalar, size_t scalar_len) { + memset(out, 0, sizeof(*out)); + Point tmp; + + for (size_t i = 0; i < scalar_len; i++) { + for (unsigned int bit_num = 0; bit_num < 8; bit_num++) { + DoubleJacobian(out, *out); + uint32 bit = static_cast(static_cast( + (((scalar[i] >> (7 - bit_num)) & 1) << 31) >> 31)); + AddJacobian(&tmp, a, *out); + CopyConditional(out, tmp, bit); + } + } +} + +// Get224Bits reads 7 words from in and scatters their contents in +// little-endian form into 8 words at out, 28 bits per output word. +void Get224Bits(uint32* out, const uint32* in) { + out[0] = NetToHost32(in[6]) & kBottom28Bits; + out[1] = ((NetToHost32(in[5]) << 4) | + (NetToHost32(in[6]) >> 28)) & kBottom28Bits; + out[2] = ((NetToHost32(in[4]) << 8) | + (NetToHost32(in[5]) >> 24)) & kBottom28Bits; + out[3] = ((NetToHost32(in[3]) << 12) | + (NetToHost32(in[4]) >> 20)) & kBottom28Bits; + out[4] = ((NetToHost32(in[2]) << 16) | + (NetToHost32(in[3]) >> 16)) & kBottom28Bits; + out[5] = ((NetToHost32(in[1]) << 20) | + (NetToHost32(in[2]) >> 12)) & kBottom28Bits; + out[6] = ((NetToHost32(in[0]) << 24) | + (NetToHost32(in[1]) >> 8)) & kBottom28Bits; + out[7] = (NetToHost32(in[0]) >> 4) & kBottom28Bits; +} + +// Put224Bits performs the inverse operation to Get224Bits: taking 28 bits from +// each of 8 input words and writing them in big-endian order to 7 words at +// out. +void Put224Bits(uint32* out, const uint32* in) { + out[6] = HostToNet32((in[0] >> 0) | (in[1] << 28)); + out[5] = HostToNet32((in[1] >> 4) | (in[2] << 24)); + out[4] = HostToNet32((in[2] >> 8) | (in[3] << 20)); + out[3] = HostToNet32((in[3] >> 12) | (in[4] << 16)); + out[2] = HostToNet32((in[4] >> 16) | (in[5] << 12)); + out[1] = HostToNet32((in[5] >> 20) | (in[6] << 8)); + out[0] = HostToNet32((in[6] >> 24) | (in[7] << 4)); +} + +} // anonymous namespace + +namespace crypto { + +namespace p224 { + +bool Point::SetFromString(const base::StringPiece& in) { + if (in.size() != 2*28) + return false; + const uint32* inwords = reinterpret_cast(in.data()); + Get224Bits(x, inwords); + Get224Bits(y, inwords + 7); + memset(&z, 0, sizeof(z)); + z[0] = 1; + + // Check that the point is on the curve, i.e. that y² = x³ - 3x + b. + FieldElement lhs; + Square(&lhs, y); + Contract(&lhs); + + FieldElement rhs; + Square(&rhs, x); + Mul(&rhs, x, rhs); + + FieldElement three_x; + for (int i = 0; i < 8; i++) { + three_x[i] = x[i] * 3; + } + Reduce(&three_x); + Subtract(&rhs, rhs, three_x); + Reduce(&rhs); + + ::Add(&rhs, rhs, kB); + Contract(&rhs); + return memcmp(&lhs, &rhs, sizeof(lhs)) == 0; +} + +std::string Point::ToString() const { + FieldElement zinv, zinv_sq, xx, yy; + + // If this is the point at infinity we return a string of all zeros. + if (IsZero(this->z)) { + static const char zeros[56] = {0}; + return std::string(zeros, sizeof(zeros)); + } + + Invert(&zinv, this->z); + Square(&zinv_sq, zinv); + Mul(&xx, x, zinv_sq); + Mul(&zinv_sq, zinv_sq, zinv); + Mul(&yy, y, zinv_sq); + + Contract(&xx); + Contract(&yy); + + uint32 outwords[14]; + Put224Bits(outwords, xx); + Put224Bits(outwords + 7, yy); + return std::string(reinterpret_cast(outwords), sizeof(outwords)); +} + +void ScalarMult(const Point& in, const uint8* scalar, Point* out) { + ::ScalarMult(out, in, scalar, 28); +} + +// kBasePoint is the base point (generator) of the elliptic curve group. +static const Point kBasePoint = { + {22813985, 52956513, 34677300, 203240812, + 12143107, 133374265, 225162431, 191946955}, + {83918388, 223877528, 122119236, 123340192, + 266784067, 263504429, 146143011, 198407736}, + {1, 0, 0, 0, 0, 0, 0, 0}, +}; + +void ScalarBaseMult(const uint8* scalar, Point* out) { + ::ScalarMult(out, kBasePoint, scalar, 28); +} + +void Add(const Point& a, const Point& b, Point* out) { + AddJacobian(out, a, b); +} + +void Negate(const Point& in, Point* out) { + // Guide to elliptic curve cryptography, page 89 suggests that (X : X+Y : Z) + // is the negative in Jacobian coordinates, but it doesn't actually appear to + // be true in testing so this performs the negation in affine coordinates. + FieldElement zinv, zinv_sq, y; + Invert(&zinv, in.z); + Square(&zinv_sq, zinv); + Mul(&out->x, in.x, zinv_sq); + Mul(&zinv_sq, zinv_sq, zinv); + Mul(&y, in.y, zinv_sq); + + Subtract(&out->y, kP, y); + Reduce(&out->y); + + memset(&out->z, 0, sizeof(out->z)); + out->z[0] = 1; +} + +} // namespace p224 + +} // namespace crypto diff --git a/crypto/p224.h b/crypto/p224.h new file mode 100644 index 0000000000000..2efecfab559a0 --- /dev/null +++ b/crypto/p224.h @@ -0,0 +1,60 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CRYPTO_P224_H_ +#define CRYPTO_P224_H_ + +#include + +#include "base/basictypes.h" +#include "base/strings/string_piece.h" +#include "crypto/crypto_export.h" + +namespace crypto { + +// P224 implements an elliptic curve group, commonly known as P224 and defined +// in FIPS 186-3, section D.2.2. +namespace p224 { + +// An element of the field (ℤ/pℤ) is represented with 8, 28-bit limbs in +// little endian order. +typedef uint32 FieldElement[8]; + +struct CRYPTO_EXPORT Point { + // SetFromString the value of the point from the 56 byte, external + // representation. The external point representation is an (x, y) pair of a + // point on the curve. Each field element is represented as a big-endian + // number < p. + bool SetFromString(const base::StringPiece& in); + + // ToString returns an external representation of the Point. + std::string ToString() const; + + // An Point is represented in Jacobian form (x/z², y/z³). + FieldElement x, y, z; +}; + +// kScalarBytes is the number of bytes needed to represent an element of the +// P224 field. +static const size_t kScalarBytes = 28; + +// ScalarMult computes *out = in*scalar where scalar is a 28-byte, big-endian +// number. +void CRYPTO_EXPORT ScalarMult(const Point& in, const uint8* scalar, Point* out); + +// ScalarBaseMult computes *out = g*scalar where g is the base point of the +// curve and scalar is a 28-byte, big-endian number. +void CRYPTO_EXPORT ScalarBaseMult(const uint8* scalar, Point* out); + +// Add computes *out = a+b. +void CRYPTO_EXPORT Add(const Point& a, const Point& b, Point* out); + +// Negate calculates out = -a; +void CRYPTO_EXPORT Negate(const Point& a, Point* out); + +} // namespace p224 + +} // namespace crypto + +#endif // CRYPTO_P224_H_ diff --git a/crypto/p224_spake.cc b/crypto/p224_spake.cc new file mode 100644 index 0000000000000..a6dec40568a6d --- /dev/null +++ b/crypto/p224_spake.cc @@ -0,0 +1,268 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This code implements SPAKE2, a variant of EKE: +// http://www.di.ens.fr/~pointche/pub.php?reference=AbPo04 + +#include + +#include + +#include +#include +#include +#include + +namespace { + +// The following two points (M and N in the protocol) are verifiable random +// points on the curve and can be generated with the following code: + +// #include +// #include +// #include +// +// #include +// #include +// #include +// +// static const char kSeed1[] = "P224 point generation seed (M)"; +// static const char kSeed2[] = "P224 point generation seed (N)"; +// +// void find_seed(const char* seed) { +// SHA256_CTX sha256; +// uint8_t digest[SHA256_DIGEST_LENGTH]; +// +// SHA256_Init(&sha256); +// SHA256_Update(&sha256, seed, strlen(seed)); +// SHA256_Final(digest, &sha256); +// +// BIGNUM x, y; +// EC_GROUP* p224 = EC_GROUP_new_by_curve_name(NID_secp224r1); +// EC_POINT* p = EC_POINT_new(p224); +// +// for (unsigned i = 0;; i++) { +// BN_init(&x); +// BN_bin2bn(digest, 28, &x); +// +// if (EC_POINT_set_compressed_coordinates_GFp( +// p224, p, &x, digest[28] & 1, NULL)) { +// BN_init(&y); +// EC_POINT_get_affine_coordinates_GFp(p224, p, &x, &y, NULL); +// char* x_str = BN_bn2hex(&x); +// char* y_str = BN_bn2hex(&y); +// printf("Found after %u iterations:\n%s\n%s\n", i, x_str, y_str); +// OPENSSL_free(x_str); +// OPENSSL_free(y_str); +// BN_free(&x); +// BN_free(&y); +// break; +// } +// +// SHA256_Init(&sha256); +// SHA256_Update(&sha256, digest, sizeof(digest)); +// SHA256_Final(digest, &sha256); +// +// BN_free(&x); +// } +// +// EC_POINT_free(p); +// EC_GROUP_free(p224); +// } +// +// int main() { +// find_seed(kSeed1); +// find_seed(kSeed2); +// return 0; +// } + +const crypto::p224::Point kM = { + {174237515, 77186811, 235213682, 33849492, + 33188520, 48266885, 177021753, 81038478}, + {104523827, 245682244, 266509668, 236196369, + 28372046, 145351378, 198520366, 113345994}, + {1, 0, 0, 0, 0, 0, 0, 0}, +}; + +const crypto::p224::Point kN = { + {136176322, 263523628, 251628795, 229292285, + 5034302, 185981975, 171998428, 11653062}, + {197567436, 51226044, 60372156, 175772188, + 42075930, 8083165, 160827401, 65097570}, + {1, 0, 0, 0, 0, 0, 0, 0}, +}; + +} // anonymous namespace + +namespace crypto { + +P224EncryptedKeyExchange::P224EncryptedKeyExchange( + PeerType peer_type, const base::StringPiece& password) + : state_(kStateInitial), + is_server_(peer_type == kPeerTypeServer) { + memset(&x_, 0, sizeof(x_)); + memset(&expected_authenticator_, 0, sizeof(expected_authenticator_)); + + // x_ is a random scalar. + RandBytes(x_, sizeof(x_)); + + // Calculate |password| hash to get SPAKE password value. + SHA256HashString(std::string(password.data(), password.length()), + pw_, sizeof(pw_)); + + Init(); +} + +void P224EncryptedKeyExchange::Init() { + // X = g**x_ + p224::Point X; + p224::ScalarBaseMult(x_, &X); + + // The client masks the Diffie-Hellman value, X, by adding M**pw and the + // server uses N**pw. + p224::Point MNpw; + p224::ScalarMult(is_server_ ? kN : kM, pw_, &MNpw); + + // X* = X + (N|M)**pw + p224::Point Xstar; + p224::Add(X, MNpw, &Xstar); + + next_message_ = Xstar.ToString(); +} + +const std::string& P224EncryptedKeyExchange::GetNextMessage() { + if (state_ == kStateInitial) { + state_ = kStateRecvDH; + return next_message_; + } else if (state_ == kStateSendHash) { + state_ = kStateRecvHash; + return next_message_; + } + + LOG(FATAL) << "P224EncryptedKeyExchange::GetNextMessage called in" + " bad state " << state_; + next_message_ = ""; + return next_message_; +} + +P224EncryptedKeyExchange::Result P224EncryptedKeyExchange::ProcessMessage( + const base::StringPiece& message) { + if (state_ == kStateRecvHash) { + // This is the final state of the protocol: we are reading the peer's + // authentication hash and checking that it matches the one that we expect. + if (message.size() != sizeof(expected_authenticator_)) { + error_ = "peer's hash had an incorrect size"; + return kResultFailed; + } + if (!SecureMemEqual(message.data(), expected_authenticator_, + message.size())) { + error_ = "peer's hash had incorrect value"; + return kResultFailed; + } + state_ = kStateDone; + return kResultSuccess; + } + + if (state_ != kStateRecvDH) { + LOG(FATAL) << "P224EncryptedKeyExchange::ProcessMessage called in" + " bad state " << state_; + error_ = "internal error"; + return kResultFailed; + } + + // Y* is the other party's masked, Diffie-Hellman value. + p224::Point Ystar; + if (!Ystar.SetFromString(message)) { + error_ = "failed to parse peer's masked Diffie-Hellman value"; + return kResultFailed; + } + + // We calculate the mask value: (N|M)**pw + p224::Point MNpw, minus_MNpw, Y, k; + p224::ScalarMult(is_server_ ? kM : kN, pw_, &MNpw); + p224::Negate(MNpw, &minus_MNpw); + + // Y = Y* - (N|M)**pw + p224::Add(Ystar, minus_MNpw, &Y); + + // K = Y**x_ + p224::ScalarMult(Y, x_, &k); + + // If everything worked out, then K is the same for both parties. + key_ = k.ToString(); + + std::string client_masked_dh, server_masked_dh; + if (is_server_) { + client_masked_dh = message.as_string(); + server_masked_dh = next_message_; + } else { + client_masked_dh = next_message_; + server_masked_dh = message.as_string(); + } + + // Now we calculate the hashes that each side will use to prove to the other + // that they derived the correct value for K. + uint8 client_hash[kSHA256Length], server_hash[kSHA256Length]; + CalculateHash(kPeerTypeClient, client_masked_dh, server_masked_dh, key_, + client_hash); + CalculateHash(kPeerTypeServer, client_masked_dh, server_masked_dh, key_, + server_hash); + + const uint8* my_hash = is_server_ ? server_hash : client_hash; + const uint8* their_hash = is_server_ ? client_hash : server_hash; + + next_message_ = + std::string(reinterpret_cast(my_hash), kSHA256Length); + memcpy(expected_authenticator_, their_hash, kSHA256Length); + state_ = kStateSendHash; + return kResultPending; +} + +void P224EncryptedKeyExchange::CalculateHash( + PeerType peer_type, + const std::string& client_masked_dh, + const std::string& server_masked_dh, + const std::string& k, + uint8* out_digest) { + std::string hash_contents; + + if (peer_type == kPeerTypeServer) { + hash_contents = "server"; + } else { + hash_contents = "client"; + } + + hash_contents += client_masked_dh; + hash_contents += server_masked_dh; + hash_contents += + std::string(reinterpret_cast(pw_), sizeof(pw_)); + hash_contents += k; + + SHA256HashString(hash_contents, out_digest, kSHA256Length); +} + +const std::string& P224EncryptedKeyExchange::error() const { + return error_; +} + +const std::string& P224EncryptedKeyExchange::GetKey() const { + DCHECK_EQ(state_, kStateDone); + return GetUnverifiedKey(); +} + +const std::string& P224EncryptedKeyExchange::GetUnverifiedKey() const { + // Key is already final when state is kStateSendHash. Subsequent states are + // used only for verification of the key. Some users may combine verification + // with sending verifiable data instead of |expected_authenticator_|. + DCHECK_GE(state_, kStateSendHash); + return key_; +} + +void P224EncryptedKeyExchange::SetXForTesting(const std::string& x) { + memset(&x_, 0, sizeof(x_)); + memcpy(&x_, x.data(), std::min(x.size(), sizeof(x_))); + Init(); +} + +} // namespace crypto diff --git a/crypto/p224_spake.h b/crypto/p224_spake.h new file mode 100644 index 0000000000000..556b15cd09f7d --- /dev/null +++ b/crypto/p224_spake.h @@ -0,0 +1,126 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CRYPTO_P224_SPAKE_H_ +#define CRYPTO_P224_SPAKE_H_ + +#include +#include +#include +#include + +namespace crypto { + +// P224EncryptedKeyExchange implements SPAKE2, a variant of Encrypted +// Key Exchange. It allows two parties that have a secret common +// password to establish a common secure key by exchanging messages +// over an insecure channel without disclosing the password. +// +// The password can be low entropy as authenticating with an attacker only +// gives the attacker a one-shot password oracle. No other information about +// the password is leaked. (However, you must be sure to limit the number of +// permitted authentication attempts otherwise they get many one-shot oracles.) +// +// The protocol requires several RTTs (actually two, but you shouldn't assume +// that.) To use the object, call GetNextMessage() and pass that message to the +// peer. Get a message from the peer and feed it into ProcessMessage. Then +// examine the return value of ProcessMessage: +// kResultPending: Another round is required. Call GetNextMessage and repeat. +// kResultFailed: The authentication has failed. You can get a human readable +// error message by calling error(). +// kResultSuccess: The authentication was successful. +// +// In each exchange, each peer always sends a message. +class CRYPTO_EXPORT P224EncryptedKeyExchange { + public: + enum Result { + kResultPending, + kResultFailed, + kResultSuccess, + }; + + // PeerType's values are named client and server due to convention. But + // they could be called "A" and "B" as far as the protocol is concerned so + // long as the two parties don't both get the same label. + enum PeerType { + kPeerTypeClient, + kPeerTypeServer, + }; + + // peer_type: the type of the local authentication party. + // password: secret session password. Both parties to the + // authentication must pass the same value. For the case of a + // TLS connection, see RFC 5705. + P224EncryptedKeyExchange(PeerType peer_type, + const base::StringPiece& password); + + // GetNextMessage returns a byte string which must be passed to the other + // party in the authentication. + const std::string& GetNextMessage(); + + // ProcessMessage processes a message which must have been generated by a + // call to GetNextMessage() by the other party. + Result ProcessMessage(const base::StringPiece& message); + + // In the event that ProcessMessage() returns kResultFailed, error will + // return a human readable error message. + const std::string& error() const; + + // The key established as result of the key exchange. Must be called + // at then end after ProcessMessage() returns kResultSuccess. + const std::string& GetKey() const; + + // The key established as result of the key exchange. Can be called after + // the first ProcessMessage() + const std::string& GetUnverifiedKey() const; + + private: + // The authentication state machine is very simple and each party proceeds + // through each of these states, in order. + enum State { + kStateInitial, + kStateRecvDH, + kStateSendHash, + kStateRecvHash, + kStateDone, + }; + + FRIEND_TEST_ALL_PREFIXES(MutualAuth, ExpectedValues); + + void Init(); + + // Sets internal random scalar. Should be used by tests only. + void SetXForTesting(const std::string& x); + + State state_; + const bool is_server_; + // next_message_ contains a value for GetNextMessage() to return. + std::string next_message_; + std::string error_; + + // CalculateHash computes the verification hash for the given peer and writes + // |kSHA256Length| bytes at |out_digest|. + void CalculateHash( + PeerType peer_type, + const std::string& client_masked_dh, + const std::string& server_masked_dh, + const std::string& k, + uint8* out_digest); + + // x_ is the secret Diffie-Hellman exponent (see paper referenced in .cc + // file). + uint8 x_[p224::kScalarBytes]; + // pw_ is SHA256(P(password), P(session))[:28] where P() prepends a uint32, + // big-endian length prefix (see paper referenced in .cc file). + uint8 pw_[p224::kScalarBytes]; + // expected_authenticator_ is used to store the hash value expected from the + // other party. + uint8 expected_authenticator_[kSHA256Length]; + + std::string key_; +}; + +} // namespace crypto + +#endif // CRYPTO_P224_SPAKE_H_ diff --git a/crypto/p224_spake_unittest.cc b/crypto/p224_spake_unittest.cc new file mode 100644 index 0000000000000..15b5be268413d --- /dev/null +++ b/crypto/p224_spake_unittest.cc @@ -0,0 +1,174 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/p224_spake.h" + +#include + +#include "base/logging.h" +#include "base/strings/string_number_conversions.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace crypto { + +namespace { + +std::string HexEncodeString(const std::string& binary_data) { + return base::HexEncode(binary_data.c_str(), binary_data.size()); +} + +bool RunExchange(P224EncryptedKeyExchange* client, + P224EncryptedKeyExchange* server, + bool is_password_same) { + for (;;) { + std::string client_message, server_message; + client_message = client->GetNextMessage(); + server_message = server->GetNextMessage(); + + P224EncryptedKeyExchange::Result client_result, server_result; + client_result = client->ProcessMessage(server_message); + server_result = server->ProcessMessage(client_message); + + // Check that we never hit the case where only one succeeds. + EXPECT_EQ(client_result == P224EncryptedKeyExchange::kResultSuccess, + server_result == P224EncryptedKeyExchange::kResultSuccess); + + if (client_result == P224EncryptedKeyExchange::kResultFailed || + server_result == P224EncryptedKeyExchange::kResultFailed) { + return false; + } + + EXPECT_EQ(is_password_same, + client->GetUnverifiedKey() == server->GetUnverifiedKey()); + + if (client_result == P224EncryptedKeyExchange::kResultSuccess && + server_result == P224EncryptedKeyExchange::kResultSuccess) { + return true; + } + + EXPECT_EQ(P224EncryptedKeyExchange::kResultPending, client_result); + EXPECT_EQ(P224EncryptedKeyExchange::kResultPending, server_result); + } +} + +const char kPassword[] = "foo"; + +} // namespace + +TEST(MutualAuth, CorrectAuth) { + P224EncryptedKeyExchange client( + P224EncryptedKeyExchange::kPeerTypeClient, kPassword); + P224EncryptedKeyExchange server( + P224EncryptedKeyExchange::kPeerTypeServer, kPassword); + + EXPECT_TRUE(RunExchange(&client, &server, true)); + EXPECT_EQ(client.GetKey(), server.GetKey()); +} + +TEST(MutualAuth, IncorrectPassword) { + P224EncryptedKeyExchange client( + P224EncryptedKeyExchange::kPeerTypeClient, + kPassword); + P224EncryptedKeyExchange server( + P224EncryptedKeyExchange::kPeerTypeServer, + "wrongpassword"); + + EXPECT_FALSE(RunExchange(&client, &server, false)); +} + +TEST(MutualAuth, ExpectedValues) { + P224EncryptedKeyExchange client(P224EncryptedKeyExchange::kPeerTypeClient, + kPassword); + client.SetXForTesting("Client x"); + P224EncryptedKeyExchange server(P224EncryptedKeyExchange::kPeerTypeServer, + kPassword); + server.SetXForTesting("Server x"); + + std::string client_message = client.GetNextMessage(); + EXPECT_EQ( + "3508EF7DECC8AB9F9C439FBB0154288BBECC0A82E8448F4CF29554EB" + "BE9D486686226255EAD1D077C635B1A41F46AC91D7F7F32CED9EC3E0", + HexEncodeString(client_message)); + + std::string server_message = server.GetNextMessage(); + EXPECT_EQ( + "A3088C18B75D2C2B107105661AEC85424777475EB29F1DDFB8C14AFB" + "F1603D0DF38413A00F420ACF2059E7997C935F5A957A193D09A2B584", + HexEncodeString(server_message)); + + EXPECT_EQ(P224EncryptedKeyExchange::kResultPending, + client.ProcessMessage(server_message)); + EXPECT_EQ(P224EncryptedKeyExchange::kResultPending, + server.ProcessMessage(client_message)); + + EXPECT_EQ(client.GetUnverifiedKey(), server.GetUnverifiedKey()); + // Must stay the same. External implementations should be able to pair with. + EXPECT_EQ( + "CE7CCFC435CDA4F01EC8826788B1F8B82EF7D550A34696B371096E64" + "C487D4FE193F7D1A6FF6820BC7F807796BA3889E8F999BBDEFC32FFA", + HexEncodeString(server.GetUnverifiedKey())); + + EXPECT_TRUE(RunExchange(&client, &server, true)); + EXPECT_EQ(client.GetKey(), server.GetKey()); +} + +TEST(MutualAuth, Fuzz) { + static const unsigned kIterations = 40; + + for (unsigned i = 0; i < kIterations; i++) { + P224EncryptedKeyExchange client( + P224EncryptedKeyExchange::kPeerTypeClient, kPassword); + P224EncryptedKeyExchange server( + P224EncryptedKeyExchange::kPeerTypeServer, kPassword); + + // We'll only be testing small values of i, but we don't want that to bias + // the test coverage. So we disperse the value of i by multiplying by the + // FNV, 32-bit prime, producing a poor-man's PRNG. + const uint32 rand = i * 16777619; + + for (unsigned round = 0;; round++) { + std::string client_message, server_message; + client_message = client.GetNextMessage(); + server_message = server.GetNextMessage(); + + if ((rand & 1) == round) { + const bool server_or_client = rand & 2; + std::string* m = server_or_client ? &server_message : &client_message; + if (rand & 4) { + // Truncate + *m = m->substr(0, (i >> 3) % m->size()); + } else { + // Corrupt + const size_t bits = m->size() * 8; + const size_t bit_to_corrupt = (rand >> 3) % bits; + const_cast(m->data())[bit_to_corrupt / 8] ^= + 1 << (bit_to_corrupt % 8); + } + } + + P224EncryptedKeyExchange::Result client_result, server_result; + client_result = client.ProcessMessage(server_message); + server_result = server.ProcessMessage(client_message); + + // If we have corrupted anything, we expect the authentication to fail, + // although one side can succeed if we happen to corrupt the second round + // message to the other. + ASSERT_FALSE( + client_result == P224EncryptedKeyExchange::kResultSuccess && + server_result == P224EncryptedKeyExchange::kResultSuccess); + + if (client_result == P224EncryptedKeyExchange::kResultFailed || + server_result == P224EncryptedKeyExchange::kResultFailed) { + break; + } + + ASSERT_EQ(P224EncryptedKeyExchange::kResultPending, + client_result); + ASSERT_EQ(P224EncryptedKeyExchange::kResultPending, + server_result); + } + } +} + +} // namespace crypto diff --git a/crypto/p224_unittest.cc b/crypto/p224_unittest.cc new file mode 100644 index 0000000000000..aaf5f59f47e77 --- /dev/null +++ b/crypto/p224_unittest.cc @@ -0,0 +1,824 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include +#include + +#include "crypto/p224.h" + +#include "testing/gtest/include/gtest/gtest.h" + +namespace crypto { + +using p224::Point; + +// kBasePointExternal is the P224 base point in external representation. +static const uint8 kBasePointExternal[56] = { + 0xb7, 0x0e, 0x0c, 0xbd, 0x6b, 0xb4, 0xbf, 0x7f, + 0x32, 0x13, 0x90, 0xb9, 0x4a, 0x03, 0xc1, 0xd3, + 0x56, 0xc2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xd6, + 0x11, 0x5c, 0x1d, 0x21, 0xbd, 0x37, 0x63, 0x88, + 0xb5, 0xf7, 0x23, 0xfb, 0x4c, 0x22, 0xdf, 0xe6, + 0xcd, 0x43, 0x75, 0xa0, 0x5a, 0x07, 0x47, 0x64, + 0x44, 0xd5, 0x81, 0x99, 0x85, 0x00, 0x7e, 0x34, +}; + +// TestVector represents a test of scalar multiplication of the base point. +// |scalar| is a big-endian scalar and |affine| is the external representation +// of g*scalar. +struct TestVector { + uint8 scalar[28]; + uint8 affine[28*2]; +}; + +static const int kNumNISTTestVectors = 52; + +// kNISTTestVectors are the NIST test vectors for P224. +static const TestVector kNISTTestVectors[kNumNISTTestVectors] = { + { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01}, + {0xb7, 0x0e, 0x0c, 0xbd, 0x6b, 0xb4, 0xbf, 0x7f, + 0x32, 0x13, 0x90, 0xb9, 0x4a, 0x03, 0xc1, 0xd3, + 0x56, 0xc2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xd6, + 0x11, 0x5c, 0x1d, 0x21, 0xbd, 0x37, 0x63, 0x88, + 0xb5, 0xf7, 0x23, 0xfb, 0x4c, 0x22, 0xdf, 0xe6, + 0xcd, 0x43, 0x75, 0xa0, 0x5a, 0x07, 0x47, 0x64, + 0x44, 0xd5, 0x81, 0x99, 0x85, 0x00, 0x7e, 0x34 + }, + }, + { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, }, + + {0x70, 0x6a, 0x46, 0xdc, 0x76, 0xdc, 0xb7, 0x67, + 0x98, 0xe6, 0x0e, 0x6d, 0x89, 0x47, 0x47, 0x88, + 0xd1, 0x6d, 0xc1, 0x80, 0x32, 0xd2, 0x68, 0xfd, + 0x1a, 0x70, 0x4f, 0xa6, 0x1c, 0x2b, 0x76, 0xa7, + 0xbc, 0x25, 0xe7, 0x70, 0x2a, 0x70, 0x4f, 0xa9, + 0x86, 0x89, 0x28, 0x49, 0xfc, 0xa6, 0x29, 0x48, + 0x7a, 0xcf, 0x37, 0x09, 0xd2, 0xe4, 0xe8, 0xbb, + }, + }, + { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, }, + {0xdf, 0x1b, 0x1d, 0x66, 0xa5, 0x51, 0xd0, 0xd3, + 0x1e, 0xff, 0x82, 0x25, 0x58, 0xb9, 0xd2, 0xcc, + 0x75, 0xc2, 0x18, 0x02, 0x79, 0xfe, 0x0d, 0x08, + 0xfd, 0x89, 0x6d, 0x04, 0xa3, 0xf7, 0xf0, 0x3c, + 0xad, 0xd0, 0xbe, 0x44, 0x4c, 0x0a, 0xa5, 0x68, + 0x30, 0x13, 0x0d, 0xdf, 0x77, 0xd3, 0x17, 0x34, + 0x4e, 0x1a, 0xf3, 0x59, 0x19, 0x81, 0xa9, 0x25, + }, + }, + { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x04, }, + {0xae, 0x99, 0xfe, 0xeb, 0xb5, 0xd2, 0x69, 0x45, + 0xb5, 0x48, 0x92, 0x09, 0x2a, 0x8a, 0xee, 0x02, + 0x91, 0x29, 0x30, 0xfa, 0x41, 0xcd, 0x11, 0x4e, + 0x40, 0x44, 0x73, 0x01, 0x04, 0x82, 0x58, 0x0a, + 0x0e, 0xc5, 0xbc, 0x47, 0xe8, 0x8b, 0xc8, 0xc3, + 0x78, 0x63, 0x2c, 0xd1, 0x96, 0xcb, 0x3f, 0xa0, + 0x58, 0xa7, 0x11, 0x4e, 0xb0, 0x30, 0x54, 0xc9, + }, + }, + { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x05, }, + {0x31, 0xc4, 0x9a, 0xe7, 0x5b, 0xce, 0x78, 0x07, + 0xcd, 0xff, 0x22, 0x05, 0x5d, 0x94, 0xee, 0x90, + 0x21, 0xfe, 0xdb, 0xb5, 0xab, 0x51, 0xc5, 0x75, + 0x26, 0xf0, 0x11, 0xaa, 0x27, 0xe8, 0xbf, 0xf1, + 0x74, 0x56, 0x35, 0xec, 0x5b, 0xa0, 0xc9, 0xf1, + 0xc2, 0xed, 0xe1, 0x54, 0x14, 0xc6, 0x50, 0x7d, + 0x29, 0xff, 0xe3, 0x7e, 0x79, 0x0a, 0x07, 0x9b, + }, + }, + { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x06, }, + {0x1f, 0x24, 0x83, 0xf8, 0x25, 0x72, 0x25, 0x1f, + 0xca, 0x97, 0x5f, 0xea, 0x40, 0xdb, 0x82, 0x1d, + 0xf8, 0xad, 0x82, 0xa3, 0xc0, 0x02, 0xee, 0x6c, + 0x57, 0x11, 0x24, 0x08, 0x89, 0xfa, 0xf0, 0xcc, + 0xb7, 0x50, 0xd9, 0x9b, 0x55, 0x3c, 0x57, 0x4f, + 0xad, 0x7e, 0xcf, 0xb0, 0x43, 0x85, 0x86, 0xeb, + 0x39, 0x52, 0xaf, 0x5b, 0x4b, 0x15, 0x3c, 0x7e, + }, + }, + { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x07, }, + {0xdb, 0x2f, 0x6b, 0xe6, 0x30, 0xe2, 0x46, 0xa5, + 0xcf, 0x7d, 0x99, 0xb8, 0x51, 0x94, 0xb1, 0x23, + 0xd4, 0x87, 0xe2, 0xd4, 0x66, 0xb9, 0x4b, 0x24, + 0xa0, 0x3c, 0x3e, 0x28, 0x0f, 0x3a, 0x30, 0x08, + 0x54, 0x97, 0xf2, 0xf6, 0x11, 0xee, 0x25, 0x17, + 0xb1, 0x63, 0xef, 0x8c, 0x53, 0xb7, 0x15, 0xd1, + 0x8b, 0xb4, 0xe4, 0x80, 0x8d, 0x02, 0xb9, 0x63, + }, + }, + { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, }, + {0x85, 0x8e, 0x6f, 0x9c, 0xc6, 0xc1, 0x2c, 0x31, + 0xf5, 0xdf, 0x12, 0x4a, 0xa7, 0x77, 0x67, 0xb0, + 0x5c, 0x8b, 0xc0, 0x21, 0xbd, 0x68, 0x3d, 0x2b, + 0x55, 0x57, 0x15, 0x50, 0x04, 0x6d, 0xcd, 0x3e, + 0xa5, 0xc4, 0x38, 0x98, 0xc5, 0xc5, 0xfc, 0x4f, + 0xda, 0xc7, 0xdb, 0x39, 0xc2, 0xf0, 0x2e, 0xbe, + 0xe4, 0xe3, 0x54, 0x1d, 0x1e, 0x78, 0x04, 0x7a, + }, + }, + { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x09, }, + {0x2f, 0xdc, 0xcc, 0xfe, 0xe7, 0x20, 0xa7, 0x7e, + 0xf6, 0xcb, 0x3b, 0xfb, 0xb4, 0x47, 0xf9, 0x38, + 0x31, 0x17, 0xe3, 0xda, 0xa4, 0xa0, 0x7e, 0x36, + 0xed, 0x15, 0xf7, 0x8d, 0x37, 0x17, 0x32, 0xe4, + 0xf4, 0x1b, 0xf4, 0xf7, 0x88, 0x30, 0x35, 0xe6, + 0xa7, 0x9f, 0xce, 0xdc, 0x0e, 0x19, 0x6e, 0xb0, + 0x7b, 0x48, 0x17, 0x16, 0x97, 0x51, 0x74, 0x63, + }, + }, + { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0a, }, + {0xae, 0xa9, 0xe1, 0x7a, 0x30, 0x65, 0x17, 0xeb, + 0x89, 0x15, 0x2a, 0xa7, 0x09, 0x6d, 0x2c, 0x38, + 0x1e, 0xc8, 0x13, 0xc5, 0x1a, 0xa8, 0x80, 0xe7, + 0xbe, 0xe2, 0xc0, 0xfd, 0x39, 0xbb, 0x30, 0xea, + 0xb3, 0x37, 0xe0, 0xa5, 0x21, 0xb6, 0xcb, 0xa1, + 0xab, 0xe4, 0xb2, 0xb3, 0xa3, 0xe5, 0x24, 0xc1, + 0x4a, 0x3f, 0xe3, 0xeb, 0x11, 0x6b, 0x65, 0x5f, + }, + }, + { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0b, }, + {0xef, 0x53, 0xb6, 0x29, 0x4a, 0xca, 0x43, 0x1f, + 0x0f, 0x3c, 0x22, 0xdc, 0x82, 0xeb, 0x90, 0x50, + 0x32, 0x4f, 0x1d, 0x88, 0xd3, 0x77, 0xe7, 0x16, + 0x44, 0x8e, 0x50, 0x7c, 0x20, 0xb5, 0x10, 0x00, + 0x40, 0x92, 0xe9, 0x66, 0x36, 0xcf, 0xb7, 0xe3, + 0x2e, 0xfd, 0xed, 0x82, 0x65, 0xc2, 0x66, 0xdf, + 0xb7, 0x54, 0xfa, 0x6d, 0x64, 0x91, 0xa6, 0xda, + }, + }, + { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0c, }, + {0x6e, 0x31, 0xee, 0x1d, 0xc1, 0x37, 0xf8, 0x1b, + 0x05, 0x67, 0x52, 0xe4, 0xde, 0xab, 0x14, 0x43, + 0xa4, 0x81, 0x03, 0x3e, 0x9b, 0x4c, 0x93, 0xa3, + 0x04, 0x4f, 0x4f, 0x7a, 0x20, 0x7d, 0xdd, 0xf0, + 0x38, 0x5b, 0xfd, 0xea, 0xb6, 0xe9, 0xac, 0xda, + 0x8d, 0xa0, 0x6b, 0x3b, 0xbe, 0xf2, 0x24, 0xa9, + 0x3a, 0xb1, 0xe9, 0xe0, 0x36, 0x10, 0x9d, 0x13, + }, + }, + { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0d, }, + {0x34, 0xe8, 0xe1, 0x7a, 0x43, 0x0e, 0x43, 0x28, + 0x97, 0x93, 0xc3, 0x83, 0xfa, 0xc9, 0x77, 0x42, + 0x47, 0xb4, 0x0e, 0x9e, 0xbd, 0x33, 0x66, 0x98, + 0x1f, 0xcf, 0xae, 0xca, 0x25, 0x28, 0x19, 0xf7, + 0x1c, 0x7f, 0xb7, 0xfb, 0xcb, 0x15, 0x9b, 0xe3, + 0x37, 0xd3, 0x7d, 0x33, 0x36, 0xd7, 0xfe, 0xb9, + 0x63, 0x72, 0x4f, 0xdf, 0xb0, 0xec, 0xb7, 0x67, + }, + }, + { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0e, }, + {0xa5, 0x36, 0x40, 0xc8, 0x3d, 0xc2, 0x08, 0x60, + 0x3d, 0xed, 0x83, 0xe4, 0xec, 0xf7, 0x58, 0xf2, + 0x4c, 0x35, 0x7d, 0x7c, 0xf4, 0x80, 0x88, 0xb2, + 0xce, 0x01, 0xe9, 0xfa, 0xd5, 0x81, 0x4c, 0xd7, + 0x24, 0x19, 0x9c, 0x4a, 0x5b, 0x97, 0x4a, 0x43, + 0x68, 0x5f, 0xbf, 0x5b, 0x8b, 0xac, 0x69, 0x45, + 0x9c, 0x94, 0x69, 0xbc, 0x8f, 0x23, 0xcc, 0xaf, + }, + }, + { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0f, }, + {0xba, 0xa4, 0xd8, 0x63, 0x55, 0x11, 0xa7, 0xd2, + 0x88, 0xae, 0xbe, 0xed, 0xd1, 0x2c, 0xe5, 0x29, + 0xff, 0x10, 0x2c, 0x91, 0xf9, 0x7f, 0x86, 0x7e, + 0x21, 0x91, 0x6b, 0xf9, 0x97, 0x9a, 0x5f, 0x47, + 0x59, 0xf8, 0x0f, 0x4f, 0xb4, 0xec, 0x2e, 0x34, + 0xf5, 0x56, 0x6d, 0x59, 0x56, 0x80, 0xa1, 0x17, + 0x35, 0xe7, 0xb6, 0x10, 0x46, 0x12, 0x79, 0x89, + }, + }, + { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, }, + {0x0b, 0x6e, 0xc4, 0xfe, 0x17, 0x77, 0x38, 0x24, + 0x04, 0xef, 0x67, 0x99, 0x97, 0xba, 0x8d, 0x1c, + 0xc5, 0xcd, 0x8e, 0x85, 0x34, 0x92, 0x59, 0xf5, + 0x90, 0xc4, 0xc6, 0x6d, 0x33, 0x99, 0xd4, 0x64, + 0x34, 0x59, 0x06, 0xb1, 0x1b, 0x00, 0xe3, 0x63, + 0xef, 0x42, 0x92, 0x21, 0xf2, 0xec, 0x72, 0x0d, + 0x2f, 0x66, 0x5d, 0x7d, 0xea, 0xd5, 0xb4, 0x82, + }, + }, + { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x11, }, + {0xb8, 0x35, 0x7c, 0x3a, 0x6c, 0xee, 0xf2, 0x88, + 0x31, 0x0e, 0x17, 0xb8, 0xbf, 0xef, 0xf9, 0x20, + 0x08, 0x46, 0xca, 0x8c, 0x19, 0x42, 0x49, 0x7c, + 0x48, 0x44, 0x03, 0xbc, 0xff, 0x14, 0x9e, 0xfa, + 0x66, 0x06, 0xa6, 0xbd, 0x20, 0xef, 0x7d, 0x1b, + 0x06, 0xbd, 0x92, 0xf6, 0x90, 0x46, 0x39, 0xdc, + 0xe5, 0x17, 0x4d, 0xb6, 0xcc, 0x55, 0x4a, 0x26, + }, + }, + { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x12, }, + {0xc9, 0xff, 0x61, 0xb0, 0x40, 0x87, 0x4c, 0x05, + 0x68, 0x47, 0x92, 0x16, 0x82, 0x4a, 0x15, 0xea, + 0xb1, 0xa8, 0x38, 0xa7, 0x97, 0xd1, 0x89, 0x74, + 0x62, 0x26, 0xe4, 0xcc, 0xea, 0x98, 0xd6, 0x0e, + 0x5f, 0xfc, 0x9b, 0x8f, 0xcf, 0x99, 0x9f, 0xab, + 0x1d, 0xf7, 0xe7, 0xef, 0x70, 0x84, 0xf2, 0x0d, + 0xdb, 0x61, 0xbb, 0x04, 0x5a, 0x6c, 0xe0, 0x02, + }, + }, + { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x13, }, + {0xa1, 0xe8, 0x1c, 0x04, 0xf3, 0x0c, 0xe2, 0x01, + 0xc7, 0xc9, 0xac, 0xe7, 0x85, 0xed, 0x44, 0xcc, + 0x33, 0xb4, 0x55, 0xa0, 0x22, 0xf2, 0xac, 0xdb, + 0xc6, 0xca, 0xe8, 0x3c, 0xdc, 0xf1, 0xf6, 0xc3, + 0xdb, 0x09, 0xc7, 0x0a, 0xcc, 0x25, 0x39, 0x1d, + 0x49, 0x2f, 0xe2, 0x5b, 0x4a, 0x18, 0x0b, 0xab, + 0xd6, 0xce, 0xa3, 0x56, 0xc0, 0x47, 0x19, 0xcd, + }, + }, + { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x14, }, + {0xfc, 0xc7, 0xf2, 0xb4, 0x5d, 0xf1, 0xcd, 0x5a, + 0x3c, 0x0c, 0x07, 0x31, 0xca, 0x47, 0xa8, 0xaf, + 0x75, 0xcf, 0xb0, 0x34, 0x7e, 0x83, 0x54, 0xee, + 0xfe, 0x78, 0x24, 0x55, 0x0d, 0x5d, 0x71, 0x10, + 0x27, 0x4c, 0xba, 0x7c, 0xde, 0xe9, 0x0e, 0x1a, + 0x8b, 0x0d, 0x39, 0x4c, 0x37, 0x6a, 0x55, 0x73, + 0xdb, 0x6b, 0xe0, 0xbf, 0x27, 0x47, 0xf5, 0x30, + }, + }, + { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x8e, 0xbb, 0xb9, + 0x5e, 0xed, 0x0e, 0x13, }, + {0x61, 0xf0, 0x77, 0xc6, 0xf6, 0x2e, 0xd8, 0x02, + 0xda, 0xd7, 0xc2, 0xf3, 0x8f, 0x5c, 0x67, 0xf2, + 0xcc, 0x45, 0x36, 0x01, 0xe6, 0x1b, 0xd0, 0x76, + 0xbb, 0x46, 0x17, 0x9e, 0x22, 0x72, 0xf9, 0xe9, + 0xf5, 0x93, 0x3e, 0x70, 0x38, 0x8e, 0xe6, 0x52, + 0x51, 0x34, 0x43, 0xb5, 0xe2, 0x89, 0xdd, 0x13, + 0x5d, 0xcc, 0x0d, 0x02, 0x99, 0xb2, 0x25, 0xe4, + }, + }, + { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x9d, 0x89, + 0x3d, 0x4c, 0xdd, 0x74, 0x72, 0x46, 0xcd, 0xca, + 0x43, 0x59, 0x0e, 0x13, }, + {0x02, 0x98, 0x95, 0xf0, 0xaf, 0x49, 0x6b, 0xfc, + 0x62, 0xb6, 0xef, 0x8d, 0x8a, 0x65, 0xc8, 0x8c, + 0x61, 0x39, 0x49, 0xb0, 0x36, 0x68, 0xaa, 0xb4, + 0xf0, 0x42, 0x9e, 0x35, 0x3e, 0xa6, 0xe5, 0x3f, + 0x9a, 0x84, 0x1f, 0x20, 0x19, 0xec, 0x24, 0xbd, + 0xe1, 0xa7, 0x56, 0x77, 0xaa, 0x9b, 0x59, 0x02, + 0xe6, 0x10, 0x81, 0xc0, 0x10, 0x64, 0xde, 0x93, + }, + }, + { + {0x41, 0xff, 0xc1, 0xff, 0xff, 0xfe, 0x01, 0xff, + 0xfc, 0x00, 0x03, 0xff, 0xfe, 0x00, 0x07, 0xc0, + 0x01, 0xff, 0xf0, 0x00, 0x03, 0xff, 0xf0, 0x7f, + 0xfe, 0x00, 0x07, 0xc0, }, + {0xab, 0x68, 0x99, 0x30, 0xbc, 0xae, 0x4a, 0x4a, + 0xa5, 0xf5, 0xcb, 0x08, 0x5e, 0x82, 0x3e, 0x8a, + 0xe3, 0x0f, 0xd3, 0x65, 0xeb, 0x1d, 0xa4, 0xab, + 0xa9, 0xcf, 0x03, 0x79, 0x33, 0x45, 0xa1, 0x21, + 0xbb, 0xd2, 0x33, 0x54, 0x8a, 0xf0, 0xd2, 0x10, + 0x65, 0x4e, 0xb4, 0x0b, 0xab, 0x78, 0x8a, 0x03, + 0x66, 0x64, 0x19, 0xbe, 0x6f, 0xbd, 0x34, 0xe7, + }, + }, + { + {0x7f, 0xff, 0xff, 0xc0, 0x3f, 0xff, 0xc0, 0x03, + 0xff, 0xff, 0xfc, 0x00, 0x7f, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x07, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0x0e, 0x00, 0xff, }, + {0xbd, 0xb6, 0xa8, 0x81, 0x7c, 0x1f, 0x89, 0xda, + 0x1c, 0x2f, 0x3d, 0xd8, 0xe9, 0x7f, 0xeb, 0x44, + 0x94, 0xf2, 0xed, 0x30, 0x2a, 0x4c, 0xe2, 0xbc, + 0x7f, 0x5f, 0x40, 0x25, 0x4c, 0x70, 0x20, 0xd5, + 0x7c, 0x00, 0x41, 0x18, 0x89, 0x46, 0x2d, 0x77, + 0xa5, 0x43, 0x8b, 0xb4, 0xe9, 0x7d, 0x17, 0x77, + 0x00, 0xbf, 0x72, 0x43, 0xa0, 0x7f, 0x16, 0x80, + }, + }, + { + {0x7f, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xf0, 0x1f, 0xff, 0xf8, 0xff, 0xff, + 0xc0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, + 0x00, 0x0f, 0xff, 0xff, }, + {0xd5, 0x8b, 0x61, 0xaa, 0x41, 0xc3, 0x2d, 0xd5, + 0xeb, 0xa4, 0x62, 0x64, 0x7d, 0xba, 0x75, 0xc5, + 0xd6, 0x7c, 0x83, 0x60, 0x6c, 0x0a, 0xf2, 0xbd, + 0x92, 0x84, 0x46, 0xa9, 0xd2, 0x4b, 0xa6, 0xa8, + 0x37, 0xbe, 0x04, 0x60, 0xdd, 0x10, 0x7a, 0xe7, + 0x77, 0x25, 0x69, 0x6d, 0x21, 0x14, 0x46, 0xc5, + 0x60, 0x9b, 0x45, 0x95, 0x97, 0x6b, 0x16, 0xbd, + }, + }, + { + {0x7f, 0xff, 0xff, 0xc0, 0x00, 0xff, 0xfe, 0x3f, + 0xff, 0xfc, 0x10, 0x00, 0x00, 0x20, 0x00, 0x3f, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, + 0x3f, 0xff, 0xff, 0xff, }, + {0xdc, 0x9f, 0xa7, 0x79, 0x78, 0xa0, 0x05, 0x51, + 0x09, 0x80, 0xe9, 0x29, 0xa1, 0x48, 0x5f, 0x63, + 0x71, 0x6d, 0xf6, 0x95, 0xd7, 0xa0, 0xc1, 0x8b, + 0xb5, 0x18, 0xdf, 0x03, 0xed, 0xe2, 0xb0, 0x16, + 0xf2, 0xdd, 0xff, 0xc2, 0xa8, 0xc0, 0x15, 0xb1, + 0x34, 0x92, 0x82, 0x75, 0xce, 0x09, 0xe5, 0x66, + 0x1b, 0x7a, 0xb1, 0x4c, 0xe0, 0xd1, 0xd4, 0x03, + }, + }, + { + {0x70, 0x01, 0xf0, 0x00, 0x1c, 0x00, 0x01, 0xc0, + 0x00, 0x00, 0x1f, 0xff, 0xff, 0xfc, 0x00, 0x00, + 0x1f, 0xff, 0xff, 0xf8, 0x00, 0x0f, 0xc0, 0x00, + 0x00, 0x01, 0xfc, 0x00, }, + {0x49, 0x9d, 0x8b, 0x28, 0x29, 0xcf, 0xb8, 0x79, + 0xc9, 0x01, 0xf7, 0xd8, 0x5d, 0x35, 0x70, 0x45, + 0xed, 0xab, 0x55, 0x02, 0x88, 0x24, 0xd0, 0xf0, + 0x5b, 0xa2, 0x79, 0xba, 0xbf, 0x92, 0x95, 0x37, + 0xb0, 0x6e, 0x40, 0x15, 0x91, 0x96, 0x39, 0xd9, + 0x4f, 0x57, 0x83, 0x8f, 0xa3, 0x3f, 0xc3, 0xd9, + 0x52, 0x59, 0x8d, 0xcd, 0xbb, 0x44, 0xd6, 0x38, + }, + }, + { + {0x00, 0x00, 0x00, 0x00, 0x1f, 0xfc, 0x00, 0x00, + 0x00, 0xff, 0xf0, 0x30, 0x00, 0x1f, 0x00, 0x00, + 0xff, 0xff, 0xf0, 0x00, 0x00, 0x38, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, }, + {0x82, 0x46, 0xc9, 0x99, 0x13, 0x71, 0x86, 0x63, + 0x2c, 0x5f, 0x9e, 0xdd, 0xf3, 0xb1, 0xb0, 0xe1, + 0x76, 0x4c, 0x5e, 0x8b, 0xd0, 0xe0, 0xd8, 0xa5, + 0x54, 0xb9, 0xcb, 0x77, 0xe8, 0x0e, 0xd8, 0x66, + 0x0b, 0xc1, 0xcb, 0x17, 0xac, 0x7d, 0x84, 0x5b, + 0xe4, 0x0a, 0x7a, 0x02, 0x2d, 0x33, 0x06, 0xf1, + 0x16, 0xae, 0x9f, 0x81, 0xfe, 0xa6, 0x59, 0x47, + }, + }, + { + {0x7f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xfe, 0x08, 0x00, 0x00, 0x1f, + 0xf0, 0x00, 0x1f, 0xff, }, + {0x66, 0x70, 0xc2, 0x0a, 0xfc, 0xce, 0xae, 0xa6, + 0x72, 0xc9, 0x7f, 0x75, 0xe2, 0xe9, 0xdd, 0x5c, + 0x84, 0x60, 0xe5, 0x4b, 0xb3, 0x85, 0x38, 0xeb, + 0xb4, 0xbd, 0x30, 0xeb, 0xf2, 0x80, 0xd8, 0x00, + 0x8d, 0x07, 0xa4, 0xca, 0xf5, 0x42, 0x71, 0xf9, + 0x93, 0x52, 0x7d, 0x46, 0xff, 0x3f, 0xf4, 0x6f, + 0xd1, 0x19, 0x0a, 0x3f, 0x1f, 0xaa, 0x4f, 0x74, + }, + }, + { + {0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xc0, 0x00, 0x07, 0xff, 0xff, 0xe0, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, }, + {0x00, 0x0e, 0xca, 0x93, 0x42, 0x47, 0x42, 0x5c, + 0xfd, 0x94, 0x9b, 0x79, 0x5c, 0xb5, 0xce, 0x1e, + 0xff, 0x40, 0x15, 0x50, 0x38, 0x6e, 0x28, 0xd1, + 0xa4, 0xc5, 0xa8, 0xeb, 0xd4, 0xc0, 0x10, 0x40, + 0xdb, 0xa1, 0x96, 0x28, 0x93, 0x1b, 0xc8, 0x85, + 0x53, 0x70, 0x31, 0x7c, 0x72, 0x2c, 0xbd, 0x9c, + 0xa6, 0x15, 0x69, 0x85, 0xf1, 0xc2, 0xe9, 0xce, + }, + }, + { + {0x7f, 0xff, 0xfc, 0x03, 0xff, 0x80, 0x7f, 0xff, + 0xe0, 0x00, 0x1f, 0xff, 0xff, 0x80, 0x0f, 0xff, + 0x80, 0x00, 0x01, 0xff, 0xff, 0x00, 0x01, 0xff, + 0xff, 0xfe, 0x00, 0x1f, }, + {0xef, 0x35, 0x3b, 0xf5, 0xc7, 0x3c, 0xd5, 0x51, + 0xb9, 0x6d, 0x59, 0x6f, 0xbc, 0x9a, 0x67, 0xf1, + 0x6d, 0x61, 0xdd, 0x9f, 0xe5, 0x6a, 0xf1, 0x9d, + 0xe1, 0xfb, 0xa9, 0xcd, 0x21, 0x77, 0x1b, 0x9c, + 0xdc, 0xe3, 0xe8, 0x43, 0x0c, 0x09, 0xb3, 0x83, + 0x8b, 0xe7, 0x0b, 0x48, 0xc2, 0x1e, 0x15, 0xbc, + 0x09, 0xee, 0x1f, 0x2d, 0x79, 0x45, 0xb9, 0x1f, + }, + }, + { + {0x00, 0x00, 0x00, 0x07, 0xff, 0xc0, 0x7f, 0xff, + 0xff, 0xff, 0x01, 0xff, 0xfe, 0x03, 0xff, 0xfe, + 0x40, 0x00, 0x38, 0x00, 0x07, 0xe0, 0x00, 0x3f, + 0xfe, 0x00, 0x00, 0x00, }, + {0x40, 0x36, 0x05, 0x2a, 0x30, 0x91, 0xeb, 0x48, + 0x10, 0x46, 0xad, 0x32, 0x89, 0xc9, 0x5d, 0x3a, + 0xc9, 0x05, 0xca, 0x00, 0x23, 0xde, 0x2c, 0x03, + 0xec, 0xd4, 0x51, 0xcf, 0xd7, 0x68, 0x16, 0x5a, + 0x38, 0xa2, 0xb9, 0x6f, 0x81, 0x25, 0x86, 0xa9, + 0xd5, 0x9d, 0x41, 0x36, 0x03, 0x5d, 0x9c, 0x85, + 0x3a, 0x5b, 0xf2, 0xe1, 0xc8, 0x6a, 0x49, 0x93, + }, + }, + { + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, + 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45, + 0x5c, 0x5c, 0x2a, 0x29, }, + {0xfc, 0xc7, 0xf2, 0xb4, 0x5d, 0xf1, 0xcd, 0x5a, + 0x3c, 0x0c, 0x07, 0x31, 0xca, 0x47, 0xa8, 0xaf, + 0x75, 0xcf, 0xb0, 0x34, 0x7e, 0x83, 0x54, 0xee, + 0xfe, 0x78, 0x24, 0x55, 0xf2, 0xa2, 0x8e, 0xef, + 0xd8, 0xb3, 0x45, 0x83, 0x21, 0x16, 0xf1, 0xe5, + 0x74, 0xf2, 0xc6, 0xb2, 0xc8, 0x95, 0xaa, 0x8c, + 0x24, 0x94, 0x1f, 0x40, 0xd8, 0xb8, 0x0a, 0xd1, + }, + }, + { + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, + 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45, + 0x5c, 0x5c, 0x2a, 0x2a, }, + {0xa1, 0xe8, 0x1c, 0x04, 0xf3, 0x0c, 0xe2, 0x01, + 0xc7, 0xc9, 0xac, 0xe7, 0x85, 0xed, 0x44, 0xcc, + 0x33, 0xb4, 0x55, 0xa0, 0x22, 0xf2, 0xac, 0xdb, + 0xc6, 0xca, 0xe8, 0x3c, 0x23, 0x0e, 0x09, 0x3c, + 0x24, 0xf6, 0x38, 0xf5, 0x33, 0xda, 0xc6, 0xe2, + 0xb6, 0xd0, 0x1d, 0xa3, 0xb5, 0xe7, 0xf4, 0x54, + 0x29, 0x31, 0x5c, 0xa9, 0x3f, 0xb8, 0xe6, 0x34, + }, + }, + { + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, + 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45, + 0x5c, 0x5c, 0x2a, 0x2b, }, + {0xc9, 0xff, 0x61, 0xb0, 0x40, 0x87, 0x4c, 0x05, + 0x68, 0x47, 0x92, 0x16, 0x82, 0x4a, 0x15, 0xea, + 0xb1, 0xa8, 0x38, 0xa7, 0x97, 0xd1, 0x89, 0x74, + 0x62, 0x26, 0xe4, 0xcc, 0x15, 0x67, 0x29, 0xf1, + 0xa0, 0x03, 0x64, 0x70, 0x30, 0x66, 0x60, 0x54, + 0xe2, 0x08, 0x18, 0x0f, 0x8f, 0x7b, 0x0d, 0xf2, + 0x24, 0x9e, 0x44, 0xfb, 0xa5, 0x93, 0x1f, 0xff, + }, + }, + { + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, + 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45, + 0x5c, 0x5c, 0x2a, 0x2c, }, + {0xb8, 0x35, 0x7c, 0x3a, 0x6c, 0xee, 0xf2, 0x88, + 0x31, 0x0e, 0x17, 0xb8, 0xbf, 0xef, 0xf9, 0x20, + 0x08, 0x46, 0xca, 0x8c, 0x19, 0x42, 0x49, 0x7c, + 0x48, 0x44, 0x03, 0xbc, 0x00, 0xeb, 0x61, 0x05, + 0x99, 0xf9, 0x59, 0x42, 0xdf, 0x10, 0x82, 0xe4, + 0xf9, 0x42, 0x6d, 0x08, 0x6f, 0xb9, 0xc6, 0x23, + 0x1a, 0xe8, 0xb2, 0x49, 0x33, 0xaa, 0xb5, 0xdb, + }, + }, + { + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, + 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45, + 0x5c, 0x5c, 0x2a, 0x2d, }, + {0x0b, 0x6e, 0xc4, 0xfe, 0x17, 0x77, 0x38, 0x24, + 0x04, 0xef, 0x67, 0x99, 0x97, 0xba, 0x8d, 0x1c, + 0xc5, 0xcd, 0x8e, 0x85, 0x34, 0x92, 0x59, 0xf5, + 0x90, 0xc4, 0xc6, 0x6d, 0xcc, 0x66, 0x2b, 0x9b, + 0xcb, 0xa6, 0xf9, 0x4e, 0xe4, 0xff, 0x1c, 0x9c, + 0x10, 0xbd, 0x6d, 0xdd, 0x0d, 0x13, 0x8d, 0xf2, + 0xd0, 0x99, 0xa2, 0x82, 0x15, 0x2a, 0x4b, 0x7f, + }, + }, + { + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, + 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45, + 0x5c, 0x5c, 0x2a, 0x2e, }, + {0xba, 0xa4, 0xd8, 0x63, 0x55, 0x11, 0xa7, 0xd2, + 0x88, 0xae, 0xbe, 0xed, 0xd1, 0x2c, 0xe5, 0x29, + 0xff, 0x10, 0x2c, 0x91, 0xf9, 0x7f, 0x86, 0x7e, + 0x21, 0x91, 0x6b, 0xf9, 0x68, 0x65, 0xa0, 0xb8, + 0xa6, 0x07, 0xf0, 0xb0, 0x4b, 0x13, 0xd1, 0xcb, + 0x0a, 0xa9, 0x92, 0xa5, 0xa9, 0x7f, 0x5e, 0xe8, + 0xca, 0x18, 0x49, 0xef, 0xb9, 0xed, 0x86, 0x78, + }, + }, + { + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, + 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45, + 0x5c, 0x5c, 0x2a, 0x2f, }, + {0xa5, 0x36, 0x40, 0xc8, 0x3d, 0xc2, 0x08, 0x60, + 0x3d, 0xed, 0x83, 0xe4, 0xec, 0xf7, 0x58, 0xf2, + 0x4c, 0x35, 0x7d, 0x7c, 0xf4, 0x80, 0x88, 0xb2, + 0xce, 0x01, 0xe9, 0xfa, 0x2a, 0x7e, 0xb3, 0x28, + 0xdb, 0xe6, 0x63, 0xb5, 0xa4, 0x68, 0xb5, 0xbc, + 0x97, 0xa0, 0x40, 0xa3, 0x74, 0x53, 0x96, 0xba, + 0x63, 0x6b, 0x96, 0x43, 0x70, 0xdc, 0x33, 0x52, + }, + }, + { + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, + 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45, + 0x5c, 0x5c, 0x2a, 0x30, }, + {0x34, 0xe8, 0xe1, 0x7a, 0x43, 0x0e, 0x43, 0x28, + 0x97, 0x93, 0xc3, 0x83, 0xfa, 0xc9, 0x77, 0x42, + 0x47, 0xb4, 0x0e, 0x9e, 0xbd, 0x33, 0x66, 0x98, + 0x1f, 0xcf, 0xae, 0xca, 0xda, 0xd7, 0xe6, 0x08, + 0xe3, 0x80, 0x48, 0x04, 0x34, 0xea, 0x64, 0x1c, + 0xc8, 0x2c, 0x82, 0xcb, 0xc9, 0x28, 0x01, 0x46, + 0x9c, 0x8d, 0xb0, 0x20, 0x4f, 0x13, 0x48, 0x9a, + }, + }, + { + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, + 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45, + 0x5c, 0x5c, 0x2a, 0x31, }, + {0x6e, 0x31, 0xee, 0x1d, 0xc1, 0x37, 0xf8, 0x1b, + 0x05, 0x67, 0x52, 0xe4, 0xde, 0xab, 0x14, 0x43, + 0xa4, 0x81, 0x03, 0x3e, 0x9b, 0x4c, 0x93, 0xa3, + 0x04, 0x4f, 0x4f, 0x7a, 0xdf, 0x82, 0x22, 0x0f, + 0xc7, 0xa4, 0x02, 0x15, 0x49, 0x16, 0x53, 0x25, + 0x72, 0x5f, 0x94, 0xc3, 0x41, 0x0d, 0xdb, 0x56, + 0xc5, 0x4e, 0x16, 0x1f, 0xc9, 0xef, 0x62, 0xee, + }, + }, + { + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, + 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45, + 0x5c, 0x5c, 0x2a, 0x32, }, + {0xef, 0x53, 0xb6, 0x29, 0x4a, 0xca, 0x43, 0x1f, + 0x0f, 0x3c, 0x22, 0xdc, 0x82, 0xeb, 0x90, 0x50, + 0x32, 0x4f, 0x1d, 0x88, 0xd3, 0x77, 0xe7, 0x16, + 0x44, 0x8e, 0x50, 0x7c, 0xdf, 0x4a, 0xef, 0xff, + 0xbf, 0x6d, 0x16, 0x99, 0xc9, 0x30, 0x48, 0x1c, + 0xd1, 0x02, 0x12, 0x7c, 0x9a, 0x3d, 0x99, 0x20, + 0x48, 0xab, 0x05, 0x92, 0x9b, 0x6e, 0x59, 0x27, + }, + }, + { + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, + 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45, + 0x5c, 0x5c, 0x2a, 0x33, }, + {0xae, 0xa9, 0xe1, 0x7a, 0x30, 0x65, 0x17, 0xeb, + 0x89, 0x15, 0x2a, 0xa7, 0x09, 0x6d, 0x2c, 0x38, + 0x1e, 0xc8, 0x13, 0xc5, 0x1a, 0xa8, 0x80, 0xe7, + 0xbe, 0xe2, 0xc0, 0xfd, 0xc6, 0x44, 0xcf, 0x15, + 0x4c, 0xc8, 0x1f, 0x5a, 0xde, 0x49, 0x34, 0x5e, + 0x54, 0x1b, 0x4d, 0x4b, 0x5c, 0x1a, 0xdb, 0x3e, + 0xb5, 0xc0, 0x1c, 0x14, 0xee, 0x94, 0x9a, 0xa2, + }, + }, + { + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, + 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45, + 0x5c, 0x5c, 0x2a, 0x34, }, + {0x2f, 0xdc, 0xcc, 0xfe, 0xe7, 0x20, 0xa7, 0x7e, + 0xf6, 0xcb, 0x3b, 0xfb, 0xb4, 0x47, 0xf9, 0x38, + 0x31, 0x17, 0xe3, 0xda, 0xa4, 0xa0, 0x7e, 0x36, + 0xed, 0x15, 0xf7, 0x8d, 0xc8, 0xe8, 0xcd, 0x1b, + 0x0b, 0xe4, 0x0b, 0x08, 0x77, 0xcf, 0xca, 0x19, + 0x58, 0x60, 0x31, 0x22, 0xf1, 0xe6, 0x91, 0x4f, + 0x84, 0xb7, 0xe8, 0xe9, 0x68, 0xae, 0x8b, 0x9e, + }, + }, + { + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, + 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45, + 0x5c, 0x5c, 0x2a, 0x35, }, + {0x85, 0x8e, 0x6f, 0x9c, 0xc6, 0xc1, 0x2c, 0x31, + 0xf5, 0xdf, 0x12, 0x4a, 0xa7, 0x77, 0x67, 0xb0, + 0x5c, 0x8b, 0xc0, 0x21, 0xbd, 0x68, 0x3d, 0x2b, + 0x55, 0x57, 0x15, 0x50, 0xfb, 0x92, 0x32, 0xc1, + 0x5a, 0x3b, 0xc7, 0x67, 0x3a, 0x3a, 0x03, 0xb0, + 0x25, 0x38, 0x24, 0xc5, 0x3d, 0x0f, 0xd1, 0x41, + 0x1b, 0x1c, 0xab, 0xe2, 0xe1, 0x87, 0xfb, 0x87, + }, + }, + { + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, + 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45, + 0x5c, 0x5c, 0x2a, 0x36, }, + {0xdb, 0x2f, 0x6b, 0xe6, 0x30, 0xe2, 0x46, 0xa5, + 0xcf, 0x7d, 0x99, 0xb8, 0x51, 0x94, 0xb1, 0x23, + 0xd4, 0x87, 0xe2, 0xd4, 0x66, 0xb9, 0x4b, 0x24, + 0xa0, 0x3c, 0x3e, 0x28, 0xf0, 0xc5, 0xcf, 0xf7, + 0xab, 0x68, 0x0d, 0x09, 0xee, 0x11, 0xda, 0xe8, + 0x4e, 0x9c, 0x10, 0x72, 0xac, 0x48, 0xea, 0x2e, + 0x74, 0x4b, 0x1b, 0x7f, 0x72, 0xfd, 0x46, 0x9e, + }, + }, + { + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, + 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45, + 0x5c, 0x5c, 0x2a, 0x37, }, + {0x1f, 0x24, 0x83, 0xf8, 0x25, 0x72, 0x25, 0x1f, + 0xca, 0x97, 0x5f, 0xea, 0x40, 0xdb, 0x82, 0x1d, + 0xf8, 0xad, 0x82, 0xa3, 0xc0, 0x02, 0xee, 0x6c, + 0x57, 0x11, 0x24, 0x08, 0x76, 0x05, 0x0f, 0x33, + 0x48, 0xaf, 0x26, 0x64, 0xaa, 0xc3, 0xa8, 0xb0, + 0x52, 0x81, 0x30, 0x4e, 0xbc, 0x7a, 0x79, 0x14, + 0xc6, 0xad, 0x50, 0xa4, 0xb4, 0xea, 0xc3, 0x83, + }, + }, + { + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, + 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45, + 0x5c, 0x5c, 0x2a, 0x38, }, + {0x31, 0xc4, 0x9a, 0xe7, 0x5b, 0xce, 0x78, 0x07, + 0xcd, 0xff, 0x22, 0x05, 0x5d, 0x94, 0xee, 0x90, + 0x21, 0xfe, 0xdb, 0xb5, 0xab, 0x51, 0xc5, 0x75, + 0x26, 0xf0, 0x11, 0xaa, 0xd8, 0x17, 0x40, 0x0e, + 0x8b, 0xa9, 0xca, 0x13, 0xa4, 0x5f, 0x36, 0x0e, + 0x3d, 0x12, 0x1e, 0xaa, 0xeb, 0x39, 0xaf, 0x82, + 0xd6, 0x00, 0x1c, 0x81, 0x86, 0xf5, 0xf8, 0x66, + }, + }, + { + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, + 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45, + 0x5c, 0x5c, 0x2a, 0x39, }, + {0xae, 0x99, 0xfe, 0xeb, 0xb5, 0xd2, 0x69, 0x45, + 0xb5, 0x48, 0x92, 0x09, 0x2a, 0x8a, 0xee, 0x02, + 0x91, 0x29, 0x30, 0xfa, 0x41, 0xcd, 0x11, 0x4e, + 0x40, 0x44, 0x73, 0x01, 0xfb, 0x7d, 0xa7, 0xf5, + 0xf1, 0x3a, 0x43, 0xb8, 0x17, 0x74, 0x37, 0x3c, + 0x87, 0x9c, 0xd3, 0x2d, 0x69, 0x34, 0xc0, 0x5f, + 0xa7, 0x58, 0xee, 0xb1, 0x4f, 0xcf, 0xab, 0x38, + }, + }, + { + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, + 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45, + 0x5c, 0x5c, 0x2a, 0x3a, }, + {0xdf, 0x1b, 0x1d, 0x66, 0xa5, 0x51, 0xd0, 0xd3, + 0x1e, 0xff, 0x82, 0x25, 0x58, 0xb9, 0xd2, 0xcc, + 0x75, 0xc2, 0x18, 0x02, 0x79, 0xfe, 0x0d, 0x08, + 0xfd, 0x89, 0x6d, 0x04, 0x5c, 0x08, 0x0f, 0xc3, + 0x52, 0x2f, 0x41, 0xbb, 0xb3, 0xf5, 0x5a, 0x97, + 0xcf, 0xec, 0xf2, 0x1f, 0x88, 0x2c, 0xe8, 0xcb, + 0xb1, 0xe5, 0x0c, 0xa6, 0xe6, 0x7e, 0x56, 0xdc, + }, + }, + { + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, + 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45, + 0x5c, 0x5c, 0x2a, 0x3b, }, + {0x70, 0x6a, 0x46, 0xdc, 0x76, 0xdc, 0xb7, 0x67, + 0x98, 0xe6, 0x0e, 0x6d, 0x89, 0x47, 0x47, 0x88, + 0xd1, 0x6d, 0xc1, 0x80, 0x32, 0xd2, 0x68, 0xfd, + 0x1a, 0x70, 0x4f, 0xa6, 0xe3, 0xd4, 0x89, 0x58, + 0x43, 0xda, 0x18, 0x8f, 0xd5, 0x8f, 0xb0, 0x56, + 0x79, 0x76, 0xd7, 0xb5, 0x03, 0x59, 0xd6, 0xb7, + 0x85, 0x30, 0xc8, 0xf6, 0x2d, 0x1b, 0x17, 0x46, + }, + }, + { + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, + 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45, + 0x5c, 0x5c, 0x2a, 0x3c, }, + {0xb7, 0x0e, 0x0c, 0xbd, 0x6b, 0xb4, 0xbf, 0x7f, + 0x32, 0x13, 0x90, 0xb9, 0x4a, 0x03, 0xc1, 0xd3, + 0x56, 0xc2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xd6, + 0x11, 0x5c, 0x1d, 0x21, 0x42, 0xc8, 0x9c, 0x77, + 0x4a, 0x08, 0xdc, 0x04, 0xb3, 0xdd, 0x20, 0x19, + 0x32, 0xbc, 0x8a, 0x5e, 0xa5, 0xf8, 0xb8, 0x9b, + 0xbb, 0x2a, 0x7e, 0x66, 0x7a, 0xff, 0x81, 0xcd, + }, + }, +}; + +TEST(P224, ExternalToInternalAndBack) { + Point point; + + EXPECT_TRUE(point.SetFromString(base::StringPiece( + reinterpret_cast(kBasePointExternal), + sizeof(kBasePointExternal)))); + + const std::string external = point.ToString(); + + ASSERT_EQ(external.size(), 56u); + EXPECT_TRUE(memcmp(external.data(), kBasePointExternal, + sizeof(kBasePointExternal)) == 0); +} + +TEST(P224, ScalarBaseMult) { + Point point; + + for (size_t i = 0; i < arraysize(kNISTTestVectors); i++) { + p224::ScalarBaseMult(kNISTTestVectors[i].scalar, &point); + const std::string external = point.ToString(); + ASSERT_EQ(external.size(), 56u); + EXPECT_TRUE(memcmp(external.data(), kNISTTestVectors[i].affine, + external.size()) == 0); + } +} + +TEST(P224, Addition) { + Point a, b, minus_b, sum, a_again; + + ASSERT_TRUE(a.SetFromString(base::StringPiece( + reinterpret_cast(kNISTTestVectors[10].affine), 56))); + ASSERT_TRUE(b.SetFromString(base::StringPiece( + reinterpret_cast(kNISTTestVectors[11].affine), 56))); + + p224::Negate(b, &minus_b); + p224::Add(a, b, &sum); + EXPECT_TRUE(memcmp(&sum, &a, sizeof(sum)) != 0); + p224::Add(minus_b, sum, &a_again); + EXPECT_TRUE(a_again.ToString() == a.ToString()); +} + +TEST(P224, Infinity) { + char zeros[56]; + memset(zeros, 0, sizeof(zeros)); + + // Test that x^0 = ∞. + Point a; + p224::ScalarBaseMult(reinterpret_cast(zeros), &a); + EXPECT_TRUE(memcmp(zeros, a.ToString().data(), sizeof(zeros)) == 0); + + // We shouldn't allow ∞ to be imported. + EXPECT_FALSE(a.SetFromString(std::string(zeros, sizeof(zeros)))); +} + +} // namespace crypto diff --git a/crypto/random_unittest.cc b/crypto/random_unittest.cc index 846d9b66f3d54..00d4b2b5e861e 100644 --- a/crypto/random_unittest.cc +++ b/crypto/random_unittest.cc @@ -22,6 +22,6 @@ bool IsTrivial(const std::string& bytes) { TEST(RandBytes, RandBytes) { std::string bytes(16, '\0'); - crypto::RandBytes(WriteInto(&bytes, bytes.size()), bytes.size()); + crypto::RandBytes(base::WriteInto(&bytes, bytes.size()), bytes.size()); EXPECT_TRUE(!IsTrivial(bytes)); } diff --git a/crypto/rsa_private_key.cc b/crypto/rsa_private_key.cc new file mode 100644 index 0000000000000..812d9fa16e578 --- /dev/null +++ b/crypto/rsa_private_key.cc @@ -0,0 +1,384 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/rsa_private_key.h" + +#include +#include + +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "base/strings/string_util.h" + +// This file manually encodes and decodes RSA private keys using PrivateKeyInfo +// from PKCS #8 and RSAPrivateKey from PKCS #1. These structures are: +// +// PrivateKeyInfo ::= SEQUENCE { +// version Version, +// privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, +// privateKey PrivateKey, +// attributes [0] IMPLICIT Attributes OPTIONAL +// } +// +// RSAPrivateKey ::= SEQUENCE { +// version Version, +// modulus INTEGER, +// publicExponent INTEGER, +// privateExponent INTEGER, +// prime1 INTEGER, +// prime2 INTEGER, +// exponent1 INTEGER, +// exponent2 INTEGER, +// coefficient INTEGER +// } + +namespace { +// Helper for error handling during key import. +#define READ_ASSERT(truth) \ + if (!(truth)) { \ + NOTREACHED(); \ + return false; \ + } +} // namespace + +namespace crypto { + +const uint8 PrivateKeyInfoCodec::kRsaAlgorithmIdentifier[] = { + 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, + 0x05, 0x00 +}; + +PrivateKeyInfoCodec::PrivateKeyInfoCodec(bool big_endian) + : big_endian_(big_endian) {} + +PrivateKeyInfoCodec::~PrivateKeyInfoCodec() {} + +bool PrivateKeyInfoCodec::Export(std::vector* output) { + std::list content; + + // Version (always zero) + uint8 version = 0; + + PrependInteger(coefficient_, &content); + PrependInteger(exponent2_, &content); + PrependInteger(exponent1_, &content); + PrependInteger(prime2_, &content); + PrependInteger(prime1_, &content); + PrependInteger(private_exponent_, &content); + PrependInteger(public_exponent_, &content); + PrependInteger(modulus_, &content); + PrependInteger(&version, 1, &content); + PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content); + PrependTypeHeaderAndLength(kOctetStringTag, content.size(), &content); + + // RSA algorithm OID + for (size_t i = sizeof(kRsaAlgorithmIdentifier); i > 0; --i) + content.push_front(kRsaAlgorithmIdentifier[i - 1]); + + PrependInteger(&version, 1, &content); + PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content); + + // Copy everying into the output. + output->reserve(content.size()); + output->assign(content.begin(), content.end()); + + return true; +} + +bool PrivateKeyInfoCodec::ExportPublicKeyInfo(std::vector* output) { + // Create a sequence with the modulus (n) and public exponent (e). + std::vector bit_string; + if (!ExportPublicKey(&bit_string)) + return false; + + // Add the sequence as the contents of a bit string. + std::list content; + PrependBitString(&bit_string[0], static_cast(bit_string.size()), + &content); + + // Add the RSA algorithm OID. + for (size_t i = sizeof(kRsaAlgorithmIdentifier); i > 0; --i) + content.push_front(kRsaAlgorithmIdentifier[i - 1]); + + // Finally, wrap everything in a sequence. + PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content); + + // Copy everything into the output. + output->reserve(content.size()); + output->assign(content.begin(), content.end()); + + return true; +} + +bool PrivateKeyInfoCodec::ExportPublicKey(std::vector* output) { + // Create a sequence with the modulus (n) and public exponent (e). + std::list content; + PrependInteger(&public_exponent_[0], + static_cast(public_exponent_.size()), + &content); + PrependInteger(&modulus_[0], static_cast(modulus_.size()), &content); + PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content); + + // Copy everything into the output. + output->reserve(content.size()); + output->assign(content.begin(), content.end()); + + return true; +} + +bool PrivateKeyInfoCodec::Import(const std::vector& input) { + if (input.empty()) { + return false; + } + + // Parse the private key info up to the public key values, ignoring + // the subsequent private key values. + uint8* src = const_cast(&input.front()); + uint8* end = src + input.size(); + if (!ReadSequence(&src, end) || + !ReadVersion(&src, end) || + !ReadAlgorithmIdentifier(&src, end) || + !ReadTypeHeaderAndLength(&src, end, kOctetStringTag, NULL) || + !ReadSequence(&src, end) || + !ReadVersion(&src, end) || + !ReadInteger(&src, end, &modulus_)) + return false; + + int mod_size = modulus_.size(); + READ_ASSERT(mod_size % 2 == 0); + int primes_size = mod_size / 2; + + if (!ReadIntegerWithExpectedSize(&src, end, 4, &public_exponent_) || + !ReadIntegerWithExpectedSize(&src, end, mod_size, &private_exponent_) || + !ReadIntegerWithExpectedSize(&src, end, primes_size, &prime1_) || + !ReadIntegerWithExpectedSize(&src, end, primes_size, &prime2_) || + !ReadIntegerWithExpectedSize(&src, end, primes_size, &exponent1_) || + !ReadIntegerWithExpectedSize(&src, end, primes_size, &exponent2_) || + !ReadIntegerWithExpectedSize(&src, end, primes_size, &coefficient_)) + return false; + + READ_ASSERT(src == end); + + + return true; +} + +void PrivateKeyInfoCodec::PrependInteger(const std::vector& in, + std::list* out) { + uint8* ptr = const_cast(&in.front()); + PrependIntegerImpl(ptr, in.size(), out, big_endian_); +} + +// Helper to prepend an ASN.1 integer. +void PrivateKeyInfoCodec::PrependInteger(uint8* val, + int num_bytes, + std::list* data) { + PrependIntegerImpl(val, num_bytes, data, big_endian_); +} + +void PrivateKeyInfoCodec::PrependIntegerImpl(uint8* val, + int num_bytes, + std::list* data, + bool big_endian) { + // Reverse input if little-endian. + std::vector tmp; + if (!big_endian) { + tmp.assign(val, val + num_bytes); + std::reverse(tmp.begin(), tmp.end()); + val = &tmp.front(); + } + + // ASN.1 integers are unpadded byte arrays, so skip any null padding bytes + // from the most-significant end of the integer. + int start = 0; + while (start < (num_bytes - 1) && val[start] == 0x00) { + start++; + num_bytes--; + } + PrependBytes(val, start, num_bytes, data); + + // ASN.1 integers are signed. To encode a positive integer whose sign bit + // (the most significant bit) would otherwise be set and make the number + // negative, ASN.1 requires a leading null byte to force the integer to be + // positive. + uint8 front = data->front(); + if ((front & 0x80) != 0) { + data->push_front(0x00); + num_bytes++; + } + + PrependTypeHeaderAndLength(kIntegerTag, num_bytes, data); +} + +bool PrivateKeyInfoCodec::ReadInteger(uint8** pos, + uint8* end, + std::vector* out) { + return ReadIntegerImpl(pos, end, out, big_endian_); +} + +bool PrivateKeyInfoCodec::ReadIntegerWithExpectedSize(uint8** pos, + uint8* end, + size_t expected_size, + std::vector* out) { + std::vector temp; + if (!ReadIntegerImpl(pos, end, &temp, true)) // Big-Endian + return false; + + int pad = expected_size - temp.size(); + int index = 0; + if (out->size() == expected_size + 1) { + READ_ASSERT(out->front() == 0x00); + pad++; + index++; + } else { + READ_ASSERT(out->size() <= expected_size); + } + + out->insert(out->end(), pad, 0x00); + out->insert(out->end(), temp.begin(), temp.end()); + + // Reverse output if little-endian. + if (!big_endian_) + std::reverse(out->begin(), out->end()); + return true; +} + +bool PrivateKeyInfoCodec::ReadIntegerImpl(uint8** pos, + uint8* end, + std::vector* out, + bool big_endian) { + uint32 length = 0; + if (!ReadTypeHeaderAndLength(pos, end, kIntegerTag, &length) || !length) + return false; + + // The first byte can be zero to force positiveness. We can ignore this. + if (**pos == 0x00) { + ++(*pos); + --length; + } + + if (length) + out->insert(out->end(), *pos, (*pos) + length); + + (*pos) += length; + + // Reverse output if little-endian. + if (!big_endian) + std::reverse(out->begin(), out->end()); + return true; +} + +void PrivateKeyInfoCodec::PrependBytes(uint8* val, + int start, + int num_bytes, + std::list* data) { + while (num_bytes > 0) { + --num_bytes; + data->push_front(val[start + num_bytes]); + } +} + +void PrivateKeyInfoCodec::PrependLength(size_t size, std::list* data) { + // The high bit is used to indicate whether additional octets are needed to + // represent the length. + if (size < 0x80) { + data->push_front(static_cast(size)); + } else { + uint8 num_bytes = 0; + while (size > 0) { + data->push_front(static_cast(size & 0xFF)); + size >>= 8; + num_bytes++; + } + CHECK_LE(num_bytes, 4); + data->push_front(0x80 | num_bytes); + } +} + +void PrivateKeyInfoCodec::PrependTypeHeaderAndLength(uint8 type, + uint32 length, + std::list* output) { + PrependLength(length, output); + output->push_front(type); +} + +void PrivateKeyInfoCodec::PrependBitString(uint8* val, + int num_bytes, + std::list* output) { + // Start with the data. + PrependBytes(val, 0, num_bytes, output); + // Zero unused bits. + output->push_front(0); + // Add the length. + PrependLength(num_bytes + 1, output); + // Finally, add the bit string tag. + output->push_front((uint8) kBitStringTag); +} + +bool PrivateKeyInfoCodec::ReadLength(uint8** pos, uint8* end, uint32* result) { + READ_ASSERT(*pos < end); + int length = 0; + + // If the MSB is not set, the length is just the byte itself. + if (!(**pos & 0x80)) { + length = **pos; + (*pos)++; + } else { + // Otherwise, the lower 7 indicate the length of the length. + int length_of_length = **pos & 0x7F; + READ_ASSERT(length_of_length <= 4); + (*pos)++; + READ_ASSERT(*pos + length_of_length < end); + + length = 0; + for (int i = 0; i < length_of_length; ++i) { + length <<= 8; + length |= **pos; + (*pos)++; + } + } + + READ_ASSERT(*pos + length <= end); + if (result) *result = length; + return true; +} + +bool PrivateKeyInfoCodec::ReadTypeHeaderAndLength(uint8** pos, + uint8* end, + uint8 expected_tag, + uint32* length) { + READ_ASSERT(*pos < end); + READ_ASSERT(**pos == expected_tag); + (*pos)++; + + return ReadLength(pos, end, length); +} + +bool PrivateKeyInfoCodec::ReadSequence(uint8** pos, uint8* end) { + return ReadTypeHeaderAndLength(pos, end, kSequenceTag, NULL); +} + +bool PrivateKeyInfoCodec::ReadAlgorithmIdentifier(uint8** pos, uint8* end) { + READ_ASSERT(*pos + sizeof(kRsaAlgorithmIdentifier) < end); + READ_ASSERT(memcmp(*pos, kRsaAlgorithmIdentifier, + sizeof(kRsaAlgorithmIdentifier)) == 0); + (*pos) += sizeof(kRsaAlgorithmIdentifier); + return true; +} + +bool PrivateKeyInfoCodec::ReadVersion(uint8** pos, uint8* end) { + uint32 length = 0; + if (!ReadTypeHeaderAndLength(pos, end, kIntegerTag, &length)) + return false; + + // The version should be zero. + for (uint32 i = 0; i < length; ++i) { + READ_ASSERT(**pos == 0x00); + (*pos)++; + } + + return true; +} + +} // namespace crypto diff --git a/crypto/rsa_private_key.h b/crypto/rsa_private_key.h new file mode 100644 index 0000000000000..637be38836f8d --- /dev/null +++ b/crypto/rsa_private_key.h @@ -0,0 +1,231 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CRYPTO_RSA_PRIVATE_KEY_H_ +#define CRYPTO_RSA_PRIVATE_KEY_H_ + +#include "build/build_config.h" + +#include +#include + +#include "base/basictypes.h" +#include "crypto/crypto_export.h" + +#if defined(USE_NSS_CERTS) +#include "base/gtest_prod_util.h" +#endif + +#if defined(USE_OPENSSL) +// Forward declaration for openssl/*.h +typedef struct evp_pkey_st EVP_PKEY; +#else +// Forward declaration. +typedef struct PK11SlotInfoStr PK11SlotInfo; +typedef struct SECKEYPrivateKeyStr SECKEYPrivateKey; +typedef struct SECKEYPublicKeyStr SECKEYPublicKey; +#endif + + +namespace crypto { + +// Used internally by RSAPrivateKey for serializing and deserializing +// PKCS #8 PrivateKeyInfo and PublicKeyInfo. +class PrivateKeyInfoCodec { + public: + + // ASN.1 encoding of the AlgorithmIdentifier from PKCS #8. + static const uint8 kRsaAlgorithmIdentifier[]; + + // ASN.1 tags for some types we use. + static const uint8 kBitStringTag = 0x03; + static const uint8 kIntegerTag = 0x02; + static const uint8 kNullTag = 0x05; + static const uint8 kOctetStringTag = 0x04; + static const uint8 kSequenceTag = 0x30; + + // |big_endian| here specifies the byte-significance of the integer components + // that will be parsed & serialized (modulus(), etc...) during Import(), + // Export() and ExportPublicKeyInfo() -- not the ASN.1 DER encoding of the + // PrivateKeyInfo/PublicKeyInfo (which is always big-endian). + explicit PrivateKeyInfoCodec(bool big_endian); + + ~PrivateKeyInfoCodec(); + + // Exports the contents of the integer components to the ASN.1 DER encoding + // of the PrivateKeyInfo structure to |output|. + bool Export(std::vector* output); + + // Exports the contents of the integer components to the ASN.1 DER encoding + // of the PublicKeyInfo structure to |output|. + bool ExportPublicKeyInfo(std::vector* output); + + // Exports the contents of the integer components to the ASN.1 DER encoding + // of the RSAPublicKey structure to |output|. + bool ExportPublicKey(std::vector* output); + + // Parses the ASN.1 DER encoding of the PrivateKeyInfo structure in |input| + // and populates the integer components with |big_endian_| byte-significance. + // IMPORTANT NOTE: This is currently *not* security-approved for importing + // keys from unstrusted sources. + bool Import(const std::vector& input); + + // Accessors to the contents of the integer components of the PrivateKeyInfo + // structure. + std::vector* modulus() { return &modulus_; }; + std::vector* public_exponent() { return &public_exponent_; }; + std::vector* private_exponent() { return &private_exponent_; }; + std::vector* prime1() { return &prime1_; }; + std::vector* prime2() { return &prime2_; }; + std::vector* exponent1() { return &exponent1_; }; + std::vector* exponent2() { return &exponent2_; }; + std::vector* coefficient() { return &coefficient_; }; + + private: + // Utility wrappers for PrependIntegerImpl that use the class's |big_endian_| + // value. + void PrependInteger(const std::vector& in, std::list* out); + void PrependInteger(uint8* val, int num_bytes, std::list* data); + + // Prepends the integer stored in |val| - |val + num_bytes| with |big_endian| + // byte-significance into |data| as an ASN.1 integer. + void PrependIntegerImpl(uint8* val, + int num_bytes, + std::list* data, + bool big_endian); + + // Utility wrappers for ReadIntegerImpl that use the class's |big_endian_| + // value. + bool ReadInteger(uint8** pos, uint8* end, std::vector* out); + bool ReadIntegerWithExpectedSize(uint8** pos, + uint8* end, + size_t expected_size, + std::vector* out); + + // Reads an ASN.1 integer from |pos|, and stores the result into |out| with + // |big_endian| byte-significance. + bool ReadIntegerImpl(uint8** pos, + uint8* end, + std::vector* out, + bool big_endian); + + // Prepends the integer stored in |val|, starting a index |start|, for + // |num_bytes| bytes onto |data|. + void PrependBytes(uint8* val, + int start, + int num_bytes, + std::list* data); + + // Helper to prepend an ASN.1 length field. + void PrependLength(size_t size, std::list* data); + + // Helper to prepend an ASN.1 type header. + void PrependTypeHeaderAndLength(uint8 type, + uint32 length, + std::list* output); + + // Helper to prepend an ASN.1 bit string + void PrependBitString(uint8* val, int num_bytes, std::list* output); + + // Read an ASN.1 length field. This also checks that the length does not + // extend beyond |end|. + bool ReadLength(uint8** pos, uint8* end, uint32* result); + + // Read an ASN.1 type header and its length. + bool ReadTypeHeaderAndLength(uint8** pos, + uint8* end, + uint8 expected_tag, + uint32* length); + + // Read an ASN.1 sequence declaration. This consumes the type header and + // length field, but not the contents of the sequence. + bool ReadSequence(uint8** pos, uint8* end); + + // Read the RSA AlgorithmIdentifier. + bool ReadAlgorithmIdentifier(uint8** pos, uint8* end); + + // Read one of the two version fields in PrivateKeyInfo. + bool ReadVersion(uint8** pos, uint8* end); + + // The byte-significance of the stored components (modulus, etc..). + bool big_endian_; + + // Component integers of the PrivateKeyInfo + std::vector modulus_; + std::vector public_exponent_; + std::vector private_exponent_; + std::vector prime1_; + std::vector prime2_; + std::vector exponent1_; + std::vector exponent2_; + std::vector coefficient_; + + DISALLOW_COPY_AND_ASSIGN(PrivateKeyInfoCodec); +}; + +// Encapsulates an RSA private key. Can be used to generate new keys, export +// keys to other formats, or to extract a public key. +// TODO(hclam): This class should be ref-counted so it can be reused easily. +class CRYPTO_EXPORT RSAPrivateKey { + public: + ~RSAPrivateKey(); + + // Create a new random instance. Can return NULL if initialization fails. + static RSAPrivateKey* Create(uint16 num_bits); + + // Create a new instance by importing an existing private key. The format is + // an ASN.1-encoded PrivateKeyInfo block from PKCS #8. This can return NULL if + // initialization fails. + static RSAPrivateKey* CreateFromPrivateKeyInfo( + const std::vector& input); + +#if defined(USE_OPENSSL) + // Create a new instance from an existing EVP_PKEY, taking a + // reference to it. |key| must be an RSA key. Returns NULL on + // failure. + static RSAPrivateKey* CreateFromKey(EVP_PKEY* key); +#else + // Create a new instance by referencing an existing private key + // structure. Does not import the key. + static RSAPrivateKey* CreateFromKey(SECKEYPrivateKey* key); +#endif + +#if defined(USE_OPENSSL) + EVP_PKEY* key() { return key_; } +#else + SECKEYPrivateKey* key() { return key_; } + SECKEYPublicKey* public_key() { return public_key_; } +#endif + + // Creates a copy of the object. + RSAPrivateKey* Copy() const; + + // Exports the private key to a PKCS #1 PrivateKey block. + bool ExportPrivateKey(std::vector* output) const; + + // Exports the public key to an X509 SubjectPublicKeyInfo block. + bool ExportPublicKey(std::vector* output) const; + + private: +#if defined(USE_NSS_CERTS) + FRIEND_TEST_ALL_PREFIXES(RSAPrivateKeyNSSTest, FindFromPublicKey); + FRIEND_TEST_ALL_PREFIXES(RSAPrivateKeyNSSTest, FailedFindFromPublicKey); +#endif + + // Constructor is private. Use one of the Create*() methods above instead. + RSAPrivateKey(); + +#if defined(USE_OPENSSL) + EVP_PKEY* key_; +#else + SECKEYPrivateKey* key_; + SECKEYPublicKey* public_key_; +#endif + + DISALLOW_COPY_AND_ASSIGN(RSAPrivateKey); +}; + +} // namespace crypto + +#endif // CRYPTO_RSA_PRIVATE_KEY_H_ diff --git a/crypto/rsa_private_key_nss.cc b/crypto/rsa_private_key_nss.cc new file mode 100644 index 0000000000000..88e55fa576812 --- /dev/null +++ b/crypto/rsa_private_key_nss.cc @@ -0,0 +1,151 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/rsa_private_key.h" + +#include +#include +#include + +#include + +#include "base/debug/leak_annotations.h" +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "base/strings/string_util.h" +#include "crypto/nss_key_util.h" +#include "crypto/nss_util.h" +#include "crypto/scoped_nss_types.h" + +// TODO(rafaelw): Consider using NSS's ASN.1 encoder. +namespace { + +static bool ReadAttribute(SECKEYPrivateKey* key, + CK_ATTRIBUTE_TYPE type, + std::vector* output) { + SECItem item; + SECStatus rv; + rv = PK11_ReadRawAttribute(PK11_TypePrivKey, key, type, &item); + if (rv != SECSuccess) { + NOTREACHED(); + return false; + } + + output->assign(item.data, item.data + item.len); + SECITEM_FreeItem(&item, PR_FALSE); + return true; +} + +} // namespace + +namespace crypto { + +RSAPrivateKey::~RSAPrivateKey() { + if (key_) + SECKEY_DestroyPrivateKey(key_); + if (public_key_) + SECKEY_DestroyPublicKey(public_key_); +} + +// static +RSAPrivateKey* RSAPrivateKey::Create(uint16 num_bits) { + EnsureNSSInit(); + + ScopedPK11Slot slot(PK11_GetInternalSlot()); + if (!slot) { + NOTREACHED(); + return nullptr; + } + + ScopedSECKEYPublicKey public_key; + ScopedSECKEYPrivateKey private_key; + if (!GenerateRSAKeyPairNSS(slot.get(), num_bits, false /* not permanent */, + &public_key, &private_key)) { + return nullptr; + } + + RSAPrivateKey* rsa_key = new RSAPrivateKey; + rsa_key->public_key_ = public_key.release(); + rsa_key->key_ = private_key.release(); + return rsa_key; +} + +// static +RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo( + const std::vector& input) { + EnsureNSSInit(); + + ScopedPK11Slot slot(PK11_GetInternalSlot()); + if (!slot) { + NOTREACHED(); + return nullptr; + } + ScopedSECKEYPrivateKey key(ImportNSSKeyFromPrivateKeyInfo( + slot.get(), input, false /* not permanent */)); + if (!key || SECKEY_GetPrivateKeyType(key.get()) != rsaKey) + return nullptr; + return RSAPrivateKey::CreateFromKey(key.get()); +} + +// static +RSAPrivateKey* RSAPrivateKey::CreateFromKey(SECKEYPrivateKey* key) { + DCHECK(key); + if (SECKEY_GetPrivateKeyType(key) != rsaKey) + return NULL; + RSAPrivateKey* copy = new RSAPrivateKey(); + copy->key_ = SECKEY_CopyPrivateKey(key); + copy->public_key_ = SECKEY_ConvertToPublicKey(key); + if (!copy->key_ || !copy->public_key_) { + NOTREACHED(); + delete copy; + return NULL; + } + return copy; +} + +RSAPrivateKey* RSAPrivateKey::Copy() const { + RSAPrivateKey* copy = new RSAPrivateKey(); + copy->key_ = SECKEY_CopyPrivateKey(key_); + copy->public_key_ = SECKEY_CopyPublicKey(public_key_); + return copy; +} + +bool RSAPrivateKey::ExportPrivateKey(std::vector* output) const { + PrivateKeyInfoCodec private_key_info(true); + + // Manually read the component attributes of the private key and build up + // the PrivateKeyInfo. + if (!ReadAttribute(key_, CKA_MODULUS, private_key_info.modulus()) || + !ReadAttribute(key_, CKA_PUBLIC_EXPONENT, + private_key_info.public_exponent()) || + !ReadAttribute(key_, CKA_PRIVATE_EXPONENT, + private_key_info.private_exponent()) || + !ReadAttribute(key_, CKA_PRIME_1, private_key_info.prime1()) || + !ReadAttribute(key_, CKA_PRIME_2, private_key_info.prime2()) || + !ReadAttribute(key_, CKA_EXPONENT_1, private_key_info.exponent1()) || + !ReadAttribute(key_, CKA_EXPONENT_2, private_key_info.exponent2()) || + !ReadAttribute(key_, CKA_COEFFICIENT, private_key_info.coefficient())) { + NOTREACHED(); + return false; + } + + return private_key_info.Export(output); +} + +bool RSAPrivateKey::ExportPublicKey(std::vector* output) const { + ScopedSECItem der_pubkey(SECKEY_EncodeDERSubjectPublicKeyInfo(public_key_)); + if (!der_pubkey.get()) { + NOTREACHED(); + return false; + } + + output->assign(der_pubkey->data, der_pubkey->data + der_pubkey->len); + return true; +} + +RSAPrivateKey::RSAPrivateKey() : key_(NULL), public_key_(NULL) { + EnsureNSSInit(); +} + +} // namespace crypto diff --git a/crypto/rsa_private_key_openssl.cc b/crypto/rsa_private_key_openssl.cc new file mode 100644 index 0000000000000..52a0a7a1815e8 --- /dev/null +++ b/crypto/rsa_private_key_openssl.cc @@ -0,0 +1,138 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/rsa_private_key.h" + +#include +#include +#include +#include +#include + +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "crypto/openssl_util.h" +#include "crypto/scoped_openssl_types.h" + +namespace crypto { + +namespace { + +using ScopedPKCS8_PRIV_KEY_INFO = + ScopedOpenSSL; + +// Function pointer definition, for injecting the required key export function +// into ExportKey, below. The supplied function should export EVP_PKEY into +// the supplied BIO, returning 1 on success or 0 on failure. +using ExportFunction = int (*)(BIO*, EVP_PKEY*); + +// Helper to export |key| into |output| via the specified ExportFunction. +bool ExportKey(EVP_PKEY* key, + ExportFunction export_fn, + std::vector* output) { + if (!key) + return false; + + OpenSSLErrStackTracer err_tracer(FROM_HERE); + ScopedBIO bio(BIO_new(BIO_s_mem())); + + int res = export_fn(bio.get(), key); + if (!res) + return false; + + char* data = NULL; + long len = BIO_get_mem_data(bio.get(), &data); + if (!data || len < 0) + return false; + + output->assign(data, data + len); + return true; +} + +} // namespace + +// static +RSAPrivateKey* RSAPrivateKey::Create(uint16 num_bits) { + OpenSSLErrStackTracer err_tracer(FROM_HERE); + + ScopedRSA rsa_key(RSA_new()); + ScopedBIGNUM bn(BN_new()); + if (!rsa_key.get() || !bn.get() || !BN_set_word(bn.get(), 65537L)) + return NULL; + + if (!RSA_generate_key_ex(rsa_key.get(), num_bits, bn.get(), NULL)) + return NULL; + + scoped_ptr result(new RSAPrivateKey); + result->key_ = EVP_PKEY_new(); + if (!result->key_ || !EVP_PKEY_set1_RSA(result->key_, rsa_key.get())) + return NULL; + + return result.release(); +} + +// static +RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo( + const std::vector& input) { + if (input.empty()) + return NULL; + + OpenSSLErrStackTracer err_tracer(FROM_HERE); + + // Importing is a little more involved than exporting, as we must first + // PKCS#8 decode the input, and then import the EVP_PKEY from Private Key + // Info structure returned. + const uint8_t* ptr = &input[0]; + ScopedPKCS8_PRIV_KEY_INFO p8inf( + d2i_PKCS8_PRIV_KEY_INFO(nullptr, &ptr, input.size())); + if (!p8inf.get() || ptr != &input[0] + input.size()) + return NULL; + + scoped_ptr result(new RSAPrivateKey); + result->key_ = EVP_PKCS82PKEY(p8inf.get()); + if (!result->key_ || EVP_PKEY_id(result->key_) != EVP_PKEY_RSA) + return NULL; + + return result.release(); +} + +// static +RSAPrivateKey* RSAPrivateKey::CreateFromKey(EVP_PKEY* key) { + DCHECK(key); + if (EVP_PKEY_type(key->type) != EVP_PKEY_RSA) + return NULL; + RSAPrivateKey* copy = new RSAPrivateKey(); + copy->key_ = EVP_PKEY_up_ref(key); + return copy; +} + +RSAPrivateKey::RSAPrivateKey() + : key_(NULL) { +} + +RSAPrivateKey::~RSAPrivateKey() { + if (key_) + EVP_PKEY_free(key_); +} + +RSAPrivateKey* RSAPrivateKey::Copy() const { + scoped_ptr copy(new RSAPrivateKey()); + ScopedRSA rsa(EVP_PKEY_get1_RSA(key_)); + if (!rsa) + return NULL; + copy->key_ = EVP_PKEY_new(); + if (!EVP_PKEY_set1_RSA(copy->key_, rsa.get())) + return NULL; + return copy.release(); +} + +bool RSAPrivateKey::ExportPrivateKey(std::vector* output) const { + return ExportKey(key_, i2d_PKCS8PrivateKeyInfo_bio, output); +} + +bool RSAPrivateKey::ExportPublicKey(std::vector* output) const { + return ExportKey(key_, i2d_PUBKEY_bio, output); +} + +} // namespace crypto diff --git a/crypto/rsa_private_key_unittest.cc b/crypto/rsa_private_key_unittest.cc new file mode 100644 index 0000000000000..9e7f6ff51fe04 --- /dev/null +++ b/crypto/rsa_private_key_unittest.cc @@ -0,0 +1,470 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/rsa_private_key.h" + +#include "base/memory/scoped_ptr.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +const uint8 kTestPrivateKeyInfo[] = { + 0x30, 0x82, 0x02, 0x78, 0x02, 0x01, 0x00, 0x30, + 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, + 0x02, 0x62, 0x30, 0x82, 0x02, 0x5e, 0x02, 0x01, + 0x00, 0x02, 0x81, 0x81, 0x00, 0xb8, 0x7f, 0x2b, + 0x20, 0xdc, 0x7c, 0x9b, 0x0c, 0xdc, 0x51, 0x61, + 0x99, 0x0d, 0x36, 0x0f, 0xd4, 0x66, 0x88, 0x08, + 0x55, 0x84, 0xd5, 0x3a, 0xbf, 0x2b, 0xa4, 0x64, + 0x85, 0x7b, 0x0c, 0x04, 0x13, 0x3f, 0x8d, 0xf4, + 0xbc, 0x38, 0x0d, 0x49, 0xfe, 0x6b, 0xc4, 0x5a, + 0xb0, 0x40, 0x53, 0x3a, 0xd7, 0x66, 0x09, 0x0f, + 0x9e, 0x36, 0x74, 0x30, 0xda, 0x8a, 0x31, 0x4f, + 0x1f, 0x14, 0x50, 0xd7, 0xc7, 0x20, 0x94, 0x17, + 0xde, 0x4e, 0xb9, 0x57, 0x5e, 0x7e, 0x0a, 0xe5, + 0xb2, 0x65, 0x7a, 0x89, 0x4e, 0xb6, 0x47, 0xff, + 0x1c, 0xbd, 0xb7, 0x38, 0x13, 0xaf, 0x47, 0x85, + 0x84, 0x32, 0x33, 0xf3, 0x17, 0x49, 0xbf, 0xe9, + 0x96, 0xd0, 0xd6, 0x14, 0x6f, 0x13, 0x8d, 0xc5, + 0xfc, 0x2c, 0x72, 0xba, 0xac, 0xea, 0x7e, 0x18, + 0x53, 0x56, 0xa6, 0x83, 0xa2, 0xce, 0x93, 0x93, + 0xe7, 0x1f, 0x0f, 0xe6, 0x0f, 0x02, 0x03, 0x01, + 0x00, 0x01, 0x02, 0x81, 0x80, 0x03, 0x61, 0x89, + 0x37, 0xcb, 0xf2, 0x98, 0xa0, 0xce, 0xb4, 0xcb, + 0x16, 0x13, 0xf0, 0xe6, 0xaf, 0x5c, 0xc5, 0xa7, + 0x69, 0x71, 0xca, 0xba, 0x8d, 0xe0, 0x4d, 0xdd, + 0xed, 0xb8, 0x48, 0x8b, 0x16, 0x93, 0x36, 0x95, + 0xc2, 0x91, 0x40, 0x65, 0x17, 0xbd, 0x7f, 0xd6, + 0xad, 0x9e, 0x30, 0x28, 0x46, 0xe4, 0x3e, 0xcc, + 0x43, 0x78, 0xf9, 0xfe, 0x1f, 0x33, 0x23, 0x1e, + 0x31, 0x12, 0x9d, 0x3c, 0xa7, 0x08, 0x82, 0x7b, + 0x7d, 0x25, 0x4e, 0x5e, 0x19, 0xa8, 0x9b, 0xed, + 0x86, 0xb2, 0xcb, 0x3c, 0xfe, 0x4e, 0xa1, 0xfa, + 0x62, 0x87, 0x3a, 0x17, 0xf7, 0x60, 0xec, 0x38, + 0x29, 0xe8, 0x4f, 0x34, 0x9f, 0x76, 0x9d, 0xee, + 0xa3, 0xf6, 0x85, 0x6b, 0x84, 0x43, 0xc9, 0x1e, + 0x01, 0xff, 0xfd, 0xd0, 0x29, 0x4c, 0xfa, 0x8e, + 0x57, 0x0c, 0xc0, 0x71, 0xa5, 0xbb, 0x88, 0x46, + 0x29, 0x5c, 0xc0, 0x4f, 0x01, 0x02, 0x41, 0x00, + 0xf5, 0x83, 0xa4, 0x64, 0x4a, 0xf2, 0xdd, 0x8c, + 0x2c, 0xed, 0xa8, 0xd5, 0x60, 0x5a, 0xe4, 0xc7, + 0xcc, 0x61, 0xcd, 0x38, 0x42, 0x20, 0xd3, 0x82, + 0x18, 0xf2, 0x35, 0x00, 0x72, 0x2d, 0xf7, 0x89, + 0x80, 0x67, 0xb5, 0x93, 0x05, 0x5f, 0xdd, 0x42, + 0xba, 0x16, 0x1a, 0xea, 0x15, 0xc6, 0xf0, 0xb8, + 0x8c, 0xbc, 0xbf, 0x54, 0x9e, 0xf1, 0xc1, 0xb2, + 0xb3, 0x8b, 0xb6, 0x26, 0x02, 0x30, 0xc4, 0x81, + 0x02, 0x41, 0x00, 0xc0, 0x60, 0x62, 0x80, 0xe1, + 0x22, 0x78, 0xf6, 0x9d, 0x83, 0x18, 0xeb, 0x72, + 0x45, 0xd7, 0xc8, 0x01, 0x7f, 0xa9, 0xca, 0x8f, + 0x7d, 0xd6, 0xb8, 0x31, 0x2b, 0x84, 0x7f, 0x62, + 0xd9, 0xa9, 0x22, 0x17, 0x7d, 0x06, 0x35, 0x6c, + 0xf3, 0xc1, 0x94, 0x17, 0x85, 0x5a, 0xaf, 0x9c, + 0x5c, 0x09, 0x3c, 0xcf, 0x2f, 0x44, 0x9d, 0xb6, + 0x52, 0x68, 0x5f, 0xf9, 0x59, 0xc8, 0x84, 0x2b, + 0x39, 0x22, 0x8f, 0x02, 0x41, 0x00, 0xb2, 0x04, + 0xe2, 0x0e, 0x56, 0xca, 0x03, 0x1a, 0xc0, 0xf9, + 0x12, 0x92, 0xa5, 0x6b, 0x42, 0xb8, 0x1c, 0xda, + 0x4d, 0x93, 0x9d, 0x5f, 0x6f, 0xfd, 0xc5, 0x58, + 0xda, 0x55, 0x98, 0x74, 0xfc, 0x28, 0x17, 0x93, + 0x1b, 0x75, 0x9f, 0x50, 0x03, 0x7f, 0x7e, 0xae, + 0xc8, 0x95, 0x33, 0x75, 0x2c, 0xd6, 0xa4, 0x35, + 0xb8, 0x06, 0x03, 0xba, 0x08, 0x59, 0x2b, 0x17, + 0x02, 0xdc, 0x4c, 0x7a, 0x50, 0x01, 0x02, 0x41, + 0x00, 0x9d, 0xdb, 0x39, 0x59, 0x09, 0xe4, 0x30, + 0xa0, 0x24, 0xf5, 0xdb, 0x2f, 0xf0, 0x2f, 0xf1, + 0x75, 0x74, 0x0d, 0x5e, 0xb5, 0x11, 0x73, 0xb0, + 0x0a, 0xaa, 0x86, 0x4c, 0x0d, 0xff, 0x7e, 0x1d, + 0xb4, 0x14, 0xd4, 0x09, 0x91, 0x33, 0x5a, 0xfd, + 0xa0, 0x58, 0x80, 0x9b, 0xbe, 0x78, 0x2e, 0x69, + 0x82, 0x15, 0x7c, 0x72, 0xf0, 0x7b, 0x18, 0x39, + 0xff, 0x6e, 0xeb, 0xc6, 0x86, 0xf5, 0xb4, 0xc7, + 0x6f, 0x02, 0x41, 0x00, 0x8d, 0x1a, 0x37, 0x0f, + 0x76, 0xc4, 0x82, 0xfa, 0x5c, 0xc3, 0x79, 0x35, + 0x3e, 0x70, 0x8a, 0xbf, 0x27, 0x49, 0xb0, 0x99, + 0x63, 0xcb, 0x77, 0x5f, 0xa8, 0x82, 0x65, 0xf6, + 0x03, 0x52, 0x51, 0xf1, 0xae, 0x2e, 0x05, 0xb3, + 0xc6, 0xa4, 0x92, 0xd1, 0xce, 0x6c, 0x72, 0xfb, + 0x21, 0xb3, 0x02, 0x87, 0xe4, 0xfd, 0x61, 0xca, + 0x00, 0x42, 0x19, 0xf0, 0xda, 0x5a, 0x53, 0xe3, + 0xb1, 0xc5, 0x15, 0xf3 +}; + +} // namespace + +// Generate random private keys with two different sizes. Reimport, then +// export them again. We should get back the same exact bytes. +TEST(RSAPrivateKeyUnitTest, InitRandomTest) { + scoped_ptr keypair1( + crypto::RSAPrivateKey::Create(1024)); + scoped_ptr keypair2( + crypto::RSAPrivateKey::Create(2048)); + ASSERT_TRUE(keypair1.get()); + ASSERT_TRUE(keypair2.get()); + + std::vector privkey1; + std::vector privkey2; + std::vector pubkey1; + std::vector pubkey2; + + ASSERT_TRUE(keypair1->ExportPrivateKey(&privkey1)); + ASSERT_TRUE(keypair2->ExportPrivateKey(&privkey2)); + ASSERT_TRUE(keypair1->ExportPublicKey(&pubkey1)); + ASSERT_TRUE(keypair2->ExportPublicKey(&pubkey2)); + + scoped_ptr keypair3( + crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(privkey1)); + scoped_ptr keypair4( + crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(privkey2)); + ASSERT_TRUE(keypair3.get()); + ASSERT_TRUE(keypair4.get()); + + std::vector privkey3; + std::vector privkey4; + ASSERT_TRUE(keypair3->ExportPrivateKey(&privkey3)); + ASSERT_TRUE(keypair4->ExportPrivateKey(&privkey4)); + + ASSERT_EQ(privkey1.size(), privkey3.size()); + ASSERT_EQ(privkey2.size(), privkey4.size()); + ASSERT_TRUE(0 == memcmp(&privkey1.front(), &privkey3.front(), + privkey1.size())); + ASSERT_TRUE(0 == memcmp(&privkey2.front(), &privkey4.front(), + privkey2.size())); +} + +// Test Copy() method. +TEST(RSAPrivateKeyUnitTest, CopyTest) { + std::vector input( + kTestPrivateKeyInfo, kTestPrivateKeyInfo + sizeof(kTestPrivateKeyInfo)); + + scoped_ptr key( + crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(input)); + + scoped_ptr key_copy(key->Copy()); + ASSERT_TRUE(key_copy.get()); + + std::vector privkey_copy; + ASSERT_TRUE(key_copy->ExportPrivateKey(&privkey_copy)); + ASSERT_EQ(input, privkey_copy); +} + +// Test that CreateFromPrivateKeyInfo fails if there is extra data after the RSA +// key. +TEST(RSAPrivateKeyUnitTest, ExtraData) { + std::vector input( + kTestPrivateKeyInfo, kTestPrivateKeyInfo + sizeof(kTestPrivateKeyInfo)); + input.push_back(0); + + scoped_ptr key( + crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(input)); + + // Import should fail. + EXPECT_FALSE(key); +} + +TEST(RSAPrivateKeyUnitTest, NotRsaKey) { + // Defines a valid P-256 private key. + const uint8 kTestEcPrivateKeyInfo[] = { + 0x30, 0x81, 0x87, 0x02, 0x01, 0x00, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, + 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, + 0x03, 0x01, 0x07, 0x04, 0x6D, 0x30, 0x6B, 0x02, 0x01, 0x01, 0x04, 0x20, + 0x1F, 0xE3, 0x39, 0x50, 0xC5, 0xF4, 0x61, 0x12, 0x4A, 0xE9, 0x92, 0xC2, + 0xBD, 0xFD, 0xF1, 0xC7, 0x3B, 0x16, 0x15, 0xF5, 0x71, 0xBD, 0x56, 0x7E, + 0x60, 0xD1, 0x9A, 0xA1, 0xF4, 0x8C, 0xDF, 0x42, 0xA1, 0x44, 0x03, 0x42, + 0x00, 0x04, 0x7C, 0x11, 0x0C, 0x66, 0xDC, 0xFD, 0xA8, 0x07, 0xF6, 0xE6, + 0x9E, 0x45, 0xDD, 0xB3, 0xC7, 0x4F, 0x69, 0xA1, 0x48, 0x4D, 0x20, 0x3E, + 0x8D, 0xC5, 0xAD, 0xA8, 0xE9, 0xA9, 0xDD, 0x7C, 0xB3, 0xC7, 0x0D, 0xF4, + 0x48, 0x98, 0x6E, 0x51, 0xBD, 0xE5, 0xD1, 0x57, 0x6F, 0x99, 0x90, 0x1F, + 0x9C, 0x2C, 0x6A, 0x80, 0x6A, 0x47, 0xFD, 0x90, 0x76, 0x43, 0xA7, 0x2B, + 0x83, 0x55, 0x97, 0xEF, 0xC8, 0xC6 + }; + + std::vector input( + kTestEcPrivateKeyInfo, + kTestEcPrivateKeyInfo + sizeof(kTestEcPrivateKeyInfo)); + + scoped_ptr key( + crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(input)); + + // Import should fail as the given PKCS8 bytes were for an EC key not RSA key. + EXPECT_FALSE(key); +} + +// Verify that generated public keys look good. This test data was generated +// with the openssl command line tool. +TEST(RSAPrivateKeyUnitTest, PublicKeyTest) { + const uint8 expected_public_key_info[] = { + 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, + 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, + 0x89, 0x02, 0x81, 0x81, 0x00, 0xb8, 0x7f, 0x2b, + 0x20, 0xdc, 0x7c, 0x9b, 0x0c, 0xdc, 0x51, 0x61, + 0x99, 0x0d, 0x36, 0x0f, 0xd4, 0x66, 0x88, 0x08, + 0x55, 0x84, 0xd5, 0x3a, 0xbf, 0x2b, 0xa4, 0x64, + 0x85, 0x7b, 0x0c, 0x04, 0x13, 0x3f, 0x8d, 0xf4, + 0xbc, 0x38, 0x0d, 0x49, 0xfe, 0x6b, 0xc4, 0x5a, + 0xb0, 0x40, 0x53, 0x3a, 0xd7, 0x66, 0x09, 0x0f, + 0x9e, 0x36, 0x74, 0x30, 0xda, 0x8a, 0x31, 0x4f, + 0x1f, 0x14, 0x50, 0xd7, 0xc7, 0x20, 0x94, 0x17, + 0xde, 0x4e, 0xb9, 0x57, 0x5e, 0x7e, 0x0a, 0xe5, + 0xb2, 0x65, 0x7a, 0x89, 0x4e, 0xb6, 0x47, 0xff, + 0x1c, 0xbd, 0xb7, 0x38, 0x13, 0xaf, 0x47, 0x85, + 0x84, 0x32, 0x33, 0xf3, 0x17, 0x49, 0xbf, 0xe9, + 0x96, 0xd0, 0xd6, 0x14, 0x6f, 0x13, 0x8d, 0xc5, + 0xfc, 0x2c, 0x72, 0xba, 0xac, 0xea, 0x7e, 0x18, + 0x53, 0x56, 0xa6, 0x83, 0xa2, 0xce, 0x93, 0x93, + 0xe7, 0x1f, 0x0f, 0xe6, 0x0f, 0x02, 0x03, 0x01, + 0x00, 0x01 + }; + + std::vector input( + kTestPrivateKeyInfo, kTestPrivateKeyInfo + sizeof(kTestPrivateKeyInfo)); + + scoped_ptr key( + crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(input)); + ASSERT_TRUE(key.get()); + + std::vector output; + ASSERT_TRUE(key->ExportPublicKey(&output)); + + ASSERT_TRUE( + memcmp(expected_public_key_info, &output.front(), output.size()) == 0); +} + +// These two test keys each contain an integer that has 0x00 for its most +// significant byte. When encoded as ASN.1, this byte is dropped and there are +// two interesting sub-cases. When the sign bit of the integer is set, an extra +// null byte is added back to force the encoded value to be positive. When the +// sign bit is not set, the encoded integer is just left shorter than usual. +// See also: http://code.google.com/p/chromium/issues/detail?id=14877. +// +// Before we were handling this correctly, we would see one of two failures: +// * RSAPrivateKey::CreateFromPrivateKeyInfo would return null because the +// underlying windows API failed to import the key. +// * The import would succeed, but incorrectly interpret the data. On export, +// the key would contain different values. +// +// This test case verifies these two failures modes don't occur. +TEST(RSAPrivateKeyUnitTest, ShortIntegers) { + const uint8 short_integer_with_high_bit[] = { + 0x30, 0x82, 0x02, 0x77, 0x02, 0x01, 0x00, 0x30, + 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, + 0x02, 0x61, 0x30, 0x82, 0x02, 0x5d, 0x02, 0x01, + 0x00, 0x02, 0x81, 0x81, 0x00, 0x92, 0x59, 0x32, + 0x7d, 0x8e, 0xaf, 0x2e, 0xd5, 0xb2, 0x5c, 0x67, + 0xc8, 0x7d, 0x48, 0xb7, 0x84, 0x12, 0xd0, 0x76, + 0xda, 0xe1, 0xa3, 0x1e, 0x40, 0x01, 0x14, 0x5c, + 0xef, 0x26, 0x6e, 0x28, 0xa2, 0xf7, 0xa5, 0xb4, + 0x02, 0x37, 0xd0, 0x53, 0x10, 0xcb, 0x7c, 0x6a, + 0xf4, 0x53, 0x9f, 0xb8, 0xe0, 0x83, 0x93, 0xd1, + 0x19, 0xd8, 0x28, 0xd1, 0xd1, 0xd8, 0x87, 0x8f, + 0x92, 0xfd, 0x73, 0xc0, 0x4d, 0x3e, 0x07, 0x22, + 0x1f, 0xc1, 0x20, 0xb0, 0x70, 0xb2, 0x3b, 0xea, + 0xb1, 0xe5, 0x0a, 0xfd, 0x56, 0x49, 0x5e, 0x39, + 0x90, 0x91, 0xce, 0x04, 0x83, 0x29, 0xaa, 0xfd, + 0x12, 0xa4, 0x42, 0x26, 0x6c, 0x6e, 0x79, 0x70, + 0x77, 0x03, 0xb2, 0x07, 0x01, 0x3d, 0x85, 0x81, + 0x95, 0x9e, 0xda, 0x5a, 0xa3, 0xf4, 0x2d, 0x38, + 0x04, 0x58, 0xf5, 0x6b, 0xc9, 0xf1, 0xb5, 0x65, + 0xfe, 0x66, 0x0d, 0xa2, 0xd5, 0x02, 0x03, 0x01, + 0x00, 0x01, 0x02, 0x81, 0x80, 0x5e, 0x01, 0x5f, + 0xb6, 0x59, 0x1d, 0xdc, 0x36, 0xb6, 0x60, 0x36, + 0xe6, 0x08, 0xdb, 0xd9, 0xcd, 0xc3, 0x8c, 0x16, + 0x9c, 0x98, 0x8d, 0x7f, 0xd3, 0xdb, 0x1d, 0xaa, + 0x68, 0x8f, 0xc5, 0xf8, 0xe2, 0x5d, 0xb3, 0x19, + 0xc2, 0xc6, 0xf9, 0x51, 0x32, 0x1b, 0x93, 0x6a, + 0xdc, 0x50, 0x8e, 0xeb, 0x61, 0x84, 0x03, 0x42, + 0x30, 0x98, 0xb1, 0xf7, 0xbd, 0x14, 0x9a, 0x57, + 0x36, 0x33, 0x09, 0xd4, 0x3e, 0x90, 0xda, 0xef, + 0x09, 0x6e, 0xef, 0x49, 0xb6, 0x60, 0x68, 0x5e, + 0x54, 0x17, 0x25, 0x5b, 0x37, 0xe3, 0x35, 0x63, + 0x5b, 0x60, 0x3c, 0xbd, 0x50, 0xdf, 0x46, 0x43, + 0x08, 0xa4, 0x71, 0x21, 0xf1, 0x30, 0x71, 0xdc, + 0xda, 0xd7, 0x6f, 0xd2, 0x18, 0xbd, 0x39, 0xf1, + 0xe1, 0xbe, 0xa8, 0x8d, 0x62, 0xdf, 0xa2, 0x3e, + 0xb6, 0x15, 0x26, 0xb6, 0x57, 0xbd, 0x63, 0xdb, + 0xc1, 0x91, 0xec, 0xb8, 0x01, 0x02, 0x41, 0x00, + 0xc6, 0x1a, 0x06, 0x48, 0xf2, 0x12, 0x1c, 0x9f, + 0x74, 0x20, 0x5c, 0x85, 0xa2, 0xda, 0xe5, 0x62, + 0x96, 0x8d, 0x22, 0x7b, 0x78, 0x73, 0xea, 0xbb, + 0x9f, 0x59, 0x42, 0x13, 0x15, 0xc8, 0x11, 0x50, + 0x6c, 0x55, 0xf6, 0xdf, 0x8b, 0xfe, 0xc7, 0xdd, + 0xa8, 0xca, 0x54, 0x41, 0xe8, 0xce, 0xbe, 0x7d, + 0xbd, 0xe2, 0x13, 0x4b, 0x5b, 0x61, 0xeb, 0x69, + 0x6c, 0xb1, 0x9b, 0x28, 0x68, 0x5b, 0xd6, 0x01, + 0x02, 0x41, 0x00, 0xbd, 0x1e, 0xfe, 0x51, 0x99, + 0xb6, 0xe3, 0x84, 0xfe, 0xf1, 0x9e, 0xfd, 0x9c, + 0xe7, 0x86, 0x43, 0x68, 0x7f, 0x2f, 0x6a, 0x2a, + 0x4c, 0xae, 0xa6, 0x41, 0x1c, 0xf0, 0x10, 0x37, + 0x54, 0x23, 0xba, 0x05, 0x0d, 0x18, 0x27, 0x8d, + 0xb8, 0xe4, 0x8f, 0xf2, 0x25, 0x73, 0x8a, 0xd7, + 0x05, 0x98, 0x6b, 0x3d, 0x55, 0xb7, 0x6f, 0x7c, + 0xec, 0x77, 0x61, 0x54, 0x7b, 0xb6, 0x6b, 0x31, + 0xec, 0x94, 0xd5, 0x02, 0x41, 0x00, 0x90, 0xa2, + 0xa5, 0x9e, 0x12, 0xa7, 0x68, 0xa0, 0x7e, 0xdf, + 0xb5, 0xcd, 0x98, 0x26, 0xab, 0xbd, 0xbc, 0x5f, + 0xd5, 0x22, 0x42, 0xc2, 0x97, 0x4a, 0x5f, 0x40, + 0x82, 0xfe, 0x7e, 0x33, 0xb1, 0x78, 0x7f, 0x70, + 0x90, 0x2b, 0x8d, 0x01, 0xfb, 0x18, 0xfa, 0x48, + 0xa7, 0x15, 0xec, 0x0d, 0x2e, 0x85, 0x8d, 0xe2, + 0x86, 0xe5, 0xc9, 0x15, 0x88, 0x14, 0x53, 0xd8, + 0xa4, 0x88, 0xef, 0x10, 0xc6, 0x01, 0x02, 0x41, + 0x00, 0xba, 0xe4, 0xaf, 0x14, 0xfa, 0xdf, 0xf6, + 0xd5, 0xce, 0x8f, 0xfe, 0xbb, 0xc8, 0x5c, 0x30, + 0x9d, 0xda, 0xdd, 0x9d, 0x80, 0xc0, 0x0e, 0x89, + 0xa5, 0xb8, 0xc1, 0x1d, 0x28, 0x19, 0x55, 0x67, + 0xfd, 0x03, 0xd2, 0xdd, 0xe4, 0xf0, 0xb4, 0x20, + 0x03, 0x74, 0x9b, 0xb8, 0x24, 0x23, 0xbb, 0xde, + 0xd5, 0x53, 0x86, 0xaa, 0xc1, 0x5d, 0x65, 0xdd, + 0xcf, 0xec, 0x8a, 0x59, 0x4a, 0x73, 0xca, 0xc5, + 0x85, 0x02, 0x40, 0x00, 0xc4, 0x5e, 0x8d, 0xa4, + 0xea, 0xbb, 0x6a, 0x9b, 0xe6, 0x3a, 0x4d, 0xc1, + 0xdb, 0xe5, 0x52, 0x38, 0xf9, 0x59, 0x91, 0x2d, + 0x90, 0x82, 0xe3, 0x31, 0x1b, 0x48, 0xb7, 0x42, + 0xfa, 0x1d, 0x83, 0xd5, 0x3d, 0x02, 0xc2, 0x12, + 0x71, 0x10, 0x3a, 0xbd, 0x92, 0x8f, 0x9b, 0xa2, + 0x6b, 0x2d, 0x21, 0xa4, 0x65, 0xe9, 0xfa, 0x8c, + 0x30, 0x2a, 0x89, 0xce, 0xd0, 0xa7, 0x67, 0xd8, + 0x45, 0x84, 0xb0 + }; + + const uint8 short_integer_without_high_bit[] = { + 0x30, 0x82, 0x02, 0x76, 0x02, 0x01, 0x00, 0x30, + 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, + 0x02, 0x60, 0x30, 0x82, 0x02, 0x5c, 0x02, 0x01, + 0x00, 0x02, 0x81, 0x81, 0x00, 0xc3, 0x9e, 0x8d, + 0xc4, 0x6d, 0x38, 0xe8, 0x0e, 0x9f, 0x84, 0x03, + 0x40, 0x8e, 0x81, 0x2e, 0x56, 0x67, 0x78, 0x11, + 0x85, 0x27, 0x81, 0x52, 0xf2, 0x1b, 0x3e, 0x5b, + 0xf8, 0xab, 0xfc, 0xaf, 0xca, 0x5c, 0x26, 0xd5, + 0xfa, 0xd4, 0x55, 0x50, 0x38, 0xb9, 0x9d, 0x89, + 0x92, 0x7e, 0x34, 0xcf, 0x37, 0x82, 0x48, 0x2d, + 0xaa, 0xc4, 0x6a, 0x0e, 0x93, 0xea, 0xad, 0x8a, + 0x33, 0xf0, 0x42, 0x23, 0xe0, 0x4c, 0x98, 0xbf, + 0x01, 0x00, 0x1b, 0xfe, 0x06, 0x15, 0xc6, 0xe3, + 0x80, 0x79, 0x6d, 0xfe, 0x48, 0xcd, 0x40, 0xbb, + 0xf9, 0x58, 0xe6, 0xbf, 0xd5, 0x4c, 0x29, 0x48, + 0x53, 0x78, 0x06, 0x03, 0x0d, 0x59, 0xf5, 0x20, + 0xe0, 0xe6, 0x8c, 0xb2, 0xf5, 0xd8, 0x61, 0x52, + 0x7e, 0x40, 0x83, 0xd7, 0x69, 0xae, 0xd7, 0x75, + 0x02, 0x2d, 0x49, 0xd5, 0x15, 0x5b, 0xf1, 0xd9, + 0x4d, 0x60, 0x7d, 0x62, 0xa5, 0x02, 0x03, 0x01, + 0x00, 0x01, 0x02, 0x7f, 0x6d, 0x45, 0x23, 0xeb, + 0x95, 0x17, 0x34, 0x88, 0xf6, 0x91, 0xc7, 0x3f, + 0x48, 0x5a, 0xe0, 0x87, 0x63, 0x44, 0xae, 0x84, + 0xb2, 0x8c, 0x8a, 0xc8, 0xb2, 0x6f, 0x22, 0xf0, + 0xc5, 0x21, 0x61, 0x10, 0xa8, 0x69, 0x09, 0x1e, + 0x13, 0x7d, 0x94, 0x52, 0x1b, 0x5c, 0xe4, 0x7b, + 0xf0, 0x03, 0x8f, 0xbc, 0x72, 0x09, 0xdf, 0x78, + 0x84, 0x3e, 0xb9, 0xe5, 0xe6, 0x31, 0x0a, 0x01, + 0xf9, 0x32, 0xf8, 0xd6, 0x57, 0xa3, 0x87, 0xe6, + 0xf5, 0x98, 0xbc, 0x8e, 0x41, 0xb9, 0x50, 0x17, + 0x7b, 0xd3, 0x97, 0x5a, 0x44, 0x3a, 0xee, 0xff, + 0x6b, 0xb3, 0x3a, 0x52, 0xe7, 0xa4, 0x96, 0x9a, + 0xf6, 0x83, 0xc8, 0x97, 0x1c, 0x63, 0xa1, 0xd6, + 0xb3, 0xa8, 0xb2, 0xc7, 0x73, 0x25, 0x0f, 0x58, + 0x36, 0xb9, 0x7a, 0x47, 0xa7, 0x4d, 0x30, 0xfe, + 0x4d, 0x74, 0x56, 0xe8, 0xfb, 0xd6, 0x50, 0xe5, + 0xe0, 0x28, 0x15, 0x02, 0x41, 0x00, 0xeb, 0x15, + 0x62, 0xb6, 0x37, 0x41, 0x7c, 0xc5, 0x00, 0x22, + 0x2c, 0x5a, 0x5e, 0xe4, 0xb2, 0x11, 0x87, 0x89, + 0xad, 0xf4, 0x57, 0x68, 0x90, 0xb7, 0x9f, 0xe2, + 0x79, 0x20, 0x6b, 0x98, 0x00, 0x0d, 0x3a, 0x3b, + 0xc1, 0xcd, 0x36, 0xf9, 0x27, 0xda, 0x40, 0x36, + 0x1d, 0xb8, 0x5c, 0x96, 0xeb, 0x04, 0x08, 0xe1, + 0x3f, 0xfa, 0x94, 0x8b, 0x0f, 0xa0, 0xff, 0xc1, + 0x51, 0xea, 0x90, 0xad, 0x15, 0xc7, 0x02, 0x41, + 0x00, 0xd5, 0x06, 0x45, 0xd7, 0x55, 0x63, 0x1a, + 0xf0, 0x89, 0x81, 0xae, 0x87, 0x23, 0xa2, 0x39, + 0xfe, 0x3d, 0x82, 0xc7, 0xcb, 0x15, 0xb9, 0xe3, + 0xe2, 0x5b, 0xc6, 0xd2, 0x55, 0xdd, 0xab, 0x55, + 0x29, 0x7c, 0xda, 0x0e, 0x1c, 0x09, 0xfc, 0x73, + 0x0d, 0x01, 0xed, 0x6d, 0x2f, 0x05, 0xd0, 0xd5, + 0x1d, 0xce, 0x18, 0x7f, 0xb0, 0xc8, 0x47, 0x77, + 0xd2, 0xa9, 0x9e, 0xfc, 0x39, 0x4b, 0x3d, 0x94, + 0x33, 0x02, 0x41, 0x00, 0x8f, 0x94, 0x09, 0x2d, + 0x17, 0x44, 0x75, 0x0a, 0xf1, 0x10, 0xee, 0x1b, + 0xe7, 0xd7, 0x2f, 0xf6, 0xca, 0xdc, 0x49, 0x15, + 0x72, 0x09, 0x58, 0x51, 0xfe, 0x61, 0xd8, 0xee, + 0xf7, 0x27, 0xe7, 0xe8, 0x2c, 0x47, 0xf1, 0x0f, + 0x00, 0x63, 0x5e, 0x76, 0xcb, 0x3f, 0x02, 0x19, + 0xe6, 0xda, 0xfa, 0x01, 0x05, 0xd7, 0x65, 0x37, + 0x0b, 0x60, 0x7f, 0x94, 0x2a, 0x80, 0x8d, 0x22, + 0x81, 0x68, 0x65, 0x63, 0x02, 0x41, 0x00, 0xc2, + 0xd4, 0x18, 0xde, 0x47, 0x9e, 0xfb, 0x8d, 0x91, + 0x05, 0xc5, 0x3c, 0x9d, 0xcf, 0x8a, 0x60, 0xc7, + 0x9b, 0x2b, 0xe5, 0xc6, 0xba, 0x1b, 0xfc, 0xf3, + 0xd9, 0x54, 0x97, 0xe9, 0xc4, 0x00, 0x80, 0x90, + 0x4a, 0xd2, 0x6a, 0xbc, 0x8b, 0x62, 0x22, 0x3c, + 0x68, 0x0c, 0xda, 0xdb, 0xe3, 0xd2, 0x76, 0x8e, + 0xff, 0x03, 0x12, 0x09, 0x2a, 0xac, 0x21, 0x44, + 0xb7, 0x3e, 0x91, 0x9c, 0x09, 0xf6, 0xd7, 0x02, + 0x41, 0x00, 0xc0, 0xa1, 0xbb, 0x70, 0xdc, 0xf8, + 0xeb, 0x17, 0x61, 0xd4, 0x8c, 0x7c, 0x3b, 0x82, + 0x91, 0x58, 0xff, 0xf9, 0x19, 0xac, 0x3a, 0x73, + 0xa7, 0x20, 0xe5, 0x22, 0x02, 0xc4, 0xf6, 0xb9, + 0xb9, 0x43, 0x53, 0x35, 0x88, 0xe1, 0x05, 0xb6, + 0x43, 0x9b, 0x39, 0xc8, 0x04, 0x4d, 0x2b, 0x01, + 0xf7, 0xe6, 0x1b, 0x8d, 0x7e, 0x89, 0xe3, 0x43, + 0xd4, 0xf3, 0xab, 0x28, 0xd4, 0x5a, 0x1f, 0x20, + 0xea, 0xbe + }; + + std::vector input1; + std::vector input2; + + input1.resize(sizeof(short_integer_with_high_bit)); + input2.resize(sizeof(short_integer_without_high_bit)); + + memcpy(&input1.front(), short_integer_with_high_bit, + sizeof(short_integer_with_high_bit)); + memcpy(&input2.front(), short_integer_without_high_bit, + sizeof(short_integer_without_high_bit)); + + scoped_ptr keypair1( + crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(input1)); + scoped_ptr keypair2( + crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(input2)); + ASSERT_TRUE(keypair1.get()); + ASSERT_TRUE(keypair2.get()); + + std::vector output1; + std::vector output2; + ASSERT_TRUE(keypair1->ExportPrivateKey(&output1)); + ASSERT_TRUE(keypair2->ExportPrivateKey(&output2)); + + ASSERT_EQ(input1.size(), output1.size()); + ASSERT_EQ(input2.size(), output2.size()); + ASSERT_TRUE(0 == memcmp(&output1.front(), &input1.front(), + input1.size())); + ASSERT_TRUE(0 == memcmp(&output2.front(), &input2.front(), + input2.size())); +} + +TEST(RSAPrivateKeyUnitTest, CreateFromKeyTest) { + scoped_ptr key_pair( + crypto::RSAPrivateKey::Create(512)); + ASSERT_TRUE(key_pair.get()); + + scoped_ptr key_copy( + crypto::RSAPrivateKey::CreateFromKey(key_pair->key())); + ASSERT_TRUE(key_copy.get()); + + std::vector privkey; + std::vector pubkey; + ASSERT_TRUE(key_pair->ExportPrivateKey(&privkey)); + ASSERT_TRUE(key_pair->ExportPublicKey(&pubkey)); + + std::vector privkey_copy; + std::vector pubkey_copy; + ASSERT_TRUE(key_copy->ExportPrivateKey(&privkey_copy)); + ASSERT_TRUE(key_copy->ExportPublicKey(&pubkey_copy)); + + ASSERT_EQ(privkey, privkey_copy); + ASSERT_EQ(pubkey, pubkey_copy); +} + diff --git a/crypto/scoped_capi_types.h b/crypto/scoped_capi_types.h new file mode 100644 index 0000000000000..ac92e394b9c5d --- /dev/null +++ b/crypto/scoped_capi_types.h @@ -0,0 +1,121 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CRYPTO_SCOPED_CAPI_TYPES_H_ +#define CRYPTO_SCOPED_CAPI_TYPES_H_ + +#include + +#include + +#include "base/logging.h" +#include "crypto/wincrypt_shim.h" + +namespace crypto { + +// Simple destructor for the Free family of CryptoAPI functions, such as +// CryptDestroyHash, which take only a single argument to release. +template +struct CAPIDestroyer { + void operator()(CAPIHandle handle) const { + if (handle) { + BOOL ok = Destroyer(handle); + DCHECK(ok); + } + } +}; + +// Destructor for the Close/Release family of CryptoAPI functions, which take +// a second DWORD parameter indicating flags to use when closing or releasing. +// This includes functions like CertCloseStore or CryptReleaseContext. +template +struct CAPIDestroyerWithFlags { + void operator()(CAPIHandle handle) const { + if (handle) { + BOOL ok = Destroyer(handle, flags); + DCHECK(ok); + } + } +}; + +// scoped_ptr-like class for the CryptoAPI cryptography and certificate +// handles. Because these handles are defined as integer types, and not +// pointers, the existing scoped classes, such as scoped_ptr, are insufficient. +// The semantics are the same as scoped_ptr. +template +class ScopedCAPIHandle { + public: + explicit ScopedCAPIHandle(CAPIHandle handle = NULL) : handle_(handle) {} + + ~ScopedCAPIHandle() { + reset(); + } + + void reset(CAPIHandle handle = NULL) { + if (handle_ != handle) { + FreeProc free_proc; + free_proc(handle_); + handle_ = handle; + } + } + + operator CAPIHandle() const { return handle_; } + CAPIHandle get() const { return handle_; } + + CAPIHandle* receive() { + CHECK(handle_ == NULL); + return &handle_; + } + + bool operator==(CAPIHandle handle) const { + return handle_ == handle; + } + + bool operator!=(CAPIHandle handle) const { + return handle_ != handle; + } + + void swap(ScopedCAPIHandle& b) { + CAPIHandle tmp = b.handle_; + b.handle_ = handle_; + handle_ = tmp; + } + + CAPIHandle release() { + CAPIHandle tmp = handle_; + handle_ = NULL; + return tmp; + } + + private: + CAPIHandle handle_; + + DISALLOW_COPY_AND_ASSIGN(ScopedCAPIHandle); +}; + +template inline +bool operator==(CH h, const ScopedCAPIHandle& b) { + return h == b.get(); +} + +template inline +bool operator!=(CH h, const ScopedCAPIHandle& b) { + return h != b.get(); +} + +typedef ScopedCAPIHandle< + HCRYPTPROV, + CAPIDestroyerWithFlags > ScopedHCRYPTPROV; + +typedef ScopedCAPIHandle< + HCRYPTKEY, CAPIDestroyer > ScopedHCRYPTKEY; + +typedef ScopedCAPIHandle< + HCRYPTHASH, CAPIDestroyer > ScopedHCRYPTHASH; + +} // namespace crypto + +#endif // CRYPTO_SCOPED_CAPI_TYPES_H_ diff --git a/crypto/scoped_nss_types.h b/crypto/scoped_nss_types.h new file mode 100644 index 0000000000000..fdfb83c154f8c --- /dev/null +++ b/crypto/scoped_nss_types.h @@ -0,0 +1,61 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CRYPTO_SCOPED_NSS_TYPES_H_ +#define CRYPTO_SCOPED_NSS_TYPES_H_ + +#include +#include +#include +#include + +#include "base/memory/scoped_ptr.h" + +namespace crypto { + +template +struct NSSDestroyer { + typedef void AllowSelfReset; + void operator()(Type* ptr) const { + Destroyer(ptr); + } +}; + +template +struct NSSDestroyer1 { + typedef void AllowSelfReset; + void operator()(Type* ptr) const { + Destroyer(ptr, freeit); + } +}; + +// Define some convenient scopers around NSS pointers. +typedef scoped_ptr > + ScopedPK11Context; +typedef scoped_ptr > + ScopedPK11Slot; +typedef scoped_ptr > + ScopedPK11SlotList; +typedef scoped_ptr > + ScopedPK11SymKey; +typedef scoped_ptr > + ScopedSECKEYPublicKey; +typedef scoped_ptr > + ScopedSECKEYPrivateKey; +typedef scoped_ptr > + ScopedSECAlgorithmID; +typedef scoped_ptr > + ScopedSECItem; +typedef scoped_ptr > + ScopedPLArenaPool; + +} // namespace crypto + +#endif // CRYPTO_SCOPED_NSS_TYPES_H_ diff --git a/crypto/scoped_openssl_types.h b/crypto/scoped_openssl_types.h index cc056e49efea9..73f763271bb7c 100644 --- a/crypto/scoped_openssl_types.h +++ b/crypto/scoped_openssl_types.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include "base/memory/scoped_ptr.h" @@ -22,15 +23,13 @@ namespace crypto { // base::internal::RunnableAdapter<>, but that's far too heavy weight. template struct OpenSSLDestroyer { - typedef void AllowSelfReset; + using AllowSelfReset = void; void operator()(Type* ptr) const { Destroyer(ptr); } }; template -struct ScopedOpenSSL { - typedef scoped_ptr > - Type; -}; +using ScopedOpenSSL = + scoped_ptr>; struct OpenSSLFree { void operator()(uint8_t* ptr) const { OPENSSL_free(ptr); } @@ -40,19 +39,21 @@ struct OpenSSLFree { // short-hand and prevalence. Note that OpenSSL types related to X.509 are // intentionally not included, as crypto/ does not generally deal with // certificates or PKI. -typedef ScopedOpenSSL::Type ScopedBIGNUM; -typedef ScopedOpenSSL::Type ScopedEC_KEY; -typedef ScopedOpenSSL::Type ScopedBIO; -typedef ScopedOpenSSL::Type ScopedDSA; -typedef ScopedOpenSSL::Type ScopedECDSA_SIG; -typedef ScopedOpenSSL::Type ScopedEC_KEY; -typedef ScopedOpenSSL::Type ScopedEVP_MD_CTX; -typedef ScopedOpenSSL::Type ScopedEVP_PKEY; -typedef ScopedOpenSSL::Type ScopedEVP_PKEY_CTX; -typedef ScopedOpenSSL::Type ScopedRSA; +using ScopedBIGNUM = ScopedOpenSSL; +using ScopedEC_Key = ScopedOpenSSL; +using ScopedBIO = ScopedOpenSSL; +using ScopedDSA = ScopedOpenSSL; +using ScopedECDSA_SIG = ScopedOpenSSL; +using ScopedEC_GROUP = ScopedOpenSSL; +using ScopedEC_KEY = ScopedOpenSSL; +using ScopedEC_POINT = ScopedOpenSSL; +using ScopedEVP_MD_CTX = ScopedOpenSSL; +using ScopedEVP_PKEY = ScopedOpenSSL; +using ScopedEVP_PKEY_CTX = ScopedOpenSSL; +using ScopedRSA = ScopedOpenSSL; // The bytes must have been allocated with OPENSSL_malloc. -typedef scoped_ptr ScopedOpenSSLBytes; +using ScopedOpenSSLBytes = scoped_ptr; } // namespace crypto diff --git a/crypto/scoped_test_nss_chromeos_user.cc b/crypto/scoped_test_nss_chromeos_user.cc new file mode 100644 index 0000000000000..aec25d8dff0c3 --- /dev/null +++ b/crypto/scoped_test_nss_chromeos_user.cc @@ -0,0 +1,37 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/scoped_test_nss_chromeos_user.h" + +#include "base/logging.h" +#include "crypto/nss_util.h" +#include "crypto/nss_util_internal.h" + +namespace crypto { + +ScopedTestNSSChromeOSUser::ScopedTestNSSChromeOSUser( + const std::string& username_hash) + : username_hash_(username_hash), constructed_successfully_(false) { + if (!temp_dir_.CreateUniqueTempDir()) + return; + // This opens a software DB in the given folder. In production code that is in + // the home folder, but for testing the temp folder is used. + constructed_successfully_ = + InitializeNSSForChromeOSUser(username_hash, temp_dir_.path()); +} + +ScopedTestNSSChromeOSUser::~ScopedTestNSSChromeOSUser() { + if (constructed_successfully_) + CloseChromeOSUserForTesting(username_hash_); +} + +void ScopedTestNSSChromeOSUser::FinishInit() { + DCHECK(constructed_successfully_); + if (!ShouldInitializeTPMForChromeOSUser(username_hash_)) + return; + WillInitializeTPMForChromeOSUser(username_hash_); + InitializePrivateSoftwareSlotForChromeOSUser(username_hash_); +} + +} // namespace crypto diff --git a/crypto/scoped_test_nss_chromeos_user.h b/crypto/scoped_test_nss_chromeos_user.h new file mode 100644 index 0000000000000..1638517704dee --- /dev/null +++ b/crypto/scoped_test_nss_chromeos_user.h @@ -0,0 +1,43 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CRYPTO_SCOPED_TEST_NSS_CHROMEOS_USER_H_ +#define CRYPTO_SCOPED_TEST_NSS_CHROMEOS_USER_H_ + +#include + +#include "base/files/scoped_temp_dir.h" +#include "base/macros.h" +#include "crypto/crypto_export.h" + +namespace crypto { + +// Opens a persistent NSS software database in a temporary directory for the +// user with |username_hash|. This database will be used for both the user's +// public and private slot. +class CRYPTO_EXPORT_PRIVATE ScopedTestNSSChromeOSUser { + public: + // Opens the software database and sets the public slot for the user. The + // private slot will not be initialized until FinishInit() is called. + explicit ScopedTestNSSChromeOSUser(const std::string& username_hash); + ~ScopedTestNSSChromeOSUser(); + + std::string username_hash() const { return username_hash_; } + bool constructed_successfully() const { return constructed_successfully_; } + + // Completes initialization of user. Causes any waiting private slot callbacks + // to run, see GetPrivateSlotForChromeOSUser(). + void FinishInit(); + + private: + const std::string username_hash_; + base::ScopedTempDir temp_dir_; + bool constructed_successfully_; + + DISALLOW_COPY_AND_ASSIGN(ScopedTestNSSChromeOSUser); +}; + +} // namespace crypto + +#endif // CRYPTO_SCOPED_TEST_NSS_CHROMEOS_USER_H_ diff --git a/crypto/scoped_test_nss_db.cc b/crypto/scoped_test_nss_db.cc new file mode 100644 index 0000000000000..452c26d73e505 --- /dev/null +++ b/crypto/scoped_test_nss_db.cc @@ -0,0 +1,53 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/scoped_test_nss_db.h" + +#include "base/logging.h" +#include "base/threading/thread_restrictions.h" +#include "crypto/nss_util.h" +#include "crypto/nss_util_internal.h" + +namespace crypto { + +ScopedTestNSSDB::ScopedTestNSSDB() { + EnsureNSSInit(); + // NSS is allowed to do IO on the current thread since dispatching + // to a dedicated thread would still have the affect of blocking + // the current thread, due to NSS's internal locking requirements + base::ThreadRestrictions::ScopedAllowIO allow_io; + + if (!temp_dir_.CreateUniqueTempDir()) + return; + + const char kTestDescription[] = "Test DB"; + slot_ = OpenSoftwareNSSDB(temp_dir_.path(), kTestDescription); +} + +ScopedTestNSSDB::~ScopedTestNSSDB() { + // Don't close when NSS is < 3.15.1, because it would require an additional + // sleep for 1 second after closing the database, due to + // http://bugzil.la/875601. + if (!NSS_VersionCheck("3.15.1")) { + LOG(ERROR) << "NSS version is < 3.15.1, test DB will not be closed."; + temp_dir_.Take(); + return; + } + + // NSS is allowed to do IO on the current thread since dispatching + // to a dedicated thread would still have the affect of blocking + // the current thread, due to NSS's internal locking requirements + base::ThreadRestrictions::ScopedAllowIO allow_io; + + if (slot_) { + SECStatus status = SECMOD_CloseUserDB(slot_.get()); + if (status != SECSuccess) + PLOG(ERROR) << "SECMOD_CloseUserDB failed: " << PORT_GetError(); + } + + if (!temp_dir_.Delete()) + LOG(ERROR) << "Could not delete temporary directory."; +} + +} // namespace crypto diff --git a/crypto/scoped_test_nss_db.h b/crypto/scoped_test_nss_db.h new file mode 100644 index 0000000000000..88c2d55dbe4ed --- /dev/null +++ b/crypto/scoped_test_nss_db.h @@ -0,0 +1,35 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CRYPTO_SCOPED_TEST_NSS_DB_H_ +#define CRYPTO_SCOPED_TEST_NSS_DB_H_ + +#include "base/files/scoped_temp_dir.h" +#include "base/macros.h" +#include "crypto/crypto_export.h" +#include "crypto/scoped_nss_types.h" + +namespace crypto { + +// Opens a persistent NSS database in a temporary directory. +// Prior NSS version 3.15.1, because of http://bugzil.la/875601 , the opened DB +// will not be closed automatically. +class CRYPTO_EXPORT_PRIVATE ScopedTestNSSDB { + public: + ScopedTestNSSDB(); + ~ScopedTestNSSDB(); + + bool is_open() const { return slot_; } + PK11SlotInfo* slot() const { return slot_.get(); } + + private: + base::ScopedTempDir temp_dir_; + ScopedPK11Slot slot_; + + DISALLOW_COPY_AND_ASSIGN(ScopedTestNSSDB); +}; + +} // namespace crypto + +#endif // CRYPTO_SCOPED_TEST_NSS_DB_H_ diff --git a/crypto/scoped_test_system_nss_key_slot.cc b/crypto/scoped_test_system_nss_key_slot.cc new file mode 100644 index 0000000000000..53fbbffc1a99f --- /dev/null +++ b/crypto/scoped_test_system_nss_key_slot.cc @@ -0,0 +1,32 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/scoped_test_system_nss_key_slot.h" + +#include "crypto/nss_util_internal.h" +#include "crypto/scoped_test_nss_db.h" + +namespace crypto { + +ScopedTestSystemNSSKeySlot::ScopedTestSystemNSSKeySlot() + : test_db_(new ScopedTestNSSDB) { + if (!test_db_->is_open()) + return; + SetSystemKeySlotForTesting( + ScopedPK11Slot(PK11_ReferenceSlot(test_db_->slot()))); +} + +ScopedTestSystemNSSKeySlot::~ScopedTestSystemNSSKeySlot() { + SetSystemKeySlotForTesting(ScopedPK11Slot()); +} + +bool ScopedTestSystemNSSKeySlot::ConstructedSuccessfully() const { + return test_db_->is_open(); +} + +PK11SlotInfo* ScopedTestSystemNSSKeySlot::slot() const { + return test_db_->slot(); +} + +} // namespace crypto diff --git a/crypto/scoped_test_system_nss_key_slot.h b/crypto/scoped_test_system_nss_key_slot.h new file mode 100644 index 0000000000000..ac3b72c4ce0bd --- /dev/null +++ b/crypto/scoped_test_system_nss_key_slot.h @@ -0,0 +1,43 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CRYPTO_SCOPED_TEST_SYSTEM_NSS_KEY_SLOT_H_ +#define CRYPTO_SCOPED_TEST_SYSTEM_NSS_KEY_SLOT_H_ + +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "crypto/crypto_export.h" + +// Forward declaration, from +typedef struct PK11SlotInfoStr PK11SlotInfo; + +namespace crypto { + +class ScopedTestNSSDB; + +// Opens a persistent NSS software database in a temporary directory and sets +// the test system slot to the opened database. This helper should be created in +// tests to fake the system token that is usually provided by the Chaps module. +// |slot| is exposed through |GetSystemNSSKeySlot| and |IsTPMTokenReady| will +// return true. +// |InitializeTPMTokenAndSystemSlot|, which triggers the TPM initialization, +// does not have to be called if this helper is used. +// At most one instance of this helper must be used at a time. +class CRYPTO_EXPORT_PRIVATE ScopedTestSystemNSSKeySlot { + public: + explicit ScopedTestSystemNSSKeySlot(); + ~ScopedTestSystemNSSKeySlot(); + + bool ConstructedSuccessfully() const; + PK11SlotInfo* slot() const; + + private: + scoped_ptr test_db_; + + DISALLOW_COPY_AND_ASSIGN(ScopedTestSystemNSSKeySlot); +}; + +} // namespace crypto + +#endif // CRYPTO_SCOPED_TEST_SYSTEM_NSS_KEY_SLOT_H_ diff --git a/crypto/secure_hash_default.cc b/crypto/secure_hash_default.cc new file mode 100644 index 0000000000000..739b402b6c199 --- /dev/null +++ b/crypto/secure_hash_default.cc @@ -0,0 +1,94 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/secure_hash.h" + +#include "base/logging.h" +#include "base/pickle.h" +#include "crypto/third_party/nss/chromium-blapi.h" +#include "crypto/third_party/nss/chromium-sha256.h" + +namespace crypto { + +namespace { + +const char kSHA256Descriptor[] = "NSS"; + +class SecureHashSHA256NSS : public SecureHash { + public: + static const int kSecureHashVersion = 1; + + SecureHashSHA256NSS() { + SHA256_Begin(&ctx_); + } + + ~SecureHashSHA256NSS() override { memset(&ctx_, 0, sizeof(ctx_)); } + + // SecureHash implementation: + void Update(const void* input, size_t len) override { + SHA256_Update(&ctx_, static_cast(input), len); + } + + void Finish(void* output, size_t len) override { + SHA256_End(&ctx_, static_cast(output), NULL, + static_cast(len)); + } + + bool Serialize(base::Pickle* pickle) override; + bool Deserialize(base::PickleIterator* data_iterator) override; + + private: + SHA256Context ctx_; +}; + +bool SecureHashSHA256NSS::Serialize(base::Pickle* pickle) { + if (!pickle) + return false; + + if (!pickle->WriteInt(kSecureHashVersion) || + !pickle->WriteString(kSHA256Descriptor) || + !pickle->WriteBytes(&ctx_, sizeof(ctx_))) { + return false; + } + + return true; +} + +bool SecureHashSHA256NSS::Deserialize(base::PickleIterator* data_iterator) { + int version; + if (!data_iterator->ReadInt(&version)) + return false; + + if (version > kSecureHashVersion) + return false; // We don't know how to deal with this. + + std::string type; + if (!data_iterator->ReadString(&type)) + return false; + + if (type != kSHA256Descriptor) + return false; // It's the wrong kind. + + const char* data = NULL; + if (!data_iterator->ReadBytes(&data, sizeof(ctx_))) + return false; + + memcpy(&ctx_, data, sizeof(ctx_)); + + return true; +} + +} // namespace + +SecureHash* SecureHash::Create(Algorithm algorithm) { + switch (algorithm) { + case SHA256: + return new SecureHashSHA256NSS(); + default: + NOTIMPLEMENTED(); + return NULL; + } +} + +} // namespace crypto diff --git a/crypto/secure_hash_openssl.cc b/crypto/secure_hash_openssl.cc index 9e77c3fa5f8f9..1033b8e25eb82 100644 --- a/crypto/secure_hash_openssl.cc +++ b/crypto/secure_hash_openssl.cc @@ -4,7 +4,7 @@ #include "crypto/secure_hash.h" -#include +#include #include #include "base/basictypes.h" diff --git a/crypto/secure_util.cc b/crypto/secure_util.cc new file mode 100644 index 0000000000000..3fe8aa961a027 --- /dev/null +++ b/crypto/secure_util.cc @@ -0,0 +1,19 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/secure_util.h" + +namespace crypto { + +bool SecureMemEqual(const void* s1, const void* s2, size_t n) { + const unsigned char* s1_ptr = reinterpret_cast(s1); + const unsigned char* s2_ptr = reinterpret_cast(s2); + unsigned char tmp = 0; + for (size_t i = 0; i < n; ++i, ++s1_ptr, ++s2_ptr) + tmp |= *s1_ptr ^ *s2_ptr; + return (tmp == 0); +} + +} // namespace crypto + diff --git a/crypto/secure_util.h b/crypto/secure_util.h new file mode 100644 index 0000000000000..cfe05ca15540b --- /dev/null +++ b/crypto/secure_util.h @@ -0,0 +1,29 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CRYPTO_SECURE_UTIL_H_ +#define CRYPTO_SECURE_UTIL_H_ + +#include + +#include "crypto/crypto_export.h" + +namespace crypto { + +// Performs a constant-time comparison of two strings, returning true if the +// strings are equal. +// +// For cryptographic operations, comparison functions such as memcmp() may +// expose side-channel information about input, allowing an attacker to +// perform timing analysis to determine what the expected bits should be. In +// order to avoid such attacks, the comparison must execute in constant time, +// so as to not to reveal to the attacker where the difference(s) are. +// For an example attack, see +// http://groups.google.com/group/keyczar-discuss/browse_thread/thread/5571eca0948b2a13 +CRYPTO_EXPORT bool SecureMemEqual(const void* s1, const void* s2, size_t n); + +} // namespace crypto + +#endif // CRYPTO_SECURE_UTIL_H_ + diff --git a/crypto/signature_creator.h b/crypto/signature_creator.h new file mode 100644 index 0000000000000..ab9d2c1a21b58 --- /dev/null +++ b/crypto/signature_creator.h @@ -0,0 +1,73 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CRYPTO_SIGNATURE_CREATOR_H_ +#define CRYPTO_SIGNATURE_CREATOR_H_ + +#include + +#include "build/build_config.h" +#include "base/basictypes.h" +#include "crypto/crypto_export.h" + +#if defined(USE_OPENSSL) +// Forward declaration for openssl/*.h +typedef struct env_md_ctx_st EVP_MD_CTX; +#elif defined(USE_NSS_CERTS) || defined(OS_WIN) || defined(OS_MACOSX) +// Forward declaration. +struct SGNContextStr; +#endif + +namespace crypto { + +class RSAPrivateKey; + +// Signs data using a bare private key (as opposed to a full certificate). +// Currently can only sign data using SHA-1 or SHA-256 with RSA PKCS#1v1.5. +class CRYPTO_EXPORT SignatureCreator { + public: + // The set of supported hash functions. Extend as required. + enum HashAlgorithm { + SHA1, + SHA256, + }; + + ~SignatureCreator(); + + // Create an instance. The caller must ensure that the provided PrivateKey + // instance outlives the created SignatureCreator. Uses the HashAlgorithm + // specified. + static SignatureCreator* Create(RSAPrivateKey* key, HashAlgorithm hash_alg); + + + // Signs the precomputed |hash_alg| digest |data| using private |key| as + // specified in PKCS #1 v1.5. + static bool Sign(RSAPrivateKey* key, + HashAlgorithm hash_alg, + const uint8* data, + int data_len, + std::vector* signature); + + // Update the signature with more data. + bool Update(const uint8* data_part, int data_part_len); + + // Finalize the signature. + bool Final(std::vector* signature); + + private: + // Private constructor. Use the Create() method instead. + SignatureCreator(); + +#if defined(USE_OPENSSL) + EVP_MD_CTX* sign_context_; +#elif defined(USE_NSS_CERTS) || defined(OS_WIN) || defined(OS_MACOSX) + SGNContextStr* sign_context_; +#endif + + DISALLOW_COPY_AND_ASSIGN(SignatureCreator); +}; + +} // namespace crypto + +#endif // CRYPTO_SIGNATURE_CREATOR_H_ diff --git a/crypto/signature_creator_nss.cc b/crypto/signature_creator_nss.cc new file mode 100644 index 0000000000000..da03312881dbb --- /dev/null +++ b/crypto/signature_creator_nss.cc @@ -0,0 +1,118 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/signature_creator.h" + +#include +#include +#include + +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "crypto/nss_util.h" +#include "crypto/rsa_private_key.h" + +namespace crypto { + +namespace { + +SECOidTag ToNSSSigOid(SignatureCreator::HashAlgorithm hash_alg) { + switch (hash_alg) { + case SignatureCreator::SHA1: + return SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; + case SignatureCreator::SHA256: + return SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION; + } + return SEC_OID_UNKNOWN; +} + +SECOidTag ToNSSHashOid(SignatureCreator::HashAlgorithm hash_alg) { + switch (hash_alg) { + case SignatureCreator::SHA1: + return SEC_OID_SHA1; + case SignatureCreator::SHA256: + return SEC_OID_SHA256; + } + return SEC_OID_UNKNOWN; +} + +} // namespace + +SignatureCreator::~SignatureCreator() { + if (sign_context_) { + SGN_DestroyContext(sign_context_, PR_TRUE); + sign_context_ = NULL; + } +} + +// static +SignatureCreator* SignatureCreator::Create(RSAPrivateKey* key, + HashAlgorithm hash_alg) { + scoped_ptr result(new SignatureCreator); + result->sign_context_ = SGN_NewContext(ToNSSSigOid(hash_alg), key->key()); + if (!result->sign_context_) { + NOTREACHED(); + return NULL; + } + + SECStatus rv = SGN_Begin(result->sign_context_); + if (rv != SECSuccess) { + NOTREACHED(); + return NULL; + } + + return result.release(); +} + +// static +bool SignatureCreator::Sign(RSAPrivateKey* key, + HashAlgorithm hash_alg, + const uint8* data, + int data_len, + std::vector* signature) { + SECItem data_item; + data_item.type = siBuffer; + data_item.data = const_cast(data); + data_item.len = data_len; + + SECItem signature_item; + SECStatus rv = SGN_Digest(key->key(), ToNSSHashOid(hash_alg), &signature_item, + &data_item); + if (rv != SECSuccess) { + NOTREACHED(); + return false; + } + signature->assign(signature_item.data, + signature_item.data + signature_item.len); + SECITEM_FreeItem(&signature_item, PR_FALSE); + return true; +} + +bool SignatureCreator::Update(const uint8* data_part, int data_part_len) { + SECStatus rv = SGN_Update(sign_context_, data_part, data_part_len); + if (rv != SECSuccess) { + NOTREACHED(); + return false; + } + + return true; +} + +bool SignatureCreator::Final(std::vector* signature) { + SECItem signature_item; + SECStatus rv = SGN_End(sign_context_, &signature_item); + if (rv != SECSuccess) { + return false; + } + signature->assign(signature_item.data, + signature_item.data + signature_item.len); + SECITEM_FreeItem(&signature_item, PR_FALSE); + return true; +} + +SignatureCreator::SignatureCreator() : sign_context_(NULL) { + EnsureNSSInit(); +} + +} // namespace crypto diff --git a/crypto/signature_creator_openssl.cc b/crypto/signature_creator_openssl.cc new file mode 100644 index 0000000000000..0d90d50044da8 --- /dev/null +++ b/crypto/signature_creator_openssl.cc @@ -0,0 +1,114 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/signature_creator.h" + +#include +#include + +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "base/stl_util.h" +#include "crypto/openssl_util.h" +#include "crypto/rsa_private_key.h" +#include "crypto/scoped_openssl_types.h" + +namespace crypto { + +namespace { + +const EVP_MD* ToOpenSSLDigest(SignatureCreator::HashAlgorithm hash_alg) { + switch (hash_alg) { + case SignatureCreator::SHA1: + return EVP_sha1(); + case SignatureCreator::SHA256: + return EVP_sha256(); + } + return NULL; +} + +int ToOpenSSLDigestType(SignatureCreator::HashAlgorithm hash_alg) { + switch (hash_alg) { + case SignatureCreator::SHA1: + return NID_sha1; + case SignatureCreator::SHA256: + return NID_sha256; + } + return NID_undef; +} + +} // namespace + +// static +SignatureCreator* SignatureCreator::Create(RSAPrivateKey* key, + HashAlgorithm hash_alg) { + OpenSSLErrStackTracer err_tracer(FROM_HERE); + scoped_ptr result(new SignatureCreator); + const EVP_MD* const digest = ToOpenSSLDigest(hash_alg); + DCHECK(digest); + if (!digest) { + return NULL; + } + if (!EVP_DigestSignInit(result->sign_context_, NULL, digest, NULL, + key->key())) { + return NULL; + } + return result.release(); +} + +// static +bool SignatureCreator::Sign(RSAPrivateKey* key, + HashAlgorithm hash_alg, + const uint8* data, + int data_len, + std::vector* signature) { + ScopedRSA rsa_key(EVP_PKEY_get1_RSA(key->key())); + if (!rsa_key) + return false; + signature->resize(RSA_size(rsa_key.get())); + + unsigned int len = 0; + if (!RSA_sign(ToOpenSSLDigestType(hash_alg), data, data_len, + vector_as_array(signature), &len, rsa_key.get())) { + signature->clear(); + return false; + } + signature->resize(len); + return true; +} + +SignatureCreator::SignatureCreator() + : sign_context_(EVP_MD_CTX_create()) { +} + +SignatureCreator::~SignatureCreator() { + EVP_MD_CTX_destroy(sign_context_); +} + +bool SignatureCreator::Update(const uint8* data_part, int data_part_len) { + OpenSSLErrStackTracer err_tracer(FROM_HERE); + return !!EVP_DigestSignUpdate(sign_context_, data_part, data_part_len); +} + +bool SignatureCreator::Final(std::vector* signature) { + OpenSSLErrStackTracer err_tracer(FROM_HERE); + + // Determine the maximum length of the signature. + size_t len = 0; + if (!EVP_DigestSignFinal(sign_context_, NULL, &len)) { + signature->clear(); + return false; + } + signature->resize(len); + + // Sign it. + if (!EVP_DigestSignFinal(sign_context_, vector_as_array(signature), &len)) { + signature->clear(); + return false; + } + signature->resize(len); + return true; +} + +} // namespace crypto diff --git a/crypto/signature_creator_unittest.cc b/crypto/signature_creator_unittest.cc new file mode 100644 index 0000000000000..694becdcb4475 --- /dev/null +++ b/crypto/signature_creator_unittest.cc @@ -0,0 +1,143 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include + +#include "base/memory/scoped_ptr.h" +#include "base/sha1.h" +#include "crypto/rsa_private_key.h" +#include "crypto/sha2.h" +#include "crypto/signature_creator.h" +#include "crypto/signature_verifier.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +// This is the algorithm ID for SHA-1 with RSA encryption. +const uint8 kSHA1WithRSAAlgorithmID[] = { + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00 +}; + +// This is the algorithm ID for SHA-1 with RSA encryption. +const uint8 kSHA256WithRSAAlgorithmID[] = { + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x0B, 0x05, 0x00 +}; + +} + +TEST(SignatureCreatorTest, BasicTest) { + // Do a verify round trip. + scoped_ptr key_original( + crypto::RSAPrivateKey::Create(1024)); + ASSERT_TRUE(key_original.get()); + + std::vector key_info; + key_original->ExportPrivateKey(&key_info); + scoped_ptr key( + crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_info)); + ASSERT_TRUE(key.get()); + + scoped_ptr signer( + crypto::SignatureCreator::Create(key.get(), + crypto::SignatureCreator::SHA1)); + ASSERT_TRUE(signer.get()); + + std::string data("Hello, World!"); + ASSERT_TRUE(signer->Update(reinterpret_cast(data.c_str()), + data.size())); + + std::vector signature; + ASSERT_TRUE(signer->Final(&signature)); + + std::vector public_key_info; + ASSERT_TRUE(key_original->ExportPublicKey(&public_key_info)); + + crypto::SignatureVerifier verifier; + ASSERT_TRUE(verifier.VerifyInit( + kSHA1WithRSAAlgorithmID, sizeof(kSHA1WithRSAAlgorithmID), + &signature.front(), signature.size(), + &public_key_info.front(), public_key_info.size())); + + verifier.VerifyUpdate(reinterpret_cast(data.c_str()), + data.size()); + ASSERT_TRUE(verifier.VerifyFinal()); +} + +TEST(SignatureCreatorTest, SignDigestTest) { + // Do a verify round trip. + scoped_ptr key_original( + crypto::RSAPrivateKey::Create(1024)); + ASSERT_TRUE(key_original.get()); + + std::vector key_info; + key_original->ExportPrivateKey(&key_info); + scoped_ptr key( + crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_info)); + ASSERT_TRUE(key.get()); + + std::string data("Hello, World!"); + std::string sha1 = base::SHA1HashString(data); + // Sign sha1 of the input data. + std::vector signature; + ASSERT_TRUE(crypto::SignatureCreator::Sign( + key.get(), + crypto::SignatureCreator::SHA1, + reinterpret_cast(sha1.c_str()), + sha1.size(), + &signature)); + + std::vector public_key_info; + ASSERT_TRUE(key_original->ExportPublicKey(&public_key_info)); + + // Verify the input data. + crypto::SignatureVerifier verifier; + ASSERT_TRUE(verifier.VerifyInit( + kSHA1WithRSAAlgorithmID, sizeof(kSHA1WithRSAAlgorithmID), + &signature.front(), signature.size(), + &public_key_info.front(), public_key_info.size())); + + verifier.VerifyUpdate(reinterpret_cast(data.c_str()), + data.size()); + ASSERT_TRUE(verifier.VerifyFinal()); +} + +TEST(SignatureCreatorTest, SignSHA256DigestTest) { + // Do a verify round trip. + scoped_ptr key_original( + crypto::RSAPrivateKey::Create(1024)); + ASSERT_TRUE(key_original.get()); + + std::vector key_info; + key_original->ExportPrivateKey(&key_info); + scoped_ptr key( + crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_info)); + ASSERT_TRUE(key.get()); + + std::string data("Hello, World!"); + std::string sha256 = crypto::SHA256HashString(data); + // Sign sha256 of the input data. + std::vector signature; + ASSERT_TRUE(crypto::SignatureCreator::Sign( + key.get(), + crypto::SignatureCreator::HashAlgorithm::SHA256, + reinterpret_cast(sha256.c_str()), + sha256.size(), + &signature)); + + std::vector public_key_info; + ASSERT_TRUE(key_original->ExportPublicKey(&public_key_info)); + + // Verify the input data. + crypto::SignatureVerifier verifier; + ASSERT_TRUE(verifier.VerifyInit( + kSHA256WithRSAAlgorithmID, sizeof(kSHA256WithRSAAlgorithmID), + &signature.front(), signature.size(), + &public_key_info.front(), public_key_info.size())); + + verifier.VerifyUpdate(reinterpret_cast(data.c_str()), + data.size()); + ASSERT_TRUE(verifier.VerifyFinal()); +} diff --git a/crypto/signature_verifier.h b/crypto/signature_verifier.h new file mode 100644 index 0000000000000..fbf87d4cc64d8 --- /dev/null +++ b/crypto/signature_verifier.h @@ -0,0 +1,145 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CRYPTO_SIGNATURE_VERIFIER_H_ +#define CRYPTO_SIGNATURE_VERIFIER_H_ + +#include + +#include "build/build_config.h" +#include "base/basictypes.h" +#include "crypto/crypto_export.h" + +#if defined(USE_OPENSSL) +typedef struct env_md_st EVP_MD; +typedef struct evp_pkey_ctx_st EVP_PKEY_CTX; +#else +typedef struct HASHContextStr HASHContext; +typedef struct SECKEYPublicKeyStr SECKEYPublicKey; +typedef struct VFYContextStr VFYContext; +#endif + +namespace crypto { + +// The SignatureVerifier class verifies a signature using a bare public key +// (as opposed to a certificate). +class CRYPTO_EXPORT SignatureVerifier { + public: + // The set of supported hash functions. Extend as required. + enum HashAlgorithm { + SHA1, + SHA256, + }; + + SignatureVerifier(); + ~SignatureVerifier(); + + // Streaming interface: + + // Initiates a signature verification operation. This should be followed + // by one or more VerifyUpdate calls and a VerifyFinal call. + // NOTE: for RSA-PSS signatures, use VerifyInitRSAPSS instead. + // + // The signature algorithm is specified as a DER encoded ASN.1 + // AlgorithmIdentifier structure: + // AlgorithmIdentifier ::= SEQUENCE { + // algorithm OBJECT IDENTIFIER, + // parameters ANY DEFINED BY algorithm OPTIONAL } + // + // The signature is encoded according to the signature algorithm, but it + // must not be further encoded in an ASN.1 BIT STRING. + // Note: An RSA signature is actually a big integer. It must be in + // big-endian byte order. + // + // The public key is specified as a DER encoded ASN.1 SubjectPublicKeyInfo + // structure, which contains not only the public key but also its type + // (algorithm): + // SubjectPublicKeyInfo ::= SEQUENCE { + // algorithm AlgorithmIdentifier, + // subjectPublicKey BIT STRING } + bool VerifyInit(const uint8* signature_algorithm, + int signature_algorithm_len, + const uint8* signature, + int signature_len, + const uint8* public_key_info, + int public_key_info_len); + + // Initiates a RSA-PSS signature verification operation. This should be + // followed by one or more VerifyUpdate calls and a VerifyFinal call. + // + // The RSA-PSS signature algorithm parameters are specified with the + // |hash_alg|, |mask_hash_alg|, and |salt_len| arguments. + // + // An RSA-PSS signature is a nonnegative integer encoded as a byte string + // (of the same length as the RSA modulus) in big-endian byte order. It + // must not be further encoded in an ASN.1 BIT STRING. + // + // The public key is specified as a DER encoded ASN.1 SubjectPublicKeyInfo + // structure, which contains not only the public key but also its type + // (algorithm): + // SubjectPublicKeyInfo ::= SEQUENCE { + // algorithm AlgorithmIdentifier, + // subjectPublicKey BIT STRING } + bool VerifyInitRSAPSS(HashAlgorithm hash_alg, + HashAlgorithm mask_hash_alg, + int salt_len, + const uint8* signature, + int signature_len, + const uint8* public_key_info, + int public_key_info_len); + + // Feeds a piece of the data to the signature verifier. + void VerifyUpdate(const uint8* data_part, int data_part_len); + + // Concludes a signature verification operation. Returns true if the + // signature is valid. Returns false if the signature is invalid or an + // error occurred. + bool VerifyFinal(); + + // Note: we can provide a one-shot interface if there is interest: + // bool Verify(const uint8* data, + // int data_len, + // const uint8* signature_algorithm, + // int signature_algorithm_len, + // const uint8* signature, + // int signature_len, + // const uint8* public_key_info, + // int public_key_info_len); + + private: +#if defined(USE_OPENSSL) + bool CommonInit(const EVP_MD* digest, + const uint8* signature, + int signature_len, + const uint8* public_key_info, + int public_key_info_len, + EVP_PKEY_CTX** pkey_ctx); +#else + static SECKEYPublicKey* DecodePublicKeyInfo(const uint8* public_key_info, + int public_key_info_len); +#endif + + void Reset(); + + std::vector signature_; + +#if defined(USE_OPENSSL) + struct VerifyContext; + VerifyContext* verify_context_; +#else + // Used for all signature types except RSA-PSS. + VFYContext* vfy_context_; + + // Used for RSA-PSS signatures. + HashAlgorithm hash_alg_; + HashAlgorithm mask_hash_alg_; + unsigned int salt_len_; + SECKEYPublicKey* public_key_; + HASHContext* hash_context_; +#endif +}; + +} // namespace crypto + +#endif // CRYPTO_SIGNATURE_VERIFIER_H_ diff --git a/crypto/signature_verifier_nss.cc b/crypto/signature_verifier_nss.cc new file mode 100644 index 0000000000000..5be620da6bd1f --- /dev/null +++ b/crypto/signature_verifier_nss.cc @@ -0,0 +1,226 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/signature_verifier.h" + +#include +#include +#include +#include +#include +#include + +#include "base/logging.h" +#include "crypto/nss_util.h" +#include "crypto/third_party/nss/chromium-nss.h" + +namespace crypto { + +namespace { + +HASH_HashType ToNSSHashType(SignatureVerifier::HashAlgorithm hash_alg) { + switch (hash_alg) { + case SignatureVerifier::SHA1: + return HASH_AlgSHA1; + case SignatureVerifier::SHA256: + return HASH_AlgSHA256; + } + return HASH_AlgNULL; +} + +SECStatus VerifyRSAPSS_End(SECKEYPublicKey* public_key, + HASHContext* hash_context, + HASH_HashType mask_hash_alg, + unsigned int salt_len, + const unsigned char* signature, + unsigned int signature_len) { + unsigned int hash_len = HASH_ResultLenContext(hash_context); + std::vector hash(hash_len); + HASH_End(hash_context, &hash[0], &hash_len, hash.size()); + + unsigned int modulus_len = SECKEY_PublicKeyStrength(public_key); + if (signature_len != modulus_len) { + PORT_SetError(SEC_ERROR_BAD_SIGNATURE); + return SECFailure; + } + std::vector enc(signature_len); + SECStatus rv = PK11_PubEncryptRaw(public_key, &enc[0], + const_cast(signature), + signature_len, NULL); + if (rv != SECSuccess) { + LOG(WARNING) << "PK11_PubEncryptRaw failed"; + return rv; + } + return emsa_pss_verify(&hash[0], &enc[0], enc.size(), + HASH_GetType(hash_context), mask_hash_alg, + salt_len); +} + +} // namespace + +SignatureVerifier::SignatureVerifier() + : vfy_context_(NULL), + hash_alg_(SHA1), + mask_hash_alg_(SHA1), + salt_len_(0), + public_key_(NULL), + hash_context_(NULL) { + EnsureNSSInit(); +} + +SignatureVerifier::~SignatureVerifier() { + Reset(); +} + +bool SignatureVerifier::VerifyInit(const uint8* signature_algorithm, + int signature_algorithm_len, + const uint8* signature, + int signature_len, + const uint8* public_key_info, + int public_key_info_len) { + if (vfy_context_ || hash_context_) + return false; + + signature_.assign(signature, signature + signature_len); + + SECKEYPublicKey* public_key = DecodePublicKeyInfo(public_key_info, + public_key_info_len); + if (!public_key) + return false; + + PLArenaPool* arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (!arena) { + SECKEY_DestroyPublicKey(public_key); + return false; + } + + SECItem sig_alg_der; + sig_alg_der.type = siBuffer; + sig_alg_der.data = const_cast(signature_algorithm); + sig_alg_der.len = signature_algorithm_len; + SECAlgorithmID sig_alg_id; + SECStatus rv; + rv = SEC_QuickDERDecodeItem(arena, &sig_alg_id, + SEC_ASN1_GET(SECOID_AlgorithmIDTemplate), + &sig_alg_der); + if (rv != SECSuccess) { + SECKEY_DestroyPublicKey(public_key); + PORT_FreeArena(arena, PR_TRUE); + return false; + } + + SECItem sig; + sig.type = siBuffer; + sig.data = const_cast(signature); + sig.len = signature_len; + SECOidTag hash_alg_tag; + vfy_context_ = VFY_CreateContextWithAlgorithmID(public_key, &sig, + &sig_alg_id, &hash_alg_tag, + NULL); + SECKEY_DestroyPublicKey(public_key); // Done with public_key. + PORT_FreeArena(arena, PR_TRUE); // Done with sig_alg_id. + if (!vfy_context_) { + // A corrupted RSA signature could be detected without the data, so + // VFY_CreateContextWithAlgorithmID may fail with SEC_ERROR_BAD_SIGNATURE + // (-8182). + return false; + } + + rv = VFY_Begin(vfy_context_); + if (rv != SECSuccess) { + NOTREACHED(); + return false; + } + return true; +} + +bool SignatureVerifier::VerifyInitRSAPSS(HashAlgorithm hash_alg, + HashAlgorithm mask_hash_alg, + int salt_len, + const uint8* signature, + int signature_len, + const uint8* public_key_info, + int public_key_info_len) { + if (vfy_context_ || hash_context_) + return false; + + signature_.assign(signature, signature + signature_len); + + SECKEYPublicKey* public_key = DecodePublicKeyInfo(public_key_info, + public_key_info_len); + if (!public_key) + return false; + + public_key_ = public_key; + hash_alg_ = hash_alg; + mask_hash_alg_ = mask_hash_alg; + salt_len_ = salt_len; + hash_context_ = HASH_Create(ToNSSHashType(hash_alg_)); + if (!hash_context_) + return false; + HASH_Begin(hash_context_); + return true; +} + +void SignatureVerifier::VerifyUpdate(const uint8* data_part, + int data_part_len) { + if (vfy_context_) { + SECStatus rv = VFY_Update(vfy_context_, data_part, data_part_len); + DCHECK_EQ(SECSuccess, rv); + } else { + HASH_Update(hash_context_, data_part, data_part_len); + } +} + +bool SignatureVerifier::VerifyFinal() { + SECStatus rv; + if (vfy_context_) { + rv = VFY_End(vfy_context_); + } else { + rv = VerifyRSAPSS_End(public_key_, hash_context_, + ToNSSHashType(mask_hash_alg_), salt_len_, + signature_.data(), + signature_.size()); + } + Reset(); + + // If signature verification fails, the error code is + // SEC_ERROR_BAD_SIGNATURE (-8182). + return (rv == SECSuccess); +} + +// static +SECKEYPublicKey* SignatureVerifier::DecodePublicKeyInfo( + const uint8* public_key_info, + int public_key_info_len) { + CERTSubjectPublicKeyInfo* spki = NULL; + SECItem spki_der; + spki_der.type = siBuffer; + spki_der.data = const_cast(public_key_info); + spki_der.len = public_key_info_len; + spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_der); + if (!spki) + return NULL; + SECKEYPublicKey* public_key = SECKEY_ExtractPublicKey(spki); + SECKEY_DestroySubjectPublicKeyInfo(spki); // Done with spki. + return public_key; +} + +void SignatureVerifier::Reset() { + if (vfy_context_) { + VFY_DestroyContext(vfy_context_, PR_TRUE); + vfy_context_ = NULL; + } + if (hash_context_) { + HASH_Destroy(hash_context_); + hash_context_ = NULL; + } + if (public_key_) { + SECKEY_DestroyPublicKey(public_key_); + public_key_ = NULL; + } + signature_.clear(); +} + +} // namespace crypto diff --git a/crypto/signature_verifier_openssl.cc b/crypto/signature_verifier_openssl.cc new file mode 100644 index 0000000000000..a33d665ec1320 --- /dev/null +++ b/crypto/signature_verifier_openssl.cc @@ -0,0 +1,160 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/signature_verifier.h" + +#include +#include + +#include + +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "base/stl_util.h" +#include "crypto/openssl_util.h" +#include "crypto/scoped_openssl_types.h" + +namespace crypto { + +namespace { + +const EVP_MD* ToOpenSSLDigest(SignatureVerifier::HashAlgorithm hash_alg) { + switch (hash_alg) { + case SignatureVerifier::SHA1: + return EVP_sha1(); + case SignatureVerifier::SHA256: + return EVP_sha256(); + } + return NULL; +} + +} // namespace + +struct SignatureVerifier::VerifyContext { + ScopedEVP_MD_CTX ctx; +}; + +SignatureVerifier::SignatureVerifier() + : verify_context_(NULL) { +} + +SignatureVerifier::~SignatureVerifier() { + Reset(); +} + +bool SignatureVerifier::VerifyInit(const uint8* signature_algorithm, + int signature_algorithm_len, + const uint8* signature, + int signature_len, + const uint8* public_key_info, + int public_key_info_len) { + OpenSSLErrStackTracer err_tracer(FROM_HERE); + ScopedOpenSSL algorithm( + d2i_X509_ALGOR(NULL, &signature_algorithm, signature_algorithm_len)); + if (!algorithm.get()) + return false; + int nid = OBJ_obj2nid(algorithm.get()->algorithm); + const EVP_MD* digest; + if (nid == NID_ecdsa_with_SHA1) { + digest = EVP_sha1(); + } else if (nid == NID_ecdsa_with_SHA256) { + digest = EVP_sha256(); + } else { + // This works for PKCS #1 v1.5 RSA signatures, but not for ECDSA + // signatures. + digest = EVP_get_digestbyobj(algorithm.get()->algorithm); + } + if (!digest) + return false; + + return CommonInit(digest, signature, signature_len, public_key_info, + public_key_info_len, NULL); +} + +bool SignatureVerifier::VerifyInitRSAPSS(HashAlgorithm hash_alg, + HashAlgorithm mask_hash_alg, + int salt_len, + const uint8* signature, + int signature_len, + const uint8* public_key_info, + int public_key_info_len) { + OpenSSLErrStackTracer err_tracer(FROM_HERE); + const EVP_MD* const digest = ToOpenSSLDigest(hash_alg); + DCHECK(digest); + if (!digest) { + return false; + } + + EVP_PKEY_CTX* pkey_ctx; + if (!CommonInit(digest, signature, signature_len, public_key_info, + public_key_info_len, &pkey_ctx)) { + return false; + } + + int rv = EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING); + if (rv != 1) + return false; + const EVP_MD* const mgf_digest = ToOpenSSLDigest(mask_hash_alg); + DCHECK(mgf_digest); + if (!mgf_digest) { + return false; + } + rv = EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, mgf_digest); + if (rv != 1) + return false; + rv = EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, salt_len); + return rv == 1; +} + +void SignatureVerifier::VerifyUpdate(const uint8* data_part, + int data_part_len) { + DCHECK(verify_context_); + OpenSSLErrStackTracer err_tracer(FROM_HERE); + int rv = EVP_DigestVerifyUpdate(verify_context_->ctx.get(), + data_part, data_part_len); + DCHECK_EQ(rv, 1); +} + +bool SignatureVerifier::VerifyFinal() { + DCHECK(verify_context_); + OpenSSLErrStackTracer err_tracer(FROM_HERE); + int rv = EVP_DigestVerifyFinal(verify_context_->ctx.get(), + vector_as_array(&signature_), + signature_.size()); + DCHECK_EQ(static_cast(!!rv), rv); + Reset(); + return rv == 1; +} + +bool SignatureVerifier::CommonInit(const EVP_MD* digest, + const uint8* signature, + int signature_len, + const uint8* public_key_info, + int public_key_info_len, + EVP_PKEY_CTX** pkey_ctx) { + if (verify_context_) + return false; + + verify_context_ = new VerifyContext; + + signature_.assign(signature, signature + signature_len); + + const uint8_t* ptr = public_key_info; + ScopedEVP_PKEY public_key(d2i_PUBKEY(nullptr, &ptr, public_key_info_len)); + if (!public_key.get() || ptr != public_key_info + public_key_info_len) + return false; + + verify_context_->ctx.reset(EVP_MD_CTX_create()); + int rv = EVP_DigestVerifyInit(verify_context_->ctx.get(), pkey_ctx, + digest, nullptr, public_key.get()); + return rv == 1; +} + +void SignatureVerifier::Reset() { + delete verify_context_; + verify_context_ = NULL; + signature_.clear(); +} + +} // namespace crypto diff --git a/crypto/signature_verifier_unittest.cc b/crypto/signature_verifier_unittest.cc new file mode 100644 index 0000000000000..a661ff7f8ab8c --- /dev/null +++ b/crypto/signature_verifier_unittest.cc @@ -0,0 +1,1167 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/signature_verifier.h" + +#include "base/numerics/safe_conversions.h" +#include "testing/gtest/include/gtest/gtest.h" + +TEST(SignatureVerifierTest, BasicTest) { + // The input data in this test comes from real certificates. + // + // tbs_certificate ("to-be-signed certificate", the part of a certificate + // that is signed), signature_algorithm, and algorithm come from the + // certificate of bugs.webkit.org. + // + // public_key_info comes from the certificate of the issuer, Go Daddy Secure + // Certification Authority. + // + // The bytes in the array initializers are formatted to expose the DER + // encoding of the ASN.1 structures. + + // The data that is signed is the following ASN.1 structure: + // TBSCertificate ::= SEQUENCE { + // ... -- omitted, not important + // } + const uint8 tbs_certificate[1017] = { + 0x30, 0x82, 0x03, 0xf5, // a SEQUENCE of length 1013 (0x3f5) + 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x43, 0xdd, 0x63, 0x30, 0x0d, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, + 0x00, 0x30, 0x81, 0xca, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, + 0x04, 0x08, 0x13, 0x07, 0x41, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x61, 0x31, + 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0a, 0x53, 0x63, + 0x6f, 0x74, 0x74, 0x73, 0x64, 0x61, 0x6c, 0x65, 0x31, 0x1a, 0x30, 0x18, + 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x11, 0x47, 0x6f, 0x44, 0x61, 0x64, + 0x64, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, + 0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x68, + 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x2e, 0x67, 0x6f, 0x64, 0x61, 0x64, + 0x64, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73, + 0x69, 0x74, 0x6f, 0x72, 0x79, 0x31, 0x30, 0x30, 0x2e, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x27, 0x47, 0x6f, 0x20, 0x44, 0x61, 0x64, 0x64, 0x79, + 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x11, 0x30, 0x0f, 0x06, + 0x03, 0x55, 0x04, 0x05, 0x13, 0x08, 0x30, 0x37, 0x39, 0x36, 0x39, 0x32, + 0x38, 0x37, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x38, 0x30, 0x33, 0x31, 0x38, + 0x32, 0x33, 0x33, 0x35, 0x31, 0x39, 0x5a, 0x17, 0x0d, 0x31, 0x31, 0x30, + 0x33, 0x31, 0x38, 0x32, 0x33, 0x33, 0x35, 0x31, 0x39, 0x5a, 0x30, 0x79, + 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, + 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, + 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x12, + 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x43, 0x75, 0x70, + 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, + 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, + 0x6e, 0x63, 0x2e, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0b, + 0x13, 0x0c, 0x4d, 0x61, 0x63, 0x20, 0x4f, 0x53, 0x20, 0x46, 0x6f, 0x72, + 0x67, 0x65, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x0c, 0x2a, 0x2e, 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2e, 0x6f, 0x72, + 0x67, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, + 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xa7, 0x62, 0x79, 0x41, 0xda, 0x28, + 0xf2, 0xc0, 0x4f, 0xe0, 0x25, 0xaa, 0xa1, 0x2e, 0x3b, 0x30, 0x94, 0xb5, + 0xc9, 0x26, 0x3a, 0x1b, 0xe2, 0xd0, 0xcc, 0xa2, 0x95, 0xe2, 0x91, 0xc0, + 0xf0, 0x40, 0x9e, 0x27, 0x6e, 0xbd, 0x6e, 0xde, 0x7c, 0xb6, 0x30, 0x5c, + 0xb8, 0x9b, 0x01, 0x2f, 0x92, 0x04, 0xa1, 0xef, 0x4a, 0xb1, 0x6c, 0xb1, + 0x7e, 0x8e, 0xcd, 0xa6, 0xf4, 0x40, 0x73, 0x1f, 0x2c, 0x96, 0xad, 0xff, + 0x2a, 0x6d, 0x0e, 0xba, 0x52, 0x84, 0x83, 0xb0, 0x39, 0xee, 0xc9, 0x39, + 0xdc, 0x1e, 0x34, 0xd0, 0xd8, 0x5d, 0x7a, 0x09, 0xac, 0xa9, 0xee, 0xca, + 0x65, 0xf6, 0x85, 0x3a, 0x6b, 0xee, 0xe4, 0x5c, 0x5e, 0xf8, 0xda, 0xd1, + 0xce, 0x88, 0x47, 0xcd, 0x06, 0x21, 0xe0, 0xb9, 0x4b, 0xe4, 0x07, 0xcb, + 0x57, 0xdc, 0xca, 0x99, 0x54, 0xf7, 0x0e, 0xd5, 0x17, 0x95, 0x05, 0x2e, + 0xe9, 0xb1, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, 0xce, 0x30, + 0x82, 0x01, 0xca, 0x30, 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, + 0x30, 0x00, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, + 0x02, 0x05, 0xa0, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16, + 0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, + 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x30, 0x57, + 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x50, 0x30, 0x4e, 0x30, 0x4c, 0xa0, + 0x4a, 0xa0, 0x48, 0x86, 0x46, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, + 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, + 0x2e, 0x67, 0x6f, 0x64, 0x61, 0x64, 0x64, 0x79, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x2f, + 0x67, 0x6f, 0x64, 0x61, 0x64, 0x64, 0x79, 0x65, 0x78, 0x74, 0x65, 0x6e, + 0x64, 0x65, 0x64, 0x69, 0x73, 0x73, 0x75, 0x69, 0x6e, 0x67, 0x33, 0x2e, + 0x63, 0x72, 0x6c, 0x30, 0x52, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x4b, + 0x30, 0x49, 0x30, 0x47, 0x06, 0x0b, 0x60, 0x86, 0x48, 0x01, 0x86, 0xfd, + 0x6d, 0x01, 0x07, 0x17, 0x02, 0x30, 0x38, 0x30, 0x36, 0x06, 0x08, 0x2b, + 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x2a, 0x68, 0x74, 0x74, + 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x74, 0x65, 0x73, 0x2e, 0x67, 0x6f, 0x64, 0x61, 0x64, 0x64, 0x79, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, + 0x6f, 0x72, 0x79, 0x30, 0x7f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, + 0x07, 0x01, 0x01, 0x04, 0x73, 0x30, 0x71, 0x30, 0x23, 0x06, 0x08, 0x2b, + 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x17, 0x68, 0x74, 0x74, + 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x67, 0x6f, 0x64, + 0x61, 0x64, 0x64, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x4a, 0x06, 0x08, + 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x3e, 0x68, 0x74, + 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x65, 0x73, 0x2e, 0x67, 0x6f, 0x64, 0x61, 0x64, 0x64, + 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, + 0x74, 0x6f, 0x72, 0x79, 0x2f, 0x67, 0x64, 0x5f, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x2e, 0x63, 0x72, 0x74, + 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x48, + 0xdf, 0x60, 0x32, 0xcc, 0x89, 0x01, 0xb6, 0xdc, 0x2f, 0xe3, 0x73, 0xb5, + 0x9c, 0x16, 0x58, 0x32, 0x68, 0xa9, 0xc3, 0x30, 0x1f, 0x06, 0x03, 0x55, + 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xfd, 0xac, 0x61, 0x32, + 0x93, 0x6c, 0x45, 0xd6, 0xe2, 0xee, 0x85, 0x5f, 0x9a, 0xba, 0xe7, 0x76, + 0x99, 0x68, 0xcc, 0xe7, 0x30, 0x23, 0x06, 0x03, 0x55, 0x1d, 0x11, 0x04, + 0x1c, 0x30, 0x1a, 0x82, 0x0c, 0x2a, 0x2e, 0x77, 0x65, 0x62, 0x6b, 0x69, + 0x74, 0x2e, 0x6f, 0x72, 0x67, 0x82, 0x0a, 0x77, 0x65, 0x62, 0x6b, 0x69, + 0x74, 0x2e, 0x6f, 0x72, 0x67 + }; + + // The signature algorithm is specified as the following ASN.1 structure: + // AlgorithmIdentifier ::= SEQUENCE { + // algorithm OBJECT IDENTIFIER, + // parameters ANY DEFINED BY algorithm OPTIONAL } + // + const uint8 signature_algorithm[15] = { + 0x30, 0x0d, // a SEQUENCE of length 13 (0xd) + 0x06, 0x09, // an OBJECT IDENTIFIER of length 9 + // 1.2.840.113549.1.1.5 - sha1WithRSAEncryption + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, + 0x05, 0x00, // a NULL of length 0 + }; + + // RSA signature, a big integer in the big-endian byte order. + const uint8 signature[256] = { + 0x1e, 0x6a, 0xe7, 0xe0, 0x4f, 0xe7, 0x4d, 0xd0, 0x69, 0x7c, 0xf8, 0x8f, + 0x99, 0xb4, 0x18, 0x95, 0x36, 0x24, 0x0f, 0x0e, 0xa3, 0xea, 0x34, 0x37, + 0xf4, 0x7d, 0xd5, 0x92, 0x35, 0x53, 0x72, 0x76, 0x3f, 0x69, 0xf0, 0x82, + 0x56, 0xe3, 0x94, 0x7a, 0x1d, 0x1a, 0x81, 0xaf, 0x9f, 0xc7, 0x43, 0x01, + 0x64, 0xd3, 0x7c, 0x0d, 0xc8, 0x11, 0x4e, 0x4a, 0xe6, 0x1a, 0xc3, 0x01, + 0x74, 0xe8, 0x35, 0x87, 0x5c, 0x61, 0xaa, 0x8a, 0x46, 0x06, 0xbe, 0x98, + 0x95, 0x24, 0x9e, 0x01, 0xe3, 0xe6, 0xa0, 0x98, 0xee, 0x36, 0x44, 0x56, + 0x8d, 0x23, 0x9c, 0x65, 0xea, 0x55, 0x6a, 0xdf, 0x66, 0xee, 0x45, 0xe8, + 0xa0, 0xe9, 0x7d, 0x9a, 0xba, 0x94, 0xc5, 0xc8, 0xc4, 0x4b, 0x98, 0xff, + 0x9a, 0x01, 0x31, 0x6d, 0xf9, 0x2b, 0x58, 0xe7, 0xe7, 0x2a, 0xc5, 0x4d, + 0xbb, 0xbb, 0xcd, 0x0d, 0x70, 0xe1, 0xad, 0x03, 0xf5, 0xfe, 0xf4, 0x84, + 0x71, 0x08, 0xd2, 0xbc, 0x04, 0x7b, 0x26, 0x1c, 0xa8, 0x0f, 0x9c, 0xd8, + 0x12, 0x6a, 0x6f, 0x2b, 0x67, 0xa1, 0x03, 0x80, 0x9a, 0x11, 0x0b, 0xe9, + 0xe0, 0xb5, 0xb3, 0xb8, 0x19, 0x4e, 0x0c, 0xa4, 0xd9, 0x2b, 0x3b, 0xc2, + 0xca, 0x20, 0xd3, 0x0c, 0xa4, 0xff, 0x93, 0x13, 0x1f, 0xfc, 0xba, 0x94, + 0x93, 0x8c, 0x64, 0x15, 0x2e, 0x28, 0xa9, 0x55, 0x8c, 0x2c, 0x48, 0xd3, + 0xd3, 0xc1, 0x50, 0x69, 0x19, 0xe8, 0x34, 0xd3, 0xf1, 0x04, 0x9f, 0x0a, + 0x7a, 0x21, 0x87, 0xbf, 0xb9, 0x59, 0x37, 0x2e, 0xf4, 0x71, 0xa5, 0x3e, + 0xbe, 0xcd, 0x70, 0x83, 0x18, 0xf8, 0x8a, 0x72, 0x85, 0x45, 0x1f, 0x08, + 0x01, 0x6f, 0x37, 0xf5, 0x2b, 0x7b, 0xea, 0xb9, 0x8b, 0xa3, 0xcc, 0xfd, + 0x35, 0x52, 0xdd, 0x66, 0xde, 0x4f, 0x30, 0xc5, 0x73, 0x81, 0xb6, 0xe8, + 0x3c, 0xd8, 0x48, 0x8a + }; + + // The public key is specified as the following ASN.1 structure: + // SubjectPublicKeyInfo ::= SEQUENCE { + // algorithm AlgorithmIdentifier, + // subjectPublicKey BIT STRING } + const uint8 public_key_info[294] = { + 0x30, 0x82, 0x01, 0x22, // a SEQUENCE of length 290 (0x122) + // algorithm + 0x30, 0x0d, // a SEQUENCE of length 13 + 0x06, 0x09, // an OBJECT IDENTIFIER of length 9 + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, + 0x05, 0x00, // a NULL of length 0 + // subjectPublicKey + 0x03, 0x82, 0x01, 0x0f, // a BIT STRING of length 271 (0x10f) + 0x00, // number of unused bits + 0x30, 0x82, 0x01, 0x0a, // a SEQUENCE of length 266 (0x10a) + // modulus + 0x02, 0x82, 0x01, 0x01, // an INTEGER of length 257 (0x101) + 0x00, 0xc4, 0x2d, 0xd5, 0x15, 0x8c, 0x9c, 0x26, 0x4c, 0xec, + 0x32, 0x35, 0xeb, 0x5f, 0xb8, 0x59, 0x01, 0x5a, 0xa6, 0x61, + 0x81, 0x59, 0x3b, 0x70, 0x63, 0xab, 0xe3, 0xdc, 0x3d, 0xc7, + 0x2a, 0xb8, 0xc9, 0x33, 0xd3, 0x79, 0xe4, 0x3a, 0xed, 0x3c, + 0x30, 0x23, 0x84, 0x8e, 0xb3, 0x30, 0x14, 0xb6, 0xb2, 0x87, + 0xc3, 0x3d, 0x95, 0x54, 0x04, 0x9e, 0xdf, 0x99, 0xdd, 0x0b, + 0x25, 0x1e, 0x21, 0xde, 0x65, 0x29, 0x7e, 0x35, 0xa8, 0xa9, + 0x54, 0xeb, 0xf6, 0xf7, 0x32, 0x39, 0xd4, 0x26, 0x55, 0x95, + 0xad, 0xef, 0xfb, 0xfe, 0x58, 0x86, 0xd7, 0x9e, 0xf4, 0x00, + 0x8d, 0x8c, 0x2a, 0x0c, 0xbd, 0x42, 0x04, 0xce, 0xa7, 0x3f, + 0x04, 0xf6, 0xee, 0x80, 0xf2, 0xaa, 0xef, 0x52, 0xa1, 0x69, + 0x66, 0xda, 0xbe, 0x1a, 0xad, 0x5d, 0xda, 0x2c, 0x66, 0xea, + 0x1a, 0x6b, 0xbb, 0xe5, 0x1a, 0x51, 0x4a, 0x00, 0x2f, 0x48, + 0xc7, 0x98, 0x75, 0xd8, 0xb9, 0x29, 0xc8, 0xee, 0xf8, 0x66, + 0x6d, 0x0a, 0x9c, 0xb3, 0xf3, 0xfc, 0x78, 0x7c, 0xa2, 0xf8, + 0xa3, 0xf2, 0xb5, 0xc3, 0xf3, 0xb9, 0x7a, 0x91, 0xc1, 0xa7, + 0xe6, 0x25, 0x2e, 0x9c, 0xa8, 0xed, 0x12, 0x65, 0x6e, 0x6a, + 0xf6, 0x12, 0x44, 0x53, 0x70, 0x30, 0x95, 0xc3, 0x9c, 0x2b, + 0x58, 0x2b, 0x3d, 0x08, 0x74, 0x4a, 0xf2, 0xbe, 0x51, 0xb0, + 0xbf, 0x87, 0xd0, 0x4c, 0x27, 0x58, 0x6b, 0xb5, 0x35, 0xc5, + 0x9d, 0xaf, 0x17, 0x31, 0xf8, 0x0b, 0x8f, 0xee, 0xad, 0x81, + 0x36, 0x05, 0x89, 0x08, 0x98, 0xcf, 0x3a, 0xaf, 0x25, 0x87, + 0xc0, 0x49, 0xea, 0xa7, 0xfd, 0x67, 0xf7, 0x45, 0x8e, 0x97, + 0xcc, 0x14, 0x39, 0xe2, 0x36, 0x85, 0xb5, 0x7e, 0x1a, 0x37, + 0xfd, 0x16, 0xf6, 0x71, 0x11, 0x9a, 0x74, 0x30, 0x16, 0xfe, + 0x13, 0x94, 0xa3, 0x3f, 0x84, 0x0d, 0x4f, + // public exponent + 0x02, 0x03, // an INTEGER of length 3 + 0x01, 0x00, 0x01 + }; + + // We use the signature verifier to perform four signature verification + // tests. + crypto::SignatureVerifier verifier; + bool ok; + + // Test 1: feed all of the data to the verifier at once (a single + // VerifyUpdate call). + ok = verifier.VerifyInit(signature_algorithm, + sizeof(signature_algorithm), + signature, sizeof(signature), + public_key_info, sizeof(public_key_info)); + EXPECT_TRUE(ok); + verifier.VerifyUpdate(tbs_certificate, sizeof(tbs_certificate)); + ok = verifier.VerifyFinal(); + EXPECT_TRUE(ok); + + // Test 2: feed the data to the verifier in three parts (three VerifyUpdate + // calls). + ok = verifier.VerifyInit(signature_algorithm, + sizeof(signature_algorithm), + signature, sizeof(signature), + public_key_info, sizeof(public_key_info)); + EXPECT_TRUE(ok); + verifier.VerifyUpdate(tbs_certificate, 256); + verifier.VerifyUpdate(tbs_certificate + 256, 256); + verifier.VerifyUpdate(tbs_certificate + 512, sizeof(tbs_certificate) - 512); + ok = verifier.VerifyFinal(); + EXPECT_TRUE(ok); + + // Test 3: verify the signature with incorrect data. + uint8 bad_tbs_certificate[sizeof(tbs_certificate)]; + memcpy(bad_tbs_certificate, tbs_certificate, sizeof(tbs_certificate)); + bad_tbs_certificate[10] += 1; // Corrupt one byte of the data. + ok = verifier.VerifyInit(signature_algorithm, + sizeof(signature_algorithm), + signature, sizeof(signature), + public_key_info, sizeof(public_key_info)); + EXPECT_TRUE(ok); + verifier.VerifyUpdate(bad_tbs_certificate, sizeof(bad_tbs_certificate)); + ok = verifier.VerifyFinal(); + EXPECT_FALSE(ok); + + // Test 4: verify a bad signature. + uint8 bad_signature[sizeof(signature)]; + memcpy(bad_signature, signature, sizeof(signature)); + bad_signature[10] += 1; // Corrupt one byte of the signature. + ok = verifier.VerifyInit(signature_algorithm, + sizeof(signature_algorithm), + bad_signature, sizeof(bad_signature), + public_key_info, sizeof(public_key_info)); + + // A crypto library (e.g., NSS) may detect that the signature is corrupted + // and cause VerifyInit to return false, so it is fine for 'ok' to be false. + if (ok) { + verifier.VerifyUpdate(tbs_certificate, sizeof(tbs_certificate)); + ok = verifier.VerifyFinal(); + EXPECT_FALSE(ok); + } + + // Test 5: import an invalid key. + uint8_t bad_public_key_info[sizeof(public_key_info)]; + memcpy(bad_public_key_info, public_key_info, sizeof(public_key_info)); + bad_public_key_info[0] += 1; // Corrupt part of the SPKI syntax. + ok = verifier.VerifyInit(signature_algorithm, + sizeof(signature_algorithm), + signature, sizeof(signature), + bad_public_key_info, sizeof(bad_public_key_info)); + EXPECT_FALSE(ok); + + // Test 6: import a key with extra data. + uint8_t long_public_key_info[sizeof(public_key_info) + 5]; + memset(long_public_key_info, 0, sizeof(long_public_key_info)); + memcpy(long_public_key_info, public_key_info, sizeof(public_key_info)); + ok = verifier.VerifyInit(signature_algorithm, + sizeof(signature_algorithm), + signature, sizeof(signature), + long_public_key_info, sizeof(long_public_key_info)); + EXPECT_FALSE(ok); +} + +////////////////////////////////////////////////////////////////////// +// +// RSA-PSS signature verification known answer test +// +////////////////////////////////////////////////////////////////////// + +// The following RSA-PSS signature test vectors come from the pss-vect.txt +// file downloaded from +// ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip. +// +// For each key, 6 random messages of length between 1 and 256 octets have +// been RSASSA-PSS signed. +// +// Hash function: SHA-1 +// Mask generation function: MGF1 with SHA-1 +// Salt length: 20 octets + +// Example 1: A 1024-bit RSA Key Pair" + +// RSA modulus n: +static const char rsa_modulus_n_1[] = + "a5 6e 4a 0e 70 10 17 58 9a 51 87 dc 7e a8 41 d1 " + "56 f2 ec 0e 36 ad 52 a4 4d fe b1 e6 1f 7a d9 91 " + "d8 c5 10 56 ff ed b1 62 b4 c0 f2 83 a1 2a 88 a3 " + "94 df f5 26 ab 72 91 cb b3 07 ce ab fc e0 b1 df " + "d5 cd 95 08 09 6d 5b 2b 8b 6d f5 d6 71 ef 63 77 " + "c0 92 1c b2 3c 27 0a 70 e2 59 8e 6f f8 9d 19 f1 " + "05 ac c2 d3 f0 cb 35 f2 92 80 e1 38 6b 6f 64 c4 " + "ef 22 e1 e1 f2 0d 0c e8 cf fb 22 49 bd 9a 21 37 "; +// RSA public exponent e: " +static const char rsa_public_exponent_e_1[] = + "01 00 01 "; + +// RSASSA-PSS Signature Example 1.1 +// Message to be signed: +static const char message_1_1[] = + "cd c8 7d a2 23 d7 86 df 3b 45 e0 bb bc 72 13 26 " + "d1 ee 2a f8 06 cc 31 54 75 cc 6f 0d 9c 66 e1 b6 " + "23 71 d4 5c e2 39 2e 1a c9 28 44 c3 10 10 2f 15 " + "6a 0d 8d 52 c1 f4 c4 0b a3 aa 65 09 57 86 cb 76 " + "97 57 a6 56 3b a9 58 fe d0 bc c9 84 e8 b5 17 a3 " + "d5 f5 15 b2 3b 8a 41 e7 4a a8 67 69 3f 90 df b0 " + "61 a6 e8 6d fa ae e6 44 72 c0 0e 5f 20 94 57 29 " + "cb eb e7 7f 06 ce 78 e0 8f 40 98 fb a4 1f 9d 61 " + "93 c0 31 7e 8b 60 d4 b6 08 4a cb 42 d2 9e 38 08 " + "a3 bc 37 2d 85 e3 31 17 0f cb f7 cc 72 d0 b7 1c " + "29 66 48 b3 a4 d1 0f 41 62 95 d0 80 7a a6 25 ca " + "b2 74 4f d9 ea 8f d2 23 c4 25 37 02 98 28 bd 16 " + "be 02 54 6f 13 0f d2 e3 3b 93 6d 26 76 e0 8a ed " + "1b 73 31 8b 75 0a 01 67 d0 "; +// Salt: +static const char salt_1_1[] = + "de e9 59 c7 e0 64 11 36 14 20 ff 80 18 5e d5 7f " + "3e 67 76 af "; +// Signature: +static const char signature_1_1[] = + "90 74 30 8f b5 98 e9 70 1b 22 94 38 8e 52 f9 71 " + "fa ac 2b 60 a5 14 5a f1 85 df 52 87 b5 ed 28 87 " + "e5 7c e7 fd 44 dc 86 34 e4 07 c8 e0 e4 36 0b c2 " + "26 f3 ec 22 7f 9d 9e 54 63 8e 8d 31 f5 05 12 15 " + "df 6e bb 9c 2f 95 79 aa 77 59 8a 38 f9 14 b5 b9 " + "c1 bd 83 c4 e2 f9 f3 82 a0 d0 aa 35 42 ff ee 65 " + "98 4a 60 1b c6 9e b2 8d eb 27 dc a1 2c 82 c2 d4 " + "c3 f6 6c d5 00 f1 ff 2b 99 4d 8a 4e 30 cb b3 3c "; + +// RSASSA-PSS Signature Example 1.2 +// Message to be signed: +static const char message_1_2[] = + "85 13 84 cd fe 81 9c 22 ed 6c 4c cb 30 da eb 5c " + "f0 59 bc 8e 11 66 b7 e3 53 0c 4c 23 3e 2b 5f 8f " + "71 a1 cc a5 82 d4 3e cc 72 b1 bc a1 6d fc 70 13 " + "22 6b 9e "; +// Salt: +static const char salt_1_2[] = + "ef 28 69 fa 40 c3 46 cb 18 3d ab 3d 7b ff c9 8f " + "d5 6d f4 2d "; +// Signature: +static const char signature_1_2[] = + "3e f7 f4 6e 83 1b f9 2b 32 27 41 42 a5 85 ff ce " + "fb dc a7 b3 2a e9 0d 10 fb 0f 0c 72 99 84 f0 4e " + "f2 9a 9d f0 78 07 75 ce 43 73 9b 97 83 83 90 db " + "0a 55 05 e6 3d e9 27 02 8d 9d 29 b2 19 ca 2c 45 " + "17 83 25 58 a5 5d 69 4a 6d 25 b9 da b6 60 03 c4 " + "cc cd 90 78 02 19 3b e5 17 0d 26 14 7d 37 b9 35 " + "90 24 1b e5 1c 25 05 5f 47 ef 62 75 2c fb e2 14 " + "18 fa fe 98 c2 2c 4d 4d 47 72 4f db 56 69 e8 43 "; + +// RSASSA-PSS Signature Example 1.3 +// Message to be signed: +static const char message_1_3[] = + "a4 b1 59 94 17 61 c4 0c 6a 82 f2 b8 0d 1b 94 f5 " + "aa 26 54 fd 17 e1 2d 58 88 64 67 9b 54 cd 04 ef " + "8b d0 30 12 be 8d c3 7f 4b 83 af 79 63 fa ff 0d " + "fa 22 54 77 43 7c 48 01 7f f2 be 81 91 cf 39 55 " + "fc 07 35 6e ab 3f 32 2f 7f 62 0e 21 d2 54 e5 db " + "43 24 27 9f e0 67 e0 91 0e 2e 81 ca 2c ab 31 c7 " + "45 e6 7a 54 05 8e b5 0d 99 3c db 9e d0 b4 d0 29 " + "c0 6d 21 a9 4c a6 61 c3 ce 27 fa e1 d6 cb 20 f4 " + "56 4d 66 ce 47 67 58 3d 0e 5f 06 02 15 b5 90 17 " + "be 85 ea 84 89 39 12 7b d8 c9 c4 d4 7b 51 05 6c " + "03 1c f3 36 f1 7c 99 80 f3 b8 f5 b9 b6 87 8e 8b " + "79 7a a4 3b 88 26 84 33 3e 17 89 3f e9 ca a6 aa " + "29 9f 7e d1 a1 8e e2 c5 48 64 b7 b2 b9 9b 72 61 " + "8f b0 25 74 d1 39 ef 50 f0 19 c9 ee f4 16 97 13 " + "38 e7 d4 70 "; +// Salt: +static const char salt_1_3[] = + "71 0b 9c 47 47 d8 00 d4 de 87 f1 2a fd ce 6d f1 " + "81 07 cc 77 "; +// Signature: +static const char signature_1_3[] = + "66 60 26 fb a7 1b d3 e7 cf 13 15 7c c2 c5 1a 8e " + "4a a6 84 af 97 78 f9 18 49 f3 43 35 d1 41 c0 01 " + "54 c4 19 76 21 f9 62 4a 67 5b 5a bc 22 ee 7d 5b " + "aa ff aa e1 c9 ba ca 2c c3 73 b3 f3 3e 78 e6 14 " + "3c 39 5a 91 aa 7f ac a6 64 eb 73 3a fd 14 d8 82 " + "72 59 d9 9a 75 50 fa ca 50 1e f2 b0 4e 33 c2 3a " + "a5 1f 4b 9e 82 82 ef db 72 8c c0 ab 09 40 5a 91 " + "60 7c 63 69 96 1b c8 27 0d 2d 4f 39 fc e6 12 b1 "; + +// RSASSA-PSS Signature Example 1.4 +// Message to be signed: +static const char message_1_4[] = + "bc 65 67 47 fa 9e af b3 f0 "; +// Salt: +static const char salt_1_4[] = + "05 6f 00 98 5d e1 4d 8e f5 ce a9 e8 2f 8c 27 be " + "f7 20 33 5e "; +// Signature: +static const char signature_1_4[] = + "46 09 79 3b 23 e9 d0 93 62 dc 21 bb 47 da 0b 4f " + "3a 76 22 64 9a 47 d4 64 01 9b 9a ea fe 53 35 9c " + "17 8c 91 cd 58 ba 6b cb 78 be 03 46 a7 bc 63 7f " + "4b 87 3d 4b ab 38 ee 66 1f 19 96 34 c5 47 a1 ad " + "84 42 e0 3d a0 15 b1 36 e5 43 f7 ab 07 c0 c1 3e " + "42 25 b8 de 8c ce 25 d4 f6 eb 84 00 f8 1f 7e 18 " + "33 b7 ee 6e 33 4d 37 09 64 ca 79 fd b8 72 b4 d7 " + "52 23 b5 ee b0 81 01 59 1f b5 32 d1 55 a6 de 87 "; + +// RSASSA-PSS Signature Example 1.5 +// Message to be signed: +static const char message_1_5[] = + "b4 55 81 54 7e 54 27 77 0c 76 8e 8b 82 b7 55 64 " + "e0 ea 4e 9c 32 59 4d 6b ff 70 65 44 de 0a 87 76 " + "c7 a8 0b 45 76 55 0e ee 1b 2a ca bc 7e 8b 7d 3e " + "f7 bb 5b 03 e4 62 c1 10 47 ea dd 00 62 9a e5 75 " + "48 0a c1 47 0f e0 46 f1 3a 2b f5 af 17 92 1d c4 " + "b0 aa 8b 02 be e6 33 49 11 65 1d 7f 85 25 d1 0f " + "32 b5 1d 33 be 52 0d 3d df 5a 70 99 55 a3 df e7 " + "82 83 b9 e0 ab 54 04 6d 15 0c 17 7f 03 7f dc cc " + "5b e4 ea 5f 68 b5 e5 a3 8c 9d 7e dc cc c4 97 5f " + "45 5a 69 09 b4 "; +// Salt: +static const char salt_1_5[] = + "80 e7 0f f8 6a 08 de 3e c6 09 72 b3 9b 4f bf dc " + "ea 67 ae 8e "; +// Signature: +static const char signature_1_5[] = + "1d 2a ad 22 1c a4 d3 1d df 13 50 92 39 01 93 98 " + "e3 d1 4b 32 dc 34 dc 5a f4 ae ae a3 c0 95 af 73 " + "47 9c f0 a4 5e 56 29 63 5a 53 a0 18 37 76 15 b1 " + "6c b9 b1 3b 3e 09 d6 71 eb 71 e3 87 b8 54 5c 59 " + "60 da 5a 64 77 6e 76 8e 82 b2 c9 35 83 bf 10 4c " + "3f db 23 51 2b 7b 4e 89 f6 33 dd 00 63 a5 30 db " + "45 24 b0 1c 3f 38 4c 09 31 0e 31 5a 79 dc d3 d6 " + "84 02 2a 7f 31 c8 65 a6 64 e3 16 97 8b 75 9f ad "; + +// RSASSA-PSS Signature Example 1.6 +// Message to be signed: +static const char message_1_6[] = + "10 aa e9 a0 ab 0b 59 5d 08 41 20 7b 70 0d 48 d7 " + "5f ae dd e3 b7 75 cd 6b 4c c8 8a e0 6e 46 94 ec " + "74 ba 18 f8 52 0d 4f 5e a6 9c bb e7 cc 2b eb a4 " + "3e fd c1 02 15 ac 4e b3 2d c3 02 a1 f5 3d c6 c4 " + "35 22 67 e7 93 6c fe bf 7c 8d 67 03 57 84 a3 90 " + "9f a8 59 c7 b7 b5 9b 8e 39 c5 c2 34 9f 18 86 b7 " + "05 a3 02 67 d4 02 f7 48 6a b4 f5 8c ad 5d 69 ad " + "b1 7a b8 cd 0c e1 ca f5 02 5a f4 ae 24 b1 fb 87 " + "94 c6 07 0c c0 9a 51 e2 f9 91 13 11 e3 87 7d 00 " + "44 c7 1c 57 a9 93 39 50 08 80 6b 72 3a c3 83 73 " + "d3 95 48 18 18 52 8c 1e 70 53 73 92 82 05 35 29 " + "51 0e 93 5c d0 fa 77 b8 fa 53 cc 2d 47 4b d4 fb " + "3c c5 c6 72 d6 ff dc 90 a0 0f 98 48 71 2c 4b cf " + "e4 6c 60 57 36 59 b1 1e 64 57 e8 61 f0 f6 04 b6 " + "13 8d 14 4f 8c e4 e2 da 73 "; +// Salt: +static const char salt_1_6[] = + "a8 ab 69 dd 80 1f 00 74 c2 a1 fc 60 64 98 36 c6 " + "16 d9 96 81 "; +// Signature: +static const char signature_1_6[] = + "2a 34 f6 12 5e 1f 6b 0b f9 71 e8 4f bd 41 c6 32 " + "be 8f 2c 2a ce 7d e8 b6 92 6e 31 ff 93 e9 af 98 " + "7f bc 06 e5 1e 9b e1 4f 51 98 f9 1f 3f 95 3b d6 " + "7d a6 0a 9d f5 97 64 c3 dc 0f e0 8e 1c be f0 b7 " + "5f 86 8d 10 ad 3f ba 74 9f ef 59 fb 6d ac 46 a0 " + "d6 e5 04 36 93 31 58 6f 58 e4 62 8f 39 aa 27 89 " + "82 54 3b c0 ee b5 37 dc 61 95 80 19 b3 94 fb 27 " + "3f 21 58 58 a0 a0 1a c4 d6 50 b9 55 c6 7f 4c 58 "; + +// Example 9: A 1536-bit RSA Key Pair + +// RSA modulus n: +static const char rsa_modulus_n_9[] = + "e6 bd 69 2a c9 66 45 79 04 03 fd d0 f5 be b8 b9 " + "bf 92 ed 10 00 7f c3 65 04 64 19 dd 06 c0 5c 5b " + "5b 2f 48 ec f9 89 e4 ce 26 91 09 97 9c bb 40 b4 " + "a0 ad 24 d2 24 83 d1 ee 31 5a d4 cc b1 53 42 68 " + "35 26 91 c5 24 f6 dd 8e 6c 29 d2 24 cf 24 69 73 " + "ae c8 6c 5b f6 b1 40 1a 85 0d 1b 9a d1 bb 8c bc " + "ec 47 b0 6f 0f 8c 7f 45 d3 fc 8f 31 92 99 c5 43 " + "3d db c2 b3 05 3b 47 de d2 ec d4 a4 ca ef d6 14 " + "83 3d c8 bb 62 2f 31 7e d0 76 b8 05 7f e8 de 3f " + "84 48 0a d5 e8 3e 4a 61 90 4a 4f 24 8f b3 97 02 " + "73 57 e1 d3 0e 46 31 39 81 5c 6f d4 fd 5a c5 b8 " + "17 2a 45 23 0e cb 63 18 a0 4f 14 55 d8 4e 5a 8b "; +// RSA public exponent e: +static const char rsa_public_exponent_e_9[] = + "01 00 01 "; + +// RSASSA-PSS Signature Example 9.1 +// Message to be signed: +static const char message_9_1[] = + "a8 8e 26 58 55 e9 d7 ca 36 c6 87 95 f0 b3 1b 59 " + "1c d6 58 7c 71 d0 60 a0 b3 f7 f3 ea ef 43 79 59 " + "22 02 8b c2 b6 ad 46 7c fc 2d 7f 65 9c 53 85 aa " + "70 ba 36 72 cd de 4c fe 49 70 cc 79 04 60 1b 27 " + "88 72 bf 51 32 1c 4a 97 2f 3c 95 57 0f 34 45 d4 " + "f5 79 80 e0 f2 0d f5 48 46 e6 a5 2c 66 8f 12 88 " + "c0 3f 95 00 6e a3 2f 56 2d 40 d5 2a f9 fe b3 2f " + "0f a0 6d b6 5b 58 8a 23 7b 34 e5 92 d5 5c f9 79 " + "f9 03 a6 42 ef 64 d2 ed 54 2a a8 c7 7d c1 dd 76 " + "2f 45 a5 93 03 ed 75 e5 41 ca 27 1e 2b 60 ca 70 " + "9e 44 fa 06 61 13 1e 8d 5d 41 63 fd 8d 39 85 66 " + "ce 26 de 87 30 e7 2f 9c ca 73 76 41 c2 44 15 94 " + "20 63 70 28 df 0a 18 07 9d 62 08 ea 8b 47 11 a2 " + "c7 50 f5 "; +// Salt: +static const char salt_9_1[] = + "c0 a4 25 31 3d f8 d7 56 4b d2 43 4d 31 15 23 d5 " + "25 7e ed 80 "; +// Signature: +static const char signature_9_1[] = + "58 61 07 22 6c 3c e0 13 a7 c8 f0 4d 1a 6a 29 59 " + "bb 4b 8e 20 5b a4 3a 27 b5 0f 12 41 11 bc 35 ef " + "58 9b 03 9f 59 32 18 7c b6 96 d7 d9 a3 2c 0c 38 " + "30 0a 5c dd a4 83 4b 62 d2 eb 24 0a f3 3f 79 d1 " + "3d fb f0 95 bf 59 9e 0d 96 86 94 8c 19 64 74 7b " + "67 e8 9c 9a ba 5c d8 50 16 23 6f 56 6c c5 80 2c " + "b1 3e ad 51 bc 7c a6 be f3 b9 4d cb db b1 d5 70 " + "46 97 71 df 0e 00 b1 a8 a0 67 77 47 2d 23 16 27 " + "9e da e8 64 74 66 8d 4e 1e ff f9 5f 1d e6 1c 60 " + "20 da 32 ae 92 bb f1 65 20 fe f3 cf 4d 88 f6 11 " + "21 f2 4b bd 9f e9 1b 59 ca f1 23 5b 2a 93 ff 81 " + "fc 40 3a dd f4 eb de a8 49 34 a9 cd af 8e 1a 9e "; + +// RSASSA-PSS Signature Example 9.2 +// Message to be signed: +static const char message_9_2[] = + "c8 c9 c6 af 04 ac da 41 4d 22 7e f2 3e 08 20 c3 " + "73 2c 50 0d c8 72 75 e9 5b 0d 09 54 13 99 3c 26 " + "58 bc 1d 98 85 81 ba 87 9c 2d 20 1f 14 cb 88 ce " + "d1 53 a0 19 69 a7 bf 0a 7b e7 9c 84 c1 48 6b c1 " + "2b 3f a6 c5 98 71 b6 82 7c 8c e2 53 ca 5f ef a8 " + "a8 c6 90 bf 32 6e 8e 37 cd b9 6d 90 a8 2e ba b6 " + "9f 86 35 0e 18 22 e8 bd 53 6a 2e "; +// Salt: +static const char salt_9_2[] = + "b3 07 c4 3b 48 50 a8 da c2 f1 5f 32 e3 78 39 ef " + "8c 5c 0e 91 "; +// Signature: +static const char signature_9_2[] = + "80 b6 d6 43 25 52 09 f0 a4 56 76 38 97 ac 9e d2 " + "59 d4 59 b4 9c 28 87 e5 88 2e cb 44 34 cf d6 6d " + "d7 e1 69 93 75 38 1e 51 cd 7f 55 4f 2c 27 17 04 " + "b3 99 d4 2b 4b e2 54 0a 0e ca 61 95 1f 55 26 7f " + "7c 28 78 c1 22 84 2d ad b2 8b 01 bd 5f 8c 02 5f " + "7e 22 84 18 a6 73 c0 3d 6b c0 c7 36 d0 a2 95 46 " + "bd 67 f7 86 d9 d6 92 cc ea 77 8d 71 d9 8c 20 63 " + "b7 a7 10 92 18 7a 4d 35 af 10 81 11 d8 3e 83 ea " + "e4 6c 46 aa 34 27 7e 06 04 45 89 90 37 88 f1 d5 " + "e7 ce e2 5f b4 85 e9 29 49 11 88 14 d6 f2 c3 ee " + "36 14 89 01 6f 32 7f b5 bc 51 7e b5 04 70 bf fa " + "1a fa 5f 4c e9 aa 0c e5 b8 ee 19 bf 55 01 b9 58 "; + +// RSASSA-PSS Signature Example 9.3 +// Message to be signed: +static const char message_9_3[] = + "0a fa d4 2c cd 4f c6 06 54 a5 50 02 d2 28 f5 2a " + "4a 5f e0 3b 8b bb 08 ca 82 da ca 55 8b 44 db e1 " + "26 6e 50 c0 e7 45 a3 6d 9d 29 04 e3 40 8a bc d1 " + "fd 56 99 94 06 3f 4a 75 cc 72 f2 fe e2 a0 cd 89 " + "3a 43 af 1c 5b 8b 48 7d f0 a7 16 10 02 4e 4f 6d " + "df 9f 28 ad 08 13 c1 aa b9 1b cb 3c 90 64 d5 ff " + "74 2d ef fe a6 57 09 41 39 36 9e 5e a6 f4 a9 63 " + "19 a5 cc 82 24 14 5b 54 50 62 75 8f ef d1 fe 34 " + "09 ae 16 92 59 c6 cd fd 6b 5f 29 58 e3 14 fa ec " + "be 69 d2 ca ce 58 ee 55 17 9a b9 b3 e6 d1 ec c1 " + "4a 55 7c 5f eb e9 88 59 52 64 fc 5d a1 c5 71 46 " + "2e ca 79 8a 18 a1 a4 94 0c da b4 a3 e9 20 09 cc " + "d4 2e 1e 94 7b 13 14 e3 22 38 a2 de ce 7d 23 a8 " + "9b 5b 30 c7 51 fd 0a 4a 43 0d 2c 54 85 94 "; +// Salt: +static const char salt_9_3[] = + "9a 2b 00 7e 80 97 8b bb 19 2c 35 4e b7 da 9a ed " + "fc 74 db f5 "; +// Signature: +static const char signature_9_3[] = + "48 44 08 f3 89 8c d5 f5 34 83 f8 08 19 ef bf 27 " + "08 c3 4d 27 a8 b2 a6 fa e8 b3 22 f9 24 02 37 f9 " + "81 81 7a ca 18 46 f1 08 4d aa 6d 7c 07 95 f6 e5 " + "bf 1a f5 9c 38 e1 85 84 37 ce 1f 7e c4 19 b9 8c " + "87 36 ad f6 dd 9a 00 b1 80 6d 2b d3 ad 0a 73 77 " + "5e 05 f5 2d fe f3 a5 9a b4 b0 81 43 f0 df 05 cd " + "1a d9 d0 4b ec ec a6 da a4 a2 12 98 03 e2 00 cb " + "c7 77 87 ca f4 c1 d0 66 3a 6c 59 87 b6 05 95 20 " + "19 78 2c af 2e c1 42 6d 68 fb 94 ed 1d 4b e8 16 " + "a7 ed 08 1b 77 e6 ab 33 0b 3f fc 07 38 20 fe cd " + "e3 72 7f cb e2 95 ee 61 a0 50 a3 43 65 86 37 c3 " + "fd 65 9c fb 63 73 6d e3 2d 9f 90 d3 c2 f6 3e ca "; + +// RSASSA-PSS Signature Example 9.4 +// Message to be signed: +static const char message_9_4[] = + "1d fd 43 b4 6c 93 db 82 62 9b da e2 bd 0a 12 b8 " + "82 ea 04 c3 b4 65 f5 cf 93 02 3f 01 05 96 26 db " + "be 99 f2 6b b1 be 94 9d dd d1 6d c7 f3 de bb 19 " + "a1 94 62 7f 0b 22 44 34 df 7d 87 00 e9 e9 8b 06 " + "e3 60 c1 2f db e3 d1 9f 51 c9 68 4e b9 08 9e cb " + "b0 a2 f0 45 03 99 d3 f5 9e ac 72 94 08 5d 04 4f " + "53 93 c6 ce 73 74 23 d8 b8 6c 41 53 70 d3 89 e3 " + "0b 9f 0a 3c 02 d2 5d 00 82 e8 ad 6f 3f 1e f2 4a " + "45 c3 cf 82 b3 83 36 70 63 a4 d4 61 3e 42 64 f0 " + "1b 2d ac 2e 5a a4 20 43 f8 fb 5f 69 fa 87 1d 14 " + "fb 27 3e 76 7a 53 1c 40 f0 2f 34 3b c2 fb 45 a0 " + "c7 e0 f6 be 25 61 92 3a 77 21 1d 66 a6 e2 db b4 " + "3c 36 63 50 be ae 22 da 3a c2 c1 f5 07 70 96 fc " + "b5 c4 bf 25 5f 75 74 35 1a e0 b1 e1 f0 36 32 81 " + "7c 08 56 d4 a8 ba 97 af bd c8 b8 58 55 40 2b c5 " + "69 26 fc ec 20 9f 9e a8 "; +// Salt: +static const char salt_9_4[] = + "70 f3 82 bd df 4d 5d 2d d8 8b 3b c7 b7 30 8b e6 " + "32 b8 40 45 "; +// Signature: +static const char signature_9_4[] = + "84 eb eb 48 1b e5 98 45 b4 64 68 ba fb 47 1c 01 " + "12 e0 2b 23 5d 84 b5 d9 11 cb d1 92 6e e5 07 4a " + "e0 42 44 95 cb 20 e8 23 08 b8 eb b6 5f 41 9a 03 " + "fb 40 e7 2b 78 98 1d 88 aa d1 43 05 36 85 17 2c " + "97 b2 9c 8b 7b f0 ae 73 b5 b2 26 3c 40 3d a0 ed " + "2f 80 ff 74 50 af 78 28 eb 8b 86 f0 02 8b d2 a8 " + "b1 76 a4 d2 28 cc ce a1 83 94 f2 38 b0 9f f7 58 " + "cc 00 bc 04 30 11 52 35 57 42 f2 82 b5 4e 66 3a " + "91 9e 70 9d 8d a2 4a de 55 00 a7 b9 aa 50 22 6e " + "0c a5 29 23 e6 c2 d8 60 ec 50 ff 48 0f a5 74 77 " + "e8 2b 05 65 f4 37 9f 79 c7 72 d5 c2 da 80 af 9f " + "bf 32 5e ce 6f c2 0b 00 96 16 14 be e8 9a 18 3e "; + +// RSASSA-PSS Signature Example 9.5 +// Message to be signed: +static const char message_9_5[] = + "1b dc 6e 7c 98 fb 8c f5 4e 9b 09 7b 66 a8 31 e9 " + "cf e5 2d 9d 48 88 44 8e e4 b0 97 80 93 ba 1d 7d " + "73 ae 78 b3 a6 2b a4 ad 95 cd 28 9c cb 9e 00 52 " + "26 bb 3d 17 8b cc aa 82 1f b0 44 a4 e2 1e e9 76 " + "96 c1 4d 06 78 c9 4c 2d ae 93 b0 ad 73 92 22 18 " + "55 3d aa 7e 44 eb e5 77 25 a7 a4 5c c7 2b 9b 21 " + "38 a6 b1 7c 8d b4 11 ce 82 79 ee 12 41 af f0 a8 " + "be c6 f7 7f 87 ed b0 c6 9c b2 72 36 e3 43 5a 80 " + "0b 19 2e 4f 11 e5 19 e3 fe 30 fc 30 ea cc ca 4f " + "bb 41 76 90 29 bf 70 8e 81 7a 9e 68 38 05 be 67 " + "fa 10 09 84 68 3b 74 83 8e 3b cf fa 79 36 6e ed " + "1d 48 1c 76 72 91 18 83 8f 31 ba 8a 04 8a 93 c1 " + "be 44 24 59 8e 8d f6 32 8b 7a 77 88 0a 3f 9c 7e " + "2e 8d fc a8 eb 5a 26 fb 86 bd c5 56 d4 2b be 01 " + "d9 fa 6e d8 06 46 49 1c 93 41 "; +// Salt: +static const char salt_9_5[] = + "d6 89 25 7a 86 ef fa 68 21 2c 5e 0c 61 9e ca 29 " + "5f b9 1b 67 "; +// Signature: +static const char signature_9_5[] = + "82 10 2d f8 cb 91 e7 17 99 19 a0 4d 26 d3 35 d6 " + "4f bc 2f 87 2c 44 83 39 43 24 1d e8 45 48 10 27 " + "4c df 3d b5 f4 2d 42 3d b1 52 af 71 35 f7 01 42 " + "0e 39 b4 94 a6 7c bf d1 9f 91 19 da 23 3a 23 da " + "5c 64 39 b5 ba 0d 2b c3 73 ee e3 50 70 01 37 8d " + "4a 40 73 85 6b 7f e2 ab a0 b5 ee 93 b2 7f 4a fe " + "c7 d4 d1 20 92 1c 83 f6 06 76 5b 02 c1 9e 4d 6a " + "1a 3b 95 fa 4c 42 29 51 be 4f 52 13 10 77 ef 17 " + "17 97 29 cd df bd b5 69 50 db ac ee fe 78 cb 16 " + "64 0a 09 9e a5 6d 24 38 9e ef 10 f8 fe cb 31 ba " + "3e a3 b2 27 c0 a8 66 98 bb 89 e3 e9 36 39 05 bf " + "22 77 7b 2a 3a a5 21 b6 5b 4c ef 76 d8 3b de 4c "; + +// RSASSA-PSS Signature Example 9.6 +// Message to be signed: +static const char message_9_6[] = + "88 c7 a9 f1 36 04 01 d9 0e 53 b1 01 b6 1c 53 25 " + "c3 c7 5d b1 b4 11 fb eb 8e 83 0b 75 e9 6b 56 67 " + "0a d2 45 40 4e 16 79 35 44 ee 35 4b c6 13 a9 0c " + "c9 84 87 15 a7 3d b5 89 3e 7f 6d 27 98 15 c0 c1 " + "de 83 ef 8e 29 56 e3 a5 6e d2 6a 88 8d 7a 9c dc " + "d0 42 f4 b1 6b 7f a5 1e f1 a0 57 36 62 d1 6a 30 " + "2d 0e c5 b2 85 d2 e0 3a d9 65 29 c8 7b 3d 37 4d " + "b3 72 d9 5b 24 43 d0 61 b6 b1 a3 50 ba 87 80 7e " + "d0 83 af d1 eb 05 c3 f5 2f 4e ba 5e d2 22 77 14 " + "fd b5 0b 9d 9d 9d d6 81 4f 62 f6 27 2f cd 5c db " + "ce 7a 9e f7 97 "; +// Salt: +static const char salt_9_6[] = + "c2 5f 13 bf 67 d0 81 67 1a 04 81 a1 f1 82 0d 61 " + "3b ba 22 76 "; +// Signature: +static const char signature_9_6[] = + "a7 fd b0 d2 59 16 5c a2 c8 8d 00 bb f1 02 8a 86 " + "7d 33 76 99 d0 61 19 3b 17 a9 64 8e 14 cc bb aa " + "de ac aa cd ec 81 5e 75 71 29 4e bb 8a 11 7a f2 " + "05 fa 07 8b 47 b0 71 2c 19 9e 3a d0 51 35 c5 04 " + "c2 4b 81 70 51 15 74 08 02 48 79 92 ff d5 11 d4 " + "af c6 b8 54 49 1e b3 f0 dd 52 31 39 54 2f f1 5c " + "31 01 ee 85 54 35 17 c6 a3 c7 94 17 c6 7e 2d d9 " + "aa 74 1e 9a 29 b0 6d cb 59 3c 23 36 b3 67 0a e3 " + "af ba c7 c3 e7 6e 21 54 73 e8 66 e3 38 ca 24 4d " + "e0 0b 62 62 4d 6b 94 26 82 2c ea e9 f8 cc 46 08 " + "95 f4 12 50 07 3f d4 5c 5a 1e 7b 42 5c 20 4a 42 " + "3a 69 91 59 f6 90 3e 71 0b 37 a7 bb 2b c8 04 9f "; + +// Example 10: A 2048-bit RSA Key Pair + +// RSA modulus n: +static const char rsa_modulus_n_10[] = + "a5 dd 86 7a c4 cb 02 f9 0b 94 57 d4 8c 14 a7 70 " + "ef 99 1c 56 c3 9c 0e c6 5f d1 1a fa 89 37 ce a5 " + "7b 9b e7 ac 73 b4 5c 00 17 61 5b 82 d6 22 e3 18 " + "75 3b 60 27 c0 fd 15 7b e1 2f 80 90 fe e2 a7 ad " + "cd 0e ef 75 9f 88 ba 49 97 c7 a4 2d 58 c9 aa 12 " + "cb 99 ae 00 1f e5 21 c1 3b b5 43 14 45 a8 d5 ae " + "4f 5e 4c 7e 94 8a c2 27 d3 60 40 71 f2 0e 57 7e " + "90 5f be b1 5d fa f0 6d 1d e5 ae 62 53 d6 3a 6a " + "21 20 b3 1a 5d a5 da bc 95 50 60 0e 20 f2 7d 37 " + "39 e2 62 79 25 fe a3 cc 50 9f 21 df f0 4e 6e ea " + "45 49 c5 40 d6 80 9f f9 30 7e ed e9 1f ff 58 73 " + "3d 83 85 a2 37 d6 d3 70 5a 33 e3 91 90 09 92 07 " + "0d f7 ad f1 35 7c f7 e3 70 0c e3 66 7d e8 3f 17 " + "b8 df 17 78 db 38 1d ce 09 cb 4a d0 58 a5 11 00 " + "1a 73 81 98 ee 27 cf 55 a1 3b 75 45 39 90 65 82 " + "ec 8b 17 4b d5 8d 5d 1f 3d 76 7c 61 37 21 ae 05 "; +// RSA public exponent e: +static const char rsa_public_exponent_e_10[] = + "01 00 01 "; + +// RSASSA-PSS Signature Example 10.1 +// Message to be signed: +static const char message_10_1[] = + "88 31 77 e5 12 6b 9b e2 d9 a9 68 03 27 d5 37 0c " + "6f 26 86 1f 58 20 c4 3d a6 7a 3a d6 09 "; +// Salt: +static const char salt_10_1[] = + "04 e2 15 ee 6f f9 34 b9 da 70 d7 73 0c 87 34 ab " + "fc ec de 89 "; +// Signature: +static const char signature_10_1[] = + "82 c2 b1 60 09 3b 8a a3 c0 f7 52 2b 19 f8 73 54 " + "06 6c 77 84 7a bf 2a 9f ce 54 2d 0e 84 e9 20 c5 " + "af b4 9f fd fd ac e1 65 60 ee 94 a1 36 96 01 14 " + "8e ba d7 a0 e1 51 cf 16 33 17 91 a5 72 7d 05 f2 " + "1e 74 e7 eb 81 14 40 20 69 35 d7 44 76 5a 15 e7 " + "9f 01 5c b6 6c 53 2c 87 a6 a0 59 61 c8 bf ad 74 " + "1a 9a 66 57 02 28 94 39 3e 72 23 73 97 96 c0 2a " + "77 45 5d 0f 55 5b 0e c0 1d df 25 9b 62 07 fd 0f " + "d5 76 14 ce f1 a5 57 3b aa ff 4e c0 00 69 95 16 " + "59 b8 5f 24 30 0a 25 16 0c a8 52 2d c6 e6 72 7e " + "57 d0 19 d7 e6 36 29 b8 fe 5e 89 e2 5c c1 5b eb " + "3a 64 75 77 55 92 99 28 0b 9b 28 f7 9b 04 09 00 " + "0b e2 5b bd 96 40 8b a3 b4 3c c4 86 18 4d d1 c8 " + "e6 25 53 fa 1a f4 04 0f 60 66 3d e7 f5 e4 9c 04 " + "38 8e 25 7f 1c e8 9c 95 da b4 8a 31 5d 9b 66 b1 " + "b7 62 82 33 87 6f f2 38 52 30 d0 70 d0 7e 16 66 "; + +// RSASSA-PSS Signature Example 10.2 +// Message to be signed: +static const char message_10_2[] = + "dd 67 0a 01 46 58 68 ad c9 3f 26 13 19 57 a5 0c " + "52 fb 77 7c db aa 30 89 2c 9e 12 36 11 64 ec 13 " + "97 9d 43 04 81 18 e4 44 5d b8 7b ee 58 dd 98 7b " + "34 25 d0 20 71 d8 db ae 80 70 8b 03 9d bb 64 db " + "d1 de 56 57 d9 fe d0 c1 18 a5 41 43 74 2e 0f f3 " + "c8 7f 74 e4 58 57 64 7a f3 f7 9e b0 a1 4c 9d 75 " + "ea 9a 1a 04 b7 cf 47 8a 89 7a 70 8f d9 88 f4 8e " + "80 1e db 0b 70 39 df 8c 23 bb 3c 56 f4 e8 21 ac "; +// Salt: +static const char salt_10_2[] = + "8b 2b dd 4b 40 fa f5 45 c7 78 dd f9 bc 1a 49 cb " + "57 f9 b7 1b "; +// Signature: +static const char signature_10_2[] = + "14 ae 35 d9 dd 06 ba 92 f7 f3 b8 97 97 8a ed 7c " + "d4 bf 5f f0 b5 85 a4 0b d4 6c e1 b4 2c d2 70 30 " + "53 bb 90 44 d6 4e 81 3d 8f 96 db 2d d7 00 7d 10 " + "11 8f 6f 8f 84 96 09 7a d7 5e 1f f6 92 34 1b 28 " + "92 ad 55 a6 33 a1 c5 5e 7f 0a 0a d5 9a 0e 20 3a " + "5b 82 78 ae c5 4d d8 62 2e 28 31 d8 71 74 f8 ca " + "ff 43 ee 6c 46 44 53 45 d8 4a 59 65 9b fb 92 ec " + "d4 c8 18 66 86 95 f3 47 06 f6 68 28 a8 99 59 63 " + "7f 2b f3 e3 25 1c 24 bd ba 4d 4b 76 49 da 00 22 " + "21 8b 11 9c 84 e7 9a 65 27 ec 5b 8a 5f 86 1c 15 " + "99 52 e2 3e c0 5e 1e 71 73 46 fa ef e8 b1 68 68 " + "25 bd 2b 26 2f b2 53 10 66 c0 de 09 ac de 2e 42 " + "31 69 07 28 b5 d8 5e 11 5a 2f 6b 92 b7 9c 25 ab " + "c9 bd 93 99 ff 8b cf 82 5a 52 ea 1f 56 ea 76 dd " + "26 f4 3b aa fa 18 bf a9 2a 50 4c bd 35 69 9e 26 " + "d1 dc c5 a2 88 73 85 f3 c6 32 32 f0 6f 32 44 c3 "; + +// RSASSA-PSS Signature Example 10.3 +// Message to be signed: +static const char message_10_3[] = + "48 b2 b6 a5 7a 63 c8 4c ea 85 9d 65 c6 68 28 4b " + "08 d9 6b dc aa be 25 2d b0 e4 a9 6c b1 ba c6 01 " + "93 41 db 6f be fb 8d 10 6b 0e 90 ed a6 bc c6 c6 " + "26 2f 37 e7 ea 9c 7e 5d 22 6b d7 df 85 ec 5e 71 " + "ef ff 2f 54 c5 db 57 7f f7 29 ff 91 b8 42 49 1d " + "e2 74 1d 0c 63 16 07 df 58 6b 90 5b 23 b9 1a f1 " + "3d a1 23 04 bf 83 ec a8 a7 3e 87 1f f9 db "; +// Salt: +static const char salt_10_3[] = + "4e 96 fc 1b 39 8f 92 b4 46 71 01 0c 0d c3 ef d6 " + "e2 0c 2d 73 "; +// Signature: +static const char signature_10_3[] = + "6e 3e 4d 7b 6b 15 d2 fb 46 01 3b 89 00 aa 5b bb " + "39 39 cf 2c 09 57 17 98 70 42 02 6e e6 2c 74 c5 " + "4c ff d5 d7 d5 7e fb bf 95 0a 0f 5c 57 4f a0 9d " + "3f c1 c9 f5 13 b0 5b 4f f5 0d d8 df 7e df a2 01 " + "02 85 4c 35 e5 92 18 01 19 a7 0c e5 b0 85 18 2a " + "a0 2d 9e a2 aa 90 d1 df 03 f2 da ae 88 5b a2 f5 " + "d0 5a fd ac 97 47 6f 06 b9 3b 5b c9 4a 1a 80 aa " + "91 16 c4 d6 15 f3 33 b0 98 89 2b 25 ff ac e2 66 " + "f5 db 5a 5a 3b cc 10 a8 24 ed 55 aa d3 5b 72 78 " + "34 fb 8c 07 da 28 fc f4 16 a5 d9 b2 22 4f 1f 8b " + "44 2b 36 f9 1e 45 6f de a2 d7 cf e3 36 72 68 de " + "03 07 a4 c7 4e 92 41 59 ed 33 39 3d 5e 06 55 53 " + "1c 77 32 7b 89 82 1b de df 88 01 61 c7 8c d4 19 " + "6b 54 19 f7 ac c3 f1 3e 5e bf 16 1b 6e 7c 67 24 " + "71 6c a3 3b 85 c2 e2 56 40 19 2a c2 85 96 51 d5 " + "0b de 7e b9 76 e5 1c ec 82 8b 98 b6 56 3b 86 bb "; + +// RSASSA-PSS Signature Example 10.4 +// Message to be signed: +static const char message_10_4[] = + "0b 87 77 c7 f8 39 ba f0 a6 4b bb db c5 ce 79 75 " + "5c 57 a2 05 b8 45 c1 74 e2 d2 e9 05 46 a0 89 c4 " + "e6 ec 8a df fa 23 a7 ea 97 ba e6 b6 5d 78 2b 82 " + "db 5d 2b 5a 56 d2 2a 29 a0 5e 7c 44 33 e2 b8 2a " + "62 1a bb a9 0a dd 05 ce 39 3f c4 8a 84 05 42 45 " + "1a "; +// Salt: +static const char salt_10_4[] = + "c7 cd 69 8d 84 b6 51 28 d8 83 5e 3a 8b 1e b0 e0 " + "1c b5 41 ec "; +// Signature: +static const char signature_10_4[] = + "34 04 7f f9 6c 4d c0 dc 90 b2 d4 ff 59 a1 a3 61 " + "a4 75 4b 25 5d 2e e0 af 7d 8b f8 7c 9b c9 e7 dd " + "ee de 33 93 4c 63 ca 1c 0e 3d 26 2c b1 45 ef 93 " + "2a 1f 2c 0a 99 7a a6 a3 4f 8e ae e7 47 7d 82 cc " + "f0 90 95 a6 b8 ac ad 38 d4 ee c9 fb 7e ab 7a d0 " + "2d a1 d1 1d 8e 54 c1 82 5e 55 bf 58 c2 a2 32 34 " + "b9 02 be 12 4f 9e 90 38 a8 f6 8f a4 5d ab 72 f6 " + "6e 09 45 bf 1d 8b ac c9 04 4c 6f 07 09 8c 9f ce " + "c5 8a 3a ab 10 0c 80 51 78 15 5f 03 0a 12 4c 45 " + "0e 5a cb da 47 d0 e4 f1 0b 80 a2 3f 80 3e 77 4d " + "02 3b 00 15 c2 0b 9f 9b be 7c 91 29 63 38 d5 ec " + "b4 71 ca fb 03 20 07 b6 7a 60 be 5f 69 50 4a 9f " + "01 ab b3 cb 46 7b 26 0e 2b ce 86 0b e8 d9 5b f9 " + "2c 0c 8e 14 96 ed 1e 52 85 93 a4 ab b6 df 46 2d " + "de 8a 09 68 df fe 46 83 11 68 57 a2 32 f5 eb f6 " + "c8 5b e2 38 74 5a d0 f3 8f 76 7a 5f db f4 86 fb "; + +// RSASSA-PSS Signature Example 10.5 +// Message to be signed: +static const char message_10_5[] = + "f1 03 6e 00 8e 71 e9 64 da dc 92 19 ed 30 e1 7f " + "06 b4 b6 8a 95 5c 16 b3 12 b1 ed df 02 8b 74 97 " + "6b ed 6b 3f 6a 63 d4 e7 78 59 24 3c 9c cc dc 98 " + "01 65 23 ab b0 24 83 b3 55 91 c3 3a ad 81 21 3b " + "b7 c7 bb 1a 47 0a ab c1 0d 44 25 6c 4d 45 59 d9 " + "16 "; +// Salt: +static const char salt_10_5[] = + "ef a8 bf f9 62 12 b2 f4 a3 f3 71 a1 0d 57 41 52 " + "65 5f 5d fb "; +// Signature: +static const char signature_10_5[] = + "7e 09 35 ea 18 f4 d6 c1 d1 7c e8 2e b2 b3 83 6c " + "55 b3 84 58 9c e1 9d fe 74 33 63 ac 99 48 d1 f3 " + "46 b7 bf dd fe 92 ef d7 8a db 21 fa ef c8 9a de " + "42 b1 0f 37 40 03 fe 12 2e 67 42 9a 1c b8 cb d1 " + "f8 d9 01 45 64 c4 4d 12 01 16 f4 99 0f 1a 6e 38 " + "77 4c 19 4b d1 b8 21 32 86 b0 77 b0 49 9d 2e 7b " + "3f 43 4a b1 22 89 c5 56 68 4d ee d7 81 31 93 4b " + "b3 dd 65 37 23 6f 7c 6f 3d cb 09 d4 76 be 07 72 " + "1e 37 e1 ce ed 9b 2f 7b 40 68 87 bd 53 15 73 05 " + "e1 c8 b4 f8 4d 73 3b c1 e1 86 fe 06 cc 59 b6 ed " + "b8 f4 bd 7f fe fd f4 f7 ba 9c fb 9d 57 06 89 b5 " + "a1 a4 10 9a 74 6a 69 08 93 db 37 99 25 5a 0c b9 " + "21 5d 2d 1c d4 90 59 0e 95 2e 8c 87 86 aa 00 11 " + "26 52 52 47 0c 04 1d fb c3 ee c7 c3 cb f7 1c 24 " + "86 9d 11 5c 0c b4 a9 56 f5 6d 53 0b 80 ab 58 9a " + "cf ef c6 90 75 1d df 36 e8 d3 83 f8 3c ed d2 cc "; + +// RSASSA-PSS Signature Example 10.6 +// Message to be signed: +static const char message_10_6[] = + "25 f1 08 95 a8 77 16 c1 37 45 0b b9 51 9d fa a1 " + "f2 07 fa a9 42 ea 88 ab f7 1e 9c 17 98 00 85 b5 " + "55 ae ba b7 62 64 ae 2a 3a b9 3c 2d 12 98 11 91 " + "dd ac 6f b5 94 9e b3 6a ee 3c 5d a9 40 f0 07 52 " + "c9 16 d9 46 08 fa 7d 97 ba 6a 29 15 b6 88 f2 03 " + "23 d4 e9 d9 68 01 d8 9a 72 ab 58 92 dc 21 17 c0 " + "74 34 fc f9 72 e0 58 cf 8c 41 ca 4b 4f f5 54 f7 " + "d5 06 8a d3 15 5f ce d0 f3 12 5b c0 4f 91 93 37 " + "8a 8f 5c 4c 3b 8c b4 dd 6d 1c c6 9d 30 ec ca 6e " + "aa 51 e3 6a 05 73 0e 9e 34 2e 85 5b af 09 9d ef " + "b8 af d7 "; +// Salt: +static const char salt_10_6[] = + "ad 8b 15 23 70 36 46 22 4b 66 0b 55 08 85 91 7c " + "a2 d1 df 28 "; +// Signature: +static const char signature_10_6[] = + "6d 3b 5b 87 f6 7e a6 57 af 21 f7 54 41 97 7d 21 " + "80 f9 1b 2c 5f 69 2d e8 29 55 69 6a 68 67 30 d9 " + "b9 77 8d 97 07 58 cc b2 60 71 c2 20 9f fb d6 12 " + "5b e2 e9 6e a8 1b 67 cb 9b 93 08 23 9f da 17 f7 " + "b2 b6 4e cd a0 96 b6 b9 35 64 0a 5a 1c b4 2a 91 " + "55 b1 c9 ef 7a 63 3a 02 c5 9f 0d 6e e5 9b 85 2c " + "43 b3 50 29 e7 3c 94 0f f0 41 0e 8f 11 4e ed 46 " + "bb d0 fa e1 65 e4 2b e2 52 8a 40 1c 3b 28 fd 81 " + "8e f3 23 2d ca 9f 4d 2a 0f 51 66 ec 59 c4 23 96 " + "d6 c1 1d bc 12 15 a5 6f a1 71 69 db 95 75 34 3e " + "f3 4f 9d e3 2a 49 cd c3 17 49 22 f2 29 c2 3e 18 " + "e4 5d f9 35 31 19 ec 43 19 ce dc e7 a1 7c 64 08 " + "8c 1f 6f 52 be 29 63 41 00 b3 91 9d 38 f3 d1 ed " + "94 e6 89 1e 66 a7 3b 8f b8 49 f5 87 4d f5 94 59 " + "e2 98 c7 bb ce 2e ee 78 2a 19 5a a6 6f e2 d0 73 " + "2b 25 e5 95 f5 7d 3e 06 1b 1f c3 e4 06 3b f9 8f "; + +struct SignatureExample { + const char* message; + const char* salt; + const char* signature; +}; + +struct PSSTestVector { + const char* modulus_n; + const char* public_exponent_e; + SignatureExample example[6]; +}; + +static const PSSTestVector pss_test[] = { + { + rsa_modulus_n_1, + rsa_public_exponent_e_1, + { + { message_1_1, salt_1_1, signature_1_1 }, + { message_1_2, salt_1_2, signature_1_2 }, + { message_1_3, salt_1_3, signature_1_3 }, + { message_1_4, salt_1_4, signature_1_4 }, + { message_1_5, salt_1_5, signature_1_5 }, + { message_1_6, salt_1_6, signature_1_6 }, + } + }, + { + rsa_modulus_n_9, + rsa_public_exponent_e_9, + { + { message_9_1, salt_9_1, signature_9_1 }, + { message_9_2, salt_9_2, signature_9_2 }, + { message_9_3, salt_9_3, signature_9_3 }, + { message_9_4, salt_9_4, signature_9_4 }, + { message_9_5, salt_9_5, signature_9_5 }, + { message_9_6, salt_9_6, signature_9_6 }, + } + }, + { + rsa_modulus_n_10, + rsa_public_exponent_e_10, + { + { message_10_1, salt_10_1, signature_10_1 }, + { message_10_2, salt_10_2, signature_10_2 }, + { message_10_3, salt_10_3, signature_10_3 }, + { message_10_4, salt_10_4, signature_10_4 }, + { message_10_5, salt_10_5, signature_10_5 }, + { message_10_6, salt_10_6, signature_10_6 }, + } + }, +}; + +static uint8 HexDigitValue(char digit) { + if ('0' <= digit && digit <= '9') + return digit - '0'; + if ('a' <= digit && digit <= 'f') + return digit - 'a' + 10; + return digit - 'A' + 10; +} + +static bool DecodeTestInput(const char* in, std::vector* out) { + out->clear(); + while (in[0] != '\0') { + if (!isxdigit(in[0]) || !isxdigit(in[1]) || in[2] != ' ') + return false; + uint8 octet = HexDigitValue(in[0]) * 16 + HexDigitValue(in[1]); + out->push_back(octet); + in += 3; + } + return true; +} + +// PrependASN1Length prepends an ASN.1 serialized length to the beginning of +// |out|. +static void PrependASN1Length(std::vector* out, size_t len) { + if (len < 128) { + out->insert(out->begin(), static_cast(len)); + } else if (len < 256) { + out->insert(out->begin(), static_cast(len)); + out->insert(out->begin(), 0x81); + } else if (len < 0x10000) { + out->insert(out->begin(), static_cast(len)); + out->insert(out->begin(), static_cast(len >> 8)); + out->insert(out->begin(), 0x82); + } else { + CHECK(false) << "ASN.1 length not handled: " << len; + } +} + +static bool EncodeRSAPublicKey(const std::vector& modulus_n, + const std::vector& public_exponent_e, + std::vector* public_key_info) { + // The public key is specified as the following ASN.1 structure: + // SubjectPublicKeyInfo ::= SEQUENCE { + // algorithm AlgorithmIdentifier, + // subjectPublicKey BIT STRING } + // + // The signature algorithm is specified as the following ASN.1 structure: + // AlgorithmIdentifier ::= SEQUENCE { + // algorithm OBJECT IDENTIFIER, + // parameters ANY DEFINED BY algorithm OPTIONAL } + // + // An RSA public key is specified as the following ASN.1 structure: + // RSAPublicKey ::= SEQUENCE { + // modulus INTEGER, -- n + // publicExponent INTEGER -- e + // } + static const uint8 kIntegerTag = 0x02; + static const uint8 kBitStringTag = 0x03; + static const uint8 kSequenceTag = 0x30; + public_key_info->clear(); + + // Encode the public exponent e as an INTEGER. + public_key_info->insert(public_key_info->begin(), + public_exponent_e.begin(), + public_exponent_e.end()); + PrependASN1Length(public_key_info, public_exponent_e.size()); + public_key_info->insert(public_key_info->begin(), kIntegerTag); + + // Encode the modulus n as an INTEGER. + public_key_info->insert(public_key_info->begin(), + modulus_n.begin(), modulus_n.end()); + size_t modulus_size = modulus_n.size(); + if (modulus_n[0] & 0x80) { + public_key_info->insert(public_key_info->begin(), 0x00); + modulus_size++; + } + PrependASN1Length(public_key_info, modulus_size); + public_key_info->insert(public_key_info->begin(), kIntegerTag); + + // Encode the RSAPublicKey SEQUENCE. + PrependASN1Length(public_key_info, public_key_info->size()); + public_key_info->insert(public_key_info->begin(), kSequenceTag); + + // Encode the BIT STRING. + // Number of unused bits. + public_key_info->insert(public_key_info->begin(), 0x00); + PrependASN1Length(public_key_info, public_key_info->size()); + public_key_info->insert(public_key_info->begin(), kBitStringTag); + + // Encode the AlgorithmIdentifier. + static const uint8 algorithm[] = { + 0x30, 0x0d, // a SEQUENCE of length 13 + 0x06, 0x09, // an OBJECT IDENTIFIER of length 9 + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, + 0x05, 0x00, + }; + public_key_info->insert(public_key_info->begin(), + algorithm, algorithm + sizeof(algorithm)); + + // Encode the outermost SEQUENCE. + PrependASN1Length(public_key_info, public_key_info->size()); + public_key_info->insert(public_key_info->begin(), kSequenceTag); + + return true; +} + +TEST(SignatureVerifierTest, VerifyRSAPSS) { + for (unsigned int i = 0; i < arraysize(pss_test); i++) { + SCOPED_TRACE(i); + std::vector modulus_n; + std::vector public_exponent_e; + ASSERT_TRUE(DecodeTestInput(pss_test[i].modulus_n, &modulus_n)); + ASSERT_TRUE(DecodeTestInput(pss_test[i].public_exponent_e, + &public_exponent_e)); + std::vector public_key_info; + ASSERT_TRUE(EncodeRSAPublicKey(modulus_n, public_exponent_e, + &public_key_info)); + + for (unsigned int j = 0; j < arraysize(pss_test[i].example); j++) { + SCOPED_TRACE(j); + std::vector message; + std::vector salt; + std::vector signature; + ASSERT_TRUE(DecodeTestInput(pss_test[i].example[j].message, &message)); + ASSERT_TRUE(DecodeTestInput(pss_test[i].example[j].salt, &salt)); + ASSERT_TRUE(DecodeTestInput(pss_test[i].example[j].signature, + &signature)); + + crypto::SignatureVerifier verifier; + bool ok; + + // Positive test. + ok = verifier.VerifyInitRSAPSS(crypto::SignatureVerifier::SHA1, + crypto::SignatureVerifier::SHA1, + salt.size(), + &signature[0], signature.size(), + &public_key_info[0], + public_key_info.size()); + ASSERT_TRUE(ok); + verifier.VerifyUpdate(&message[0], message.size()); + ok = verifier.VerifyFinal(); + EXPECT_TRUE(ok); + + // Modify the first byte of the message. + ok = verifier.VerifyInitRSAPSS(crypto::SignatureVerifier::SHA1, + crypto::SignatureVerifier::SHA1, + salt.size(), + &signature[0], signature.size(), + &public_key_info[0], + public_key_info.size()); + ASSERT_TRUE(ok); + message[0] += 1; + verifier.VerifyUpdate(&message[0], message.size()); + message[0] -= 1; + ok = verifier.VerifyFinal(); + EXPECT_FALSE(ok); + + // Truncate the message. + ASSERT_FALSE(message.empty()); + ok = verifier.VerifyInitRSAPSS(crypto::SignatureVerifier::SHA1, + crypto::SignatureVerifier::SHA1, + salt.size(), + &signature[0], signature.size(), + &public_key_info[0], + public_key_info.size()); + ASSERT_TRUE(ok); + verifier.VerifyUpdate(&message[0], message.size() - 1); + ok = verifier.VerifyFinal(); + EXPECT_FALSE(ok); + + // Corrupt the signature. + signature[0] += 1; + ok = verifier.VerifyInitRSAPSS(crypto::SignatureVerifier::SHA1, + crypto::SignatureVerifier::SHA1, + salt.size(), + &signature[0], signature.size(), + &public_key_info[0], + public_key_info.size()); + signature[0] -= 1; + ASSERT_TRUE(ok); + verifier.VerifyUpdate(&message[0], message.size()); + ok = verifier.VerifyFinal(); + EXPECT_FALSE(ok); + } + } +} diff --git a/crypto/symmetric_key.h b/crypto/symmetric_key.h new file mode 100644 index 0000000000000..996c5923b1898 --- /dev/null +++ b/crypto/symmetric_key.h @@ -0,0 +1,101 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CRYPTO_SYMMETRIC_KEY_H_ +#define CRYPTO_SYMMETRIC_KEY_H_ + +#include + +#include "base/basictypes.h" +#include "crypto/crypto_export.h" + +#if defined(NACL_WIN64) +// See comments for crypto_nacl_win64 in crypto.gyp. +// Must test for NACL_WIN64 before OS_WIN since former is a subset of latter. +#include "crypto/scoped_capi_types.h" +#elif defined(USE_NSS_CERTS) || \ + (!defined(USE_OPENSSL) && (defined(OS_WIN) || defined(OS_MACOSX))) +#include "crypto/scoped_nss_types.h" +#endif + +namespace crypto { + +// Wraps a platform-specific symmetric key and allows it to be held in a +// scoped_ptr. +class CRYPTO_EXPORT SymmetricKey { + public: + // Defines the algorithm that a key will be used with. See also + // classs Encrptor. + enum Algorithm { + AES, + HMAC_SHA1, + }; + + virtual ~SymmetricKey(); + + // Generates a random key suitable to be used with |algorithm| and of + // |key_size_in_bits| bits. |key_size_in_bits| must be a multiple of 8. + // The caller is responsible for deleting the returned SymmetricKey. + static SymmetricKey* GenerateRandomKey(Algorithm algorithm, + size_t key_size_in_bits); + + // Derives a key from the supplied password and salt using PBKDF2, suitable + // for use with specified |algorithm|. Note |algorithm| is not the algorithm + // used to derive the key from the password. |key_size_in_bits| must be a + // multiple of 8. The caller is responsible for deleting the returned + // SymmetricKey. + static SymmetricKey* DeriveKeyFromPassword(Algorithm algorithm, + const std::string& password, + const std::string& salt, + size_t iterations, + size_t key_size_in_bits); + + // Imports an array of key bytes in |raw_key|. This key may have been + // generated by GenerateRandomKey or DeriveKeyFromPassword and exported with + // GetRawKey, or via another compatible method. The key must be of suitable + // size for use with |algorithm|. The caller owns the returned SymmetricKey. + static SymmetricKey* Import(Algorithm algorithm, const std::string& raw_key); + +#if defined(NACL_WIN64) + HCRYPTKEY key() const { return key_.get(); } +#elif defined(USE_OPENSSL) + const std::string& key() { return key_; } +#elif defined(USE_NSS_CERTS) || defined(OS_WIN) || defined(OS_MACOSX) + PK11SymKey* key() const { return key_.get(); } +#endif + + // Extracts the raw key from the platform specific data. + // Warning: |raw_key| holds the raw key as bytes and thus must be handled + // carefully. + bool GetRawKey(std::string* raw_key); + + private: +#if defined(NACL_WIN64) + SymmetricKey(HCRYPTPROV provider, HCRYPTKEY key, + const void* key_data, size_t key_size_in_bytes); + + ScopedHCRYPTPROV provider_; + ScopedHCRYPTKEY key_; + + // Contains the raw key, if it is known during initialization and when it + // is likely that the associated |provider_| will be unable to export the + // |key_|. This is the case of HMAC keys when the key size exceeds 16 bytes + // when using the default RSA provider. + // TODO(rsleevi): See if KP_EFFECTIVE_KEYLEN is the reason why CryptExportKey + // fails with NTE_BAD_KEY/NTE_BAD_LEN + std::string raw_key_; +#elif defined(USE_OPENSSL) + SymmetricKey() {} + std::string key_; +#elif defined(USE_NSS_CERTS) || defined(OS_WIN) || defined(OS_MACOSX) + explicit SymmetricKey(PK11SymKey* key); + ScopedPK11SymKey key_; +#endif + + DISALLOW_COPY_AND_ASSIGN(SymmetricKey); +}; + +} // namespace crypto + +#endif // CRYPTO_SYMMETRIC_KEY_H_ diff --git a/crypto/symmetric_key_nss.cc b/crypto/symmetric_key_nss.cc new file mode 100644 index 0000000000000..95ca9bd073ed8 --- /dev/null +++ b/crypto/symmetric_key_nss.cc @@ -0,0 +1,149 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/symmetric_key.h" + +#include +#include + +#include "base/logging.h" +#include "crypto/nss_util.h" + +namespace crypto { + +SymmetricKey::~SymmetricKey() {} + +// static +SymmetricKey* SymmetricKey::GenerateRandomKey(Algorithm algorithm, + size_t key_size_in_bits) { + DCHECK_EQ(AES, algorithm); + + EnsureNSSInit(); + + // Whitelist supported key sizes to avoid accidentaly relying on + // algorithms available in NSS but not BoringSSL and vice + // versa. Note that BoringSSL does not support AES-192. + if (key_size_in_bits != 128 && key_size_in_bits != 256) + return NULL; + + ScopedPK11Slot slot(PK11_GetInternalSlot()); + if (!slot.get()) + return NULL; + + PK11SymKey* sym_key = PK11_KeyGen(slot.get(), CKM_AES_KEY_GEN, NULL, + key_size_in_bits / 8, NULL); + if (!sym_key) + return NULL; + + return new SymmetricKey(sym_key); +} + +// static +SymmetricKey* SymmetricKey::DeriveKeyFromPassword(Algorithm algorithm, + const std::string& password, + const std::string& salt, + size_t iterations, + size_t key_size_in_bits) { + EnsureNSSInit(); + if (salt.empty() || iterations == 0 || key_size_in_bits == 0) + return NULL; + + if (algorithm == AES) { + // Whitelist supported key sizes to avoid accidentaly relying on + // algorithms available in NSS but not BoringSSL and vice + // versa. Note that BoringSSL does not support AES-192. + if (key_size_in_bits != 128 && key_size_in_bits != 256) + return NULL; + } + + SECItem password_item; + password_item.type = siBuffer; + password_item.data = reinterpret_cast( + const_cast(password.data())); + password_item.len = password.size(); + + SECItem salt_item; + salt_item.type = siBuffer; + salt_item.data = reinterpret_cast( + const_cast(salt.data())); + salt_item.len = salt.size(); + + SECOidTag cipher_algorithm = + algorithm == AES ? SEC_OID_AES_256_CBC : SEC_OID_HMAC_SHA1; + ScopedSECAlgorithmID alg_id(PK11_CreatePBEV2AlgorithmID(SEC_OID_PKCS5_PBKDF2, + cipher_algorithm, + SEC_OID_HMAC_SHA1, + key_size_in_bits / 8, + iterations, + &salt_item)); + if (!alg_id.get()) + return NULL; + + ScopedPK11Slot slot(PK11_GetInternalSlot()); + if (!slot.get()) + return NULL; + + PK11SymKey* sym_key = PK11_PBEKeyGen(slot.get(), alg_id.get(), &password_item, + PR_FALSE, NULL); + if (!sym_key) + return NULL; + + return new SymmetricKey(sym_key); +} + +// static +SymmetricKey* SymmetricKey::Import(Algorithm algorithm, + const std::string& raw_key) { + EnsureNSSInit(); + + if (algorithm == AES) { + // Whitelist supported key sizes to avoid accidentaly relying on + // algorithms available in NSS but not BoringSSL and vice + // versa. Note that BoringSSL does not support AES-192. + if (raw_key.size() != 128/8 && raw_key.size() != 256/8) + return NULL; + } + + CK_MECHANISM_TYPE cipher = + algorithm == AES ? CKM_AES_CBC : CKM_SHA_1_HMAC; + + SECItem key_item; + key_item.type = siBuffer; + key_item.data = reinterpret_cast( + const_cast(raw_key.data())); + key_item.len = raw_key.size(); + + ScopedPK11Slot slot(PK11_GetInternalSlot()); + if (!slot.get()) + return NULL; + + // The exact value of the |origin| argument doesn't matter to NSS as long as + // it's not PK11_OriginFortezzaHack, so we pass PK11_OriginUnwrap as a + // placeholder. + PK11SymKey* sym_key = PK11_ImportSymKey(slot.get(), cipher, PK11_OriginUnwrap, + CKA_ENCRYPT, &key_item, NULL); + if (!sym_key) + return NULL; + + return new SymmetricKey(sym_key); +} + +bool SymmetricKey::GetRawKey(std::string* raw_key) { + SECStatus rv = PK11_ExtractKeyValue(key_.get()); + if (SECSuccess != rv) + return false; + + SECItem* key_item = PK11_GetKeyData(key_.get()); + if (!key_item) + return false; + + raw_key->assign(reinterpret_cast(key_item->data), key_item->len); + return true; +} + +SymmetricKey::SymmetricKey(PK11SymKey* key) : key_(key) { + DCHECK(key); +} + +} // namespace crypto diff --git a/crypto/symmetric_key_openssl.cc b/crypto/symmetric_key_openssl.cc new file mode 100644 index 0000000000000..912c9b4db2d74 --- /dev/null +++ b/crypto/symmetric_key_openssl.cc @@ -0,0 +1,104 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/symmetric_key.h" + +#include +#include + +#include + +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "base/strings/string_util.h" +#include "crypto/openssl_util.h" + +namespace crypto { + +SymmetricKey::~SymmetricKey() { + std::fill(key_.begin(), key_.end(), '\0'); // Zero out the confidential key. +} + +// static +SymmetricKey* SymmetricKey::GenerateRandomKey(Algorithm algorithm, + size_t key_size_in_bits) { + DCHECK_EQ(AES, algorithm); + + // Whitelist supported key sizes to avoid accidentaly relying on + // algorithms available in NSS but not BoringSSL and vice + // versa. Note that BoringSSL does not support AES-192. + if (key_size_in_bits != 128 && key_size_in_bits != 256) + return NULL; + + size_t key_size_in_bytes = key_size_in_bits / 8; + DCHECK_EQ(key_size_in_bits, key_size_in_bytes * 8); + + if (key_size_in_bytes == 0) + return NULL; + + OpenSSLErrStackTracer err_tracer(FROM_HERE); + scoped_ptr key(new SymmetricKey); + uint8* key_data = reinterpret_cast( + base::WriteInto(&key->key_, key_size_in_bytes + 1)); + + int rv = RAND_bytes(key_data, static_cast(key_size_in_bytes)); + return rv == 1 ? key.release() : NULL; +} + +// static +SymmetricKey* SymmetricKey::DeriveKeyFromPassword(Algorithm algorithm, + const std::string& password, + const std::string& salt, + size_t iterations, + size_t key_size_in_bits) { + DCHECK(algorithm == AES || algorithm == HMAC_SHA1); + + if (algorithm == AES) { + // Whitelist supported key sizes to avoid accidentaly relying on + // algorithms available in NSS but not BoringSSL and vice + // versa. Note that BoringSSL does not support AES-192. + if (key_size_in_bits != 128 && key_size_in_bits != 256) + return NULL; + } + + size_t key_size_in_bytes = key_size_in_bits / 8; + DCHECK_EQ(key_size_in_bits, key_size_in_bytes * 8); + + if (key_size_in_bytes == 0) + return NULL; + + OpenSSLErrStackTracer err_tracer(FROM_HERE); + scoped_ptr key(new SymmetricKey); + uint8* key_data = reinterpret_cast( + base::WriteInto(&key->key_, key_size_in_bytes + 1)); + int rv = PKCS5_PBKDF2_HMAC_SHA1(password.data(), password.length(), + reinterpret_cast(salt.data()), + salt.length(), iterations, + static_cast(key_size_in_bytes), + key_data); + return rv == 1 ? key.release() : NULL; +} + +// static +SymmetricKey* SymmetricKey::Import(Algorithm algorithm, + const std::string& raw_key) { + if (algorithm == AES) { + // Whitelist supported key sizes to avoid accidentaly relying on + // algorithms available in NSS but not BoringSSL and vice + // versa. Note that BoringSSL does not support AES-192. + if (raw_key.size() != 128/8 && raw_key.size() != 256/8) + return NULL; + } + + scoped_ptr key(new SymmetricKey); + key->key_ = raw_key; + return key.release(); +} + +bool SymmetricKey::GetRawKey(std::string* raw_key) { + *raw_key = key_; + return true; +} + +} // namespace crypto diff --git a/crypto/symmetric_key_unittest.cc b/crypto/symmetric_key_unittest.cc new file mode 100644 index 0000000000000..28e44d27da7ac --- /dev/null +++ b/crypto/symmetric_key_unittest.cc @@ -0,0 +1,225 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/symmetric_key.h" + +#include + +#include "base/memory/scoped_ptr.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" +#include "testing/gtest/include/gtest/gtest.h" + +TEST(SymmetricKeyTest, GenerateRandomKey) { + scoped_ptr key( + crypto::SymmetricKey::GenerateRandomKey(crypto::SymmetricKey::AES, 256)); + ASSERT_TRUE(NULL != key.get()); + std::string raw_key; + EXPECT_TRUE(key->GetRawKey(&raw_key)); + EXPECT_EQ(32U, raw_key.size()); + + // Do it again and check that the keys are different. + // (Note: this has a one-in-10^77 chance of failure!) + scoped_ptr key2( + crypto::SymmetricKey::GenerateRandomKey(crypto::SymmetricKey::AES, 256)); + ASSERT_TRUE(NULL != key2.get()); + std::string raw_key2; + EXPECT_TRUE(key2->GetRawKey(&raw_key2)); + EXPECT_EQ(32U, raw_key2.size()); + EXPECT_NE(raw_key, raw_key2); +} + +TEST(SymmetricKeyTest, ImportGeneratedKey) { + scoped_ptr key1( + crypto::SymmetricKey::GenerateRandomKey(crypto::SymmetricKey::AES, 256)); + ASSERT_TRUE(NULL != key1.get()); + std::string raw_key1; + EXPECT_TRUE(key1->GetRawKey(&raw_key1)); + + scoped_ptr key2( + crypto::SymmetricKey::Import(crypto::SymmetricKey::AES, raw_key1)); + ASSERT_TRUE(NULL != key2.get()); + + std::string raw_key2; + EXPECT_TRUE(key2->GetRawKey(&raw_key2)); + + EXPECT_EQ(raw_key1, raw_key2); +} + +TEST(SymmetricKeyTest, ImportDerivedKey) { + scoped_ptr key1( + crypto::SymmetricKey::DeriveKeyFromPassword( + crypto::SymmetricKey::HMAC_SHA1, "password", "somesalt", 1024, 160)); + ASSERT_TRUE(NULL != key1.get()); + std::string raw_key1; + EXPECT_TRUE(key1->GetRawKey(&raw_key1)); + + scoped_ptr key2( + crypto::SymmetricKey::Import(crypto::SymmetricKey::HMAC_SHA1, raw_key1)); + ASSERT_TRUE(NULL != key2.get()); + + std::string raw_key2; + EXPECT_TRUE(key2->GetRawKey(&raw_key2)); + + EXPECT_EQ(raw_key1, raw_key2); +} + +struct PBKDF2TestVector { + crypto::SymmetricKey::Algorithm algorithm; + const char* password; + const char* salt; + unsigned int rounds; + unsigned int key_size_in_bits; + const char* expected; // ASCII encoded hex bytes +}; + +class SymmetricKeyDeriveKeyFromPasswordTest + : public testing::TestWithParam { +}; + +TEST_P(SymmetricKeyDeriveKeyFromPasswordTest, DeriveKeyFromPassword) { + PBKDF2TestVector test_data(GetParam()); +#if defined(OS_MACOSX) && !defined(OS_IOS) + // The OS X crypto libraries have minimum salt and iteration requirements + // so some of the tests below will cause them to barf. Skip these. + if (strlen(test_data.salt) < 8 || test_data.rounds < 1000) { + VLOG(1) << "Skipped test vector for " << test_data.expected; + return; + } +#endif // OS_MACOSX + + scoped_ptr key( + crypto::SymmetricKey::DeriveKeyFromPassword( + test_data.algorithm, + test_data.password, test_data.salt, + test_data.rounds, test_data.key_size_in_bits)); + ASSERT_TRUE(NULL != key.get()); + + std::string raw_key; + key->GetRawKey(&raw_key); + EXPECT_EQ(test_data.key_size_in_bits / 8, raw_key.size()); + EXPECT_EQ(test_data.expected, + base::StringToLowerASCII(base::HexEncode(raw_key.data(), + raw_key.size()))); +} + +static const PBKDF2TestVector kTestVectors[] = { + // These tests come from + // http://www.ietf.org/id/draft-josefsson-pbkdf2-test-vectors-00.txt + { + crypto::SymmetricKey::HMAC_SHA1, + "password", + "salt", + 1, + 160, + "0c60c80f961f0e71f3a9b524af6012062fe037a6", + }, + { + crypto::SymmetricKey::HMAC_SHA1, + "password", + "salt", + 2, + 160, + "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957", + }, + { + crypto::SymmetricKey::HMAC_SHA1, + "password", + "salt", + 4096, + 160, + "4b007901b765489abead49d926f721d065a429c1", + }, + // This test takes over 30s to run on the trybots. +#if 0 + { + crypto::SymmetricKey::HMAC_SHA1, + "password", + "salt", + 16777216, + 160, + "eefe3d61cd4da4e4e9945b3d6ba2158c2634e984", + }, +#endif + + // These tests come from RFC 3962, via BSD source code at + // http://www.openbsd.org/cgi-bin/cvsweb/src/sbin/bioctl/pbkdf2.c?rev=HEAD&content-type=text/plain + { + crypto::SymmetricKey::HMAC_SHA1, + "password", + "ATHENA.MIT.EDUraeburn", + 1, + 160, + "cdedb5281bb2f801565a1122b25635150ad1f7a0", + }, + { + crypto::SymmetricKey::HMAC_SHA1, + "password", + "ATHENA.MIT.EDUraeburn", + 2, + 160, + "01dbee7f4a9e243e988b62c73cda935da05378b9", + }, + { + crypto::SymmetricKey::HMAC_SHA1, + "password", + "ATHENA.MIT.EDUraeburn", + 1200, + 160, + "5c08eb61fdf71e4e4ec3cf6ba1f5512ba7e52ddb", + }, + { + crypto::SymmetricKey::HMAC_SHA1, + "password", + "\022" "4VxxV4\022", /* 0x1234567878563412 */ + 5, + 160, + "d1daa78615f287e6a1c8b120d7062a493f98d203", + }, + { + crypto::SymmetricKey::HMAC_SHA1, + "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", + "pass phrase equals block size", + 1200, + 160, + "139c30c0966bc32ba55fdbf212530ac9c5ec59f1", + }, + { + crypto::SymmetricKey::HMAC_SHA1, + "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", + "pass phrase exceeds block size", + 1200, + 160, + "9ccad6d468770cd51b10e6a68721be611a8b4d28", + }, + { + crypto::SymmetricKey::HMAC_SHA1, + "\360\235\204\236", /* g-clef (0xf09d849e) */ + "EXAMPLE.COMpianist", + 50, + 160, + "6b9cf26d45455a43a5b8bb276a403b39e7fe37a0", + }, + + // Regression tests for AES keys, derived from the Linux NSS implementation. + { + crypto::SymmetricKey::AES, + "A test password", + "saltsalt", + 1, + 256, + "44899a7777f0e6e8b752f875f02044b8ac593de146de896f2e8a816e315a36de", + }, + { + crypto::SymmetricKey::AES, + "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", + "pass phrase exceeds block size", + 20, + 256, + "e0739745dc28b8721ba402e05214d2ac1eab54cf72bee1fba388297a09eb493c", + }, +}; + +INSTANTIATE_TEST_CASE_P(, SymmetricKeyDeriveKeyFromPasswordTest, + testing::ValuesIn(kTestVectors)); diff --git a/crypto/symmetric_key_win.cc b/crypto/symmetric_key_win.cc new file mode 100644 index 0000000000000..b3d65f6613760 --- /dev/null +++ b/crypto/symmetric_key_win.cc @@ -0,0 +1,536 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/symmetric_key.h" + +#include + +// TODO(wtc): replace scoped_array by std::vector. +#include "base/memory/scoped_ptr.h" +#include "base/sys_byteorder.h" + +namespace crypto { + +namespace { + +// The following is a non-public Microsoft header documented in MSDN under +// CryptImportKey / CryptExportKey. Following the header is the byte array of +// the actual plaintext key. +struct PlaintextBlobHeader { + BLOBHEADER hdr; + DWORD cbKeySize; +}; + +// CryptoAPI makes use of three distinct ALG_IDs for AES, rather than just +// CALG_AES (which exists, but depending on the functions you are calling, may +// result in function failure, whereas the subtype would succeed). +ALG_ID GetAESAlgIDForKeySize(size_t key_size_in_bits) { + // Only AES-128/-192/-256 is supported in CryptoAPI. + switch (key_size_in_bits) { + case 128: + return CALG_AES_128; + case 192: + return CALG_AES_192; + case 256: + return CALG_AES_256; + default: + NOTREACHED(); + return 0; + } +}; + +// Imports a raw/plaintext key of |key_size| stored in |*key_data| into a new +// key created for the specified |provider|. |alg| contains the algorithm of +// the key being imported. +// If |key_data| is intended to be used as an HMAC key, then |alg| should be +// CALG_HMAC. +// If successful, returns true and stores the imported key in |*key|. +// TODO(wtc): use this function in hmac_win.cc. +bool ImportRawKey(HCRYPTPROV provider, + ALG_ID alg, + const void* key_data, size_t key_size, + ScopedHCRYPTKEY* key) { + DCHECK_GT(key_size, 0); + + DWORD actual_size = + static_cast(sizeof(PlaintextBlobHeader) + key_size); + std::vector tmp_data(actual_size); + BYTE* actual_key = &tmp_data[0]; + memcpy(actual_key + sizeof(PlaintextBlobHeader), key_data, key_size); + PlaintextBlobHeader* key_header = + reinterpret_cast(actual_key); + memset(key_header, 0, sizeof(PlaintextBlobHeader)); + + key_header->hdr.bType = PLAINTEXTKEYBLOB; + key_header->hdr.bVersion = CUR_BLOB_VERSION; + key_header->hdr.aiKeyAlg = alg; + + key_header->cbKeySize = static_cast(key_size); + + HCRYPTKEY unsafe_key = NULL; + DWORD flags = CRYPT_EXPORTABLE; + if (alg == CALG_HMAC) { + // Though it may appear odd that IPSEC and RC2 are being used, this is + // done in accordance with Microsoft's FIPS 140-2 Security Policy for the + // RSA Enhanced Provider, as the approved means of using arbitrary HMAC + // key material. + key_header->hdr.aiKeyAlg = CALG_RC2; + flags |= CRYPT_IPSEC_HMAC_KEY; + } + + BOOL ok = + CryptImportKey(provider, actual_key, actual_size, 0, flags, &unsafe_key); + + // Clean up the temporary copy of key, regardless of whether it was imported + // sucessfully or not. + SecureZeroMemory(actual_key, actual_size); + + if (!ok) + return false; + + key->reset(unsafe_key); + return true; +} + +// Attempts to generate a random AES key of |key_size_in_bits|. Returns true +// if generation is successful, storing the generated key in |*key| and the +// key provider (CSP) in |*provider|. +bool GenerateAESKey(size_t key_size_in_bits, + ScopedHCRYPTPROV* provider, + ScopedHCRYPTKEY* key) { + DCHECK(provider); + DCHECK(key); + + ALG_ID alg = GetAESAlgIDForKeySize(key_size_in_bits); + if (alg == 0) + return false; + + ScopedHCRYPTPROV safe_provider; + // Note: The only time NULL is safe to be passed as pszContainer is when + // dwFlags contains CRYPT_VERIFYCONTEXT, as all keys generated and/or used + // will be treated as ephemeral keys and not persisted. + BOOL ok = CryptAcquireContext(safe_provider.receive(), NULL, NULL, + PROV_RSA_AES, CRYPT_VERIFYCONTEXT); + if (!ok) + return false; + + ScopedHCRYPTKEY safe_key; + // In the FIPS 140-2 Security Policy for CAPI on XP/Vista+, Microsoft notes + // that CryptGenKey makes use of the same functionality exposed via + // CryptGenRandom. The reason this is being used, as opposed to + // CryptGenRandom and CryptImportKey is for compliance with the security + // policy + ok = CryptGenKey(safe_provider.get(), alg, CRYPT_EXPORTABLE, + safe_key.receive()); + if (!ok) + return false; + + key->swap(safe_key); + provider->swap(safe_provider); + + return true; +} + +// Returns true if the HMAC key size meets the requirement of FIPS 198 +// Section 3. |alg| is the hash function used in the HMAC. +bool CheckHMACKeySize(size_t key_size_in_bits, ALG_ID alg) { + DWORD hash_size = 0; + switch (alg) { + case CALG_SHA1: + hash_size = 20; + break; + case CALG_SHA_256: + hash_size = 32; + break; + case CALG_SHA_384: + hash_size = 48; + break; + case CALG_SHA_512: + hash_size = 64; + break; + } + if (hash_size == 0) + return false; + + // An HMAC key must be >= L/2, where L is the output size of the hash + // function being used. + return (key_size_in_bits >= (hash_size / 2 * 8) && + (key_size_in_bits % 8) == 0); +} + +// Attempts to generate a random, |key_size_in_bits|-long HMAC key, for use +// with the hash function |alg|. +// |key_size_in_bits| must be >= 1/2 the hash size of |alg| for security. +// Returns true if generation is successful, storing the generated key in +// |*key| and the key provider (CSP) in |*provider|. +bool GenerateHMACKey(size_t key_size_in_bits, + ALG_ID alg, + ScopedHCRYPTPROV* provider, + ScopedHCRYPTKEY* key, + scoped_ptr* raw_key) { + DCHECK(provider); + DCHECK(key); + DCHECK(raw_key); + + if (!CheckHMACKeySize(key_size_in_bits, alg)) + return false; + + ScopedHCRYPTPROV safe_provider; + // See comment in GenerateAESKey as to why NULL is acceptable for the + // container name. + BOOL ok = CryptAcquireContext(safe_provider.receive(), NULL, NULL, + PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); + if (!ok) + return false; + + DWORD key_size_in_bytes = static_cast(key_size_in_bits / 8); + scoped_ptr random(new BYTE[key_size_in_bytes]); + ok = CryptGenRandom(safe_provider, key_size_in_bytes, random.get()); + if (!ok) + return false; + + ScopedHCRYPTKEY safe_key; + bool rv = ImportRawKey(safe_provider, CALG_HMAC, random.get(), + key_size_in_bytes, &safe_key); + if (rv) { + key->swap(safe_key); + provider->swap(safe_provider); + raw_key->swap(random); + } + + SecureZeroMemory(random.get(), key_size_in_bytes); + return rv; +} + +// Attempts to create an HMAC hash instance using the specified |provider| +// and |key|. The inner hash function will be |hash_alg|. If successful, +// returns true and stores the hash in |*hash|. +// TODO(wtc): use this function in hmac_win.cc. +bool CreateHMACHash(HCRYPTPROV provider, + HCRYPTKEY key, + ALG_ID hash_alg, + ScopedHCRYPTHASH* hash) { + ScopedHCRYPTHASH safe_hash; + BOOL ok = CryptCreateHash(provider, CALG_HMAC, key, 0, safe_hash.receive()); + if (!ok) + return false; + + HMAC_INFO hmac_info; + memset(&hmac_info, 0, sizeof(hmac_info)); + hmac_info.HashAlgid = hash_alg; + + ok = CryptSetHashParam(safe_hash, HP_HMAC_INFO, + reinterpret_cast(&hmac_info), 0); + if (!ok) + return false; + + hash->swap(safe_hash); + return true; +} + +// Computes a block of the derived key using the PBKDF2 function F for the +// specified |block_index| using the PRF |hash|, writing the output to +// |output_buf|. +// |output_buf| must have enough space to accomodate the output of the PRF +// specified by |hash|. +// Returns true if the block was successfully computed. +bool ComputePBKDF2Block(HCRYPTHASH hash, + DWORD hash_size, + const std::string& salt, + size_t iterations, + uint32 block_index, + BYTE* output_buf) { + // From RFC 2898: + // 3. The function F is defined as the exclusive-or sum of the first + // c iterates of the underlying pseudorandom function PRF applied to the + // password P and the concatenation of the salt S and the block index i: + // F (P, S, c, i) = U_1 \xor U_2 \xor ... \xor U_c + // where + // U_1 = PRF(P, S || INT (i)) + // U_2 = PRF(P, U_1) + // ... + // U_c = PRF(P, U_{c-1}) + ScopedHCRYPTHASH safe_hash; + BOOL ok = CryptDuplicateHash(hash, NULL, 0, safe_hash.receive()); + if (!ok) + return false; + + // Iteration U_1: Compute PRF for S. + ok = CryptHashData(safe_hash, reinterpret_cast(salt.data()), + static_cast(salt.size()), 0); + if (!ok) + return false; + + // Iteration U_1: and append (big-endian) INT (i). + uint32 big_endian_block_index = base::HostToNet32(block_index); + ok = CryptHashData(safe_hash, + reinterpret_cast(&big_endian_block_index), + sizeof(big_endian_block_index), 0); + + std::vector hash_value(hash_size); + + DWORD size = hash_size; + ok = CryptGetHashParam(safe_hash, HP_HASHVAL, &hash_value[0], &size, 0); + if (!ok || size != hash_size) + return false; + + memcpy(output_buf, &hash_value[0], hash_size); + + // Iteration 2 - c: Compute U_{iteration} by applying the PRF to + // U_{iteration - 1}, then xor the resultant hash with |output|, which + // contains U_1 ^ U_2 ^ ... ^ U_{iteration - 1}. + for (size_t iteration = 2; iteration <= iterations; ++iteration) { + safe_hash.reset(); + ok = CryptDuplicateHash(hash, NULL, 0, safe_hash.receive()); + if (!ok) + return false; + + ok = CryptHashData(safe_hash, &hash_value[0], hash_size, 0); + if (!ok) + return false; + + size = hash_size; + ok = CryptGetHashParam(safe_hash, HP_HASHVAL, &hash_value[0], &size, 0); + if (!ok || size != hash_size) + return false; + + for (int i = 0; i < hash_size; ++i) + output_buf[i] ^= hash_value[i]; + } + + return true; +} + +} // namespace + +SymmetricKey::~SymmetricKey() { + // TODO(wtc): create a "secure" string type that zeroes itself in the + // destructor. + if (!raw_key_.empty()) + SecureZeroMemory(const_cast(raw_key_.data()), raw_key_.size()); +} + +// static +SymmetricKey* SymmetricKey::GenerateRandomKey(Algorithm algorithm, + size_t key_size_in_bits) { + DCHECK_GE(key_size_in_bits, 8); + + ScopedHCRYPTPROV provider; + ScopedHCRYPTKEY key; + + bool ok = false; + scoped_ptr raw_key; + + switch (algorithm) { + case AES: + ok = GenerateAESKey(key_size_in_bits, &provider, &key); + break; + case HMAC_SHA1: + ok = GenerateHMACKey(key_size_in_bits, CALG_SHA1, &provider, + &key, &raw_key); + break; + } + + if (!ok) { + NOTREACHED(); + return NULL; + } + + size_t key_size_in_bytes = key_size_in_bits / 8; + if (raw_key == NULL) + key_size_in_bytes = 0; + + SymmetricKey* result = new SymmetricKey(provider.release(), + key.release(), + raw_key.get(), + key_size_in_bytes); + if (raw_key != NULL) + SecureZeroMemory(raw_key.get(), key_size_in_bytes); + + return result; +} + +// static +SymmetricKey* SymmetricKey::DeriveKeyFromPassword(Algorithm algorithm, + const std::string& password, + const std::string& salt, + size_t iterations, + size_t key_size_in_bits) { + // CryptoAPI lacks routines to perform PBKDF2 derivation as specified + // in RFC 2898, so it must be manually implemented. Only HMAC-SHA1 is + // supported as the PRF. + + // While not used until the end, sanity-check the input before proceeding + // with the expensive computation. + DWORD provider_type = 0; + ALG_ID alg = 0; + switch (algorithm) { + case AES: + provider_type = PROV_RSA_AES; + alg = GetAESAlgIDForKeySize(key_size_in_bits); + break; + case HMAC_SHA1: + provider_type = PROV_RSA_FULL; + alg = CALG_HMAC; + break; + default: + NOTREACHED(); + break; + } + if (provider_type == 0 || alg == 0) + return NULL; + + ScopedHCRYPTPROV provider; + BOOL ok = CryptAcquireContext(provider.receive(), NULL, NULL, provider_type, + CRYPT_VERIFYCONTEXT); + if (!ok) + return NULL; + + // Convert the user password into a key suitable to be fed into the PRF + // function. + ScopedHCRYPTKEY password_as_key; + BYTE* password_as_bytes = + const_cast(reinterpret_cast(password.data())); + if (!ImportRawKey(provider, CALG_HMAC, password_as_bytes, + password.size(), &password_as_key)) + return NULL; + + // Configure the PRF function. Only HMAC variants are supported, with the + // only hash function supported being SHA1. + // TODO(rsleevi): Support SHA-256 on XP SP3+. + ScopedHCRYPTHASH prf; + if (!CreateHMACHash(provider, password_as_key, CALG_SHA1, &prf)) + return NULL; + + DWORD hLen = 0; + DWORD param_size = sizeof(hLen); + ok = CryptGetHashParam(prf, HP_HASHSIZE, + reinterpret_cast(&hLen), ¶m_size, 0); + if (!ok || hLen == 0) + return NULL; + + // 1. If dkLen > (2^32 - 1) * hLen, output "derived key too long" and stop. + size_t dkLen = key_size_in_bits / 8; + DCHECK_GT(dkLen, 0); + + if ((dkLen / hLen) > 0xFFFFFFFF) { + DLOG(ERROR) << "Derived key too long."; + return NULL; + } + + // 2. Let l be the number of hLen-octet blocks in the derived key, + // rounding up, and let r be the number of octets in the last + // block: + size_t L = (dkLen + hLen - 1) / hLen; + DCHECK_GT(L, 0); + + size_t total_generated_size = L * hLen; + std::vector generated_key(total_generated_size); + BYTE* block_offset = &generated_key[0]; + + // 3. For each block of the derived key apply the function F defined below + // to the password P, the salt S, the iteration count c, and the block + // index to compute the block: + // T_1 = F (P, S, c, 1) + // T_2 = F (P, S, c, 2) + // ... + // T_l = F (P, S, c, l) + // + // 4. Concatenate the blocks and extract the first dkLen octets to produce + // a derived key DK: + // DK = T_1 || T_2 || ... || T_l<0..r-1> + for (uint32 block_index = 1; block_index <= L; ++block_index) { + if (!ComputePBKDF2Block(prf, hLen, salt, iterations, block_index, + block_offset)) + return NULL; + block_offset += hLen; + } + + // Convert the derived key bytes into a key handle for the desired algorithm. + ScopedHCRYPTKEY key; + if (!ImportRawKey(provider, alg, &generated_key[0], dkLen, &key)) + return NULL; + + SymmetricKey* result = new SymmetricKey(provider.release(), key.release(), + &generated_key[0], dkLen); + + SecureZeroMemory(&generated_key[0], total_generated_size); + + return result; +} + +// static +SymmetricKey* SymmetricKey::Import(Algorithm algorithm, + const std::string& raw_key) { + DWORD provider_type = 0; + ALG_ID alg = 0; + switch (algorithm) { + case AES: + provider_type = PROV_RSA_AES; + alg = GetAESAlgIDForKeySize(raw_key.size() * 8); + break; + case HMAC_SHA1: + provider_type = PROV_RSA_FULL; + alg = CALG_HMAC; + break; + default: + NOTREACHED(); + break; + } + if (provider_type == 0 || alg == 0) + return NULL; + + ScopedHCRYPTPROV provider; + BOOL ok = CryptAcquireContext(provider.receive(), NULL, NULL, provider_type, + CRYPT_VERIFYCONTEXT); + if (!ok) + return NULL; + + ScopedHCRYPTKEY key; + if (!ImportRawKey(provider, alg, raw_key.data(), raw_key.size(), &key)) + return NULL; + + return new SymmetricKey(provider.release(), key.release(), + raw_key.data(), raw_key.size()); +} + +bool SymmetricKey::GetRawKey(std::string* raw_key) { + // Short circuit for when the key was supplied to the constructor. + if (!raw_key_.empty()) { + *raw_key = raw_key_; + return true; + } + + DWORD size = 0; + BOOL ok = CryptExportKey(key_, 0, PLAINTEXTKEYBLOB, 0, NULL, &size); + if (!ok) + return false; + + std::vector result(size); + + ok = CryptExportKey(key_, 0, PLAINTEXTKEYBLOB, 0, &result[0], &size); + if (!ok) + return false; + + PlaintextBlobHeader* header = + reinterpret_cast(&result[0]); + raw_key->assign(reinterpret_cast(&result[sizeof(*header)]), + header->cbKeySize); + + SecureZeroMemory(&result[0], size); + + return true; +} + +SymmetricKey::SymmetricKey(HCRYPTPROV provider, + HCRYPTKEY key, + const void* key_data, size_t key_size_in_bytes) + : provider_(provider), key_(key) { + if (key_data) { + raw_key_.assign(reinterpret_cast(key_data), + key_size_in_bytes); + } +} + +} // namespace crypto diff --git a/crypto/third_party/nss/LICENSE b/crypto/third_party/nss/LICENSE new file mode 100644 index 0000000000000..03671648c17a3 --- /dev/null +++ b/crypto/third_party/nss/LICENSE @@ -0,0 +1,35 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1994-2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ diff --git a/crypto/third_party/nss/README.chromium b/crypto/third_party/nss/README.chromium new file mode 100644 index 0000000000000..1a63665e6fa17 --- /dev/null +++ b/crypto/third_party/nss/README.chromium @@ -0,0 +1,18 @@ +Name: Network Security Services (NSS) +URL: http://www.mozilla.org/projects/security/pki/nss/ +License: MPL 1.1/GPL 2.0/LGPL 2.1 + +We extracted the SHA-256 source files, eliminated unneeded dependencies, +deleted or commented out unused code, and tweaked them for Chrome's source +tree. sha512.c is renamed sha512.cc so that it can include Chrome's C++ +header "base/basictypes.h". We define NOUNROLL256 to reduce the object code +size. + +In blapi.h and sha512.cc, replaced uint32 by unsigned int so that they can +be compiled with -DNO_NSPR_10_SUPPORT. NO_NSPR_10_SUPPORT turns off the +definition of the NSPR 1.0 types int8 - int64 and uint8 - uint64 to avoid +conflict with the same-named types defined in "base/basictypes.h". + +rsawrapr.c is copied from nss/lib/softoken/rsawrapr.c, with +HASH_GetRawHashObject changed to HASH_GetHashObject. It contains the +emsa_pss_verify function for verifying RSA-PSS signatures. diff --git a/crypto/third_party/nss/chromium-blapi.h b/crypto/third_party/nss/chromium-blapi.h new file mode 100644 index 0000000000000..2ca772e4d3294 --- /dev/null +++ b/crypto/third_party/nss/chromium-blapi.h @@ -0,0 +1,101 @@ +/* + * crypto.h - public data structures and prototypes for the crypto library + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1994-2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Dr Vipul Gupta , Sun Microsystems Laboratories + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* $Id: blapi.h,v 1.27 2007/11/09 18:49:32 wtc%google.com Exp $ */ + +#ifndef CRYPTO_THIRD_PARTY_NSS_CHROMIUM_BLAPI_H_ +#define CRYPTO_THIRD_PARTY_NSS_CHROMIUM_BLAPI_H_ + +#include "crypto/third_party/nss/chromium-blapit.h" + +/******************************************/ + +extern SHA256Context *SHA256_NewContext(void); +extern void SHA256_DestroyContext(SHA256Context *cx, PRBool freeit); +extern void SHA256_Begin(SHA256Context *cx); +extern void SHA256_Update(SHA256Context *cx, const unsigned char *input, + unsigned int inputLen); +extern void SHA256_End(SHA256Context *cx, unsigned char *digest, + unsigned int *digestLen, unsigned int maxDigestLen); +extern SECStatus SHA256_HashBuf(unsigned char *dest, const unsigned char *src, + unsigned int src_length); +extern SECStatus SHA256_Hash(unsigned char *dest, const char *src); +extern void SHA256_TraceState(SHA256Context *cx); +extern unsigned int SHA256_FlattenSize(SHA256Context *cx); +extern SECStatus SHA256_Flatten(SHA256Context *cx,unsigned char *space); +extern SHA256Context * SHA256_Resurrect(unsigned char *space, void *arg); +extern void SHA256_Clone(SHA256Context *dest, SHA256Context *src); + +/******************************************/ + +extern SHA512Context *SHA512_NewContext(void); +extern void SHA512_DestroyContext(SHA512Context *cx, PRBool freeit); +extern void SHA512_Begin(SHA512Context *cx); +extern void SHA512_Update(SHA512Context *cx, const unsigned char *input, + unsigned int inputLen); +extern void SHA512_End(SHA512Context *cx, unsigned char *digest, + unsigned int *digestLen, unsigned int maxDigestLen); +extern SECStatus SHA512_HashBuf(unsigned char *dest, const unsigned char *src, + unsigned int src_length); +extern SECStatus SHA512_Hash(unsigned char *dest, const char *src); +extern void SHA512_TraceState(SHA512Context *cx); +extern unsigned int SHA512_FlattenSize(SHA512Context *cx); +extern SECStatus SHA512_Flatten(SHA512Context *cx,unsigned char *space); +extern SHA512Context * SHA512_Resurrect(unsigned char *space, void *arg); +extern void SHA512_Clone(SHA512Context *dest, SHA512Context *src); + +/******************************************/ + +extern SHA384Context *SHA384_NewContext(void); +extern void SHA384_DestroyContext(SHA384Context *cx, PRBool freeit); +extern void SHA384_Begin(SHA384Context *cx); +extern void SHA384_Update(SHA384Context *cx, const unsigned char *input, + unsigned int inputLen); +extern void SHA384_End(SHA384Context *cx, unsigned char *digest, + unsigned int *digestLen, unsigned int maxDigestLen); +extern SECStatus SHA384_HashBuf(unsigned char *dest, const unsigned char *src, + unsigned int src_length); +extern SECStatus SHA384_Hash(unsigned char *dest, const char *src); +extern void SHA384_TraceState(SHA384Context *cx); +extern unsigned int SHA384_FlattenSize(SHA384Context *cx); +extern SECStatus SHA384_Flatten(SHA384Context *cx,unsigned char *space); +extern SHA384Context * SHA384_Resurrect(unsigned char *space, void *arg); +extern void SHA384_Clone(SHA384Context *dest, SHA384Context *src); + +#endif /* CRYPTO_THIRD_PARTY_NSS_CHROMIUM_BLAPI_H_ */ diff --git a/crypto/third_party/nss/chromium-blapit.h b/crypto/third_party/nss/chromium-blapit.h new file mode 100644 index 0000000000000..938547a2c0666 --- /dev/null +++ b/crypto/third_party/nss/chromium-blapit.h @@ -0,0 +1,91 @@ +/* + * blapit.h - public data structures for the crypto library + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1994-2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Dr Vipul Gupta and + * Douglas Stebila , Sun Microsystems Laboratories + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* $Id: blapit.h,v 1.20 2007/02/28 19:47:37 rrelyea%redhat.com Exp $ */ + +#ifndef CRYPTO_THIRD_PARTY_NSS_CHROMIUM_BLAPIT_H_ +#define CRYPTO_THIRD_PARTY_NSS_CHROMIUM_BLAPIT_H_ + +#include "crypto/third_party/nss/chromium-prtypes.h" + +/* +** A status code. Status's are used by procedures that return status +** values. Again the motivation is so that a compiler can generate +** warnings when return values are wrong. Correct testing of status codes: +** +** SECStatus rv; +** rv = some_function (some_argument); +** if (rv != SECSuccess) +** do_an_error_thing(); +** +*/ +typedef enum _SECStatus { + SECWouldBlock = -2, + SECFailure = -1, + SECSuccess = 0 +} SECStatus; + +#define SHA256_LENGTH 32 /* bytes */ +#define SHA384_LENGTH 48 /* bytes */ +#define SHA512_LENGTH 64 /* bytes */ +#define HASH_LENGTH_MAX SHA512_LENGTH + +/* + * Input block size for each hash algorithm. + */ + +#define SHA256_BLOCK_LENGTH 64 /* bytes */ +#define SHA384_BLOCK_LENGTH 128 /* bytes */ +#define SHA512_BLOCK_LENGTH 128 /* bytes */ +#define HASH_BLOCK_LENGTH_MAX SHA512_BLOCK_LENGTH + +/*************************************************************************** +** Opaque objects +*/ + +struct SHA256ContextStr ; +struct SHA512ContextStr ; + +typedef struct SHA256ContextStr SHA256Context; +typedef struct SHA512ContextStr SHA512Context; +/* SHA384Context is really a SHA512ContextStr. This is not a mistake. */ +typedef struct SHA512ContextStr SHA384Context; + +#endif /* CRYPTO_THIRD_PARTY_NSS_CHROMIUM_BLAPIT_H_ */ diff --git a/crypto/third_party/nss/chromium-nss.h b/crypto/third_party/nss/chromium-nss.h new file mode 100644 index 0000000000000..437e6bd5cdb61 --- /dev/null +++ b/crypto/third_party/nss/chromium-nss.h @@ -0,0 +1,79 @@ + /* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1994-2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef CRYPTO_THIRD_PARTY_NSS_CHROMIUM_NSS_H_ +#define CRYPTO_THIRD_PARTY_NSS_CHROMIUM_NSS_H_ + +// This file contains some functions we borrowed from NSS. + +#include +#include +#include +#include + +#include "crypto/crypto_export.h" + +extern "C" SECStatus emsa_pss_verify(const unsigned char *mHash, + const unsigned char *em, + unsigned int emLen, + HASH_HashType hashAlg, + HASH_HashType maskHashAlg, + unsigned int sLen); + +// Like PK11_ImportEncryptedPrivateKeyInfo, but hardcoded for EC, and returns +// the SECKEYPrivateKey. +// See https://bugzilla.mozilla.org/show_bug.cgi?id=211546 +// When we use NSS 3.13.2 or later, +// PK11_ImportEncryptedPrivateKeyInfoAndReturnKey can be used instead. +SECStatus ImportEncryptedECPrivateKeyInfoAndReturnKey( + PK11SlotInfo* slot, + SECKEYEncryptedPrivateKeyInfo* epki, + SECItem* password, + SECItem* nickname, + SECItem* public_value, + PRBool permanent, + PRBool sensitive, + SECKEYPrivateKey** private_key, + void* wincx); + +// Like SEC_DerSignData. +CRYPTO_EXPORT SECStatus DerSignData(PLArenaPool *arena, + SECItem *result, + SECItem *input, + SECKEYPrivateKey *key, + SECOidTag algo_id); + +#endif // CRYPTO_THIRD_PARTY_NSS_CHROMIUM_NSS_H_ diff --git a/crypto/third_party/nss/chromium-prtypes.h b/crypto/third_party/nss/chromium-prtypes.h new file mode 100644 index 0000000000000..d5ea8a9d20bf3 --- /dev/null +++ b/crypto/third_party/nss/chromium-prtypes.h @@ -0,0 +1,77 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* Emulates the real prtypes.h. Defines the types and macros that sha512.cc + * needs. */ + +#ifndef CRYPTO_THIRD_PARTY_NSS_CHROMIUM_PRTYPES_H_ +#define CRYPTO_THIRD_PARTY_NSS_CHROMIUM_PRTYPES_H_ + +#include +#include + +#include "build/build_config.h" + +#if defined(ARCH_CPU_LITTLE_ENDIAN) +#define IS_LITTLE_ENDIAN 1 +#else +#define IS_BIG_ENDIAN 1 +#endif + +/* + * The C language requires that 'long' be at least 32 bits. 2147483647 is the + * largest signed 32-bit integer. + */ +#if LONG_MAX > 2147483647L +#define PR_BYTES_PER_LONG 8 +#else +#define PR_BYTES_PER_LONG 4 +#endif + +#define HAVE_LONG_LONG + +#if defined(__linux__) +#define LINUX +#endif + +typedef uint8_t PRUint8; +typedef uint32_t PRUint32; + +typedef int PRBool; + +#define PR_MIN(x,y) ((x)<(y)?(x):(y)) + +#endif /* CRYPTO_THIRD_PARTY_NSS_CHROMIUM_PRTYPES_H_ */ diff --git a/crypto/third_party/nss/chromium-sha256.h b/crypto/third_party/nss/chromium-sha256.h new file mode 100644 index 0000000000000..52815ca7f10d0 --- /dev/null +++ b/crypto/third_party/nss/chromium-sha256.h @@ -0,0 +1,51 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef CRYPTO_THIRD_PARTY_NSS_CHROMIUM_SHA_256_H_ +#define CRYPTO_THIRD_PARTY_NSS_CHROMIUM_SHA_256_H_ + +#include "crypto/third_party/nss/chromium-prtypes.h" + +struct SHA256ContextStr { + union { + PRUint32 w[64]; /* message schedule, input buffer, plus 48 words */ + PRUint8 b[256]; + } u; + PRUint32 h[8]; /* 8 state variables */ + PRUint32 sizeHi,sizeLo; /* 64-bit count of hashed bytes. */ +}; + +#endif /* CRYPTO_THIRD_PARTY_NSS_CHROMIUM_SHA_256_H_ */ diff --git a/crypto/third_party/nss/pk11akey.cc b/crypto/third_party/nss/pk11akey.cc new file mode 100644 index 0000000000000..4db582fc6c4b9 --- /dev/null +++ b/crypto/third_party/nss/pk11akey.cc @@ -0,0 +1,98 @@ + /* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1994-2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Dr Stephen Henson + * Dr Vipul Gupta , and + * Douglas Stebila , Sun Microsystems Laboratories + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "crypto/third_party/nss/chromium-nss.h" + +#include + +#include "base/logging.h" + +// Based on PK11_ImportEncryptedPrivateKeyInfo function in +// mozilla/security/nss/lib/pk11wrap/pk11akey.c. +SECStatus ImportEncryptedECPrivateKeyInfoAndReturnKey( + PK11SlotInfo* slot, + SECKEYEncryptedPrivateKeyInfo* epki, + SECItem* password, + SECItem* nickname, + SECItem* public_value, + PRBool permanent, + PRBool sensitive, + SECKEYPrivateKey** private_key, + void* wincx) { + SECItem* crypto_param = NULL; + + CK_ATTRIBUTE_TYPE usage = CKA_SIGN; + + PK11SymKey* key = PK11_PBEKeyGen(slot, + &epki->algorithm, + password, + PR_FALSE, // faulty3DES + wincx); + if (key == NULL) { + DLOG(ERROR) << "PK11_PBEKeyGen: " << PORT_GetError(); + return SECFailure; + } + + CK_MECHANISM_TYPE crypto_mech_type = PK11_GetPBECryptoMechanism( + &epki->algorithm, &crypto_param, password); + if (crypto_mech_type == CKM_INVALID_MECHANISM) { + DLOG(ERROR) << "PK11_GetPBECryptoMechanism: " << PORT_GetError(); + PK11_FreeSymKey(key); + return SECFailure; + } + + crypto_mech_type = PK11_GetPadMechanism(crypto_mech_type); + + *private_key = PK11_UnwrapPrivKey(slot, key, crypto_mech_type, crypto_param, + &epki->encryptedData, nickname, + public_value, permanent, sensitive, CKK_EC, + &usage, 1, wincx); + + if (crypto_param != NULL) + SECITEM_ZfreeItem(crypto_param, PR_TRUE); + + PK11_FreeSymKey(key); + + if (!*private_key) { + DLOG(ERROR) << "PK11_UnwrapPrivKey: " << PORT_GetError(); + return SECFailure; + } + + return SECSuccess; +} diff --git a/crypto/third_party/nss/rsawrapr.c b/crypto/third_party/nss/rsawrapr.c new file mode 100644 index 0000000000000..73e498f937d1f --- /dev/null +++ b/crypto/third_party/nss/rsawrapr.c @@ -0,0 +1,160 @@ +/* + * PKCS#1 encoding and decoding functions. + * This file is believed to contain no code licensed from other parties. + * + * 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/. */ + +#include "seccomon.h" +#include "secerr.h" +#include "sechash.h" + +/* Needed for RSA-PSS functions */ +static const unsigned char eightZeros[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + +/* + * Mask generation function MGF1 as defined in PKCS #1 v2.1 / RFC 3447. + */ +static SECStatus +MGF1(HASH_HashType hashAlg, unsigned char *mask, unsigned int maskLen, + const unsigned char *mgfSeed, unsigned int mgfSeedLen) +{ + unsigned int digestLen; + PRUint32 counter, rounds; + unsigned char *tempHash, *temp; + const SECHashObject *hash; + void *hashContext; + unsigned char C[4]; + + hash = HASH_GetHashObject(hashAlg); + if (hash == NULL) + return SECFailure; + + hashContext = (*hash->create)(); + rounds = (maskLen + hash->length - 1) / hash->length; + for (counter = 0; counter < rounds; counter++) { + C[0] = (unsigned char)((counter >> 24) & 0xff); + C[1] = (unsigned char)((counter >> 16) & 0xff); + C[2] = (unsigned char)((counter >> 8) & 0xff); + C[3] = (unsigned char)(counter & 0xff); + + /* This could be optimized when the clone functions in + * rawhash.c are implemented. */ + (*hash->begin)(hashContext); + (*hash->update)(hashContext, mgfSeed, mgfSeedLen); + (*hash->update)(hashContext, C, sizeof C); + + tempHash = mask + counter * hash->length; + if (counter != (rounds-1)) { + (*hash->end)(hashContext, tempHash, &digestLen, hash->length); + } else { /* we're in the last round and need to cut the hash */ + temp = (unsigned char *)PORT_Alloc(hash->length); + (*hash->end)(hashContext, temp, &digestLen, hash->length); + PORT_Memcpy(tempHash, temp, maskLen - counter * hash->length); + PORT_Free(temp); + } + } + (*hash->destroy)(hashContext, PR_TRUE); + + return SECSuccess; +} + +/* + * Verify a RSA-PSS signature. + * Described in RFC 3447, section 9.1.2. + * We use mHash instead of M as input. + * emBits from the RFC is just modBits - 1, see section 8.1.2. + * We only support MGF1 as the MGF. + * + * NOTE: this code assumes modBits is a multiple of 8. + */ +SECStatus +emsa_pss_verify(const unsigned char *mHash, + const unsigned char *em, unsigned int emLen, + HASH_HashType hashAlg, HASH_HashType maskHashAlg, + unsigned int sLen) +{ + const SECHashObject *hash; + void *hash_context; + unsigned char *db; + unsigned char *H_; /* H' from the RFC */ + unsigned int i, dbMaskLen; + SECStatus rv; + + hash = HASH_GetHashObject(hashAlg); + dbMaskLen = emLen - hash->length - 1; + + /* Step 3 + 4 + 6 */ + if ((emLen < (hash->length + sLen + 2)) || + (em[emLen - 1] != 0xbc) || + ((em[0] & 0x80) != 0)) { + PORT_SetError(SEC_ERROR_BAD_SIGNATURE); + return SECFailure; + } + + /* Step 7 */ + db = (unsigned char *)PORT_Alloc(dbMaskLen); + if (db == NULL) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + return SECFailure; + } + /* &em[dbMaskLen] points to H, used as mgfSeed */ + MGF1(maskHashAlg, db, dbMaskLen, &em[dbMaskLen], hash->length); + + /* Step 8 */ + for (i = 0; i < dbMaskLen; i++) { + db[i] ^= em[i]; + } + + /* Step 9 */ + db[0] &= 0x7f; + + /* Step 10 */ + for (i = 0; i < (dbMaskLen - sLen - 1); i++) { + if (db[i] != 0) { + PORT_Free(db); + PORT_SetError(SEC_ERROR_BAD_SIGNATURE); + return SECFailure; + } + } + if (db[dbMaskLen - sLen - 1] != 0x01) { + PORT_Free(db); + PORT_SetError(SEC_ERROR_BAD_SIGNATURE); + return SECFailure; + } + + /* Step 12 + 13 */ + H_ = (unsigned char *)PORT_Alloc(hash->length); + if (H_ == NULL) { + PORT_Free(db); + PORT_SetError(SEC_ERROR_NO_MEMORY); + return SECFailure; + } + hash_context = (*hash->create)(); + if (hash_context == NULL) { + PORT_Free(db); + PORT_Free(H_); + PORT_SetError(SEC_ERROR_NO_MEMORY); + return SECFailure; + } + (*hash->begin)(hash_context); + (*hash->update)(hash_context, eightZeros, 8); + (*hash->update)(hash_context, mHash, hash->length); + (*hash->update)(hash_context, &db[dbMaskLen - sLen], sLen); + (*hash->end)(hash_context, H_, &i, hash->length); + (*hash->destroy)(hash_context, PR_TRUE); + + PORT_Free(db); + + /* Step 14 */ + if (PORT_Memcmp(H_, &em[dbMaskLen], hash->length) != 0) { + PORT_SetError(SEC_ERROR_BAD_SIGNATURE); + rv = SECFailure; + } else { + rv = SECSuccess; + } + + PORT_Free(H_); + return rv; +} diff --git a/crypto/third_party/nss/secsign.cc b/crypto/third_party/nss/secsign.cc new file mode 100644 index 0000000000000..a788defc70410 --- /dev/null +++ b/crypto/third_party/nss/secsign.cc @@ -0,0 +1,132 @@ +/* + * Signature stuff. + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1994-2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Dr Vipul Gupta , Sun Microsystems Laboratories + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "crypto/third_party/nss/chromium-nss.h" + +#include + +#include +#include +#include +#include + +#include "base/basictypes.h" +#include "base/logging.h" +#include "build/build_config.h" + +SECStatus DerSignData(PLArenaPool *arena, + SECItem *result, + SECItem *input, + SECKEYPrivateKey *key, + SECOidTag algo_id) { + if (key->keyType != ecKey) { + return SEC_DerSignData(arena, result, input->data, input->len, key, + algo_id); + } + + // NSS has a private function sec_DecodeSigAlg it uses to figure out the + // correct hash from the algorithm id. + HASH_HashType hash_type; + switch (algo_id) { + case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE: + hash_type = HASH_AlgSHA1; + break; +#ifdef SHA224_LENGTH + case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE: + hash_type = HASH_AlgSHA224; + break; +#endif + case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE: + hash_type = HASH_AlgSHA256; + break; + case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE: + hash_type = HASH_AlgSHA384; + break; + case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE: + hash_type = HASH_AlgSHA512; + break; + default: + PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); + return SECFailure; + } + + // Hash the input. + std::vector hash_data(HASH_ResultLen(hash_type)); + SECStatus rv = HASH_HashBuf( + hash_type, &hash_data[0], input->data, input->len); + if (rv != SECSuccess) + return rv; + SECItem hash = {siBuffer, &hash_data[0], + static_cast(hash_data.size())}; + + // Compute signature of hash. + int signature_len = PK11_SignatureLen(key); + std::vector signature_data(signature_len); + SECItem sig = {siBuffer, &signature_data[0], + static_cast(signature_len)}; + rv = PK11_Sign(key, &sig, &hash); + if (rv != SECSuccess) + return rv; + + CERTSignedData sd; + PORT_Memset(&sd, 0, sizeof(sd)); + // Fill in tbsCertificate. + sd.data.data = (unsigned char*) input->data; + sd.data.len = input->len; + + // Fill in signatureAlgorithm. + rv = SECOID_SetAlgorithmID(arena, &sd.signatureAlgorithm, algo_id, 0); + if (rv != SECSuccess) + return rv; + + // Fill in signatureValue. + rv = DSAU_EncodeDerSigWithLen(&sd.signature, &sig, sig.len); + if (rv != SECSuccess) + return rv; + sd.signature.len <<= 3; // Convert to bit string. + + // DER encode the signed data object. + void* encode_result = SEC_ASN1EncodeItem( + arena, result, &sd, SEC_ASN1_GET(CERT_SignedDataTemplate)); + + PORT_Free(sd.signature.data); + + return encode_result ? SECSuccess : SECFailure; +} diff --git a/crypto/third_party/nss/sha512.cc b/crypto/third_party/nss/sha512.cc new file mode 100644 index 0000000000000..5ef4e5062dcb1 --- /dev/null +++ b/crypto/third_party/nss/sha512.cc @@ -0,0 +1,1391 @@ +/* + * sha512.c - implementation of SHA256, SHA384 and SHA512 + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* $Id: sha512.c,v 1.9 2006/10/13 16:54:04 wtchang%redhat.com Exp $ */ + +// Prevent manual unrolling in the sha256 code, which reduces the binary code +// size from ~10k to ~1k. The performance should be reasonable for our use. +#define NOUNROLL256 1 + +#include "crypto/third_party/nss/chromium-prtypes.h" /* for PRUintXX */ +#if defined(_X86_) || defined(SHA_NO_LONG_LONG) +#define NOUNROLL512 1 +#undef HAVE_LONG_LONG +#endif +#include "crypto/third_party/nss/chromium-blapi.h" +#include "crypto/third_party/nss/chromium-sha256.h" /* for struct SHA256ContextStr */ + +#include +#include +#define PORT_New(type) static_cast(malloc(sizeof(type))) +#define PORT_ZFree(ptr, len) do { memset(ptr, 0, len); free(ptr); } while (0) +#define PORT_Strlen(s) static_cast(strlen(s)) +#define PORT_Memcpy memcpy + +/* ============= Common constants and defines ======================= */ + +#define W ctx->u.w +#define B ctx->u.b +#define H ctx->h + +#define SHR(x,n) (x >> n) +#define SHL(x,n) (x << n) +#define Ch(x,y,z) ((x & y) ^ (~x & z)) +#define Maj(x,y,z) ((x & y) ^ (x & z) ^ (y & z)) + +/* Padding used with all flavors of SHA */ +static const PRUint8 pad[240] = { +0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + /* compiler will fill the rest in with zeros */ +}; + +/* ============= SHA256 implemenmtation ================================== */ + +/* SHA-256 constants, K256. */ +static const PRUint32 K256[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +/* SHA-256 initial hash values */ +static const PRUint32 H256[8] = { + 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, + 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 +}; + +#if defined(_MSC_VER) && defined(_X86_) +#ifndef FORCEINLINE +#if (_MSC_VER >= 1200) +#define FORCEINLINE __forceinline +#else +#define FORCEINLINE __inline +#endif +#endif +#define FASTCALL __fastcall + +static FORCEINLINE PRUint32 FASTCALL +swap4b(PRUint32 dwd) +{ + __asm { + mov eax,dwd + bswap eax + } +} + +#define SHA_HTONL(x) swap4b(x) +#define BYTESWAP4(x) x = SHA_HTONL(x) + +#elif defined(LINUX) && defined(_X86_) +#undef __OPTIMIZE__ +#define __OPTIMIZE__ 1 +#undef __pentium__ +#define __pentium__ 1 +#include +#define SHA_HTONL(x) bswap_32(x) +#define BYTESWAP4(x) x = SHA_HTONL(x) + +#else /* neither windows nor Linux PC */ +#define SWAP4MASK 0x00FF00FF +#define SHA_HTONL(x) (t1 = (x), t1 = (t1 << 16) | (t1 >> 16), \ + ((t1 & SWAP4MASK) << 8) | ((t1 >> 8) & SWAP4MASK)) +#define BYTESWAP4(x) x = SHA_HTONL(x) +#endif + +#if defined(_MSC_VER) && defined(_X86_) +#pragma intrinsic (_lrotr, _lrotl) +#define ROTR32(x,n) _lrotr(x,n) +#define ROTL32(x,n) _lrotl(x,n) +#else +#define ROTR32(x,n) ((x >> n) | (x << ((8 * sizeof x) - n))) +#define ROTL32(x,n) ((x << n) | (x >> ((8 * sizeof x) - n))) +#endif + +/* Capitol Sigma and lower case sigma functions */ +#define S0(x) (ROTR32(x, 2) ^ ROTR32(x,13) ^ ROTR32(x,22)) +#define S1(x) (ROTR32(x, 6) ^ ROTR32(x,11) ^ ROTR32(x,25)) +#define s0(x) (t1 = x, ROTR32(t1, 7) ^ ROTR32(t1,18) ^ SHR(t1, 3)) +#define s1(x) (t2 = x, ROTR32(t2,17) ^ ROTR32(t2,19) ^ SHR(t2,10)) + +SHA256Context * +SHA256_NewContext(void) +{ + SHA256Context *ctx = PORT_New(SHA256Context); + return ctx; +} + +void +SHA256_DestroyContext(SHA256Context *ctx, PRBool freeit) +{ + if (freeit) { + PORT_ZFree(ctx, sizeof *ctx); + } +} + +void +SHA256_Begin(SHA256Context *ctx) +{ + memset(ctx, 0, sizeof *ctx); + memcpy(H, H256, sizeof H256); +} + +static void +SHA256_Compress(SHA256Context *ctx) +{ + { + register PRUint32 t1, t2; + +#if defined(IS_LITTLE_ENDIAN) + BYTESWAP4(W[0]); + BYTESWAP4(W[1]); + BYTESWAP4(W[2]); + BYTESWAP4(W[3]); + BYTESWAP4(W[4]); + BYTESWAP4(W[5]); + BYTESWAP4(W[6]); + BYTESWAP4(W[7]); + BYTESWAP4(W[8]); + BYTESWAP4(W[9]); + BYTESWAP4(W[10]); + BYTESWAP4(W[11]); + BYTESWAP4(W[12]); + BYTESWAP4(W[13]); + BYTESWAP4(W[14]); + BYTESWAP4(W[15]); +#endif + +#define INITW(t) W[t] = (s1(W[t-2]) + W[t-7] + s0(W[t-15]) + W[t-16]) + + /* prepare the "message schedule" */ +#ifdef NOUNROLL256 + { + int t; + for (t = 16; t < 64; ++t) { + INITW(t); + } + } +#else + INITW(16); + INITW(17); + INITW(18); + INITW(19); + + INITW(20); + INITW(21); + INITW(22); + INITW(23); + INITW(24); + INITW(25); + INITW(26); + INITW(27); + INITW(28); + INITW(29); + + INITW(30); + INITW(31); + INITW(32); + INITW(33); + INITW(34); + INITW(35); + INITW(36); + INITW(37); + INITW(38); + INITW(39); + + INITW(40); + INITW(41); + INITW(42); + INITW(43); + INITW(44); + INITW(45); + INITW(46); + INITW(47); + INITW(48); + INITW(49); + + INITW(50); + INITW(51); + INITW(52); + INITW(53); + INITW(54); + INITW(55); + INITW(56); + INITW(57); + INITW(58); + INITW(59); + + INITW(60); + INITW(61); + INITW(62); + INITW(63); + +#endif +#undef INITW + } + { + PRUint32 a, b, c, d, e, f, g, h; + + a = H[0]; + b = H[1]; + c = H[2]; + d = H[3]; + e = H[4]; + f = H[5]; + g = H[6]; + h = H[7]; + +#define ROUND(n,a,b,c,d,e,f,g,h) \ + h += S1(e) + Ch(e,f,g) + K256[n] + W[n]; \ + d += h; \ + h += S0(a) + Maj(a,b,c); + +#ifdef NOUNROLL256 + { + int t; + for (t = 0; t < 64; t+= 8) { + ROUND(t+0,a,b,c,d,e,f,g,h) + ROUND(t+1,h,a,b,c,d,e,f,g) + ROUND(t+2,g,h,a,b,c,d,e,f) + ROUND(t+3,f,g,h,a,b,c,d,e) + ROUND(t+4,e,f,g,h,a,b,c,d) + ROUND(t+5,d,e,f,g,h,a,b,c) + ROUND(t+6,c,d,e,f,g,h,a,b) + ROUND(t+7,b,c,d,e,f,g,h,a) + } + } +#else + ROUND( 0,a,b,c,d,e,f,g,h) + ROUND( 1,h,a,b,c,d,e,f,g) + ROUND( 2,g,h,a,b,c,d,e,f) + ROUND( 3,f,g,h,a,b,c,d,e) + ROUND( 4,e,f,g,h,a,b,c,d) + ROUND( 5,d,e,f,g,h,a,b,c) + ROUND( 6,c,d,e,f,g,h,a,b) + ROUND( 7,b,c,d,e,f,g,h,a) + + ROUND( 8,a,b,c,d,e,f,g,h) + ROUND( 9,h,a,b,c,d,e,f,g) + ROUND(10,g,h,a,b,c,d,e,f) + ROUND(11,f,g,h,a,b,c,d,e) + ROUND(12,e,f,g,h,a,b,c,d) + ROUND(13,d,e,f,g,h,a,b,c) + ROUND(14,c,d,e,f,g,h,a,b) + ROUND(15,b,c,d,e,f,g,h,a) + + ROUND(16,a,b,c,d,e,f,g,h) + ROUND(17,h,a,b,c,d,e,f,g) + ROUND(18,g,h,a,b,c,d,e,f) + ROUND(19,f,g,h,a,b,c,d,e) + ROUND(20,e,f,g,h,a,b,c,d) + ROUND(21,d,e,f,g,h,a,b,c) + ROUND(22,c,d,e,f,g,h,a,b) + ROUND(23,b,c,d,e,f,g,h,a) + + ROUND(24,a,b,c,d,e,f,g,h) + ROUND(25,h,a,b,c,d,e,f,g) + ROUND(26,g,h,a,b,c,d,e,f) + ROUND(27,f,g,h,a,b,c,d,e) + ROUND(28,e,f,g,h,a,b,c,d) + ROUND(29,d,e,f,g,h,a,b,c) + ROUND(30,c,d,e,f,g,h,a,b) + ROUND(31,b,c,d,e,f,g,h,a) + + ROUND(32,a,b,c,d,e,f,g,h) + ROUND(33,h,a,b,c,d,e,f,g) + ROUND(34,g,h,a,b,c,d,e,f) + ROUND(35,f,g,h,a,b,c,d,e) + ROUND(36,e,f,g,h,a,b,c,d) + ROUND(37,d,e,f,g,h,a,b,c) + ROUND(38,c,d,e,f,g,h,a,b) + ROUND(39,b,c,d,e,f,g,h,a) + + ROUND(40,a,b,c,d,e,f,g,h) + ROUND(41,h,a,b,c,d,e,f,g) + ROUND(42,g,h,a,b,c,d,e,f) + ROUND(43,f,g,h,a,b,c,d,e) + ROUND(44,e,f,g,h,a,b,c,d) + ROUND(45,d,e,f,g,h,a,b,c) + ROUND(46,c,d,e,f,g,h,a,b) + ROUND(47,b,c,d,e,f,g,h,a) + + ROUND(48,a,b,c,d,e,f,g,h) + ROUND(49,h,a,b,c,d,e,f,g) + ROUND(50,g,h,a,b,c,d,e,f) + ROUND(51,f,g,h,a,b,c,d,e) + ROUND(52,e,f,g,h,a,b,c,d) + ROUND(53,d,e,f,g,h,a,b,c) + ROUND(54,c,d,e,f,g,h,a,b) + ROUND(55,b,c,d,e,f,g,h,a) + + ROUND(56,a,b,c,d,e,f,g,h) + ROUND(57,h,a,b,c,d,e,f,g) + ROUND(58,g,h,a,b,c,d,e,f) + ROUND(59,f,g,h,a,b,c,d,e) + ROUND(60,e,f,g,h,a,b,c,d) + ROUND(61,d,e,f,g,h,a,b,c) + ROUND(62,c,d,e,f,g,h,a,b) + ROUND(63,b,c,d,e,f,g,h,a) +#endif + + H[0] += a; + H[1] += b; + H[2] += c; + H[3] += d; + H[4] += e; + H[5] += f; + H[6] += g; + H[7] += h; + } +#undef ROUND +} + +#undef s0 +#undef s1 +#undef S0 +#undef S1 + +void +SHA256_Update(SHA256Context *ctx, const unsigned char *input, + unsigned int inputLen) +{ + unsigned int inBuf = ctx->sizeLo & 0x3f; + if (!inputLen) + return; + + /* Add inputLen into the count of bytes processed, before processing */ + if ((ctx->sizeLo += inputLen) < inputLen) + ctx->sizeHi++; + + /* if data already in buffer, attemp to fill rest of buffer */ + if (inBuf) { + unsigned int todo = SHA256_BLOCK_LENGTH - inBuf; + if (inputLen < todo) + todo = inputLen; + memcpy(B + inBuf, input, todo); + input += todo; + inputLen -= todo; + if (inBuf + todo == SHA256_BLOCK_LENGTH) + SHA256_Compress(ctx); + } + + /* if enough data to fill one or more whole buffers, process them. */ + while (inputLen >= SHA256_BLOCK_LENGTH) { + memcpy(B, input, SHA256_BLOCK_LENGTH); + input += SHA256_BLOCK_LENGTH; + inputLen -= SHA256_BLOCK_LENGTH; + SHA256_Compress(ctx); + } + /* if data left over, fill it into buffer */ + if (inputLen) + memcpy(B, input, inputLen); +} + +void +SHA256_End(SHA256Context *ctx, unsigned char *digest, + unsigned int *digestLen, unsigned int maxDigestLen) +{ + unsigned int inBuf = ctx->sizeLo & 0x3f; + unsigned int padLen = (inBuf < 56) ? (56 - inBuf) : (56 + 64 - inBuf); + PRUint32 hi, lo; +#ifdef SWAP4MASK + PRUint32 t1; +#endif + + hi = (ctx->sizeHi << 3) | (ctx->sizeLo >> 29); + lo = (ctx->sizeLo << 3); + + SHA256_Update(ctx, pad, padLen); + +#if defined(IS_LITTLE_ENDIAN) + W[14] = SHA_HTONL(hi); + W[15] = SHA_HTONL(lo); +#else + W[14] = hi; + W[15] = lo; +#endif + SHA256_Compress(ctx); + + /* now output the answer */ +#if defined(IS_LITTLE_ENDIAN) + BYTESWAP4(H[0]); + BYTESWAP4(H[1]); + BYTESWAP4(H[2]); + BYTESWAP4(H[3]); + BYTESWAP4(H[4]); + BYTESWAP4(H[5]); + BYTESWAP4(H[6]); + BYTESWAP4(H[7]); +#endif + padLen = PR_MIN(SHA256_LENGTH, maxDigestLen); + memcpy(digest, H, padLen); + if (digestLen) + *digestLen = padLen; +} + +/* Comment out unused code, mostly the SHA384 and SHA512 implementations. */ +#if 0 +SECStatus +SHA256_HashBuf(unsigned char *dest, const unsigned char *src, + unsigned int src_length) +{ + SHA256Context ctx; + unsigned int outLen; + + SHA256_Begin(&ctx); + SHA256_Update(&ctx, src, src_length); + SHA256_End(&ctx, dest, &outLen, SHA256_LENGTH); + + return SECSuccess; +} + + +SECStatus +SHA256_Hash(unsigned char *dest, const char *src) +{ + return SHA256_HashBuf(dest, (const unsigned char *)src, PORT_Strlen(src)); +} + + +void SHA256_TraceState(SHA256Context *ctx) { } + +unsigned int +SHA256_FlattenSize(SHA256Context *ctx) +{ + return sizeof *ctx; +} + +SECStatus +SHA256_Flatten(SHA256Context *ctx,unsigned char *space) +{ + PORT_Memcpy(space, ctx, sizeof *ctx); + return SECSuccess; +} + +SHA256Context * +SHA256_Resurrect(unsigned char *space, void *arg) +{ + SHA256Context *ctx = SHA256_NewContext(); + if (ctx) + PORT_Memcpy(ctx, space, sizeof *ctx); + return ctx; +} + +void SHA256_Clone(SHA256Context *dest, SHA256Context *src) +{ + memcpy(dest, src, sizeof *dest); +} + + +/* ======= SHA512 and SHA384 common constants and defines ================= */ + +/* common #defines for SHA512 and SHA384 */ +#if defined(HAVE_LONG_LONG) +#define ROTR64(x,n) ((x >> n) | (x << (64 - n))) +#define ROTL64(x,n) ((x << n) | (x >> (64 - n))) + +#define S0(x) (ROTR64(x,28) ^ ROTR64(x,34) ^ ROTR64(x,39)) +#define S1(x) (ROTR64(x,14) ^ ROTR64(x,18) ^ ROTR64(x,41)) +#define s0(x) (t1 = x, ROTR64(t1, 1) ^ ROTR64(t1, 8) ^ SHR(t1,7)) +#define s1(x) (t2 = x, ROTR64(t2,19) ^ ROTR64(t2,61) ^ SHR(t2,6)) + +#if PR_BYTES_PER_LONG == 8 +#define ULLC(hi,lo) 0x ## hi ## lo ## UL +#elif defined(_MSC_VER) +#define ULLC(hi,lo) 0x ## hi ## lo ## ui64 +#else +#define ULLC(hi,lo) 0x ## hi ## lo ## ULL +#endif + +#define SHA_MASK16 ULLC(0000FFFF,0000FFFF) +#define SHA_MASK8 ULLC(00FF00FF,00FF00FF) +#define SHA_HTONLL(x) (t1 = x, \ + t1 = ((t1 & SHA_MASK8 ) << 8) | ((t1 >> 8) & SHA_MASK8 ), \ + t1 = ((t1 & SHA_MASK16) << 16) | ((t1 >> 16) & SHA_MASK16), \ + (t1 >> 32) | (t1 << 32)) +#define BYTESWAP8(x) x = SHA_HTONLL(x) + +#else /* no long long */ + +#if defined(IS_LITTLE_ENDIAN) +#define ULLC(hi,lo) { 0x ## lo ## U, 0x ## hi ## U } +#else +#define ULLC(hi,lo) { 0x ## hi ## U, 0x ## lo ## U } +#endif + +#define SHA_HTONLL(x) ( BYTESWAP4(x.lo), BYTESWAP4(x.hi), \ + x.hi ^= x.lo ^= x.hi ^= x.lo, x) +#define BYTESWAP8(x) do { PRUint32 tmp; BYTESWAP4(x.lo); BYTESWAP4(x.hi); \ + tmp = x.lo; x.lo = x.hi; x.hi = tmp; } while (0) +#endif + +/* SHA-384 and SHA-512 constants, K512. */ +static const PRUint64 K512[80] = { +#if PR_BYTES_PER_LONG == 8 + 0x428a2f98d728ae22UL , 0x7137449123ef65cdUL , + 0xb5c0fbcfec4d3b2fUL , 0xe9b5dba58189dbbcUL , + 0x3956c25bf348b538UL , 0x59f111f1b605d019UL , + 0x923f82a4af194f9bUL , 0xab1c5ed5da6d8118UL , + 0xd807aa98a3030242UL , 0x12835b0145706fbeUL , + 0x243185be4ee4b28cUL , 0x550c7dc3d5ffb4e2UL , + 0x72be5d74f27b896fUL , 0x80deb1fe3b1696b1UL , + 0x9bdc06a725c71235UL , 0xc19bf174cf692694UL , + 0xe49b69c19ef14ad2UL , 0xefbe4786384f25e3UL , + 0x0fc19dc68b8cd5b5UL , 0x240ca1cc77ac9c65UL , + 0x2de92c6f592b0275UL , 0x4a7484aa6ea6e483UL , + 0x5cb0a9dcbd41fbd4UL , 0x76f988da831153b5UL , + 0x983e5152ee66dfabUL , 0xa831c66d2db43210UL , + 0xb00327c898fb213fUL , 0xbf597fc7beef0ee4UL , + 0xc6e00bf33da88fc2UL , 0xd5a79147930aa725UL , + 0x06ca6351e003826fUL , 0x142929670a0e6e70UL , + 0x27b70a8546d22ffcUL , 0x2e1b21385c26c926UL , + 0x4d2c6dfc5ac42aedUL , 0x53380d139d95b3dfUL , + 0x650a73548baf63deUL , 0x766a0abb3c77b2a8UL , + 0x81c2c92e47edaee6UL , 0x92722c851482353bUL , + 0xa2bfe8a14cf10364UL , 0xa81a664bbc423001UL , + 0xc24b8b70d0f89791UL , 0xc76c51a30654be30UL , + 0xd192e819d6ef5218UL , 0xd69906245565a910UL , + 0xf40e35855771202aUL , 0x106aa07032bbd1b8UL , + 0x19a4c116b8d2d0c8UL , 0x1e376c085141ab53UL , + 0x2748774cdf8eeb99UL , 0x34b0bcb5e19b48a8UL , + 0x391c0cb3c5c95a63UL , 0x4ed8aa4ae3418acbUL , + 0x5b9cca4f7763e373UL , 0x682e6ff3d6b2b8a3UL , + 0x748f82ee5defb2fcUL , 0x78a5636f43172f60UL , + 0x84c87814a1f0ab72UL , 0x8cc702081a6439ecUL , + 0x90befffa23631e28UL , 0xa4506cebde82bde9UL , + 0xbef9a3f7b2c67915UL , 0xc67178f2e372532bUL , + 0xca273eceea26619cUL , 0xd186b8c721c0c207UL , + 0xeada7dd6cde0eb1eUL , 0xf57d4f7fee6ed178UL , + 0x06f067aa72176fbaUL , 0x0a637dc5a2c898a6UL , + 0x113f9804bef90daeUL , 0x1b710b35131c471bUL , + 0x28db77f523047d84UL , 0x32caab7b40c72493UL , + 0x3c9ebe0a15c9bebcUL , 0x431d67c49c100d4cUL , + 0x4cc5d4becb3e42b6UL , 0x597f299cfc657e2aUL , + 0x5fcb6fab3ad6faecUL , 0x6c44198c4a475817UL +#else + ULLC(428a2f98,d728ae22), ULLC(71374491,23ef65cd), + ULLC(b5c0fbcf,ec4d3b2f), ULLC(e9b5dba5,8189dbbc), + ULLC(3956c25b,f348b538), ULLC(59f111f1,b605d019), + ULLC(923f82a4,af194f9b), ULLC(ab1c5ed5,da6d8118), + ULLC(d807aa98,a3030242), ULLC(12835b01,45706fbe), + ULLC(243185be,4ee4b28c), ULLC(550c7dc3,d5ffb4e2), + ULLC(72be5d74,f27b896f), ULLC(80deb1fe,3b1696b1), + ULLC(9bdc06a7,25c71235), ULLC(c19bf174,cf692694), + ULLC(e49b69c1,9ef14ad2), ULLC(efbe4786,384f25e3), + ULLC(0fc19dc6,8b8cd5b5), ULLC(240ca1cc,77ac9c65), + ULLC(2de92c6f,592b0275), ULLC(4a7484aa,6ea6e483), + ULLC(5cb0a9dc,bd41fbd4), ULLC(76f988da,831153b5), + ULLC(983e5152,ee66dfab), ULLC(a831c66d,2db43210), + ULLC(b00327c8,98fb213f), ULLC(bf597fc7,beef0ee4), + ULLC(c6e00bf3,3da88fc2), ULLC(d5a79147,930aa725), + ULLC(06ca6351,e003826f), ULLC(14292967,0a0e6e70), + ULLC(27b70a85,46d22ffc), ULLC(2e1b2138,5c26c926), + ULLC(4d2c6dfc,5ac42aed), ULLC(53380d13,9d95b3df), + ULLC(650a7354,8baf63de), ULLC(766a0abb,3c77b2a8), + ULLC(81c2c92e,47edaee6), ULLC(92722c85,1482353b), + ULLC(a2bfe8a1,4cf10364), ULLC(a81a664b,bc423001), + ULLC(c24b8b70,d0f89791), ULLC(c76c51a3,0654be30), + ULLC(d192e819,d6ef5218), ULLC(d6990624,5565a910), + ULLC(f40e3585,5771202a), ULLC(106aa070,32bbd1b8), + ULLC(19a4c116,b8d2d0c8), ULLC(1e376c08,5141ab53), + ULLC(2748774c,df8eeb99), ULLC(34b0bcb5,e19b48a8), + ULLC(391c0cb3,c5c95a63), ULLC(4ed8aa4a,e3418acb), + ULLC(5b9cca4f,7763e373), ULLC(682e6ff3,d6b2b8a3), + ULLC(748f82ee,5defb2fc), ULLC(78a5636f,43172f60), + ULLC(84c87814,a1f0ab72), ULLC(8cc70208,1a6439ec), + ULLC(90befffa,23631e28), ULLC(a4506ceb,de82bde9), + ULLC(bef9a3f7,b2c67915), ULLC(c67178f2,e372532b), + ULLC(ca273ece,ea26619c), ULLC(d186b8c7,21c0c207), + ULLC(eada7dd6,cde0eb1e), ULLC(f57d4f7f,ee6ed178), + ULLC(06f067aa,72176fba), ULLC(0a637dc5,a2c898a6), + ULLC(113f9804,bef90dae), ULLC(1b710b35,131c471b), + ULLC(28db77f5,23047d84), ULLC(32caab7b,40c72493), + ULLC(3c9ebe0a,15c9bebc), ULLC(431d67c4,9c100d4c), + ULLC(4cc5d4be,cb3e42b6), ULLC(597f299c,fc657e2a), + ULLC(5fcb6fab,3ad6faec), ULLC(6c44198c,4a475817) +#endif +}; + +struct SHA512ContextStr { + union { + PRUint64 w[80]; /* message schedule, input buffer, plus 64 words */ + PRUint32 l[160]; + PRUint8 b[640]; + } u; + PRUint64 h[8]; /* 8 state variables */ + PRUint64 sizeLo; /* 64-bit count of hashed bytes. */ +}; + +/* =========== SHA512 implementation ===================================== */ + +/* SHA-512 initial hash values */ +static const PRUint64 H512[8] = { +#if PR_BYTES_PER_LONG == 8 + 0x6a09e667f3bcc908UL , 0xbb67ae8584caa73bUL , + 0x3c6ef372fe94f82bUL , 0xa54ff53a5f1d36f1UL , + 0x510e527fade682d1UL , 0x9b05688c2b3e6c1fUL , + 0x1f83d9abfb41bd6bUL , 0x5be0cd19137e2179UL +#else + ULLC(6a09e667,f3bcc908), ULLC(bb67ae85,84caa73b), + ULLC(3c6ef372,fe94f82b), ULLC(a54ff53a,5f1d36f1), + ULLC(510e527f,ade682d1), ULLC(9b05688c,2b3e6c1f), + ULLC(1f83d9ab,fb41bd6b), ULLC(5be0cd19,137e2179) +#endif +}; + + +SHA512Context * +SHA512_NewContext(void) +{ + SHA512Context *ctx = PORT_New(SHA512Context); + return ctx; +} + +void +SHA512_DestroyContext(SHA512Context *ctx, PRBool freeit) +{ + if (freeit) { + PORT_ZFree(ctx, sizeof *ctx); + } +} + +void +SHA512_Begin(SHA512Context *ctx) +{ + memset(ctx, 0, sizeof *ctx); + memcpy(H, H512, sizeof H512); +} + +#if defined(SHA512_TRACE) +#if defined(HAVE_LONG_LONG) +#define DUMP(n,a,d,e,h) printf(" t = %2d, %s = %016lx, %s = %016lx\n", \ + n, #e, d, #a, h); +#else +#define DUMP(n,a,d,e,h) printf(" t = %2d, %s = %08x%08x, %s = %08x%08x\n", \ + n, #e, d.hi, d.lo, #a, h.hi, h.lo); +#endif +#else +#define DUMP(n,a,d,e,h) +#endif + +#if defined(HAVE_LONG_LONG) + +#define ADDTO(x,y) y += x + +#define INITW(t) W[t] = (s1(W[t-2]) + W[t-7] + s0(W[t-15]) + W[t-16]) + +#define ROUND(n,a,b,c,d,e,f,g,h) \ + h += S1(e) + Ch(e,f,g) + K512[n] + W[n]; \ + d += h; \ + h += S0(a) + Maj(a,b,c); \ + DUMP(n,a,d,e,h) + +#else /* use only 32-bit variables, and don't unroll loops */ + +#undef NOUNROLL512 +#define NOUNROLL512 1 + +#define ADDTO(x,y) y.lo += x.lo; y.hi += x.hi + (x.lo > y.lo) + +#define ROTR64a(x,n,lo,hi) (x.lo >> n | x.hi << (32-n)) +#define ROTR64A(x,n,lo,hi) (x.lo << (64-n) | x.hi >> (n-32)) +#define SHR64a(x,n,lo,hi) (x.lo >> n | x.hi << (32-n)) + +/* Capitol Sigma and lower case sigma functions */ +#define s0lo(x) (ROTR64a(x,1,lo,hi) ^ ROTR64a(x,8,lo,hi) ^ SHR64a(x,7,lo,hi)) +#define s0hi(x) (ROTR64a(x,1,hi,lo) ^ ROTR64a(x,8,hi,lo) ^ (x.hi >> 7)) + +#define s1lo(x) (ROTR64a(x,19,lo,hi) ^ ROTR64A(x,61,lo,hi) ^ SHR64a(x,6,lo,hi)) +#define s1hi(x) (ROTR64a(x,19,hi,lo) ^ ROTR64A(x,61,hi,lo) ^ (x.hi >> 6)) + +#define S0lo(x)(ROTR64a(x,28,lo,hi) ^ ROTR64A(x,34,lo,hi) ^ ROTR64A(x,39,lo,hi)) +#define S0hi(x)(ROTR64a(x,28,hi,lo) ^ ROTR64A(x,34,hi,lo) ^ ROTR64A(x,39,hi,lo)) + +#define S1lo(x)(ROTR64a(x,14,lo,hi) ^ ROTR64a(x,18,lo,hi) ^ ROTR64A(x,41,lo,hi)) +#define S1hi(x)(ROTR64a(x,14,hi,lo) ^ ROTR64a(x,18,hi,lo) ^ ROTR64A(x,41,hi,lo)) + +/* 32-bit versions of Ch and Maj */ +#define Chxx(x,y,z,lo) ((x.lo & y.lo) ^ (~x.lo & z.lo)) +#define Majx(x,y,z,lo) ((x.lo & y.lo) ^ (x.lo & z.lo) ^ (y.lo & z.lo)) + +#define INITW(t) \ + do { \ + PRUint32 lo, tm; \ + PRUint32 cy = 0; \ + lo = s1lo(W[t-2]); \ + lo += (tm = W[t-7].lo); if (lo < tm) cy++; \ + lo += (tm = s0lo(W[t-15])); if (lo < tm) cy++; \ + lo += (tm = W[t-16].lo); if (lo < tm) cy++; \ + W[t].lo = lo; \ + W[t].hi = cy + s1hi(W[t-2]) + W[t-7].hi + s0hi(W[t-15]) + W[t-16].hi; \ + } while (0) + +#define ROUND(n,a,b,c,d,e,f,g,h) \ + { \ + PRUint32 lo, tm, cy; \ + lo = S1lo(e); \ + lo += (tm = Chxx(e,f,g,lo)); cy = (lo < tm); \ + lo += (tm = K512[n].lo); if (lo < tm) cy++; \ + lo += (tm = W[n].lo); if (lo < tm) cy++; \ + h.lo += lo; if (h.lo < lo) cy++; \ + h.hi += cy + S1hi(e) + Chxx(e,f,g,hi) + K512[n].hi + W[n].hi; \ + d.lo += h.lo; \ + d.hi += h.hi + (d.lo < h.lo); \ + lo = S0lo(a); \ + lo += (tm = Majx(a,b,c,lo)); cy = (lo < tm); \ + h.lo += lo; if (h.lo < lo) cy++; \ + h.hi += cy + S0hi(a) + Majx(a,b,c,hi); \ + DUMP(n,a,d,e,h) \ + } +#endif + +static void +SHA512_Compress(SHA512Context *ctx) +{ +#if defined(IS_LITTLE_ENDIAN) + { +#if defined(HAVE_LONG_LONG) + PRUint64 t1; +#else + PRUint32 t1; +#endif + BYTESWAP8(W[0]); + BYTESWAP8(W[1]); + BYTESWAP8(W[2]); + BYTESWAP8(W[3]); + BYTESWAP8(W[4]); + BYTESWAP8(W[5]); + BYTESWAP8(W[6]); + BYTESWAP8(W[7]); + BYTESWAP8(W[8]); + BYTESWAP8(W[9]); + BYTESWAP8(W[10]); + BYTESWAP8(W[11]); + BYTESWAP8(W[12]); + BYTESWAP8(W[13]); + BYTESWAP8(W[14]); + BYTESWAP8(W[15]); + } +#endif + + { + PRUint64 t1, t2; +#ifdef NOUNROLL512 + { + /* prepare the "message schedule" */ + int t; + for (t = 16; t < 80; ++t) { + INITW(t); + } + } +#else + INITW(16); + INITW(17); + INITW(18); + INITW(19); + + INITW(20); + INITW(21); + INITW(22); + INITW(23); + INITW(24); + INITW(25); + INITW(26); + INITW(27); + INITW(28); + INITW(29); + + INITW(30); + INITW(31); + INITW(32); + INITW(33); + INITW(34); + INITW(35); + INITW(36); + INITW(37); + INITW(38); + INITW(39); + + INITW(40); + INITW(41); + INITW(42); + INITW(43); + INITW(44); + INITW(45); + INITW(46); + INITW(47); + INITW(48); + INITW(49); + + INITW(50); + INITW(51); + INITW(52); + INITW(53); + INITW(54); + INITW(55); + INITW(56); + INITW(57); + INITW(58); + INITW(59); + + INITW(60); + INITW(61); + INITW(62); + INITW(63); + INITW(64); + INITW(65); + INITW(66); + INITW(67); + INITW(68); + INITW(69); + + INITW(70); + INITW(71); + INITW(72); + INITW(73); + INITW(74); + INITW(75); + INITW(76); + INITW(77); + INITW(78); + INITW(79); +#endif + } +#ifdef SHA512_TRACE + { + int i; + for (i = 0; i < 80; ++i) { +#ifdef HAVE_LONG_LONG + printf("W[%2d] = %016lx\n", i, W[i]); +#else + printf("W[%2d] = %08x%08x\n", i, W[i].hi, W[i].lo); +#endif + } + } +#endif + { + PRUint64 a, b, c, d, e, f, g, h; + + a = H[0]; + b = H[1]; + c = H[2]; + d = H[3]; + e = H[4]; + f = H[5]; + g = H[6]; + h = H[7]; + +#ifdef NOUNROLL512 + { + int t; + for (t = 0; t < 80; t+= 8) { + ROUND(t+0,a,b,c,d,e,f,g,h) + ROUND(t+1,h,a,b,c,d,e,f,g) + ROUND(t+2,g,h,a,b,c,d,e,f) + ROUND(t+3,f,g,h,a,b,c,d,e) + ROUND(t+4,e,f,g,h,a,b,c,d) + ROUND(t+5,d,e,f,g,h,a,b,c) + ROUND(t+6,c,d,e,f,g,h,a,b) + ROUND(t+7,b,c,d,e,f,g,h,a) + } + } +#else + ROUND( 0,a,b,c,d,e,f,g,h) + ROUND( 1,h,a,b,c,d,e,f,g) + ROUND( 2,g,h,a,b,c,d,e,f) + ROUND( 3,f,g,h,a,b,c,d,e) + ROUND( 4,e,f,g,h,a,b,c,d) + ROUND( 5,d,e,f,g,h,a,b,c) + ROUND( 6,c,d,e,f,g,h,a,b) + ROUND( 7,b,c,d,e,f,g,h,a) + + ROUND( 8,a,b,c,d,e,f,g,h) + ROUND( 9,h,a,b,c,d,e,f,g) + ROUND(10,g,h,a,b,c,d,e,f) + ROUND(11,f,g,h,a,b,c,d,e) + ROUND(12,e,f,g,h,a,b,c,d) + ROUND(13,d,e,f,g,h,a,b,c) + ROUND(14,c,d,e,f,g,h,a,b) + ROUND(15,b,c,d,e,f,g,h,a) + + ROUND(16,a,b,c,d,e,f,g,h) + ROUND(17,h,a,b,c,d,e,f,g) + ROUND(18,g,h,a,b,c,d,e,f) + ROUND(19,f,g,h,a,b,c,d,e) + ROUND(20,e,f,g,h,a,b,c,d) + ROUND(21,d,e,f,g,h,a,b,c) + ROUND(22,c,d,e,f,g,h,a,b) + ROUND(23,b,c,d,e,f,g,h,a) + + ROUND(24,a,b,c,d,e,f,g,h) + ROUND(25,h,a,b,c,d,e,f,g) + ROUND(26,g,h,a,b,c,d,e,f) + ROUND(27,f,g,h,a,b,c,d,e) + ROUND(28,e,f,g,h,a,b,c,d) + ROUND(29,d,e,f,g,h,a,b,c) + ROUND(30,c,d,e,f,g,h,a,b) + ROUND(31,b,c,d,e,f,g,h,a) + + ROUND(32,a,b,c,d,e,f,g,h) + ROUND(33,h,a,b,c,d,e,f,g) + ROUND(34,g,h,a,b,c,d,e,f) + ROUND(35,f,g,h,a,b,c,d,e) + ROUND(36,e,f,g,h,a,b,c,d) + ROUND(37,d,e,f,g,h,a,b,c) + ROUND(38,c,d,e,f,g,h,a,b) + ROUND(39,b,c,d,e,f,g,h,a) + + ROUND(40,a,b,c,d,e,f,g,h) + ROUND(41,h,a,b,c,d,e,f,g) + ROUND(42,g,h,a,b,c,d,e,f) + ROUND(43,f,g,h,a,b,c,d,e) + ROUND(44,e,f,g,h,a,b,c,d) + ROUND(45,d,e,f,g,h,a,b,c) + ROUND(46,c,d,e,f,g,h,a,b) + ROUND(47,b,c,d,e,f,g,h,a) + + ROUND(48,a,b,c,d,e,f,g,h) + ROUND(49,h,a,b,c,d,e,f,g) + ROUND(50,g,h,a,b,c,d,e,f) + ROUND(51,f,g,h,a,b,c,d,e) + ROUND(52,e,f,g,h,a,b,c,d) + ROUND(53,d,e,f,g,h,a,b,c) + ROUND(54,c,d,e,f,g,h,a,b) + ROUND(55,b,c,d,e,f,g,h,a) + + ROUND(56,a,b,c,d,e,f,g,h) + ROUND(57,h,a,b,c,d,e,f,g) + ROUND(58,g,h,a,b,c,d,e,f) + ROUND(59,f,g,h,a,b,c,d,e) + ROUND(60,e,f,g,h,a,b,c,d) + ROUND(61,d,e,f,g,h,a,b,c) + ROUND(62,c,d,e,f,g,h,a,b) + ROUND(63,b,c,d,e,f,g,h,a) + + ROUND(64,a,b,c,d,e,f,g,h) + ROUND(65,h,a,b,c,d,e,f,g) + ROUND(66,g,h,a,b,c,d,e,f) + ROUND(67,f,g,h,a,b,c,d,e) + ROUND(68,e,f,g,h,a,b,c,d) + ROUND(69,d,e,f,g,h,a,b,c) + ROUND(70,c,d,e,f,g,h,a,b) + ROUND(71,b,c,d,e,f,g,h,a) + + ROUND(72,a,b,c,d,e,f,g,h) + ROUND(73,h,a,b,c,d,e,f,g) + ROUND(74,g,h,a,b,c,d,e,f) + ROUND(75,f,g,h,a,b,c,d,e) + ROUND(76,e,f,g,h,a,b,c,d) + ROUND(77,d,e,f,g,h,a,b,c) + ROUND(78,c,d,e,f,g,h,a,b) + ROUND(79,b,c,d,e,f,g,h,a) +#endif + + ADDTO(a,H[0]); + ADDTO(b,H[1]); + ADDTO(c,H[2]); + ADDTO(d,H[3]); + ADDTO(e,H[4]); + ADDTO(f,H[5]); + ADDTO(g,H[6]); + ADDTO(h,H[7]); + } +} + +void +SHA512_Update(SHA512Context *ctx, const unsigned char *input, + unsigned int inputLen) +{ + unsigned int inBuf; + if (!inputLen) + return; + +#if defined(HAVE_LONG_LONG) + inBuf = (unsigned int)ctx->sizeLo & 0x7f; + /* Add inputLen into the count of bytes processed, before processing */ + ctx->sizeLo += inputLen; +#else + inBuf = (unsigned int)ctx->sizeLo.lo & 0x7f; + ctx->sizeLo.lo += inputLen; + if (ctx->sizeLo.lo < inputLen) ctx->sizeLo.hi++; +#endif + + /* if data already in buffer, attemp to fill rest of buffer */ + if (inBuf) { + unsigned int todo = SHA512_BLOCK_LENGTH - inBuf; + if (inputLen < todo) + todo = inputLen; + memcpy(B + inBuf, input, todo); + input += todo; + inputLen -= todo; + if (inBuf + todo == SHA512_BLOCK_LENGTH) + SHA512_Compress(ctx); + } + + /* if enough data to fill one or more whole buffers, process them. */ + while (inputLen >= SHA512_BLOCK_LENGTH) { + memcpy(B, input, SHA512_BLOCK_LENGTH); + input += SHA512_BLOCK_LENGTH; + inputLen -= SHA512_BLOCK_LENGTH; + SHA512_Compress(ctx); + } + /* if data left over, fill it into buffer */ + if (inputLen) + memcpy(B, input, inputLen); +} + +void +SHA512_End(SHA512Context *ctx, unsigned char *digest, + unsigned int *digestLen, unsigned int maxDigestLen) +{ +#if defined(HAVE_LONG_LONG) + unsigned int inBuf = (unsigned int)ctx->sizeLo & 0x7f; + unsigned int padLen = (inBuf < 112) ? (112 - inBuf) : (112 + 128 - inBuf); + PRUint64 lo, t1; + lo = (ctx->sizeLo << 3); +#else + unsigned int inBuf = (unsigned int)ctx->sizeLo.lo & 0x7f; + unsigned int padLen = (inBuf < 112) ? (112 - inBuf) : (112 + 128 - inBuf); + PRUint64 lo = ctx->sizeLo; + PRUint32 t1; + lo.lo <<= 3; +#endif + + SHA512_Update(ctx, pad, padLen); + +#if defined(HAVE_LONG_LONG) + W[14] = 0; +#else + W[14].lo = 0; + W[14].hi = 0; +#endif + + W[15] = lo; +#if defined(IS_LITTLE_ENDIAN) + BYTESWAP8(W[15]); +#endif + SHA512_Compress(ctx); + + /* now output the answer */ +#if defined(IS_LITTLE_ENDIAN) + BYTESWAP8(H[0]); + BYTESWAP8(H[1]); + BYTESWAP8(H[2]); + BYTESWAP8(H[3]); + BYTESWAP8(H[4]); + BYTESWAP8(H[5]); + BYTESWAP8(H[6]); + BYTESWAP8(H[7]); +#endif + padLen = PR_MIN(SHA512_LENGTH, maxDigestLen); + memcpy(digest, H, padLen); + if (digestLen) + *digestLen = padLen; +} + +SECStatus +SHA512_HashBuf(unsigned char *dest, const unsigned char *src, + unsigned int src_length) +{ + SHA512Context ctx; + unsigned int outLen; + + SHA512_Begin(&ctx); + SHA512_Update(&ctx, src, src_length); + SHA512_End(&ctx, dest, &outLen, SHA512_LENGTH); + + return SECSuccess; +} + + +SECStatus +SHA512_Hash(unsigned char *dest, const char *src) +{ + return SHA512_HashBuf(dest, (const unsigned char *)src, PORT_Strlen(src)); +} + + +void SHA512_TraceState(SHA512Context *ctx) { } + +unsigned int +SHA512_FlattenSize(SHA512Context *ctx) +{ + return sizeof *ctx; +} + +SECStatus +SHA512_Flatten(SHA512Context *ctx,unsigned char *space) +{ + PORT_Memcpy(space, ctx, sizeof *ctx); + return SECSuccess; +} + +SHA512Context * +SHA512_Resurrect(unsigned char *space, void *arg) +{ + SHA512Context *ctx = SHA512_NewContext(); + if (ctx) + PORT_Memcpy(ctx, space, sizeof *ctx); + return ctx; +} + +void SHA512_Clone(SHA512Context *dest, SHA512Context *src) +{ + memcpy(dest, src, sizeof *dest); +} + +/* ======================================================================= */ +/* SHA384 uses a SHA512Context as the real context. +** The only differences between SHA384 an SHA512 are: +** a) the intialization values for the context, and +** b) the number of bytes of data produced as output. +*/ + +/* SHA-384 initial hash values */ +static const PRUint64 H384[8] = { +#if PR_BYTES_PER_LONG == 8 + 0xcbbb9d5dc1059ed8UL , 0x629a292a367cd507UL , + 0x9159015a3070dd17UL , 0x152fecd8f70e5939UL , + 0x67332667ffc00b31UL , 0x8eb44a8768581511UL , + 0xdb0c2e0d64f98fa7UL , 0x47b5481dbefa4fa4UL +#else + ULLC(cbbb9d5d,c1059ed8), ULLC(629a292a,367cd507), + ULLC(9159015a,3070dd17), ULLC(152fecd8,f70e5939), + ULLC(67332667,ffc00b31), ULLC(8eb44a87,68581511), + ULLC(db0c2e0d,64f98fa7), ULLC(47b5481d,befa4fa4) +#endif +}; + +SHA384Context * +SHA384_NewContext(void) +{ + return SHA512_NewContext(); +} + +void +SHA384_DestroyContext(SHA384Context *ctx, PRBool freeit) +{ + SHA512_DestroyContext(ctx, freeit); +} + +void +SHA384_Begin(SHA384Context *ctx) +{ + memset(ctx, 0, sizeof *ctx); + memcpy(H, H384, sizeof H384); +} + +void +SHA384_Update(SHA384Context *ctx, const unsigned char *input, + unsigned int inputLen) +{ + SHA512_Update(ctx, input, inputLen); +} + +void +SHA384_End(SHA384Context *ctx, unsigned char *digest, + unsigned int *digestLen, unsigned int maxDigestLen) +{ +#define SHA_MIN(a,b) (a < b ? a : b) + unsigned int maxLen = SHA_MIN(maxDigestLen, SHA384_LENGTH); + SHA512_End(ctx, digest, digestLen, maxLen); +} + +SECStatus +SHA384_HashBuf(unsigned char *dest, const unsigned char *src, + unsigned int src_length) +{ + SHA512Context ctx; + unsigned int outLen; + + SHA384_Begin(&ctx); + SHA512_Update(&ctx, src, src_length); + SHA512_End(&ctx, dest, &outLen, SHA384_LENGTH); + + return SECSuccess; +} + +SECStatus +SHA384_Hash(unsigned char *dest, const char *src) +{ + return SHA384_HashBuf(dest, (const unsigned char *)src, PORT_Strlen(src)); +} + +void SHA384_TraceState(SHA384Context *ctx) { } + +unsigned int +SHA384_FlattenSize(SHA384Context *ctx) +{ + return sizeof(SHA384Context); +} + +SECStatus +SHA384_Flatten(SHA384Context *ctx,unsigned char *space) +{ + return SHA512_Flatten(ctx, space); +} + +SHA384Context * +SHA384_Resurrect(unsigned char *space, void *arg) +{ + return SHA512_Resurrect(space, arg); +} + +void SHA384_Clone(SHA384Context *dest, SHA384Context *src) +{ + memcpy(dest, src, sizeof *dest); +} +#endif /* Comment out unused code. */ + +/* ======================================================================= */ +#ifdef SELFTEST +#include + +static const char abc[] = { "abc" }; +static const char abcdbc[] = { + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" +}; +static const char abcdef[] = { + "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" + "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" +}; + +void +dumpHash32(const unsigned char *buf, unsigned int bufLen) +{ + unsigned int i; + for (i = 0; i < bufLen; i += 4) { + printf(" %02x%02x%02x%02x", buf[i], buf[i+1], buf[i+2], buf[i+3]); + } + printf("\n"); +} + +void test256(void) +{ + unsigned char outBuf[SHA256_LENGTH]; + + printf("SHA256, input = %s\n", abc); + SHA256_Hash(outBuf, abc); + dumpHash32(outBuf, sizeof outBuf); + + printf("SHA256, input = %s\n", abcdbc); + SHA256_Hash(outBuf, abcdbc); + dumpHash32(outBuf, sizeof outBuf); +} + +void +dumpHash64(const unsigned char *buf, unsigned int bufLen) +{ + unsigned int i; + for (i = 0; i < bufLen; i += 8) { + if (i % 32 == 0) + printf("\n"); + printf(" %02x%02x%02x%02x%02x%02x%02x%02x", + buf[i ], buf[i+1], buf[i+2], buf[i+3], + buf[i+4], buf[i+5], buf[i+6], buf[i+7]); + } + printf("\n"); +} + +void test512(void) +{ + unsigned char outBuf[SHA512_LENGTH]; + + printf("SHA512, input = %s\n", abc); + SHA512_Hash(outBuf, abc); + dumpHash64(outBuf, sizeof outBuf); + + printf("SHA512, input = %s\n", abcdef); + SHA512_Hash(outBuf, abcdef); + dumpHash64(outBuf, sizeof outBuf); +} + +void time512(void) +{ + unsigned char outBuf[SHA512_LENGTH]; + + SHA512_Hash(outBuf, abc); + SHA512_Hash(outBuf, abcdef); +} + +void test384(void) +{ + unsigned char outBuf[SHA384_LENGTH]; + + printf("SHA384, input = %s\n", abc); + SHA384_Hash(outBuf, abc); + dumpHash64(outBuf, sizeof outBuf); + + printf("SHA384, input = %s\n", abcdef); + SHA384_Hash(outBuf, abcdef); + dumpHash64(outBuf, sizeof outBuf); +} + +int main (int argc, char *argv[], char *envp[]) +{ + int i = 1; + if (argc > 1) { + i = atoi(argv[1]); + } + if (i < 2) { + test256(); + test512(); + test384(); + } else { + while (i-- > 0) { + time512(); + } + printf("done\n"); + } + return 0; +} + +#endif diff --git a/crypto/wincrypt_shim.h b/crypto/wincrypt_shim.h new file mode 100644 index 0000000000000..799ac49feeb55 --- /dev/null +++ b/crypto/wincrypt_shim.h @@ -0,0 +1,25 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_CRYPTO_WINCRYPT_SHIM_H_ +#define NET_CRYPTO_WINCRYPT_SHIM_H_ + +// wincrypt.h defines macros which conflict with OpenSSL's types. This header +// includes wincrypt and undefines the OpenSSL macros which conflict. Any +// Chromium headers which include wincrypt should instead include this header. + +#include +#include + +// Undefine the macros which conflict with OpenSSL and define replacements. See +// http://msdn.microsoft.com/en-us/library/windows/desktop/aa378145(v=vs.85).aspx +#undef X509_CERT_PAIR +#undef X509_EXTENSIONS +#undef X509_NAME + +#define WINCRYPT_X509_CERT_PAIR ((LPCSTR) 53) +#define WINCRYPT_X509_EXTENSIONS ((LPCSTR) 5) +#define WINCRYPT_X509_NAME ((LPCSTR) 7) + +#endif // NET_CRYPTO_WINCRYPT_SHIM_H_ \ No newline at end of file diff --git a/foo.patch b/foo.patch new file mode 100644 index 0000000000000..dc9d8df3c69c8 --- /dev/null +++ b/foo.patch @@ -0,0 +1,56 @@ +commit 2f12ff08cc9215273040893a9b6c2b3fabccfb6b +Author: Adam Barth +Date: Thu Jul 16 18:00:01 2015 -0700 + + Improve dependencies + +diff --git a/sky/build/sky_app.gni b/sky/build/sky_app.gni +index 950bf82..6890cf6 100644 +--- a/sky/build/sky_app.gni ++++ b/sky/build/sky_app.gni +@@ -28,7 +28,7 @@ template("sky_app") { + + bundle_prefix = target_name + +- copy("copy_${bundle_prefix}_bundle") { ++ copy("gen_${bundle_prefix}_bundle") { + sources = [ + "$target_gen_dir/app.skyx", + ] +@@ -50,16 +50,20 @@ template("sky_app") { + "$target_gen_dir/app.skyx", + ] + deps = [ +- "//third_party/icu", +- ":copy_${bundle_prefix}_bundle", ++ ":$skyx_target_name", ++ ":gen_${bundle_prefix}_bundle", ++ "//third_party/icu:icudata", + ] + + if (defined(invoker.bundles)) { + foreach(bundle, invoker.bundles) { + bundle_gen_dir = get_label_info(bundle, "target_gen_dir") ++ bundle_dir = get_label_info(bundle, "dir") + bundle_name = get_label_info(bundle, "name") + sources += [ "$bundle_gen_dir/${bundle_name}.skyx" ] +- deps += [ bundle ] ++ deps += [ ++ "$bundle_dir:gen_${bundle_name}_bundle", ++ ] + } + } + } +diff --git a/sky/shell/BUILD.gn b/sky/shell/BUILD.gn +index 88c9d68..ae169d3 100644 +--- a/sky/shell/BUILD.gn ++++ b/sky/shell/BUILD.gn +@@ -136,7 +136,7 @@ if (is_android) { + "$root_build_dir/icudtl.dat", + ] + deps = [ +- "//third_party/icu", ++ "//third_party/icu:icudata", + ] + } + } else if (is_ios) { diff --git a/services/android/rules.gni b/services/android/rules.gni index 350b421b019d4..facf5057fed0d 100644 --- a/services/android/rules.gni +++ b/services/android/rules.gni @@ -44,6 +44,10 @@ template("mojo_android_java_application") { action(android_with_manifest_name) { script = "${servicess_android_path}/add_manifest_entry.py" + deps = [ + ":$android_standalone_name", + ] + input = dex_output_path inputs = [ input, @@ -74,6 +78,10 @@ template("mojo_android_java_application") { action(target_name) { script = rebase_path("mojo/public/tools/prepend.py", ".", mojo_root) + deps = [ + ":$android_with_manifest_name", + ] + input = dex_with_manifest_output_path inputs = [ input, diff --git a/sky/build/sky_app.gni b/sky/build/sky_app.gni index 950bf82c78b86..6890cf67ea48c 100644 --- a/sky/build/sky_app.gni +++ b/sky/build/sky_app.gni @@ -28,7 +28,7 @@ template("sky_app") { bundle_prefix = target_name - copy("copy_${bundle_prefix}_bundle") { + copy("gen_${bundle_prefix}_bundle") { sources = [ "$target_gen_dir/app.skyx", ] @@ -50,16 +50,20 @@ template("sky_app") { "$target_gen_dir/app.skyx", ] deps = [ - "//third_party/icu", - ":copy_${bundle_prefix}_bundle", + ":$skyx_target_name", + ":gen_${bundle_prefix}_bundle", + "//third_party/icu:icudata", ] if (defined(invoker.bundles)) { foreach(bundle, invoker.bundles) { bundle_gen_dir = get_label_info(bundle, "target_gen_dir") + bundle_dir = get_label_info(bundle, "dir") bundle_name = get_label_info(bundle, "name") sources += [ "$bundle_gen_dir/${bundle_name}.skyx" ] - deps += [ bundle ] + deps += [ + "$bundle_dir:gen_${bundle_name}_bundle", + ] } } } diff --git a/sky/engine/core/dom/shadow/ShadowRoot.cpp b/sky/engine/core/dom/shadow/ShadowRoot.cpp index a724e8f423237..20019075556e0 100644 --- a/sky/engine/core/dom/shadow/ShadowRoot.cpp +++ b/sky/engine/core/dom/shadow/ShadowRoot.cpp @@ -87,7 +87,7 @@ PassRefPtr ShadowRoot::cloneNode(bool, ExceptionState& exceptionState) PassRefPtr ShadowRoot::cloneNode(ExceptionState& exceptionState) { - return cloneNode(exceptionState); + return nullptr; } PassRefPtr ShadowRoot::cloneNode(bool deep) diff --git a/sky/engine/platform/fonts/GlyphPageTreeNode.cpp b/sky/engine/platform/fonts/GlyphPageTreeNode.cpp index 7ef8a591b3508..97ee3c1f431ac 100644 --- a/sky/engine/platform/fonts/GlyphPageTreeNode.cpp +++ b/sky/engine/platform/fonts/GlyphPageTreeNode.cpp @@ -120,10 +120,6 @@ void GlyphPageTreeNode::pruneTreeFontData(const SimpleFontData* fontData) static bool fill(GlyphPage* pageToFill, unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData) { bool hasGlyphs = fontData->fillGlyphPage(pageToFill, offset, length, buffer, bufferLength); -#if ENABLE(OPENTYPE_VERTICAL) - if (hasGlyphs && fontData->verticalData()) - fontData->verticalData()->substituteWithVerticalGlyphs(fontData, pageToFill, offset, length); -#endif return hasGlyphs; } diff --git a/sky/engine/platform/fonts/opentype/OpenTypeSanitizer.cpp b/sky/engine/platform/fonts/opentype/OpenTypeSanitizer.cpp index 7917f03c7b976..9d5d87572a0d2 100644 --- a/sky/engine/platform/fonts/opentype/OpenTypeSanitizer.cpp +++ b/sky/engine/platform/fonts/opentype/OpenTypeSanitizer.cpp @@ -30,22 +30,26 @@ #include "sky/engine/platform/fonts/opentype/OpenTypeSanitizer.h" -#include "gen/sky/platform/RuntimeEnabledFeatures.h" -#include "opentype-sanitiser.h" #include "ots-memory-stream.h" #include "sky/engine/platform/SharedBuffer.h" +#include + namespace blink { PassRefPtr OpenTypeSanitizer::sanitize() { - if (!m_buffer) + if (!m_buffer) { + setErrorString("Empty Buffer"); return nullptr; + } // This is the largest web font size which we'll try to transcode. static const size_t maxWebFontSize = 30 * 1024 * 1024; // 30 MB - if (m_buffer->size() > maxWebFontSize) + if (m_buffer->size() > maxWebFontSize) { + setErrorString("Web font size more than 30MB"); return nullptr; + } // A transcoded font is usually smaller than an original font. // However, it can be slightly bigger than the original one due to @@ -55,8 +59,12 @@ PassRefPtr OpenTypeSanitizer::sanitize() // much larger than the original. ots::ExpandingMemoryStream output(m_buffer->size(), maxWebFontSize); - if (!ots::Process(&output, reinterpret_cast(m_buffer->data()), m_buffer->size())) + BlinkOTSContext otsContext; + + if (!otsContext.Process(&output, reinterpret_cast(m_buffer->data()), m_buffer->size())) { + setErrorString(otsContext.getErrorString()); return nullptr; + } const size_t transcodeLen = output.Tell(); return SharedBuffer::create(static_cast(output.get()), transcodeLen); @@ -64,8 +72,57 @@ PassRefPtr OpenTypeSanitizer::sanitize() bool OpenTypeSanitizer::supportsFormat(const String& format) { - return equalIgnoringCase(format, "woff") - || (RuntimeEnabledFeatures::woff2Enabled() && equalIgnoringCase(format, "woff2")); + return equalIgnoringCase(format, "woff") || equalIgnoringCase(format, "woff2"); +} + +void BlinkOTSContext::Message(int level, const char *format, ...) +{ + va_list args; + va_start(args, format); + +#if COMPILER(MSVC) + int result = _vscprintf(format, args); +#else + char ch; + int result = vsnprintf(&ch, 1, format, args); +#endif + va_end(args); + + if (result <= 0) { + m_errorString = String("OTS Error"); + } else { + Vector buffer; + unsigned len = result; + buffer.grow(len + 1); + + va_start(args, format); + vsnprintf(buffer.data(), buffer.size(), format, args); + va_end(args); + m_errorString = StringImpl::create(reinterpret_cast(buffer.data()), len); + } +} + +ots::TableAction BlinkOTSContext::GetTableAction(uint32_t tag) +{ +#define TABLE_TAG(c1, c2, c3, c4) ((uint32_t)((((uint8_t)(c1)) << 24) | (((uint8_t)(c2)) << 16) | (((uint8_t)(c3)) << 8) | ((uint8_t)(c4)))) + + const uint32_t cbdtTag = TABLE_TAG('C', 'B', 'D', 'T'); + const uint32_t cblcTag = TABLE_TAG('C', 'B', 'L', 'C'); + const uint32_t colrTag = TABLE_TAG('C', 'O', 'L', 'R'); + const uint32_t cpalTag = TABLE_TAG('C', 'P', 'A', 'L'); + + switch (tag) { + // Google Color Emoji Tables + case cbdtTag: + case cblcTag: + // Windows Color Emoji Tables + case colrTag: + case cpalTag: + return ots::TABLE_ACTION_PASSTHRU; + default: + return ots::TABLE_ACTION_DEFAULT; + } +#undef TABLE_TAG } } // namespace blink diff --git a/sky/engine/platform/fonts/opentype/OpenTypeSanitizer.h b/sky/engine/platform/fonts/opentype/OpenTypeSanitizer.h index e3d522e6ddea4..9794b5bdd45cb 100644 --- a/sky/engine/platform/fonts/opentype/OpenTypeSanitizer.h +++ b/sky/engine/platform/fonts/opentype/OpenTypeSanitizer.h @@ -31,7 +31,9 @@ #ifndef SKY_ENGINE_PLATFORM_FONTS_OPENTYPE_OPENTYPESANITIZER_H_ #define SKY_ENGINE_PLATFORM_FONTS_OPENTYPE_OPENTYPESANITIZER_H_ +#include "opentype-sanitiser.h" #include "sky/engine/wtf/Forward.h" +#include "sky/engine/wtf/text/WTFString.h" namespace blink { @@ -41,17 +43,36 @@ class OpenTypeSanitizer { public: explicit OpenTypeSanitizer(SharedBuffer* buffer) : m_buffer(buffer) + , m_otsErrorString("") { } PassRefPtr sanitize(); static bool supportsFormat(const String&); + String getErrorString() const { return static_cast(m_otsErrorString); } + + void setErrorString(const String& errorString) { m_otsErrorString = errorString; } private: SharedBuffer* const m_buffer; + String m_otsErrorString; +}; + +class BlinkOTSContext: public ots::OTSContext { +public: + BlinkOTSContext() + : m_errorString("") + { + } + + virtual void Message(int level, const char *format, ...); + virtual ots::TableAction GetTableAction(uint32_t tag); + String getErrorString() const { return static_cast(m_errorString); } +private: + String m_errorString; }; } // namespace blink -#endif // SKY_ENGINE_PLATFORM_FONTS_OPENTYPE_OPENTYPESANITIZER_H_ +#endif // SKY_ENGINE_PLATFORM_FONTS_OPENTYPE_OPENTYPESANITIZER_H_ diff --git a/sky/engine/platform/fonts/opentype/OpenTypeTypes.h b/sky/engine/platform/fonts/opentype/OpenTypeTypes.h index 132e7871bada3..65d5060938ef3 100644 --- a/sky/engine/platform/fonts/opentype/OpenTypeTypes.h +++ b/sky/engine/platform/fonts/opentype/OpenTypeTypes.h @@ -98,4 +98,5 @@ struct TableBase { } // namespace OpenType } // namespace blink -#endif // SKY_ENGINE_PLATFORM_FONTS_OPENTYPE_OPENTYPETYPES_H_ + +#endif // SKY_ENGINE_PLATFORM_FONTS_OPENTYPE_OPENTYPETYPES_H_ diff --git a/sky/engine/platform/fonts/opentype/OpenTypeVerticalData.cpp b/sky/engine/platform/fonts/opentype/OpenTypeVerticalData.cpp index 8acb546136edf..378c1f0d557d3 100644 --- a/sky/engine/platform/fonts/opentype/OpenTypeVerticalData.cpp +++ b/sky/engine/platform/fonts/opentype/OpenTypeVerticalData.cpp @@ -25,28 +25,21 @@ #include "sky/engine/platform/fonts/opentype/OpenTypeVerticalData.h" #include "sky/engine/platform/SharedBuffer.h" -#include "sky/engine/platform/fonts/GlyphPage.h" #include "sky/engine/platform/fonts/SimpleFontData.h" +#include "sky/engine/platform/fonts/GlyphPage.h" #include "sky/engine/platform/fonts/opentype/OpenTypeTypes.h" #include "sky/engine/platform/geometry/FloatRect.h" #include "sky/engine/wtf/RefPtr.h" -#if ENABLE(OPENTYPE_VERTICAL) - namespace blink { namespace OpenType { -const uint32_t GSUBTag = OT_MAKE_TAG('G', 'S', 'U', 'B'); const uint32_t HheaTag = OT_MAKE_TAG('h', 'h', 'e', 'a'); const uint32_t HmtxTag = OT_MAKE_TAG('h', 'm', 't', 'x'); const uint32_t VheaTag = OT_MAKE_TAG('v', 'h', 'e', 'a'); const uint32_t VmtxTag = OT_MAKE_TAG('v', 'm', 't', 'x'); const uint32_t VORGTag = OT_MAKE_TAG('V', 'O', 'R', 'G'); -const uint32_t DefaultScriptTag = OT_MAKE_TAG('D', 'F', 'L', 'T'); - -const uint32_t VertFeatureTag = OT_MAKE_TAG('v', 'e', 'r', 't'); - #pragma pack(1) struct HheaTable { @@ -110,287 +103,6 @@ struct VORGTable { size_t requiredSize() const { return sizeof(*this) + sizeof(VertOriginYMetrics) * (numVertOriginYMetrics - 1); } }; -struct CoverageTable : TableBase { - OpenType::UInt16 coverageFormat; -}; - -struct Coverage1Table : CoverageTable { - OpenType::UInt16 glyphCount; - OpenType::GlyphID glyphArray[1]; -}; - -struct Coverage2Table : CoverageTable { - OpenType::UInt16 rangeCount; - struct RangeRecord { - OpenType::GlyphID start; - OpenType::GlyphID end; - OpenType::UInt16 startCoverageIndex; - } ranges[1]; -}; - -struct SubstitutionSubTable : TableBase { - OpenType::UInt16 substFormat; - OpenType::Offset coverageOffset; - - const CoverageTable* coverage(const SharedBuffer& buffer) const { return validateOffset(buffer, coverageOffset); } -}; - -struct SingleSubstitution2SubTable : SubstitutionSubTable { - OpenType::UInt16 glyphCount; - OpenType::GlyphID substitute[1]; -}; - -struct LookupTable : TableBase { - OpenType::UInt16 lookupType; - OpenType::UInt16 lookupFlag; - OpenType::UInt16 subTableCount; - OpenType::Offset subTableOffsets[1]; - // OpenType::UInt16 markFilteringSet; this field comes after variable length, so offset is determined dynamically. - - bool getSubstitutions(HashMap* map, const SharedBuffer& buffer) const - { - uint16_t countSubTable = subTableCount; - if (!isValidEnd(buffer, &subTableOffsets[countSubTable])) - return false; - if (lookupType != 1) // "Single Substitution Subtable" is all what we support - return false; - for (uint16_t i = 0; i < countSubTable; ++i) { - const SubstitutionSubTable* substitution = validateOffset(buffer, subTableOffsets[i]); - if (!substitution) - return false; - const CoverageTable* coverage = substitution->coverage(buffer); - if (!coverage) - return false; - if (substitution->substFormat != 2) // "Single Substitution Format 2" is all what we support - return false; - const SingleSubstitution2SubTable* singleSubstitution2 = validatePtr(buffer, substitution); - if (!singleSubstitution2) - return false; - uint16_t countTo = singleSubstitution2->glyphCount; - if (!isValidEnd(buffer, &singleSubstitution2->substitute[countTo])) - return false; - switch (coverage->coverageFormat) { - case 1: { // Coverage Format 1 (e.g., MS Gothic) - const Coverage1Table* coverage1 = validatePtr(buffer, coverage); - if (!coverage1) - return false; - uint16_t countFrom = coverage1->glyphCount; - if (!isValidEnd(buffer, &coverage1->glyphArray[countFrom]) || countTo != countFrom) - return false; - for (uint16_t i = 0; i < countTo; ++i) - map->set(coverage1->glyphArray[i], singleSubstitution2->substitute[i]); - break; - } - case 2: { // Coverage Format 2 (e.g., Adobe Kozuka Gothic) - const Coverage2Table* coverage2 = validatePtr(buffer, coverage); - if (!coverage2) - return false; - uint16_t countRange = coverage2->rangeCount; - if (!isValidEnd(buffer, &coverage2->ranges[countRange])) - return false; - for (uint16_t i = 0, indexTo = 0; i < countRange; ++i) { - uint16_t from = coverage2->ranges[i].start; - uint16_t fromEnd = coverage2->ranges[i].end + 1; // OpenType "end" is inclusive - if (indexTo + (fromEnd - from) > countTo) - return false; - for (; from != fromEnd; ++from, ++indexTo) - map->set(from, singleSubstitution2->substitute[indexTo]); - } - break; - } - default: - return false; - } - } - return true; - } -}; - -struct LookupList : TableBase { - OpenType::UInt16 lookupCount; - OpenType::Offset lookupOffsets[1]; - - const LookupTable* lookup(uint16_t index, const SharedBuffer& buffer) const - { - uint16_t count = lookupCount; - if (index >= count || !isValidEnd(buffer, &lookupOffsets[count])) - return 0; - return validateOffset(buffer, lookupOffsets[index]); - } -}; - -struct FeatureTable : TableBase { - OpenType::Offset featureParams; - OpenType::UInt16 lookupCount; - OpenType::UInt16 lookupListIndex[1]; - - bool getGlyphSubstitutions(const LookupList* lookups, HashMap* map, const SharedBuffer& buffer) const - { - uint16_t count = lookupCount; - if (!isValidEnd(buffer, &lookupListIndex[count])) - return false; - for (uint16_t i = 0; i < count; ++i) { - const LookupTable* lookup = lookups->lookup(lookupListIndex[i], buffer); - if (!lookup || !lookup->getSubstitutions(map, buffer)) - return false; - } - return true; - } -}; - -struct FeatureList : TableBase { - OpenType::UInt16 featureCount; - struct FeatureRecord { - OpenType::Tag featureTag; - OpenType::Offset featureOffset; - } features[1]; - - const FeatureTable* feature(uint16_t index, OpenType::Tag tag, const SharedBuffer& buffer) const - { - uint16_t count = featureCount; - if (index >= count || !isValidEnd(buffer, &features[count])) - return 0; - if (features[index].featureTag == tag) - return validateOffset(buffer, features[index].featureOffset); - return 0; - } - - const FeatureTable* findFeature(OpenType::Tag tag, const SharedBuffer& buffer) const - { - for (uint16_t i = 0; i < featureCount; ++i) { - if (isValidEnd(buffer, &features[i]) && features[i].featureTag == tag) - return validateOffset(buffer, features[i].featureOffset); - } - return 0; - } -}; - -struct LangSysTable : TableBase { - OpenType::Offset lookupOrder; - OpenType::UInt16 reqFeatureIndex; - OpenType::UInt16 featureCount; - OpenType::UInt16 featureIndex[1]; - - const FeatureTable* feature(OpenType::Tag featureTag, const FeatureList* features, const SharedBuffer& buffer) const - { - uint16_t count = featureCount; - if (!isValidEnd(buffer, &featureIndex[count])) - return 0; - for (uint16_t i = 0; i < count; ++i) { - const FeatureTable* featureTable = features->feature(featureIndex[i], featureTag, buffer); - if (featureTable) - return featureTable; - } - return 0; - } -}; - -struct ScriptTable : TableBase { - OpenType::Offset defaultLangSysOffset; - OpenType::UInt16 langSysCount; - struct LangSysRecord { - OpenType::Tag langSysTag; - OpenType::Offset langSysOffset; - } langSysRecords[1]; - - const LangSysTable* defaultLangSys(const SharedBuffer& buffer) const - { - uint16_t count = langSysCount; - if (!isValidEnd(buffer, &langSysRecords[count])) - return 0; - uint16_t offset = defaultLangSysOffset; - if (offset) - return validateOffset(buffer, offset); - if (count) - return validateOffset(buffer, langSysRecords[0].langSysOffset); - return 0; - } -}; - -struct ScriptList : TableBase { - OpenType::UInt16 scriptCount; - struct ScriptRecord { - OpenType::Tag scriptTag; - OpenType::Offset scriptOffset; - } scripts[1]; - - const ScriptTable* script(OpenType::Tag tag, const SharedBuffer& buffer) const - { - uint16_t count = scriptCount; - if (!isValidEnd(buffer, &scripts[count])) - return 0; - for (uint16_t i = 0; i < count; ++i) { - if (scripts[i].scriptTag == tag) - return validateOffset(buffer, scripts[i].scriptOffset); - } - return 0; - } - - const ScriptTable* defaultScript(const SharedBuffer& buffer) const - { - uint16_t count = scriptCount; - if (!count || !isValidEnd(buffer, &scripts[count])) - return 0; - const ScriptTable* scriptOfDefaultTag = script(OpenType::DefaultScriptTag, buffer); - if (scriptOfDefaultTag) - return scriptOfDefaultTag; - return validateOffset(buffer, scripts[0].scriptOffset); - } - - const LangSysTable* defaultLangSys(const SharedBuffer& buffer) const - { - const ScriptTable* scriptTable = defaultScript(buffer); - if (!scriptTable) - return 0; - return scriptTable->defaultLangSys(buffer); - } -}; - -struct GSUBTable : TableBase { - OpenType::Fixed version; - OpenType::Offset scriptListOffset; - OpenType::Offset featureListOffset; - OpenType::Offset lookupListOffset; - - const ScriptList* scriptList(const SharedBuffer& buffer) const { return validateOffset(buffer, scriptListOffset); } - const FeatureList* featureList(const SharedBuffer& buffer) const { return validateOffset(buffer, featureListOffset); } - const LookupList* lookupList(const SharedBuffer& buffer) const { return validateOffset(buffer, lookupListOffset); } - - const LangSysTable* defaultLangSys(const SharedBuffer& buffer) const - { - const ScriptList* scripts = scriptList(buffer); - if (!scripts) - return 0; - return scripts->defaultLangSys(buffer); - } - - const FeatureTable* feature(OpenType::Tag featureTag, const SharedBuffer& buffer) const - { - const LangSysTable* langSys = defaultLangSys(buffer); - const FeatureList* features = featureList(buffer); - if (!features) - return 0; - const FeatureTable* feature = 0; - if (langSys) - feature = langSys->feature(featureTag, features, buffer); - if (!feature) { - // If the font has no langSys table, or has no default script and the first script doesn't - // have the requested feature, then use the first matching feature directly. - feature = features->findFeature(featureTag, buffer); - } - return feature; - } - - bool getVerticalGlyphSubstitutions(HashMap* map, const SharedBuffer& buffer) const - { - const FeatureTable* verticalFeatureTable = feature(OpenType::VertFeatureTag, buffer); - if (!verticalFeatureTable) - return false; - const LookupList* lookups = lookupList(buffer); - return lookups && verticalFeatureTable->getGlyphSubstitutions(lookups, map, buffer); - } -}; - #pragma pack() } // namespace OpenType @@ -399,7 +111,6 @@ OpenTypeVerticalData::OpenTypeVerticalData(const FontPlatformData& platformData) : m_defaultVertOriginY(0) { loadMetrics(platformData); - loadVerticalGlyphSubstitutions(platformData); } void OpenTypeVerticalData::loadMetrics(const FontPlatformData& platformData) @@ -487,14 +198,6 @@ void OpenTypeVerticalData::loadMetrics(const FontPlatformData& platformData) } } -void OpenTypeVerticalData::loadVerticalGlyphSubstitutions(const FontPlatformData& platformData) -{ - RefPtr buffer = platformData.openTypeTable(OpenType::GSUBTag); - const OpenType::GSUBTable* gsub = OpenType::validateTable(buffer); - if (gsub) - gsub->getVerticalGlyphSubstitutions(&m_verticalGlyphMap, *buffer.get()); -} - float OpenTypeVerticalData::advanceHeight(const SimpleFontData* font, Glyph glyph) const { size_t countHeights = m_advanceHeights.size(); @@ -526,10 +229,12 @@ void OpenTypeVerticalData::getVerticalTranslationsForGlyphs(const SimpleFontData // For Y, try VORG first. if (useVORG) { - int16_t vertOriginYFUnit = m_vertOriginY.get(glyph); - if (vertOriginYFUnit) { - outXYArray[1] = -vertOriginYFUnit * sizePerUnit; - continue; + if (glyph) { + int16_t vertOriginYFUnit = m_vertOriginY.get(glyph); + if (vertOriginYFUnit) { + outXYArray[1] = -vertOriginYFUnit * sizePerUnit; + continue; + } } if (std::isnan(defaultVertOriginY)) defaultVertOriginY = -m_defaultVertOriginY * sizePerUnit; @@ -551,21 +256,4 @@ void OpenTypeVerticalData::getVerticalTranslationsForGlyphs(const SimpleFontData } } -void OpenTypeVerticalData::substituteWithVerticalGlyphs(const SimpleFontData* font, GlyphPage* glyphPage, unsigned offset, unsigned length) const -{ - const HashMap& map = m_verticalGlyphMap; - if (map.isEmpty()) - return; - - for (unsigned index = offset, end = offset + length; index < end; ++index) { - GlyphData glyphData = glyphPage->glyphDataForIndex(index); - if (glyphData.glyph && glyphData.fontData == font) { - Glyph to = map.get(glyphData.glyph); - if (to) - glyphPage->setGlyphDataForIndex(index, to, font); - } - } -} - } // namespace blink -#endif // ENABLE(OPENTYPE_VERTICAL) diff --git a/sky/engine/platform/fonts/opentype/OpenTypeVerticalData.h b/sky/engine/platform/fonts/opentype/OpenTypeVerticalData.h index 21f40f152b6da..03b2d5aeba3aa 100644 --- a/sky/engine/platform/fonts/opentype/OpenTypeVerticalData.h +++ b/sky/engine/platform/fonts/opentype/OpenTypeVerticalData.h @@ -28,17 +28,13 @@ #include "sky/engine/platform/PlatformExport.h" #include "sky/engine/platform/fonts/Glyph.h" #include "sky/engine/wtf/HashMap.h" -#include "sky/engine/wtf/OperatingSystem.h" #include "sky/engine/wtf/PassRefPtr.h" #include "sky/engine/wtf/RefCounted.h" #include "sky/engine/wtf/Vector.h" -#if ENABLE(OPENTYPE_VERTICAL) - namespace blink { class FontPlatformData; -class GlyphPage; class SimpleFontData; class PLATFORM_EXPORT OpenTypeVerticalData : public RefCounted { @@ -51,17 +47,17 @@ class PLATFORM_EXPORT OpenTypeVerticalData : public RefCounted m_verticalGlyphMap; @@ -76,6 +72,4 @@ class PLATFORM_EXPORT OpenTypeVerticalData : public RefCounted +#include "base/macros.h" #include "sky/engine/wtf/Assertions.h" #define UNIMPLEMENTED ASSERT_NOT_REACHED @@ -70,22 +71,6 @@ defined(__MIPSEL__) ((sizeof(a) / sizeof(*(a))) / \ static_cast(!(sizeof(a) % sizeof(*(a))))) -// A macro to disallow the evil copy constructor and operator= functions -// This should be used in the private: declarations for a class -#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ -TypeName(const TypeName&); \ -void operator=(const TypeName&) - -// A macro to disallow all the implicit constructors, namely the -// default constructor, copy constructor and operator= functions. -// -// This should be used in the private: declarations for a class -// that wants to prevent anyone from instantiating it. This is -// especially useful for classes containing only static methods. -#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \ -TypeName(); \ -DISALLOW_COPY_AND_ASSIGN(TypeName) - namespace WTF { namespace double_conversion { diff --git a/sky/shell/BUILD.gn b/sky/shell/BUILD.gn index 88c9d682365d2..ae169d3a4e85d 100644 --- a/sky/shell/BUILD.gn +++ b/sky/shell/BUILD.gn @@ -136,7 +136,7 @@ if (is_android) { "$root_build_dir/icudtl.dat", ] deps = [ - "//third_party/icu", + "//third_party/icu:icudata", ] } } else if (is_ios) { diff --git a/sky/shell/android/org/domokit/sky/shell/SkyApplication.java b/sky/shell/android/org/domokit/sky/shell/SkyApplication.java index 7812f428803c2..b72fcc4d13225 100644 --- a/sky/shell/android/org/domokit/sky/shell/SkyApplication.java +++ b/sky/shell/android/org/domokit/sky/shell/SkyApplication.java @@ -97,7 +97,7 @@ private void initResources() { private void initNative() { try { - LibraryLoader.get(LibraryProcessType.PROCESS_BROWSER).ensureInitialized(); + LibraryLoader.get(LibraryProcessType.PROCESS_BROWSER).ensureInitialized(this); } catch (ProcessInitException e) { Log.e(TAG, "Unable to load Sky Engine binary.", e); throw new RuntimeException(e); diff --git a/sky/shell/dart/dart_library_provider_files.cc b/sky/shell/dart/dart_library_provider_files.cc index 2bed8e8e9e3e1..c806200e78450 100644 --- a/sky/shell/dart/dart_library_provider_files.cc +++ b/sky/shell/dart/dart_library_provider_files.cc @@ -63,17 +63,17 @@ void DartLibraryProviderFiles::GetLibraryAsStream( } std::string DartLibraryProviderFiles::CanonicalizePackageURL(std::string url) { - DCHECK(StartsWithASCII(url, "package:", true)); - ReplaceFirstSubstringAfterOffset(&url, 0, "package:", ""); + DCHECK(base::StartsWithASCII(url, "package:", true)); + base::ReplaceFirstSubstringAfterOffset(&url, 0, "package:", ""); return package_root_.Append(url).AsUTF8Unsafe(); } Dart_Handle DartLibraryProviderFiles::CanonicalizeURL(Dart_Handle library, Dart_Handle url) { std::string string = blink::StdStringFromDart(url); - if (StartsWithASCII(string, "dart:", true)) + if (base::StartsWithASCII(string, "dart:", true)) return url; - if (StartsWithASCII(string, "package:", true)) + if (base::StartsWithASCII(string, "package:", true)) return blink::StdStringToDart(CanonicalizePackageURL(string)); base::FilePath base_path(blink::StdStringFromDart(Dart_LibraryUrl(library))); base::FilePath resolved_path = base_path.DirName().Append(string); diff --git a/sky/shell/dart/dart_library_provider_network.cc b/sky/shell/dart/dart_library_provider_network.cc index f91cac0b12260..7ee06aefaa4be 100644 --- a/sky/shell/dart/dart_library_provider_network.cc +++ b/sky/shell/dart/dart_library_provider_network.cc @@ -74,11 +74,11 @@ void DartLibraryProviderNetwork::GetLibraryAsStream( Dart_Handle DartLibraryProviderNetwork::CanonicalizeURL(Dart_Handle library, Dart_Handle url) { std::string string = blink::StdStringFromDart(url); - if (StartsWithASCII(string, "dart:", true)) + if (base::StartsWithASCII(string, "dart:", true)) return url; // TODO(abarth): The package root should be configurable. - if (StartsWithASCII(string, "package:", true)) - ReplaceFirstSubstringAfterOffset(&string, 0, "package:", "/packages/"); + if (base::StartsWithASCII(string, "package:", true)) + base::ReplaceFirstSubstringAfterOffset(&string, 0, "package:", "/packages/"); GURL library_url(blink::StdStringFromDart(Dart_LibraryUrl(library))); GURL resolved_url = library_url.Resolve(string); return blink::StdStringToDart(resolved_url.spec()); diff --git a/sky/shell/testing/test_runner.cc b/sky/shell/testing/test_runner.cc index c4bf2dca7e974..589f75f8594a4 100644 --- a/sky/shell/testing/test_runner.cc +++ b/sky/shell/testing/test_runner.cc @@ -124,8 +124,8 @@ void TestRunner::Run() { std::cout << "#BEGIN\n"; std::cout.flush(); - if (StartsWithASCII(data.url, kFileUrlPrefix, true)) - ReplaceFirstSubstringAfterOffset(&data.url, 0, kFileUrlPrefix, ""); + if (base::StartsWithASCII(data.url, kFileUrlPrefix, true)) + base::ReplaceFirstSubstringAfterOffset(&data.url, 0, kFileUrlPrefix, ""); if (data.is_snapshot) sky_engine_->RunFromSnapshot(data.url); diff --git a/sky/shell/ui/engine.cc b/sky/shell/ui/engine.cc index aaec2987db6d2..800f456aa51d5 100644 --- a/sky/shell/ui/engine.cc +++ b/sky/shell/ui/engine.cc @@ -179,8 +179,9 @@ void Engine::RunFromNetwork(const mojo::String& url) { void Engine::RunFromFile(const mojo::String& main, const mojo::String& package_root) { + std::string package_root_str = package_root; dart_library_provider_.reset( - new DartLibraryProviderFiles(base::FilePath(package_root))); + new DartLibraryProviderFiles(base::FilePath(package_root_str))); RunFromLibrary(main); } diff --git a/sky/tools/packager/loader.cc b/sky/tools/packager/loader.cc index 9b5e0240c9882..397eacb345d8c 100644 --- a/sky/tools/packager/loader.cc +++ b/sky/tools/packager/loader.cc @@ -57,16 +57,16 @@ Loader::Loader(const base::FilePath& package_root) } std::string Loader::CanonicalizePackageURL(std::string url) { - DCHECK(StartsWithASCII(url, "package:", true)); - ReplaceFirstSubstringAfterOffset(&url, 0, "package:", ""); + DCHECK(base::StartsWithASCII(url, "package:", true)); + base::ReplaceFirstSubstringAfterOffset(&url, 0, "package:", ""); return package_root_.Append(url).AsUTF8Unsafe(); } Dart_Handle Loader::CanonicalizeURL(Dart_Handle library, Dart_Handle url) { std::string string = StringFromDart(url); - if (StartsWithASCII(string, "dart:", true)) + if (base::StartsWithASCII(string, "dart:", true)) return url; - if (StartsWithASCII(string, "package:", true)) + if (base::StartsWithASCII(string, "package:", true)) return StringToDart(CanonicalizePackageURL(string)); base::FilePath base_path(StringFromDart(Dart_LibraryUrl(library))); base::FilePath resolved_path = base_path.DirName().Append(string); diff --git a/sky/tools/roll/patch.py b/sky/tools/roll/patch.py index 0aaf7c7a39f75..1de370a9a691f 100755 --- a/sky/tools/roll/patch.py +++ b/sky/tools/roll/patch.py @@ -7,18 +7,17 @@ import subprocess import utils -def patch_and_filter(): - """Applies the *.patch files in the current dir and some hardcoded filters.""" - os.chdir(utils.mojo_root_dir) +def patch_and_filter(dest_dir): + os.chdir(dest_dir) utils.filter_file("build/landmines.py", lambda line: not "gyp_environment" in line) utils.commit("filter gyp_environment out of build/landmines.py") - patch() + patch(dest_dir) -def patch(relative_patches_dir=os.curdir): +def patch(dest_dir, relative_patches_dir=os.curdir): """Applies the *.patch files in |relative_patches_dir|. Args: @@ -32,7 +31,7 @@ def patch(relative_patches_dir=os.curdir): relative_patches_dir) assert os.path.isdir(patches_dir) - os.chdir(utils.mojo_root_dir) + os.chdir(dest_dir) for p in utils.find(["*.patch"], patches_dir): print "applying patch %s" % os.path.basename(p) try: diff --git a/sky/tools/roll/roll.py b/sky/tools/roll/roll.py index f680d6bbfc2d4..d974c49f9cfb6 100755 --- a/sky/tools/roll/roll.py +++ b/sky/tools/roll/roll.py @@ -29,12 +29,12 @@ 'build', 'third_party/android_testrunner', 'third_party/binutils', + 'third_party/instrumented_libraries', 'third_party/pymock', 'tools/android', 'tools/clang', 'tools/generate_library_loader', 'tools/gritsettings', - 'tools/relocation_packer', 'tools/valgrind', ] @@ -147,7 +147,7 @@ def main(): rev(args.chromium_dir, args.dest_dir, dirs_from_chromium, 'chromium') try: - patch.patch_and_filter() + patch.patch_and_filter(args.dest_dir) except subprocess.CalledProcessError: print "ERROR: Roll failed due to a patch not applying" print "Fix the patch to apply, commit the result, and re-run this script" diff --git a/testing/android/appurify_support/java/src/org/chromium/test/support/RobotiumBundleGenerator.java b/testing/android/appurify_support/java/src/org/chromium/test/support/RobotiumBundleGenerator.java index 167e7b92a4f90..e006954cfb2d9 100644 --- a/testing/android/appurify_support/java/src/org/chromium/test/support/RobotiumBundleGenerator.java +++ b/testing/android/appurify_support/java/src/org/chromium/test/support/RobotiumBundleGenerator.java @@ -20,6 +20,7 @@ public class RobotiumBundleGenerator implements ResultsBundleGenerator { public Bundle generate(Map rawResults) { int testsPassed = 0; int testsFailed = 0; + int testsErrored = 0; for (Map.Entry entry : rawResults.entrySet()) { switch (entry.getValue()) { @@ -32,6 +33,9 @@ public Bundle generate(Map rawResults Log.d(TAG, "FAILED: " + entry.getKey()); ++testsFailed; break; + case UNKNOWN: + ++testsErrored; + break; default: Log.w(TAG, "Unhandled: " + entry.getKey() + ", " + entry.getValue().toString()); @@ -40,10 +44,11 @@ public Bundle generate(Map rawResults } StringBuilder resultBuilder = new StringBuilder(); - if (testsFailed > 0) { - resultBuilder.append( - "\nFAILURES!!! Tests run: " + Integer.toString(rawResults.size()) - + ", Failures: " + Integer.toString(testsFailed) + ", Errors: 0"); + if (testsFailed > 0 || testsErrored > 0) { + resultBuilder.append("\nFAILURES!!! ") + .append("Tests run: ").append(Integer.toString(rawResults.size())) + .append(", Failures: ").append(Integer.toString(testsFailed)) + .append(", Errors: ").append(Integer.toString(testsErrored)); } else { resultBuilder.append("\nOK (" + Integer.toString(testsPassed) + " tests)"); } diff --git a/testing/android/native_test.gyp b/testing/android/native_test.gyp index fcfd7d7028dff..734a00f0cac36 100644 --- a/testing/android/native_test.gyp +++ b/testing/android/native_test.gyp @@ -55,6 +55,7 @@ 'type': 'none', 'dependencies': [ 'appurify_support.gyp:appurify_support_java', + 'on_device_instrumentation.gyp:reporter_java', '../../base/base.gyp:base_native_libraries_gen', '../../base/base.gyp:base_java', ], diff --git a/testing/android/native_test/java/src/org/chromium/native_test/NativeBrowserTestActivity.java b/testing/android/native_test/java/src/org/chromium/native_test/NativeBrowserTestActivity.java index ac2ddeef84a6d..0f6628a648c7e 100644 --- a/testing/android/native_test/java/src/org/chromium/native_test/NativeBrowserTestActivity.java +++ b/testing/android/native_test/java/src/org/chromium/native_test/NativeBrowserTestActivity.java @@ -6,11 +6,17 @@ import android.os.Bundle; +import org.chromium.base.Log; + +import java.io.File; + /** * An {@link android.app.Activity} for running native browser tests. */ public abstract class NativeBrowserTestActivity extends NativeTestActivity { + private static final String TAG = "cr.native_test"; + private static final String BROWSER_TESTS_FLAGS[] = { // content::kSingleProcessTestsFlag "--single_process", @@ -32,15 +38,48 @@ public void onCreate(Bundle savedInstanceState) { @Override public void onStart() { + deletePrivateDataDirectory(); initializeBrowserProcess(); super.onStart(); } + /** Deletes a file or directory along with any of its children. + * + * Note that, like File.delete(), this returns false if the file or directory couldn't be + * fully deleted. This means that, in the directory case, some files may be deleted even if + * the entire directory couldn't be. + * + * @param file The file or directory to delete. + * @return Whether or not the file or directory was deleted. + */ + private static boolean deleteRecursive(File file) { + if (file == null) return true; + + File[] children = file.listFiles(); + if (children != null) { + for (File child : children) { + if (!deleteRecursive(child)) { + return false; + } + } + } + return file.delete(); + } + + private void deletePrivateDataDirectory() { + File privateDataDirectory = getPrivateDataDirectory(); + if (!deleteRecursive(privateDataDirectory)) { + Log.e(TAG, "Failed to remove %s", privateDataDirectory.getAbsolutePath()); + } + } + + /** Returns the test suite's private data directory. */ + protected abstract File getPrivateDataDirectory(); + /** Initializes the browser process. * * This generally includes loading native libraries and switching to the native command line, * among other things. */ protected abstract void initializeBrowserProcess(); - } diff --git a/testing/android/native_test/java/src/org/chromium/native_test/NativeTestActivity.java b/testing/android/native_test/java/src/org/chromium/native_test/NativeTestActivity.java index 35a79f8c4f58e..8e147201c5f62 100644 --- a/testing/android/native_test/java/src/org/chromium/native_test/NativeTestActivity.java +++ b/testing/android/native_test/java/src/org/chromium/native_test/NativeTestActivity.java @@ -10,12 +10,16 @@ import android.os.Bundle; import android.os.Environment; import android.os.Handler; +import android.os.Process; import org.chromium.base.CommandLine; import org.chromium.base.JNINamespace; import org.chromium.base.Log; +import org.chromium.test.reporter.TestStatusReporter; import java.io.File; +import java.util.ArrayList; +import java.util.Iterator; /** * Android's NativeActivity is mostly useful for pure-native code. @@ -28,16 +32,17 @@ public class NativeTestActivity extends Activity { "org.chromium.native_test.NativeTestActivity.CommandLineFile"; public static final String EXTRA_COMMAND_LINE_FLAGS = "org.chromium.native_test.NativeTestActivity.CommandLineFlags"; + public static final String EXTRA_SHARD = + "org.chromium.native_test.NativeTestActivity.Shard"; public static final String EXTRA_STDOUT_FILE = "org.chromium.native_test.NativeTestActivity.StdoutFile"; private static final String TAG = "cr.native_test"; private static final String EXTRA_RUN_IN_SUB_THREAD = "RunInSubThread"; - // We post a delayed task to run tests so that we do not block onCreate(). - private static final long RUN_TESTS_DELAY_IN_MS = 300; private String mCommandLineFilePath; private StringBuilder mCommandLineFlags = new StringBuilder(); + private TestStatusReporter mReporter; private boolean mRunInSubThread = false; private boolean mStdoutFifo = false; private String mStdoutFilePath; @@ -48,6 +53,7 @@ public void onCreate(Bundle savedInstanceState) { CommandLine.init(new String[]{}); parseArgumentsFromIntent(getIntent()); + mReporter = new TestStatusReporter(this); } private void parseArgumentsFromIntent(Intent intent) { @@ -68,6 +74,19 @@ private void parseArgumentsFromIntent(Intent intent) { mRunInSubThread = intent.hasExtra(EXTRA_RUN_IN_SUB_THREAD); + ArrayList shard = intent.getStringArrayListExtra(EXTRA_SHARD); + if (shard != null) { + StringBuilder filterFlag = new StringBuilder(); + filterFlag.append("--gtest_filter="); + for (Iterator test_iter = shard.iterator(); test_iter.hasNext();) { + filterFlag.append(test_iter.next()); + if (test_iter.hasNext()) { + filterFlag.append(":"); + } + } + appendCommandLineFlags(filterFlag.toString()); + } + mStdoutFilePath = intent.getStringExtra(EXTRA_STDOUT_FILE); if (mStdoutFilePath == null) { mStdoutFilePath = new File(getFilesDir(), "test.fifo").getAbsolutePath(); @@ -94,19 +113,21 @@ public void run() { } else { // Post a task to run the tests. This allows us to not block // onCreate and still run tests on the main thread. - new Handler().postDelayed(new Runnable() { + new Handler().post(new Runnable() { @Override public void run() { runTests(); } - }, RUN_TESTS_DELAY_IN_MS); + }); } } private void runTests() { + mReporter.testRunStarted(Process.myPid()); nativeRunTests(mCommandLineFlags.toString(), mCommandLineFilePath, mStdoutFilePath, mStdoutFifo, getApplicationContext()); finish(); + mReporter.testRunFinished(Process.myPid()); } // Signal a failure of the native test loader to python scripts diff --git a/testing/android/native_test/java/src/org/chromium/native_test/NativeTestInstrumentationTestRunner.java b/testing/android/native_test/java/src/org/chromium/native_test/NativeTestInstrumentationTestRunner.java index 5c0cb9308e29a..6e39401882a20 100644 --- a/testing/android/native_test/java/src/org/chromium/native_test/NativeTestInstrumentationTestRunner.java +++ b/testing/android/native_test/java/src/org/chromium/native_test/NativeTestInstrumentationTestRunner.java @@ -5,13 +5,19 @@ package org.chromium.native_test; import android.app.Activity; +import android.app.ActivityManager; import android.app.Instrumentation; import android.content.ComponentName; +import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.os.Environment; +import android.os.Handler; +import android.os.Process; +import android.util.SparseArray; import org.chromium.base.Log; +import org.chromium.test.reporter.TestStatusReceiver; import org.chromium.test.support.ResultsBundleGenerator; import org.chromium.test.support.RobotiumBundleGenerator; @@ -20,10 +26,15 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; +import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; +import java.util.ArrayDeque; +import java.util.ArrayList; import java.util.HashMap; import java.util.Map; +import java.util.Queue; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -33,22 +44,38 @@ public class NativeTestInstrumentationTestRunner extends Instrumentation { public static final String EXTRA_NATIVE_TEST_ACTIVITY = - "org.chromium.native_test.NativeTestInstrumentationTestRunner." - + "NativeTestActivity"; + "org.chromium.native_test.NativeTestInstrumentationTestRunner.NativeTestActivity"; + public static final String EXTRA_SHARD_NANO_TIMEOUT = + "org.chromium.native_test.NativeTestInstrumentationTestRunner.ShardNanoTimeout"; + public static final String EXTRA_SHARD_SIZE_LIMIT = + "org.chromium.native_test.NativeTestInstrumentationTestRunner.ShardSizeLimit"; + public static final String EXTRA_TEST_LIST_FILE = + "org.chromium.native_test.NativeTestInstrumentationTestRunner.TestList"; private static final String TAG = "cr.native_test"; - private static final int ACCEPT_TIMEOUT_MS = 5000; + private static final long DEFAULT_SHARD_NANO_TIMEOUT = 60 * 1000000000L; + // Default to no size limit. + private static final int DEFAULT_SHARD_SIZE_LIMIT = 0; private static final String DEFAULT_NATIVE_TEST_ACTIVITY = "org.chromium.native_test.NativeUnitTestActivity"; - private static final Pattern RE_TEST_OUTPUT = Pattern.compile("\\[ *([^ ]*) *\\] ?([^ ]+) .*"); + private static final Pattern RE_TEST_OUTPUT = + Pattern.compile("\\[ *([^ ]*) *\\] ?([^ ]+)( .*)?$"); private ResultsBundleGenerator mBundleGenerator = new RobotiumBundleGenerator(); private String mCommandLineFile; private String mCommandLineFlags; + private Handler mHandler = new Handler(); private String mNativeTestActivity; private Bundle mLogBundle = new Bundle(); + private TestStatusReceiver mReceiver; + private Map mResults = + new HashMap(); + private Queue> mShards = new ArrayDeque>(); + private long mShardNanoTimeout = DEFAULT_SHARD_NANO_TIMEOUT; + private int mShardSizeLimit = DEFAULT_SHARD_SIZE_LIMIT; private File mStdoutFile; + private SparseArray mMonitors = new SparseArray(); @Override public void onCreate(Bundle arguments) { @@ -57,6 +84,39 @@ public void onCreate(Bundle arguments) { mNativeTestActivity = arguments.getString(EXTRA_NATIVE_TEST_ACTIVITY); if (mNativeTestActivity == null) mNativeTestActivity = DEFAULT_NATIVE_TEST_ACTIVITY; + String shardNanoTimeout = arguments.getString(EXTRA_SHARD_NANO_TIMEOUT); + if (shardNanoTimeout != null) mShardNanoTimeout = Long.parseLong(shardNanoTimeout); + + String shardSizeLimit = arguments.getString(EXTRA_SHARD_SIZE_LIMIT); + if (shardSizeLimit != null) mShardSizeLimit = Integer.parseInt(shardSizeLimit); + + String testListFilePath = arguments.getString(EXTRA_TEST_LIST_FILE); + if (testListFilePath != null) { + File testListFile = new File(testListFilePath); + try { + BufferedReader testListFileReader = + new BufferedReader(new FileReader(testListFile)); + + String test; + ArrayList workingShard = new ArrayList(); + while ((test = testListFileReader.readLine()) != null) { + workingShard.add(test); + if (workingShard.size() == mShardSizeLimit) { + mShards.add(workingShard); + workingShard = new ArrayList(); + } + } + + if (!workingShard.isEmpty()) { + mShards.add(workingShard); + } + + testListFileReader.close(); + } catch (IOException e) { + Log.e(TAG, "Error reading %s", testListFile.getAbsolutePath(), e); + } + } + try { mStdoutFile = File.createTempFile( ".temp_stdout_", ".txt", Environment.getExternalStorageDirectory()); @@ -66,62 +126,153 @@ public void onCreate(Bundle arguments) { finish(Activity.RESULT_CANCELED, new Bundle()); return; } + start(); } @Override public void onStart() { super.onStart(); - Bundle results = runTests(); - finish(Activity.RESULT_OK, results); + + mReceiver = new TestStatusReceiver(); + mReceiver.register(getContext()); + mReceiver.registerCallback(new TestStatusReceiver.TestRunCallback() { + @Override + public void testRunStarted(int pid) { + if (pid != Process.myPid()) { + ShardMonitor m = new ShardMonitor( + pid, System.nanoTime() + mShardNanoTimeout); + mMonitors.put(pid, m); + mHandler.post(m); + } + } + + @Override + public void testRunFinished(int pid) { + ShardMonitor m = mMonitors.get(pid); + if (m != null) { + m.stopped(); + mMonitors.remove(pid); + } + mHandler.post(new ShardEnder(pid)); + } + }); + + mHandler.post(new ShardStarter()); } - /** Runs the tests in the NativeTestActivity and returns a Bundle containing the results. - */ - private Bundle runTests() { - Log.i(TAG, "Creating activity."); - Activity activityUnderTest = startNativeTestActivity(); + /** Monitors a test shard's execution. */ + private class ShardMonitor implements Runnable { + private static final int MONITOR_FREQUENCY_MS = 1000; - Log.i(TAG, "Waiting for tests to finish."); - try { - while (!activityUnderTest.isFinishing()) { - Thread.sleep(100); + private long mExpirationNanoTime; + private int mPid; + private AtomicBoolean mStopped; + + public ShardMonitor(int pid, long expirationNanoTime) { + mPid = pid; + mExpirationNanoTime = expirationNanoTime; + mStopped = new AtomicBoolean(false); + } + + public void stopped() { + mStopped.set(true); + } + + @Override + public void run() { + if (mStopped.get()) { + return; + } + + if (isAppProcessAlive(getContext(), mPid)) { + if (System.nanoTime() > mExpirationNanoTime) { + Log.e(TAG, "Test process %d timed out.", mPid); + mHandler.post(new ShardEnder(mPid)); + return; + } else { + mHandler.postDelayed(this, MONITOR_FREQUENCY_MS); + return; + } } - } catch (InterruptedException e) { - Log.e(TAG, "Interrupted while waiting for activity to be destroyed: ", e); + + Log.e(TAG, "Test process %d died unexpectedly.", mPid); + mHandler.post(new ShardEnder(mPid)); } - Log.i(TAG, "Getting results."); - Map results = parseResults(activityUnderTest); + } - Log.i(TAG, "Parsing results and generating output."); - return mBundleGenerator.generate(results); + private static boolean isAppProcessAlive(Context context, int pid) { + ActivityManager activityManager = + (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); + for (ActivityManager.RunningAppProcessInfo processInfo : + activityManager.getRunningAppProcesses()) { + if (processInfo.pid == pid) return true; + } + return false; } /** Starts the NativeTestActivty. */ - private Activity startNativeTestActivity() { - Intent i = new Intent(Intent.ACTION_MAIN); - i.setComponent(new ComponentName(getContext().getPackageName(), mNativeTestActivity)); - i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - if (mCommandLineFile != null) { - Log.i(TAG, "Passing command line file extra: %s", mCommandLineFile); - i.putExtra(NativeTestActivity.EXTRA_COMMAND_LINE_FILE, mCommandLineFile); + private class ShardStarter implements Runnable { + @Override + public void run() { + Intent i = new Intent(Intent.ACTION_MAIN); + i.setComponent(new ComponentName(getContext().getPackageName(), mNativeTestActivity)); + i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + if (mCommandLineFile != null) { + Log.i(TAG, "Passing command line file extra: %s", mCommandLineFile); + i.putExtra(NativeTestActivity.EXTRA_COMMAND_LINE_FILE, mCommandLineFile); + } + if (mCommandLineFlags != null) { + Log.i(TAG, "Passing command line flag extra: %s", mCommandLineFlags); + i.putExtra(NativeTestActivity.EXTRA_COMMAND_LINE_FLAGS, mCommandLineFlags); + } + if (mShards != null && !mShards.isEmpty()) { + ArrayList shard = mShards.remove(); + i.putStringArrayListExtra(NativeTestActivity.EXTRA_SHARD, shard); + } + i.putExtra(NativeTestActivity.EXTRA_STDOUT_FILE, mStdoutFile.getAbsolutePath()); + getContext().startActivity(i); } - if (mCommandLineFlags != null) { - Log.i(TAG, "Passing command line flag extra: %s", mCommandLineFlags); - i.putExtra(NativeTestActivity.EXTRA_COMMAND_LINE_FLAGS, mCommandLineFlags); + } + + private class ShardEnder implements Runnable { + private static final int WAIT_FOR_DEATH_MILLIS = 10; + + private int mPid; + + public ShardEnder(int pid) { + mPid = pid; + } + + @Override + public void run() { + if (mPid != Process.myPid()) { + Process.killProcess(mPid); + try { + while (isAppProcessAlive(getContext(), mPid)) { + Thread.sleep(WAIT_FOR_DEATH_MILLIS); + } + } catch (InterruptedException e) { + Log.e(TAG, "%d may still be alive.", mPid, e); + } + } + mResults.putAll(parseResults()); + + if (mShards != null && !mShards.isEmpty()) { + mHandler.post(new ShardStarter()); + } else { + finish(Activity.RESULT_OK, mBundleGenerator.generate(mResults)); + } } - i.putExtra(NativeTestActivity.EXTRA_STDOUT_FILE, mStdoutFile.getAbsolutePath()); - return startActivitySync(i); } /** * Generates a map between test names and test results from the instrumented Activity's * output. */ - private Map parseResults( - Activity activityUnderTest) { + private Map parseResults() { Map results = new HashMap(); @@ -153,7 +304,7 @@ private Map parseResults( Log.i(TAG, l); } } catch (FileNotFoundException e) { - Log.e(TAG, "Couldn't find stdout file file: ", e); + Log.e(TAG, "Couldn't find stdout file: ", e); } catch (IOException e) { Log.e(TAG, "Error handling stdout file: ", e); } finally { diff --git a/testing/android/native_test/java/src/org/chromium/native_test/NativeUnitTestActivity.java b/testing/android/native_test/java/src/org/chromium/native_test/NativeUnitTestActivity.java index 2a2a8dd65b063..3d5e572d2c634 100644 --- a/testing/android/native_test/java/src/org/chromium/native_test/NativeUnitTestActivity.java +++ b/testing/android/native_test/java/src/org/chromium/native_test/NativeUnitTestActivity.java @@ -9,7 +9,6 @@ import org.chromium.base.Log; import org.chromium.base.PathUtils; import org.chromium.base.PowerMonitor; -import org.chromium.base.ResourceExtractor; import org.chromium.base.library_loader.NativeLibraries; /** @@ -27,11 +26,6 @@ public void onCreate(Bundle savedInstanceState) { // Needed by path_utils_unittest.cc PathUtils.setPrivateDataDirectorySuffix("chrome", getApplicationContext()); - ResourceExtractor resourceExtractor = ResourceExtractor.get(getApplicationContext()); - resourceExtractor.setExtractAllPaksAndV8SnapshotForTesting(); - resourceExtractor.startExtractingResources(); - resourceExtractor.waitForCompletion(); - // Needed by system_monitor_unittest.cc PowerMonitor.createForTests(this); diff --git a/testing/android/reporter/java/src/org/chromium/test/reporter/TestStatusReceiver.java b/testing/android/reporter/java/src/org/chromium/test/reporter/TestStatusReceiver.java index e4af9b652e2ba..1f410a9fa817b 100644 --- a/testing/android/reporter/java/src/org/chromium/test/reporter/TestStatusReceiver.java +++ b/testing/android/reporter/java/src/org/chromium/test/reporter/TestStatusReceiver.java @@ -8,7 +8,8 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.util.Log; + +import org.chromium.base.Log; import java.util.ArrayList; import java.util.List; @@ -18,12 +19,13 @@ */ public class TestStatusReceiver extends BroadcastReceiver { - private static final String TAG = "ResultReceiver"; + private static final String TAG = "cr.test.reporter"; private final List mFailCallbacks = new ArrayList(); private final List mHeartbeatCallbacks = new ArrayList(); private final List mPassCallbacks = new ArrayList(); private final List mStartCallbacks = new ArrayList(); + private final List mTestRunCallbacks = new ArrayList(); /** An IntentFilter that matches the intents that this class can receive. */ private static final IntentFilter INTENT_FILTER; @@ -33,6 +35,8 @@ public class TestStatusReceiver extends BroadcastReceiver { filter.addAction(TestStatusReporter.ACTION_TEST_FAILED); filter.addAction(TestStatusReporter.ACTION_TEST_PASSED); filter.addAction(TestStatusReporter.ACTION_TEST_STARTED); + filter.addAction(TestStatusReporter.ACTION_TEST_RUN_STARTED); + filter.addAction(TestStatusReporter.ACTION_TEST_RUN_FINISHED); try { filter.addDataType(TestStatusReporter.DATA_TYPE_HEARTBEAT); filter.addDataType(TestStatusReporter.DATA_TYPE_RESULT); @@ -62,6 +66,12 @@ public interface StartCallback { void testStarted(String testClass, String testMethod); } + /** A callback used when a test run has started or finished. */ + public interface TestRunCallback { + void testRunStarted(int pid); + void testRunFinished(int pid); + } + /** Register a callback for when a test has failed. */ public void registerCallback(FailCallback c) { mFailCallbacks.add(c); @@ -82,6 +92,11 @@ public void registerCallback(StartCallback c) { mStartCallbacks.add(c); } + /** Register a callback for when a test run has started or finished. */ + public void registerCallback(TestRunCallback c) { + mTestRunCallbacks.add(c); + } + /** Register this receiver using the provided context. */ public void register(Context c) { c.registerReceiver(this, INTENT_FILTER); @@ -94,6 +109,7 @@ public void register(Context c) { */ @Override public void onReceive(Context context, Intent intent) { + int pid = intent.getIntExtra(TestStatusReporter.EXTRA_PID, 0); String testClass = intent.getStringExtra(TestStatusReporter.EXTRA_TEST_CLASS); String testMethod = intent.getStringExtra(TestStatusReporter.EXTRA_TEST_METHOD); @@ -118,8 +134,18 @@ public void onReceive(Context context, Intent intent) { c.heartbeat(); } break; + case TestStatusReporter.ACTION_TEST_RUN_STARTED: + for (TestRunCallback c: mTestRunCallbacks) { + c.testRunStarted(pid); + } + break; + case TestStatusReporter.ACTION_TEST_RUN_FINISHED: + for (TestRunCallback c: mTestRunCallbacks) { + c.testRunFinished(pid); + } + break; default: - Log.e(TAG, "Unrecognized intent received: " + intent.toString()); + Log.e(TAG, "Unrecognized intent received: %s", intent.toString()); break; } } diff --git a/testing/android/reporter/java/src/org/chromium/test/reporter/TestStatusReporter.java b/testing/android/reporter/java/src/org/chromium/test/reporter/TestStatusReporter.java index 6ac7312fad3f4..85355f90335fd 100644 --- a/testing/android/reporter/java/src/org/chromium/test/reporter/TestStatusReporter.java +++ b/testing/android/reporter/java/src/org/chromium/test/reporter/TestStatusReporter.java @@ -24,8 +24,14 @@ public class TestStatusReporter { "org.chromium.test.reporter.TestStatusReporter.TEST_PASSED"; public static final String ACTION_TEST_FAILED = "org.chromium.test.reporter.TestStatusReporter.TEST_FAILED"; + public static final String ACTION_TEST_RUN_STARTED = + "org.chromium.test.reporter.TestStatusReporter.TEST_RUN_STARTED"; + public static final String ACTION_TEST_RUN_FINISHED = + "org.chromium.test.reporter.TestStatusReporter.TEST_RUN_FINISHED"; public static final String DATA_TYPE_HEARTBEAT = "org.chromium.test.reporter/heartbeat"; public static final String DATA_TYPE_RESULT = "org.chromium.test.reporter/result"; + public static final String EXTRA_PID = + "org.chromium.test.reporter.TestStatusReporter.PID"; public static final String EXTRA_TEST_CLASS = "org.chromium.test.reporter.TestStatusReporter.TEST_CLASS"; public static final String EXTRA_TEST_METHOD = @@ -57,22 +63,18 @@ public void run() { } public void testStarted(String testClass, String testMethod) { - sendBroadcast(testClass, testMethod, ACTION_TEST_STARTED); + sendTestBroadcast(ACTION_TEST_STARTED, testClass, testMethod); } public void testPassed(String testClass, String testMethod) { - sendBroadcast(testClass, testMethod, ACTION_TEST_PASSED); + sendTestBroadcast(ACTION_TEST_PASSED, testClass, testMethod); } public void testFailed(String testClass, String testMethod) { - sendBroadcast(testClass, testMethod, ACTION_TEST_FAILED); + sendTestBroadcast(ACTION_TEST_FAILED, testClass, testMethod); } - public void stopHeartbeat() { - mKeepBeating.set(false); - } - - private void sendBroadcast(String testClass, String testMethod, String action) { + private void sendTestBroadcast(String action, String testClass, String testMethod) { Intent i = new Intent(action); i.setType(DATA_TYPE_RESULT); i.putExtra(EXTRA_TEST_CLASS, testClass); @@ -80,4 +82,23 @@ private void sendBroadcast(String testClass, String testMethod, String action) { mContext.sendBroadcast(i); } + public void testRunStarted(int pid) { + sendTestRunBroadcast(ACTION_TEST_RUN_STARTED, pid); + } + + public void testRunFinished(int pid) { + sendTestRunBroadcast(ACTION_TEST_RUN_FINISHED, pid); + } + + private void sendTestRunBroadcast(String action, int pid) { + Intent i = new Intent(action); + i.setType(DATA_TYPE_RESULT); + i.putExtra(EXTRA_PID, pid); + mContext.sendBroadcast(i); + } + + public void stopHeartbeat() { + mKeepBeating.set(false); + } + } diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json index daa9b22642d23..0cadd6a89ef9a 100644 --- a/testing/buildbot/chromium.chromiumos.json +++ b/testing/buildbot/chromium.chromiumos.json @@ -52,6 +52,9 @@ ], "gtest_tests": [ { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "base_unittests" } ] @@ -106,6 +109,9 @@ ], "gtest_tests": [ { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "base_unittests" } ] @@ -125,27 +131,48 @@ "test": "app_list_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "app_shell_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ash_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "aura_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "base_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "cacheinvalidation_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "chromeos_unittests" }, { "test": "chromevox_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "components_unittests" }, { @@ -156,6 +183,9 @@ "test": "content_browsertests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "content_unittests" }, { @@ -168,12 +198,21 @@ "test": "dbus_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "device_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "display_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "events_unittests" }, { @@ -183,18 +222,30 @@ "test": "extensions_browsertests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "extensions_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gcm_unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gfx_unittests" }, { "test": "google_apis_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gpu_unittests" }, { @@ -205,24 +256,42 @@ "test": "interactive_ui_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ipc_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "jingle_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "media_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "message_center_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "midi_unittests" }, { "test": "nacl_helper_nonsfi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "nacl_loader_unittests" }, { @@ -238,33 +307,57 @@ "test": "ppapi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "printing_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "remoting_unittests" }, { "args": [ "--test-launcher-print-test-stdio=always" ], + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sandbox_linux_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "skia_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sql_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sync_unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ui_base_unittests" }, { "test": "ui_chromeos_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ui_touch_selection_unittests" }, { @@ -274,12 +367,18 @@ "test": "unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "url_unittests" }, { "test": "views_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "wm_unittests" } ] @@ -299,6 +398,9 @@ "test": "app_list_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "app_shell_unittests" }, { @@ -308,6 +410,9 @@ "test": "ash_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "aura_unittests" }, { @@ -324,18 +429,30 @@ "test": "browser_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "cacheinvalidation_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "chromeos_unittests" }, { "test": "chromevox_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "components_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "compositor_unittests" }, { @@ -360,12 +477,21 @@ "test": "dbus_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "device_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "display_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "events_unittests" }, { @@ -375,18 +501,30 @@ "test": "extensions_browsertests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "extensions_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gcm_unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gfx_unittests" }, { "test": "google_apis_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gpu_unittests" }, { @@ -396,24 +534,42 @@ "test": "interactive_ui_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ipc_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "jingle_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "media_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "message_center_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "midi_unittests" }, { "test": "nacl_helper_nonsfi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "nacl_loader_unittests" }, { @@ -426,33 +582,57 @@ "test": "ppapi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "printing_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "remoting_unittests" }, { "args": [ "--test-launcher-print-test-stdio=always" ], + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sandbox_linux_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "skia_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sql_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sync_unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ui_base_unittests" }, { "test": "ui_chromeos_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ui_touch_selection_unittests" }, { @@ -462,12 +642,18 @@ "test": "unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "url_unittests" }, { "test": "views_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "wm_unittests" } ] @@ -487,6 +673,9 @@ "test": "app_list_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "app_shell_unittests" }, { @@ -496,6 +685,9 @@ "test": "ash_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "aura_unittests" }, { @@ -512,15 +704,27 @@ "test": "browser_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "cacheinvalidation_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "chromeos_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "components_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "compositor_unittests" }, { @@ -546,12 +750,21 @@ "test": "dbus_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "device_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "display_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "events_unittests" }, { @@ -561,18 +774,30 @@ "test": "extensions_browsertests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "extensions_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gcm_unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gfx_unittests" }, { "test": "google_apis_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gpu_unittests" }, { @@ -583,24 +808,42 @@ "test": "interactive_ui_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ipc_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "jingle_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "media_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "message_center_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "midi_unittests" }, { "test": "nacl_helper_nonsfi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "nacl_loader_unittests" }, { @@ -613,33 +856,57 @@ "test": "ppapi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "printing_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "remoting_unittests" }, { "args": [ "--test-launcher-print-test-stdio=always" ], + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sandbox_linux_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "skia_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sql_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sync_unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ui_base_unittests" }, { "test": "ui_chromeos_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ui_touch_selection_unittests" }, { @@ -649,12 +916,18 @@ "test": "unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "url_unittests" }, { "test": "views_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "wm_unittests" } ] diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index f3ce76092d1ef..4ff6efb260025 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json @@ -4,16 +4,49 @@ { "args": [ "--enable-browser-side-navigation", - "--gtest_filter=-CrossSiteRedirectorBrowserTest.VerifyCrossSiteRedirectURL:CrossSiteTransferTest.NoLeakOnCrossSiteCancel:CrossSiteTransferTest.ReplaceEntryCrossProcessThenTransfer:CrossSiteTransferTest.ReplaceEntryCrossProcessTwice:CrossSiteTransferTest.ReplaceEntryInProcessThenTranfers:DevToolsProtocolTest.NavigationPreservesMessages:NavigationControllerBrowserTest.CorrectLengthWithCurrentItemReplacement:NavigationControllerBrowserTest.FrameNavigationEntry_BlankAutoSubframe:NavigationControllerBrowserTest.NavigationTypeClassification_ClientSideRedirect:NavigationControllerBrowserTest.NavigationTypeClassification_ExistingPage:NavigationControllerBrowserTest.NavigationTypeClassification_InPage:NavigationControllerBrowserTest.NavigationTypeClassification_NewAndAutoSubframe:NavigationControllerBrowserTest.NavigationTypeClassification_NewPage:NavigationControllerBrowserTest.PreventSpoofFromSubframeAndReplace:NavigationControllerBrowserTest.StopCausesFailureDespiteJavaScriptURL:RenderViewImplTest.DecideNavigationPolicy:RenderViewImplTest.NavigationStartOverride:RenderViewImplTest.OnNavigationHttpPost:RenderViewImplTest.ReloadWhileSwappedOut:RenderViewImplTest.TestBackForward:SecurityExploitBrowserTest.AttemptDuplicateRenderViewHost:SecurityExploitBrowserTest.AttemptDuplicateRenderWidgetHost:SecurityExploitBrowserTest.InterstitialCommandFromUnderlyingContent:ServiceWorkerBrowserTest.CrossSiteTransfer:ServiceWorkerBrowserTest.ImportsBustMemcache:ServiceWorkerBrowserTest.Reload:ServiceWorkerBrowserTest.ResponseFromHTTPServiceWorkerIsNotMarkedAsSecure:ServiceWorkerBrowserTest.ResponseFromHTTPSServiceWorkerIsMarkedAsSecure:SessionHistoryTest.CrossFrameFormBackForward:SessionHistoryTest.FrameBackForward:SessionHistoryTest.FrameFormBackForward:SessionHistoryTest.LocationChangeInSubframe:SitePerProcessBrowserTest.CrossSiteDidStopLoading:WebContentsImplBrowserTest.ClearNonVisiblePendingOnFail:WebContentsViewAuraTest.ReplaceStateReloadPushState:WebRtcBrowserTest.CallInsideIframe:WebUIMojoTest.EndToEndPing" + "--gtest_filter=-ActivityLogApiTest.TriggerEvent:ActivityLogPrerenderTest.TestScriptInjected:AdbClientSocketTest.TestAdbClientSocket:AllUrlsApiTest.WhitelistedExtension:AppBannerDataFetcherBrowserTest.CancelBanner:AppBannerDataFetcherBrowserTest.NoManifest:AppBannerDataFetcherBrowserTest.PromptBanner:AppBannerDataFetcherBrowserTest.PromptBannerInHandler:AppBannerDataFetcherBrowserTest.WebAppBannerCreated:AppBannerDataFetcherBrowserTest.WebAppBannerInIFrame:AppBannerDataFetcherBrowserTest.WebAppBannerNoTypeInManifest:AppBannerDataFetcherBrowserTest.WebAppBannerNoTypeInManifestCapsExtension:AppEventPageTest.OnSuspendNoApiUse:AppEventPageTest.OnSuspendUseStorageApi:AppListSpeechRecognizerBrowserTest.RecognizeSpeech:AppViewTest.KillGuestCommunicatingWithWrongAppView:AppViewTest.TestAppViewEmbedSelfShouldFail:AppViewTest.TestAppViewGoodDataShouldSucceed:AppViewTest.TestAppViewMultipleConnects:AppViewTest.TestAppViewRefusedDataShouldFail:AppViewTest.TestAppViewWithUndefinedDataShouldSucceed:AppWindowAPITest.TestCloseEvent:AppWindowAPITest.TestCreate:AppWindowAPITest.TestFrameColors:AppWindowAPITest.TestSingleton:AppWindowAPITest.TestVisibleOnAllWorkspaces:AppWindowBrowserTest.FrameInsetsForColoredFrame:AppWindowBrowserTest.FrameInsetsForNoFrame:AutofillTest.AggregatesMinValidProfile:AutofillTest.AggregatesMinValidProfileDifferentJS:AutofillTest.AppendCountryCodeForAggregatedPhones:AutofillTest.CCInfoNotStoredWhenAutocompleteOff:AutofillTest.InvalidCreditCardNumberIsNotAggregated:AutofillTest.ProfileSavedWithValidCountryPhone:AutofillTest.ProfilesNotAggregatedWithInvalidEmail:AutofillTest.ProfilesNotAggregatedWithNoAddress:AutofillTest.ProfilesNotAggregatedWithSubmitHandler:AutofillTest.ProfileWithEmailInOtherFieldNotSaved:AutofillTest.UsePlusSignForInternationalNumber:AutofillTest.WhitespacesAndSeparatorCharsStrippedForValidCCNums:BrowserCloseManagerWithDownloadsBrowserTest/BrowserCloseManagerWithDownloadsBrowserTest.TestWithDangerousUrlDownload/0:BrowserCloseManagerWithDownloadsBrowserTest/BrowserCloseManagerWithDownloadsBrowserTest.TestWithDangerousUrlDownload/1:BrowserCloseManagerWithDownloadsBrowserTest/BrowserCloseManagerWithDownloadsBrowserTest.TestWithDownloads/0:BrowserCloseManagerWithDownloadsBrowserTest/BrowserCloseManagerWithDownloadsBrowserTest.TestWithDownloads/1:BrowserCloseManagerWithDownloadsBrowserTest/BrowserCloseManagerWithDownloadsBrowserTest.TestWithDownloadsFromDifferentProfiles/0:BrowserCloseManagerWithDownloadsBrowserTest/BrowserCloseManagerWithDownloadsBrowserTest.TestWithDownloadsFromDifferentProfiles/1:BrowserCloseManagerWithDownloadsBrowserTest/BrowserCloseManagerWithDownloadsBrowserTest.TestWithOffTheRecordDownloads/0:BrowserCloseManagerWithDownloadsBrowserTest/BrowserCloseManagerWithDownloadsBrowserTest.TestWithOffTheRecordDownloads/1:BrowserNavigatorTest.NavigateFromNTPToOptionsInSameTab:BrowserTest.BeforeUnloadVsBeforeReload:BrowserTest.CanDuplicateTab:BrowserTest.ClearPendingOnFailUnlessNTP:BrowserTest.InterstitialCancelsGuestViewDialogs:BrowserTest.InterstitialClosesDialogs:BrowserTest.InterstitialCloseTab:BrowserTest.InterstitialCommandDisable:BrowserTest.NoStopDuringTransferUntilCommit:BrowserTest.SecurityStyleChangedObserver:BrowserTest.ShouldShowLocationBar:BrowserViewTest.DevToolsUpdatesBrowserWindow:BrowsingDataRemoverBrowserTest.Download:BrowsingDataRemoverBrowserTest.DownloadProhibited:CaptivePortalBlockingPageIDNTest.ShowLoginIDNIfPortalRedirectsDetectionURL:CaptivePortalBlockingPageTest.CertReportingOptIn:CaptivePortalBlockingPageTest.CertReportingOptOut:CaptivePortalBlockingPageTest.WiFi_NoSSID_LoginURL:CaptivePortalBlockingPageTest.WiFi_NoSSID_NoLoginURL:CaptivePortalBlockingPageTest.WiFi_SSID_LoginURL:CaptivePortalBlockingPageTest.WiFi_SSID_NoLoginURL:CaptivePortalBlockingPageTest.WiredNetwork_LoginURL:CaptivePortalBlockingPageTest.WiredNetwork_LoginURL_With_SSID:CaptivePortalBlockingPageTest.WiredNetwork_NoLoginURL:CaptivePortalBlockingPageTest.WiredNetwork_NoLoginURL_With_SSID:CaptivePortalBrowserTest.AbortLoad:CaptivePortalBrowserTest.CloseLoginTab:CaptivePortalBrowserTest.Disabled:CaptivePortalBrowserTest.GoBack:CaptivePortalBrowserTest.GoBackToTimeout:CaptivePortalBrowserTest.HstsLogin:CaptivePortalBrowserTest.HttpsToHttpRedirect:CaptivePortalBrowserTest.HttpTimeout:CaptivePortalBrowserTest.HttpToHttpsRedirectLogin:CaptivePortalBrowserTest.InternetConnected:CaptivePortalBrowserTest.InterstitialTimerCertErrorAfterSlowLoad:CaptivePortalBrowserTest.InterstitialTimerNavigateAwayWhileLoading:CaptivePortalBrowserTest.InterstitialTimerNavigateWhileLoading_EndWithCaptivePortalInterstitial:CaptivePortalBrowserTest.InterstitialTimerNavigateWhileLoading_EndWithSSLInterstitial:CaptivePortalBrowserTest.InterstitialTimerReloadWhileLoading:CaptivePortalBrowserTest.InterstitialTimerStopNavigationWhileLoading:CaptivePortalBrowserTest.Login:CaptivePortalBrowserTest.LoginExtraNavigations:CaptivePortalBrowserTest.LoginFastTimeout:CaptivePortalBrowserTest.LoginIncognito:CaptivePortalBrowserTest.LoginSlow:CaptivePortalBrowserTest.NavigateBrokenTab:CaptivePortalBrowserTest.NavigateLoadingTabToTimeoutSingleSite:CaptivePortalBrowserTest.NavigateLoadingTabToTimeoutThreeSites:CaptivePortalBrowserTest.NavigateLoadingTabToTimeoutTwoSites:CaptivePortalBrowserTest.RedirectSSLCertError:CaptivePortalBrowserTest.ReloadTimeout:CaptivePortalBrowserTest.RequestFails:CaptivePortalBrowserTest.ShowCaptivePortalInterstitialOnCertError:CaptivePortalBrowserTest.SSLCertErrorLogin:CaptivePortalBrowserTest.Status511:CaptivePortalBrowserTest.TwoBrokenTabs:ChromeMainTest.SecondLaunchFromIncognitoWithNormalUrl:ChromeRenderProcessHostTest.DevToolsOnSelfInOwnProcess:ChromeRenderProcessHostTest.DevToolsOnSelfInOwnProcessPPT:ChromeRenderViewTest.BackToTranslatablePage:ChromeResourceDispatcherHostDelegateBrowserTest.PolicyHeaderForRedirect:ChromeURLDataManagerTest.200:ClearBrowserDataBrowserTest.CommitButtonDisabledWhenNoDataTypesSelected:ClearBrowserDataBrowserTest.CommitButtonDisabledWhileDeletionInProgress:ContentSettingBubbleModelMixedScriptTest.Iframe:ContentSettingsExceptionsAreaBrowserTest.OpenIncognitoWindow:ContentSettingsTest.RedirectCrossOrigin:ContentSettingsTest.RedirectLoopCookies:ContinueWhereILeftOffTest.Post:ContinueWhereILeftOffTest.PostBrowserClose:ContinueWhereILeftOffTest.PostCloseAllBrowsers:CrashRecoveryBrowserTest.DoubleReloadWithError:CrashRecoveryBrowserTest.LoadInNewTab:DevToolsBeforeUnloadTest.TestDockedDevToolsClose:DevToolsBeforeUnloadTest.TestDockedDevToolsInspectedBrowserClose:DevToolsBeforeUnloadTest.TestDockedDevToolsInspectedTabClose:DevToolsBeforeUnloadTest.TestUndockedDevToolsApplicationClose:DevToolsBeforeUnloadTest.TestUndockedDevToolsClose:DevToolsBeforeUnloadTest.TestUndockedDevToolsInspectedBrowserClose:DevToolsBeforeUnloadTest.TestUndockedDevToolsInspectedTabClose:DevToolsBeforeUnloadTest.TestWorkerWindowClosing:DevToolsExperimentalExtensionTest.TestDevToolsExperimentalExtensionAPI:DevToolsExtensionTest.TestContentScriptIsPresent:DevToolsExtensionTest.TestDevToolsExtensionAPI:DevToolsExtensionTest.TestDevToolsExtensionMessaging:DevToolsPixelOutputTests.TestScreenshotRecording:DevToolsSanityTest.TestConsoleOnNavigateBack:DevToolsSanityTest.TestDevToolsExternalNavigation:DevToolsSanityTest.TestNetworkRawHeadersText:DevToolsSanityTest.TestNetworkSize:DevToolsSanityTest.TestNetworkSyncSize:DevToolsSanityTest.TestNetworkTiming:DevToolsSanityTest.TestNoScriptDuplicatesOnPanelSwitch:DevToolsSanityTest.TestPageWithNoJavaScript:DevToolsSanityTest.TestPauseWhenLoadingDevTools:DevToolsSanityTest.TestPauseWhenScriptIsRunning:DevToolsSanityTest.TestScriptsTabIsPopulatedOnInspectedPageRefresh:DevToolsSanityTest.TestSettings:DevToolsSanityTest.TestShowScriptsTab:DevToolsSanityTest.TestToolboxLoadedUndocked:DevToolsSanityTest.TestToolboxNotLoadedDocked:DevToolsTagTest.DevToolsTaskIsProvided:DevToolsTagTest.TagsManagerRecordsATag:DnsProbeBrowserTest.CorrectionsLoadStopped:DnsProbeBrowserTest.CorrectionsLoadStoppedSlowProbe:DnsProbeBrowserTest.NoInternetProbeResultWithBrokenCorrections:DnsProbeBrowserTest.NoInternetProbeResultWithSlowBrokenCorrections:DnsProbeBrowserTest.NxdomainProbeResultWithWorkingCorrections:DnsProbeBrowserTest.NxdomainProbeResultWithWorkingSlowCorrections:DnsProbeBrowserTest.OtherErrorWithCorrectionsFailure:DnsProbeBrowserTest.OtherErrorWithCorrectionsSuccess:DnsProbeBrowserTest.SyncFailureWithBrokenCorrections:DomDistillerTabUtilsBrowserTest.TestDistillIntoWebContents:DomDistillerTabUtilsBrowserTest.TestSwapWebContents:DomDistillerViewerSourceBrowserTest.EarlyTemplateLoad:DomDistillerViewerSourceBrowserTest.EmptyURLShouldNotCrash:DomDistillerViewerSourceBrowserTest.InvalidURLShouldNotCrash:DomDistillerViewerSourceBrowserTest.MultiPageArticle:DomDistillerViewerSourceBrowserTest.NoWebUIBindingsArticleExists:DomDistillerViewerSourceBrowserTest.NoWebUIBindingsArticleNotFound:DomDistillerViewerSourceBrowserTest.NoWebUIBindingsDisplayCSS:DomDistillerViewerSourceBrowserTest.NoWebUIBindingsViewUrl:DomDistillerViewerSourceBrowserTest.PrefChange:DomDistillerViewerSourceBrowserTest.TestBadUrlErrorPage:DownloadExtensionTest.DownloadExtensionTest_FileIcon_Active:DownloadExtensionTest.DownloadExtensionTest_OnDeterminingFilename_InterruptedResume:DownloadExtensionTest.DownloadExtensionTest_Open:DownloadExtensionTest.DownloadExtensionTest_PauseResumeCancelErase:DownloadExtensionTest.DownloadExtensionTest_SearchEmptyQuery:DownloadExtensionTest.DownloadExtensionTest_SearchId:DownloadExtensionTest.DownloadExtensionTest_SearchIdAndFilename:DownloadExtensionTest.DownloadExtensionTest_SearchLimit:DownloadExtensionTest.DownloadExtensionTest_SearchPauseResumeCancelGetFileIconIncognito:DownloadExtensionTest.DownloadExtensionTest_SearchState:DownloadTest.AutoOpen:DownloadTest.BrowserCloseAfterDownload:DownloadTest.ChromeURLAfterDownload:DownloadTest.CloseNewTab1:DownloadTest.CloseNewTab2:DownloadTest.CloseNewTab3:DownloadTest.CloseShelfOnDownloadsTab:DownloadTest.ContentDisposition:DownloadTest.CrxDenyInstall:DownloadTest.CrxInstallAcceptPermissions:DownloadTest.CrxInstallDenysPermissions:DownloadTest.CrxInvalid:DownloadTest.CrxLargeTheme:DownloadTest.DontCloseNewTab2:DownloadTest.DontCloseNewTab3:DownloadTest.DownloadErrorReadonlyFolder:DownloadTest.DownloadErrorsFile:DownloadTest.DownloadErrorsServer:DownloadTest.DownloadHistoryCheck:DownloadTest.DownloadHistoryDangerCheck:DownloadTest.DownloadMimeType:DownloadTest.DownloadMimeTypeSelect:DownloadTest.DownloadResourceThrottleCancels:DownloadTest.DownloadTest_CrazyFilenames:DownloadTest.DownloadTest_DenyDanger:DownloadTest.DownloadTest_GZipWithNoContent:DownloadTest.DownloadTest_History:DownloadTest.DownloadTest_IncognitoRegular:DownloadTest.DownloadTest_PauseResumeCancel:DownloadTest.DownloadTest_PercentComplete:DownloadTest.DownloadTest_Remove:DownloadTest.DownloadTest_Renaming:DownloadTest.FeedbackService:DownloadTest.IncognitoDownload:DownloadTest.KnownSize:DownloadTest.LoadURLExternallyReferrerPolicy:DownloadTest.NewWindow:DownloadTest.PerWindowShelf:DownloadTest.DownloadTest_History:DownloadTest.Resumption_Automatic:DownloadTest.Resumption_MultipleAttempts:DownloadTest.Resumption_NoPrompt:DownloadTest.Resumption_WithPrompt:DownloadTest.Resumption_WithPromptAlways:DownloadTest.SavePageNonHTMLViaPost:DownloadTest.TestMultipleDownloadsBubble:DownloadTest.TestMultipleDownloadsInfobar:DownloadTest.UnknownSize:EphemeralAppBrowserTest.DisableRetainFileSystemEntries:EphemeralAppBrowserTest.EventDispatchWhenLaunched:EphemeralAppBrowserTest.IncludeRunningEphemeralAppsInNotifiers:EphemeralAppBrowserTest.InstallEventReceivedWhileIdle:EphemeralAppBrowserTest.InstallEventReceivedWhileRunning:EphemeralAppBrowserTest.PromoteAppAndGrantPermissions:EphemeralAppBrowserTest.PromoteAppFromSyncWhileIdle:EphemeralAppBrowserTest.PromoteAppFromSyncWhileRunning:EphemeralAppBrowserTest.PromoteAppWhileIdle:EphemeralAppBrowserTest.PromoteAppWhileRunning:EphemeralAppBrowserTest.PromoteBlacklistedEphemeralApp:EphemeralAppBrowserTest.PromoteDisabledAppFromSyncWhileIdle:EphemeralAppBrowserTest.PromoteDisabledAppFromSyncWhileRunning:EphemeralAppBrowserTest.PromoteUnsupportedEphemeralApp:EphemeralAppBrowserTest.ReleasePowerKeepAwake:EphemeralAppBrowserTest.ReplaceEphemeralAppWithDelayedInstalledApp:EphemeralAppBrowserTest.ReplaceEphemeralAppWithInstalledApp:EphemeralAppBrowserTest.RestartEventReceived:EphemeralAppBrowserTest.StickyNotificationSettings:EphemeralAppBrowserTest.UpdateEphemeralApp:EphemeralAppLauncherTest.LaunchAppWithNoPermissionWarnings:EphemeralAppServiceBrowserTest.ClearCachedApps:EphemeralAppServiceBrowserTest.DisableEphemeralAppsOnStartup:ErrorPageAutoReloadTest.AutoReload:ErrorPageAutoReloadTest.ManualReloadNotSuppressed:ErrorPageTest.DNSError_DoClickLink:ErrorPageTest.DNSError_DoReload:ErrorPageTest.DNSError_DoSearch:ErrorPageTest.StaleCacheStatus:ExperimentalPlatformAppBrowserTest.WindowsApiSetIcon:ExtensionApiNewTabTest.Tabs:ExtensionApiTest.CookiesEventsSpanning:ExtensionApiTest.Events:ExtensionApiTest.Incognito:ExtensionApiTest.JavaScriptURLPermissions:ExtensionApiTest.TabMove:ExtensionApiTest.TabsOnUpdated:ExtensionApiTest.XHROnPersistentFileSystem:ExtensionBrowserTest.WindowOpenExtension:ExtensionOverrideTest.OverrideNewTabIncognito:ExtensionPreferenceApiTest.OnChangeSplit:ExtensionResourceRequestPolicyTest.LinkToWebAccessibleResources:ExtensionResourceRequestPolicyTest.WebAccessibleResources:ExtensionStorageMonitorTest.DisableForInstalledExtensions:ExtensionStorageMonitorTest.DoubleInitialThreshold:ExtensionStorageMonitorTest.EphemeralAppLowUsage:ExtensionStorageMonitorTest.EphemeralAppWithHighUsage:ExtensionStorageMonitorTest.ExceedInitialThreshold:ExtensionStorageMonitorTest.ThrottleNotifications:ExtensionStorageMonitorTest.UnderThreshold:ExtensionStorageMonitorTest.UninstallExtension:ExtensionStorageMonitorTest.UserDisabledNotifications:ExtensionTabsTest.DefaultToIncognitoWhenItIsForcedAndNoArgs:ExtensionTabsTest.GetAllWindows:ExtensionTabsTest.QueryAllTabsWithDevTools:ExtensionURLRewriteBrowserTest.NewTabPageURL:ExtensionViewTest.LoadAPICall:ExtensionViewTest.QueuedLoadAPICall:ExtensionViewTest.ShimExtensionAttribute:ExtensionViewTest.ShimSrcAttribute:ExtensionViewTest.TestExtensionViewCreationShouldSucceed:ExtensionWebRequestApiTest.PostData1:ExtensionWebRequestApiTest.PostData2:ExtensionWebRequestApiTest.WebRequestBlocking:ExtensionWebRequestApiTest.WebRequestComplex:ExtensionWebRequestApiTest.WebRequestDeclarative1:ExtensionWebRequestApiTest.WebRequestDeclarative2:ExtensionWebRequestApiTest.WebRequestNewTab:ExtensionWebRequestApiTest.WebRequestSimple:FileSystemApiTest.FileSystemApiGetDisplayPath:FileSystemApiTest.FileSystemApiGetDisplayPathPrettify:FileSystemApiTest.FileSystemApiGetWritableRootEntryTest:FileSystemApiTest.FileSystemApiGetWritableTest:FileSystemApiTest.FileSystemApiGetWritableWithWriteTest:FileSystemApiTest.FileSystemApiInvalidChooseEntryTypeTest:FileSystemApiTest.FileSystemApiIsWritableTest:FileSystemApiTest.FileSystemApiIsWritableWithWritePermissionTest:FileSystemApiTest.FileSystemApiOpenCancelTest:FileSystemApiTest.FileSystemApiOpenDirectoryContainingGraylistTest:FileSystemApiTest.FileSystemApiOpenDirectoryOnGraylistAndAllowTest:FileSystemApiTest.FileSystemApiOpenDirectoryOnGraylistTest:FileSystemApiTest.FileSystemApiOpenDirectorySubdirectoryOfGraylistTest:FileSystemApiTest.FileSystemApiOpenDirectoryTest:FileSystemApiTest.FileSystemApiOpenDirectoryWithOnlyWritePermissionTest:FileSystemApiTest.FileSystemApiOpenDirectoryWithoutPermissionTest:FileSystemApiTest.FileSystemApiOpenDirectoryWithWriteTest:FileSystemApiTest.FileSystemApiOpenExistingFileDefaultPathTest:FileSystemApiTest.FileSystemApiOpenExistingFilePreviousPathDoesNotExistTest:FileSystemApiTest.FileSystemApiOpenExistingFileTest:FileSystemApiTest.FileSystemApiOpenExistingFileUsingPreviousPathTest:FileSystemApiTest.FileSystemApiOpenExistingFileWithWriteTest:FileSystemApiTest.FileSystemApiOpenMultipleExistingFilesTest:FileSystemApiTest.FileSystemApiOpenMultipleSuggested:FileSystemApiTest.FileSystemApiOpenMultipleWritableExistingFilesTest:FileSystemApiTest.FileSystemApiOpenWritableExistingFileTest:FileSystemApiTest.FileSystemApiOpenWritableExistingFileWithWriteTest:FileSystemApiTest.FileSystemApiRestoreDirectoryEntry:FileSystemApiTest.FileSystemApiRestoreEntry:FileSystemApiTest.FileSystemApiRetainDirectoryEntry:FileSystemApiTest.FileSystemApiRetainEntry:FileSystemApiTest.FileSystemApiSaveCancelTest:FileSystemApiTest.FileSystemApiSaveExistingFileTest:FileSystemApiTest.FileSystemApiSaveExistingFileWithWriteTest:FileSystemApiTest.FileSystemApiSaveMultipleFilesTest:FileSystemApiTest.FileSystemApiSaveNewFileTest:FileSystemApiTest.FileSystemApiSaveNewFileWithWriteTest:FileSystemApiTest.RequestFileSystem_NotChromeOS:FindInPageControllerTest.SearchWithinSpecialURL:FirstRunMasterPrefsImportNothing.ImportNothingAndShowNewTabPage:GeolocationBrowserTest.IFramesWithCachedPosition:GeolocationBrowserTest.IFramesWithFreshPosition:GeolocationBrowserTest.NoPromptForSecondTab:HostedAppTest.ShouldUseWebAppFrame:ImageWriterPrivateApiTest.TestWriteFromFile:InlineInstallPrivateApiTestApp.NoGesture:InlineInstallPrivateApiTestApp.SuccessfulInstall:InlineInstallPrivateApiTestExtension.OnlyApps:InlineLoginUISafeIframeBrowserTest.ConfirmationRequiredForNonsecureSignin:IsolatedAppTest.CookieIsolation:IsolatedAppTest.CrossProcessClientRedirect:LaunchWebAuthFlowFunctionTest.InteractionRequired:LaunchWebAuthFlowFunctionTest.InteractiveFirstNavigationSuccess:LaunchWebAuthFlowFunctionTest.LoadFailed:LaunchWebAuthFlowFunctionTest.NonInteractiveSuccess:LaunchWebAuthFlowFunctionTest.UserCloseWindow:LoadTimingBrowserTest.Basic:LoadTimingBrowserTest.EverythingAtOnce:LoadTimingBrowserTest.Integration:LoadTimingBrowserTest.Preconnect:LoadTimingBrowserTest.PreconnectProxySsl:LoadTimingBrowserTest.ReuseSocket:LoadTimingBrowserTest.Ssl:LoginPromptBrowserTest.AllowCrossdomainPromptForSubframes:LoginPromptBrowserTest.CancelRedundantAuths:LoginPromptBrowserTest.NoLoginPromptForFavicon:LoginPromptBrowserTest.ShouldReplaceExistingInterstitialWhenNavigated:LoginPromptBrowserTest.ShowCorrectUrlForCrossOriginMainFrameRedirects:LoginPromptBrowserTest.ShowCorrectUrlForCrossOriginMainFrameRequests:LoginPromptBrowserTest.SupplyRedundantAuths:LoginPromptBrowserTest.SupplyRedundantAuthsMultiProfile:LoginPromptBrowserTest.TestBasicAuth:LoginPromptBrowserTest.TestCancelAuth:LoginPromptBrowserTest.TestDigestAuth:LoginPromptBrowserTest.TestTwoAuths:MaterialPDFExtensionTest.Basic:MaterialPDFExtensionTest.BasicPlugin:MaterialPDFExtensionTest.Bookmark:MaterialPDFExtensionTest.Navigator:MaterialPDFExtensionTest.ParamsParser:MaterialPDFExtensionTest.Viewport:MaterialPDFExtensionTest.ZoomManager:MaybeSetMetadata/SafeBrowsingServiceMetadataTest.MalwareIFrame/0:MaybeSetMetadata/SafeBrowsingServiceMetadataTest.MalwareIFrame/1:MaybeSetMetadata/SafeBrowsingServiceMetadataTest.MalwareIFrame/2:MaybeSetMetadata/SafeBrowsingServiceMetadataTest.MalwareImg/0:MaybeSetMetadata/SafeBrowsingServiceMetadataTest.MalwareImg/2:MaybeSetMetadata/SafeBrowsingServiceMetadataTest.MalwareMainFrame/0:MaybeSetMetadata/SafeBrowsingServiceMetadataTest.MalwareMainFrame/1:MaybeSetMetadata/SafeBrowsingServiceMetadataTest.MalwareMainFrame/2:MediaGalleriesPlatformAppPpapiTest.SendFilesystem:MimeHandlerViewTest.Abort:MimeHandlerViewTest.Basic:MimeHandlerViewTest.DataUrl:MimeHandlerViewTest.Iframe:MimeHandlerViewTest.NonAsciiHeaders:MusicManagerPrivateTest.DeviceIdValueReturned:NetInternalsTest.netInternalsPrerenderViewFail:NetInternalsTest.netInternalsPrerenderViewSucceed:NewlibPackagedAppTest.MulticastPermissions:NewlibPackagedAppTest.NoSocketPermissions:NewlibPackagedAppTest.SocketPermissions:NewlibPackagedAppTest.SuccessfulLoad:NewTabUIBrowserTest.ShowIncognito:NonSfiPackagedAppTest.SuccessfulLoad:OptionsUIBrowserTest.LoadOptionsByURL:OptionsWebUIExtendedTest.OverlayBackToChild:OptionsWebUIExtendedTest.OverlayBackToUnrelated:OptionsWebUIExtendedTest.OverlayTabNavigation:PasswordManagerBrowserTest.CrossSiteIframeNotFillTest:PasswordManagerBrowserTest.NoLastLoadGoodLastLoad:PasswordManagerBrowserTest.NoPromptIfLinkClicked:PasswordManagerBrowserTest.PromptAfterSubmitWithSubFrameNavigation:PasswordManagerBrowserTest.SameOriginIframeAutoFillTest:PasswordManagerBrowserTestBase.CrossSiteIframeNotFillTest:PasswordManagerBrowserTestBase.NoLastLoadGoodLastLoad:PasswordManagerBrowserTestBase.NoPromptIfLinkClicked:PasswordManagerBrowserTestBase.PromptAfterSubmitWithSubFrameNavigation:PasswordManagerBrowserTestBase.SameOriginIframeAutoFillTest:PDFExtensionTest.Basic:PDFExtensionTest.BasicPlugin:PDFExtensionTest.Bookmark:PDFExtensionTest.Navigator:PDFExtensionTest.ParamsParser:PDFExtensionTest.Viewport:PDFExtensionTest.ZoomManager:PDFTestFiles/PDFExtensionTest.Load/1:PDFTestFiles/PDFExtensionTest.Load/8:PhishingClassifierDelegateTest.Navigation:PhishingClassifierTest.TestClassification:PhishingDOMFeatureExtractorTest.LinkFeatures:PlatformAppBrowserTest.ActiveAppsAreRecorded:PlatformAppBrowserTest.AppsIgnoreDefaultZoom:PlatformAppBrowserTest.AppWindowAdjustBoundsToBeVisibleOnScreen:PlatformAppBrowserTest.AppWindowRestoreState:PlatformAppBrowserTest.AppWithContextMenu:PlatformAppBrowserTest.AppWithContextMenuClicked:PlatformAppBrowserTest.AppWithContextMenuSelection:PlatformAppBrowserTest.AppWithContextMenuTextField:PlatformAppBrowserTest.ChromeRuntimeGetPackageDirectoryEntryApp:PlatformAppBrowserTest.ComponentAppBackgroundPage:PlatformAppBrowserTest.CreateAndCloseAppWindow:PlatformAppBrowserTest.DisallowNavigation:PlatformAppBrowserTest.EmptyContextMenu:PlatformAppBrowserTest.ExtensionWindowingApis:PlatformAppBrowserTest.FileAccessIsSavedToPrefs:PlatformAppBrowserTest.InstalledAppWithContextMenu:PlatformAppBrowserTest.LaunchWhiteListedExtensionWithFile:PlatformAppBrowserTest.LoadAndLaunchAppChromeRunning:PlatformAppBrowserTest.MutationEventsDisabled:PlatformAppBrowserTest.OpenLink:PlatformAppBrowserTest.ReloadRelaunches:PlatformAppBrowserTest.Restrictions:PlatformAppBrowserTest.WindowsApiAlphaEnabledHasPermissions:PlatformAppBrowserTest.WindowsApiAlwaysOnTopNoPermissions:PlatformAppBrowserTest.WindowsApiAlwaysOnTopWithOldPermissions:PlatformAppBrowserTest.WindowsApiAlwaysOnTopWithPermissions:PlatformAppBrowserTest.WindowsApiGet:PlatformAppBrowserTest.WindowsApiSetShapeHasPerm:PlatformAppBrowserTest.WindowsApiSetShapeNoPerm:PlatformAppDevToolsBrowserTest.ReOpenedWithID:PlatformAppDevToolsBrowserTest.ReOpenedWithURL:PlatformAppUrlRedirectorBrowserTest.BlankClickInAppIntercepted:PlatformAppUrlRedirectorBrowserTest.BlankClickInTabIntercepted:PlatformAppUrlRedirectorBrowserTest.ClickInTabIntercepted:PlatformAppUrlRedirectorBrowserTest.EntryInOmnibarIntercepted:PlatformAppUrlRedirectorBrowserTest.MismatchingBlankClickInAppNotIntercepted:PlatformAppUrlRedirectorBrowserTest.MismatchingWindowOpenInAppNotIntercepted:PlatformAppUrlRedirectorBrowserTest.PrerenderedClickInTabIntercepted:PlatformAppUrlRedirectorBrowserTest.WebviewNavigationNotIntercepted:PlatformAppUrlRedirectorBrowserTest.WindowOpenInAppIntercepted:PlatformAppUrlRedirectorBrowserTest.WindowOpenInTabIntercepted:PolicyTest.DownloadDirectory:PolicyTest.ExtensionInstallSources:PolicyTest.FullscreenAllowedApp:PolicyTest.HomepageLocation:PolicyTest.SafeBrowsingExtendedReportingOptInAllowed:PolicyTest.SSLErrorOverridingAllowed:PolicyTest.SSLErrorOverridingDisallowed:PolicyUITest.ExtensionLoadAndSendPolicy:PPAPINaClPNaClNonSfiTest.FileIO:PPAPINaClPNaClNonSfiTest.FileRef1:PPAPINaClPNaClNonSfiTest.Graphics2D_Replace:PPAPINaClPNaClNonSfiTest.Memory:PPAPINaClPNaClNonSfiTest.NetworkProxy:PPAPINaClPNaClNonSfiTest.PostMessage:PPAPINaClPNaClNonSfiTest.TCPSocket:PPAPINaClPNaClNonSfiTest.URLLoader0:PPAPINaClPNaClNonSfiTest.URLRequest_Stress:PPAPINaClPNaClNonSfiTest.VideoDestination:PrefsFunctionalTest.TestDownloadDirPref:PrerenderBrowserTest.CancelMatchCompleteDummy:PrerenderBrowserTest.MatchCompleteDummy:PrerenderBrowserTest.NavigateToPrerenderedPageWhenDevToolsAttached:PrerenderBrowserTest.OpenTaskManagerAfterPrerender:PrerenderBrowserTest.OpenTaskManagerAfterSwapIn:PrerenderBrowserTest.OpenTaskManagerBeforePrerender:PrerenderBrowserTest.PrerenderAbortPendingOnCancel:PrerenderBrowserTest.PrerenderAlertAfterOnload:PrerenderBrowserTest.PrerenderAlertBeforeOnload:PrerenderBrowserTest.PrerenderAllowAboutBlankSubresource:PrerenderBrowserTest.PrerenderBrowserInitiatedPostNoSwap:PrerenderBrowserTest.PrerenderCancelAll:PrerenderBrowserTest.PrerenderCancelMainFrameRedirectUnsupportedScheme:PrerenderBrowserTest.PrerenderCancelPrerenderWithPrerender:PrerenderBrowserTest.PrerenderCancelReferrer:PrerenderBrowserTest.PrerenderCancelReferrerPolicy:PrerenderBrowserTest.PrerenderCapturedWebContents:PrerenderBrowserTest.PrerenderClearCache:PrerenderBrowserTest.PrerenderClearHistory:PrerenderBrowserTest.PrerenderClickClickGoBack:PrerenderBrowserTest.PrerenderClickNavigateGoBack:PrerenderBrowserTest.PrerenderClickNewForegroundTab:PrerenderBrowserTest.PrerenderClickNewWindow:PrerenderBrowserTest.PrerenderClientRedirectFromFragment:PrerenderBrowserTest.PrerenderClientRedirectInIframe:PrerenderBrowserTest.PrerenderClientRedirectNavigateToFirst:PrerenderBrowserTest.PrerenderClientRedirectNavigateToSecond:PrerenderBrowserTest.PrerenderClientRedirectNavigateToSecondViaClick:PrerenderBrowserTest.PrerenderClientRedirectToFragment:PrerenderBrowserTest.PrerenderContentSettingBlock:PrerenderBrowserTest.PrerenderContentSettingDetect:PrerenderBrowserTest.PrerenderCrossProcessClientRedirect:PrerenderBrowserTest.PrerenderCrossProcessServerRedirect:PrerenderBrowserTest.PrerenderCrossProcessServerRedirectNoHang:PrerenderBrowserTest.PrerenderCrx:PrerenderBrowserTest.PrerenderDeferredImage:PrerenderBrowserTest.PrerenderDeferredImageAfterRedirect:PrerenderBrowserTest.PrerenderDeferredMainFrame:PrerenderBrowserTest.PrerenderDeferredMainFrameAfterRedirect:PrerenderBrowserTest.PrerenderDeferredSynchronousXHR:PrerenderBrowserTest.PrerenderDelayLoadPlugin:PrerenderBrowserTest.PrerenderDownloadClientRedirect:PrerenderBrowserTest.PrerenderDownloadIframe:PrerenderBrowserTest.PrerenderDownloadLocation:PrerenderBrowserTest.PrerenderEvents:PrerenderBrowserTest.PrerenderExcessiveMemory:PrerenderBrowserTest.PrerenderExtraHeadersNoSwap:PrerenderBrowserTest.PrerenderFavicon:PrerenderBrowserTest.PrerenderFragmentNavigateFragment:PrerenderBrowserTest.PrerenderFragmentNavigatePage:PrerenderBrowserTest.PrerenderHangingUnload:PrerenderBrowserTest.PrerenderHTML5Audio:PrerenderBrowserTest.PrerenderHTML5AudioAutoplay:PrerenderBrowserTest.PrerenderHTML5AudioJsplay:PrerenderBrowserTest.PrerenderHTML5MediaSourceVideo:PrerenderBrowserTest.PrerenderHTML5Video:PrerenderBrowserTest.PrerenderHTML5VideoJs:PrerenderBrowserTest.PrerenderHTML5VideoNetwork:PrerenderBrowserTest.PrerenderHttpAuthentication:PrerenderBrowserTest.PrerenderHttps:PrerenderBrowserTest.PrerenderImageJpeg:PrerenderBrowserTest.PrerenderImagePng:PrerenderBrowserTest.PrerenderInfiniteLoop:PrerenderBrowserTest.PrerenderInfiniteLoopMultiple:PrerenderBrowserTest.PrerenderKeepSubresourceExtensionScheme:PrerenderBrowserTest.PrerenderKeepSubresourceRedirectExtensionScheme:PrerenderBrowserTest.PrerenderLocalStorageRead:PrerenderBrowserTest.PrerenderLocalStorageWrite:PrerenderBrowserTest.PrerenderLocationReplaceGWSHistograms:PrerenderBrowserTest.PrerenderLocationReplaceNavigateToFirst:PrerenderBrowserTest.PrerenderLocationReplaceNavigateToSecond:PrerenderBrowserTest.PrerenderNaClPluginDisabled:PrerenderBrowserTest.PrerenderNavigateClickGoBack:PrerenderBrowserTest.PrerenderNavigateNavigateGoBack:PrerenderBrowserTest.PrerenderNewNavigationEntry:PrerenderBrowserTest.PrerenderNoCommitNoSwap2:PrerenderBrowserTest.PrerenderNoSSLReferrer:PrerenderBrowserTest.PrerenderPage:PrerenderBrowserTest.PrerenderPageChangeFragmentLocationHash:PrerenderBrowserTest.PrerenderPageCrossDomain:PrerenderBrowserTest.PrerenderPageNavigateFragment:PrerenderBrowserTest.PrerenderPageNewTab:PrerenderBrowserTest.PrerenderPagePending:PrerenderBrowserTest.PrerenderPageRemovesPending:PrerenderBrowserTest.PrerenderPageRemovingLink:PrerenderBrowserTest.PrerenderPageRemovingLinkWithTwoLinks:PrerenderBrowserTest.PrerenderPageRemovingLinkWithTwoLinksOneLate:PrerenderBrowserTest.PrerenderPageRemovingLinkWithTwoLinksRemovingOne:PrerenderBrowserTest.PrerenderPageWithFragment:PrerenderBrowserTest.PrerenderPageWithRedirectedFragment:PrerenderBrowserTest.PrerenderPing:PrerenderBrowserTest.PrerenderPopup:PrerenderBrowserTest.PrerenderPrint:PrerenderBrowserTest.PrerenderReferrer:PrerenderBrowserTest.PrerenderReferrerPolicy:PrerenderBrowserTest.PrerenderRegisterProtocolHandler:PrerenderBrowserTest.PrerenderRendererCrash:PrerenderBrowserTest.PrerenderReplaceCurrentEntry:PrerenderBrowserTest.PrerenderSafeBrowsingClientRedirect:PrerenderBrowserTest.PrerenderSafeBrowsingIframe:PrerenderBrowserTest.PrerenderSafeBrowsingServerRedirect:PrerenderBrowserTest.PrerenderSafeBrowsingSubresource:PrerenderBrowserTest.PrerenderSafeBrowsingTopLevel:PrerenderBrowserTest.PrerenderServerRedirectInIframe:PrerenderBrowserTest.PrerenderServerRedirectNavigateToFirst:PrerenderBrowserTest.PrerenderServerRedirectNavigateToSecond:PrerenderBrowserTest.PrerenderServerRedirectNavigateToSecondViaClick:PrerenderBrowserTest.PrerenderSessionStorage:PrerenderBrowserTest.PrerenderSSLClientCertIframe:PrerenderBrowserTest.PrerenderSSLClientCertSubresource:PrerenderBrowserTest.PrerenderSSLClientCertTopLevel:PrerenderBrowserTest.PrerenderSSLErrorIframe:PrerenderBrowserTest.PrerenderSSLErrorSubresource:PrerenderBrowserTest.PrerenderSSLErrorTopLevel:PrerenderBrowserTest.PrerenderSSLReferrerPolicy:PrerenderBrowserTest.PrerenderTargetHasPopup:PrerenderBrowserTest.PrerenderUnload:PrerenderBrowserTest.PrerenderVisibility:PrerenderBrowserTest.PrerenderWebAudioDevice:PrerenderBrowserTest.PrerenderWindowClose:PrerenderBrowserTest.PrerenderWindowSize:PrerenderBrowserTest.PrerenderXhrDelete:PrerenderBrowserTest.PrerenderXhrGet:PrerenderBrowserTest.PrerenderXhrHead:PrerenderBrowserTest.PrerenderXhrOptions:PrerenderBrowserTest.PrerenderXhrPost:PrerenderBrowserTest.PrerenderXhrPut:PrerenderBrowserTest.PrerenderXhrTrace:PrerenderBrowserTest.TaskManagementTagsBasic:PrerenderBrowserTest.TaskManagementTasksProvided:PrerenderBrowserTestWithExtensions.StreamsTest:PrerenderBrowserTestWithExtensions.TabsApi:PrerenderBrowserTestWithExtensions.WebNavigation:PrerenderBrowserTestWithNaCl.PrerenderNaClPluginEnabled:PrerenderIncognitoBrowserTest.PrerenderIncognito:PrerenderIncognitoBrowserTest.PrerenderIncognitoClosed:ProcessManagementTest.ProcessOverflow:ProfileManagerBrowserTest.DeletePasswords:ProxyBrowserTest.BasicAuthWSConnect:PushMessagingBrowserTest.AutomaticUnsubscriptionFollowsContentSettingRules:PushMessagingBrowserTest.DenyNotificationsPermissionUnsubscribes:PushMessagingBrowserTest.DenyPushPermissionUnsubscribes:PushMessagingBrowserTest.GlobalResetNotificationsPermissionUnsubscribes:PushMessagingBrowserTest.GlobalResetPushPermissionUnsubscribes:PushMessagingBrowserTest.GrantAlreadyGrantedPermissionDoesNotUnsubscribe:PushMessagingBrowserTest.LocalResetNotificationsPermissionUnsubscribes:PushMessagingBrowserTest.LocalResetPushPermissionUnsubscribes:PushMessagingBrowserTest.PermissionStateSaysDenied:PushMessagingBrowserTest.PermissionStateSaysGranted:PushMessagingBrowserTest.PermissionStateSaysPrompt:PushMessagingBrowserTest.PushEventEnforcesUserVisibleNotification:PushMessagingBrowserTest.PushEventEnforcesUserVisibleNotificationAfterQueue:PushMessagingBrowserTest.PushEventNoServiceWorker:PushMessagingBrowserTest.PushEventNotificationWithoutEventWaitUntil:PushMessagingBrowserTest.PushEventSuccess:PushMessagingBrowserTest.ResetPushPermissionAfterClearingSiteData:PushMessagingBrowserTest.SubscribeFailureNoManifest:PushMessagingBrowserTest.SubscribeFailureNotificationsBlocked:PushMessagingBrowserTest.SubscribePersisted:PushMessagingBrowserTest.SubscribeSuccessNotificationsGranted:PushMessagingBrowserTest.SubscribeSuccessNotificationsPrompt:PushMessagingBrowserTest.UnsubscribeSuccess:PushMessagingBrowserTestEmptySubscriptionOptions.RegisterFailureEmptyPushSubscriptionOptions:PushMessagingIncognitoBrowserTest.IncognitoGetSubscriptionDoesNotHang:RedirectTest.ClientEmptyReferer:RedirectTest.ClientServerServer:RedirectTest.Server:ReferrerPolicyTest.HttpLeftClickRedirectDefaultFlag:ReferrerPolicyTest.HttpLeftClickRedirectToHTTPOriginWhenCrossOrigin:ReferrerPolicyTest.HttpsMiddleClickOrigin:ReferrerPolicyTest.HttpsMiddleClickRedirect:ReferrerPolicyTest.MiddleClickOrigin:ReferrerPolicyTest.MiddleClickRedirect:RepostFormWarningTest.TestDoubleReload:RepostFormWarningTest.TestLoginAfterRepost:RestartTest.Post:SafeBrowsingBlockingPageBrowserTestWithThreatType/SafeBrowsingBlockingPageBrowserTest.DontProceed/0:SafeBrowsingBlockingPageBrowserTestWithThreatType/SafeBrowsingBlockingPageBrowserTest.DontProceed/1:SafeBrowsingBlockingPageBrowserTestWithThreatType/SafeBrowsingBlockingPageBrowserTest.DontProceed/2:SafeBrowsingBlockingPageBrowserTestWithThreatType/SafeBrowsingBlockingPageBrowserTest.IframeDontProceed/0:SafeBrowsingBlockingPageBrowserTestWithThreatType/SafeBrowsingBlockingPageBrowserTest.IframeDontProceed/1:SafeBrowsingBlockingPageBrowserTestWithThreatType/SafeBrowsingBlockingPageBrowserTest.IframeDontProceed/2:SafeBrowsingBlockingPageBrowserTestWithThreatType/SafeBrowsingBlockingPageBrowserTest.IframeOptInAndReportMalwareDetails/0:SafeBrowsingBlockingPageBrowserTestWithThreatType/SafeBrowsingBlockingPageBrowserTest.IframeOptInAndReportMalwareDetails/1:SafeBrowsingBlockingPageBrowserTestWithThreatType/SafeBrowsingBlockingPageBrowserTest.IframeOptInAndReportMalwareDetails/2:SafeBrowsingBlockingPageBrowserTestWithThreatType/SafeBrowsingBlockingPageBrowserTest.IframeProceed/0:SafeBrowsingBlockingPageBrowserTestWithThreatType/SafeBrowsingBlockingPageBrowserTest.IframeProceed/1:SafeBrowsingBlockingPageBrowserTestWithThreatType/SafeBrowsingBlockingPageBrowserTest.IframeProceed/2:SafeBrowsingBlockingPageBrowserTestWithThreatType/SafeBrowsingBlockingPageBrowserTest.LearnMore/0:SafeBrowsingBlockingPageBrowserTestWithThreatType/SafeBrowsingBlockingPageBrowserTest.LearnMore/1:SafeBrowsingBlockingPageBrowserTestWithThreatType/SafeBrowsingBlockingPageBrowserTest.LearnMore/2:SafeBrowsingBlockingPageBrowserTestWithThreatType/SafeBrowsingBlockingPageBrowserTest.Proceed/0:SafeBrowsingBlockingPageBrowserTestWithThreatType/SafeBrowsingBlockingPageBrowserTest.Proceed/1:SafeBrowsingBlockingPageBrowserTestWithThreatType/SafeBrowsingBlockingPageBrowserTest.Proceed/2:SafeBrowsingBlockingPageBrowserTestWithThreatType/SafeBrowsingBlockingPageBrowserTest.ProceedDisabled/0:SafeBrowsingBlockingPageBrowserTestWithThreatType/SafeBrowsingBlockingPageBrowserTest.ProceedDisabled/1:SafeBrowsingBlockingPageBrowserTestWithThreatType/SafeBrowsingBlockingPageBrowserTest.ProceedDisabled/2:SafeBrowsingBlockingPageBrowserTestWithThreatType/SafeBrowsingBlockingPageBrowserTest.RedirectCanceled/0:SafeBrowsingBlockingPageBrowserTestWithThreatType/SafeBrowsingBlockingPageBrowserTest.RedirectCanceled/1:SafeBrowsingBlockingPageBrowserTestWithThreatType/SafeBrowsingBlockingPageBrowserTest.RedirectCanceled/2:SafeBrowsingBlockingPageBrowserTestWithThreatType/SafeBrowsingBlockingPageBrowserTest.ReportingDisabled/0:SafeBrowsingBlockingPageBrowserTestWithThreatType/SafeBrowsingBlockingPageBrowserTest.ReportingDisabled/1:SafeBrowsingBlockingPageBrowserTestWithThreatType/SafeBrowsingBlockingPageBrowserTest.ReportingDisabled/2:SafeBrowsingBlockingPageBrowserTestWithThreatType/SafeBrowsingBlockingPageBrowserTest.ReportingDisabledByPolicy/0:SafeBrowsingBlockingPageBrowserTestWithThreatType/SafeBrowsingBlockingPageBrowserTest.ReportingDisabledByPolicy/1:SafeBrowsingBlockingPageBrowserTestWithThreatType/SafeBrowsingBlockingPageBrowserTest.ReportingDisabledByPolicy/2:SafeBrowsingBlockingPageIDNTestWithThreatType/SafeBrowsingBlockingPageIDNTest.SafeBrowsingBlockingPageDecodesIDN/0:SafeBrowsingBlockingPageIDNTestWithThreatType/SafeBrowsingBlockingPageIDNTest.SafeBrowsingBlockingPageDecodesIDN/1:SafeBrowsingBlockingPageIDNTestWithThreatType/SafeBrowsingBlockingPageIDNTest.SafeBrowsingBlockingPageDecodesIDN/2:SafeBrowsingServiceTest.Prefetch:SessionRestoreTest.IncognitotoNonIncognito:SSLBlockingPageIDNTest.SSLBlockingPageDecodesIDN:SSLUITest.BadCertFollowedByGoodCert:SSLUITest.InterstitialNotAffectedByHideShow:SSLUITest.TestBadFrameNavigation:SSLUITest.TestBadHTTPSDownload:SSLUITest.TestBrokenHTTPSWithInsecureContent:SSLUITest.TestGoodFrameNavigation:SSLUITest.TestHTTPSErrorWithNoNavEntry:SSLUITest.TestHTTPSExpiredCertAndGoBackViaButton:SSLUITest.TestHTTPSExpiredCertAndGoBackViaMenu:SSLUITest.TestHTTPSExpiredCertAndGoForward:SSLUITest.TestHTTPWithBrokenHTTPSResource:SSLUITest.TestInterstitialJavaScriptGoesBack:SSLUITest.TestRedirectBadToGoodHTTPS:SSLUITest.TestRefNavigation:SSLUITest.TestUnsafeContents:SSLUITest.TestUnsafeContentsInWorkerWithUserException:SSLUITest.TestUnsafeContentsWithUserException:SSLUITest.TestWSSInvalidCertAndGoForward:SSLUITestIgnoreLocalhostCertErrors.TestNoInterstitialOnLocalhost:SSLUITestWithClientCert.TestWSSClientCert:SSLUITestWithExtendedReporting.TestBrokenHTTPSGoBackShowYesCheckNoParamYesReportNo:SSLUITestWithExtendedReporting.TestBrokenHTTPSGoBackShowYesCheckYesParamNoReportNo:SSLUITestWithExtendedReporting.TestBrokenHTTPSGoBackWithShowYesCheckYesParamYesReportYes:SSLUITestWithExtendedReporting.TestBrokenHTTPSInIncognitoReportNo:SSLUITestWithExtendedReporting.TestBrokenHTTPSNoReportingWhenDisallowed:SSLUITestWithExtendedReporting.TestBrokenHTTPSProceedShowNoCheckYesReportNo:SSLUITestWithExtendedReporting.TestBrokenHTTPSProceedShowYesCheckYesParamNoReportNo:SSLUITestWithExtendedReporting.TestBrokenHTTPSProceedWithShowYesCheckNoParamYesReportNo:SSLUITestWithExtendedReporting.TestBrokenHTTPSProceedWithShowYesCheckYesParamInvalidReportNo:SSLUITestWithExtendedReporting.TestBrokenHTTPSProceedWithShowYesCheckYesParamYesReportYes:StreamsPrivateApiTest.Abort:StreamsPrivateApiTest.FileURL:StreamsPrivateApiTest.Headers:StreamsPrivateApiTest.Navigate:StreamsPrivateApiTest.NavigateCrossSite:StreamsPrivateApiTest.NavigateToAnAttachment:SupervisedUserBlockModeTest.HistoryVisitRecorded:SupervisedUserBlockModeTest.OpenBlockedURLInNewTab:SupervisedUserBlockModeTest.SendAccessRequestOnBlockedURL:SupervisedUserBlockModeTest.Unblock:SupervisedUserResourceThrottleTest.NoNavigationObserverBlock:TabCaptureApiTest.ApiTests:TabRestoreTest.RestoreCrossSiteWithExistingSiteInstance:TabRestoreTest.RestoreTabWithSpecialURLOnBack:TaskManagerBrowserTest.DevToolsNewDockedWindow:TaskManagerBrowserTest.DevToolsNewUndockedWindow:TaskManagerBrowserTest.DevToolsOldDockedWindow:TaskManagerBrowserTest.DevToolsOldUnockedWindow:UnloadTest.CrossSiteInfiniteBeforeUnloadAsync:WebNavigationApiTest.CrossProcess:WebNavigationApiTest.CrossProcessAbort:WebNavigationApiTest.CrossProcessFragment:WebNavigationApiTest.CrossProcessHistory:WebNavigationApiTest.Failures:WebNavigationApiTest.IFrame:WebNavigationApiTest.OpenTab:WebNavigationApiTest.RequestOpenTab:WebNavigationApiTest.ServerRedirect:WebNavigationApiTest.ServerRedirectSingleProcess:WebRtcSimulcastBrowserTest.TestVgaReturnsTwoSimulcastStreams:WebSocketBrowserTest.ReuseMainPageBasicAuthCredentialsForWebSocket:WebstoreInlineInstallerTest.ShouldBlockInlineInstallFromPopupWindow:WebUIWebViewBrowserTest.ContentScriptIsInjectedAfterTerminateAndReloadWebView:WebViewCommonTest.BasicPostMessage:WebViewDPITest.Shim_TestAutosizeBeforeNavigation:WebViewDPITest.Shim_TestAutosizeHeight:WebViewDPITest.Shim_TestAutosizeRemoveAttributes:WebViewFocusTest.TouchFocusesEmbedder:WebViewNewWindowTest.OpenURLFromTab_NewWindow_Abort:WebViewNewWindowTest.Shim_TestAddContentScriptsWithNewWindowAPI:WebViewNewWindowTest.Shim_TestNewWindow:WebViewNewWindowTest.Shim_TestNewWindowNoPreventDefault:WebViewNewWindowTest.Shim_TestNewWindowNoReferrerLink:WebViewNewWindowTest.Shim_TestNewWindowTwoListeners:WebViewNewWindowTest.UserAgent_NewWindow:WebViewPluginTest.TestLoadPluginEvent:WebViewPluginTest.TestLoadPluginInternalResource:WebViewSizeTest.AutoSize:WebViewSizeTest.Shim_TestAutosizeBeforeNavigation:WebViewSizeTest.Shim_TestAutosizeHeight:WebViewSizeTest.Shim_TestAutosizeRemoveAttributes:WebViewSizeTest.Shim_TestResizeEvents:WebViewSizeTest.Shim_TestResizeWebviewResizesContent:WebViewSizeTest.Shim_TestResizeWebviewWithDisplayNoneResizesContent:WebViewSpeechAPITest.SpeechRecognitionAPI_HasPermissionAllow:WebViewSpeechAPITest.SpeechRecognitionAPI_HasPermissionDeny:WebViewSpeechAPITest.SpeechRecognitionAPI_NoPermission:WebViewTest.AcceptTouchEvents:WebViewTest.AddRemoveWebView_AddRemoveWebView:WebViewTest.AllowTransparencyAndAllowScalingPropagate:WebViewTest.ClearData:WebViewTest.ClearDataCache:WebViewTest.CloseOnLoadcommit:WebViewTest.ConsoleMessage:WebViewTest.ContextMenuLanguageSettings:WebViewTest.ContextMenusAPI_Basic:WebViewTest.ContextMenusAPI_PreventDefault:WebViewTest.CookieIsolation:WebViewTest.Dialog_TestAlertDialog:WebViewTest.Dialog_TestConfirmDialogCancel:WebViewTest.Dialog_TestConfirmDialogDefaultCancel:WebViewTest.Dialog_TestConfirmDialogDefaultGCCancel:WebViewTest.Dialog_TestPromptDialog:WebViewTest.DisplayNoneSetSrc:WebViewTest.DOMStorageIsolation:WebViewTest.DownloadPermission:WebViewTest.ExecuteScript:WebViewTest.FileSystemAPIRequestFromMainThreadAllow:WebViewTest.FileSystemAPIRequestFromMainThreadDefaultAllow:WebViewTest.FileSystemAPIRequestFromMainThreadDeny:WebViewTest.FileSystemAPIRequestFromSharedWorkerOfMultiWebViewGuestsAllow:WebViewTest.FileSystemAPIRequestFromSharedWorkerOfMultiWebViewGuestsDefaultAllow:WebViewTest.FileSystemAPIRequestFromSharedWorkerOfMultiWebViewGuestsDeny:WebViewTest.FileSystemAPIRequestFromSharedWorkerOfSingleWebViewGuestAllow:WebViewTest.FileSystemAPIRequestFromSharedWorkerOfSingleWebViewGuestDefaultAllow:WebViewTest.FileSystemAPIRequestFromSharedWorkerOfSingleWebViewGuestDeny:WebViewTest.FileSystemAPIRequestFromWorkerAllow:WebViewTest.FileSystemAPIRequestFromWorkerDefaultAllow:WebViewTest.FileSystemAPIRequestFromWorkerDeny:WebViewTest.GeolocationAPICancelGeolocation:WebViewTest.GeolocationAPIEmbedderHasAccessAllow:WebViewTest.GeolocationAPIEmbedderHasAccessDeny:WebViewTest.GeolocationAPIEmbedderHasAccessMultipleBridgeIdAllow:WebViewTest.GeolocationAPIEmbedderHasNoAccessAllow:WebViewTest.GeolocationAPIEmbedderHasNoAccessDeny:WebViewTest.IndexedDBIsolation:WebViewTest.InterstitialTeardown:WebViewTest.InterstitialTeardownOnBrowserShutdown:WebViewTest.MediaAccessAPIAllow_TestAllow:WebViewTest.MediaAccessAPIAllow_TestAllowAndThenDeny:WebViewTest.MediaAccessAPIAllow_TestAllowAsync:WebViewTest.MediaAccessAPIAllow_TestAllowTwice:WebViewTest.MediaAccessAPIAllow_TestCheck:WebViewTest.MediaAccessAPIDeny_TestDeny:WebViewTest.MediaAccessAPIDeny_TestDenyThenAllowThrows:WebViewTest.MediaAccessAPIDeny_TestDenyWithPreventDefault:WebViewTest.MediaAccessAPIDeny_TestNoListenersImplyDeny:WebViewTest.MediaAccessAPIDeny_TestNoPreventDefaultImpliesDeny:WebViewTest.NoContentSettingsAPI:WebViewTest.NoPermission:WebViewTest.NoPrerenderer:WebViewTest.OpenURLFromTab_CurrentTab_Abort:WebViewTest.ReloadEmbedder:WebViewTest.ScreenCoordinates:WebViewTest.SendMessageToComponentExtensionFromGuest:WebViewTest.SendMessageToExtensionFromGuest:WebViewTest.SetPropertyOnDocumentInteractive:WebViewTest.SetPropertyOnDocumentReady:WebViewTest.Shim_TestAddAndRemoveContentScripts:WebViewTest.Shim_TestAddContentScript:WebViewTest.Shim_TestAddContentScriptToOneWebViewShouldNotInjectToTheOtherWebView:WebViewTest.Shim_TestAddContentScriptWithCode:WebViewTest.Shim_TestAddContentScriptWithSameNameShouldOverwriteTheExistingOne:WebViewTest.Shim_TestAddMultipleContentScripts:WebViewTest.Shim_TestAllowTransparencyAttribute:WebViewTest.Shim_TestAPIMethodExistence:WebViewTest.Shim_TestAssignSrcAfterCrash:WebViewTest.Shim_TestCannotMutateEventName:WebViewTest.Shim_TestChromeExtensionRelativePath:WebViewTest.Shim_TestChromeExtensionURL:WebViewTest.Shim_TestCloseNewWindowCleanup:WebViewTest.Shim_TestContentLoadEvent:WebViewTest.Shim_TestContentLoadEventWithDisplayNone:WebViewTest.Shim_TestContentScriptExistsAsLongAsWebViewTagExists:WebViewTest.Shim_TestContentScriptIsInjectedAfterTerminateAndReloadWebView:WebViewTest.Shim_TestDeclarativeWebRequestAPI:WebViewTest.Shim_TestDeclarativeWebRequestAPISendMessage:WebViewTest.Shim_TestDestroyOnEventListener:WebViewTest.Shim_TestDisabledZoomMode:WebViewTest.Shim_TestDisplayBlock:WebViewTest.Shim_TestDisplayNoneWebviewLoad:WebViewTest.Shim_TestDisplayNoneWebviewRemoveChild:WebViewTest.Shim_TestEventName:WebViewTest.Shim_TestExecuteScript:WebViewTest.Shim_TestExecuteScriptFail:WebViewTest.Shim_TestExecuteScriptIsAbortedWhenWebViewSourceIsChanged:WebViewTest.Shim_TestFindAPI:WebViewTest.Shim_TestFindAPI_findupdate:WebViewTest.Shim_TestFocusWhileFocused:WebViewTest.Shim_TestGarbageCollect:WebViewTest.Shim_TestGetProcessId:WebViewTest.Shim_TestInlineScriptFromAccessibleResources:WebViewTest.Shim_TestInvalidChromeExtensionURL:WebViewTest.Shim_TestLoadAbortChromeExtensionURLWrongPartition:WebViewTest.Shim_TestLoadAbortEmptyResponse:WebViewTest.Shim_TestLoadAbortIllegalChromeURL:WebViewTest.Shim_TestLoadAbortIllegalFileURL:WebViewTest.Shim_TestLoadAbortIllegalJavaScriptURL:WebViewTest.Shim_TestLoadAbortInvalidNavigation:WebViewTest.Shim_TestLoadAbortNonWebSafeScheme:WebViewTest.Shim_TestLoadDataAPI:WebViewTest.Shim_TestLoadProgressEvent:WebViewTest.Shim_TestLoadStartLoadRedirect:WebViewTest.Shim_TestNavigateAfterResize:WebViewTest.Shim_TestNavigationToExternalProtocol:WebViewTest.Shim_TestNavOnConsecutiveSrcAttributeChanges:WebViewTest.Shim_TestNavOnSrcAttributeChange:WebViewTest.Shim_TestOnEventProperty:WebViewTest.Shim_TestPartitionChangeAfterNavigation:WebViewTest.Shim_TestPartitionRemovalAfterNavigationFails:WebViewTest.Shim_TestPerOriginZoomMode:WebViewTest.Shim_TestPerViewZoomMode:WebViewTest.Shim_TestReassignSrcAttribute:WebViewTest.Shim_TestReload:WebViewTest.Shim_TestReloadAfterTerminate:WebViewTest.Shim_TestRemoveSrcAttribute:WebViewTest.Shim_TestRemoveWebviewAfterNavigation:WebViewTest.Shim_TestRemoveWebviewOnExit:WebViewTest.Shim_TestTerminateAfterExit:WebViewTest.Shim_TestWebRequestAPI:WebViewTest.Shim_TestWebRequestAPIExistence:WebViewTest.Shim_TestWebRequestAPIGoogleProperty:WebViewTest.Shim_TestWebRequestAPIWithHeaders:WebViewTest.Shim_TestWebRequestListenerSurvivesReparenting:WebViewTest.Shim_TestWebViewInsideFrame:WebViewTest.Shim_TestZoomAPI:WebViewTest.Shim_TestZoomBeforeNavigation:WebViewTest.Shim_WebViewWebRequestRegistryHasNoCache:WebViewTest.ShimSrcAttribute:WebViewTest.TaskManagerExistingWebView:WebViewTest.TaskManagerNewWebView:WebViewTest.TearDownTest:WebViewTest.TestConfirmDialog:WebViewTest.TestContextMenu:WebViewTest.TestPlugin:WebViewTest.UserAgent:WebViewTest.WhitelistedContentScript:WebViewVisibilityTest.EmbedderVisibilityChanged:WebViewVisibilityTest.GuestVisibilityChanged:WebViewVisibilityTest.Shim_TestHiddenBeforeNavigation:WebViewTest.StoragePersistence:WindowControlsTest.CloseControlWorks:WorkerDevToolsSanityTest.InspectSharedWorker" ], + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "browser_tests" + }, + { + "args": [ + "--enable-browser-side-navigation", + "--gtest_filter=-CrossSiteRedirectorBrowserTest.VerifyCrossSiteRedirectURL:CrossSiteTransferTest.NoLeakOnCrossSiteCancel:CrossSiteTransferTest.ReplaceEntryCrossProcessThenTransfer:CrossSiteTransferTest.ReplaceEntryCrossProcessTwice:CrossSiteTransferTest.ReplaceEntryInProcessThenTranfers:DevToolsProtocolTest.NavigationPreservesMessages:NavigationControllerBrowserTest.CorrectLengthWithCurrentItemReplacement:NavigationControllerBrowserTest.FrameNavigationEntry_BlankAutoSubframe:NavigationControllerBrowserTest.FrameNavigationEntry_SubframeBackForward:NavigationControllerBrowserTest.NavigationTypeClassification_ClientSideRedirect:NavigationControllerBrowserTest.NavigationTypeClassification_ExistingPage:NavigationControllerBrowserTest.NavigationTypeClassification_InPage:NavigationControllerBrowserTest.NavigationTypeClassification_NewAndAutoSubframe:NavigationControllerBrowserTest.NavigationTypeClassification_NewPage:NavigationControllerBrowserTest.PreventSpoofFromSubframeAndReplace:NavigationControllerBrowserTest.ReloadOriginalRequest:NavigationControllerBrowserTest.StopCausesFailureDespiteJavaScriptURL:RenderViewImplTest.OnNavigationHttpPost:RenderViewImplTest.ReloadWhileSwappedOut:RenderViewImplTest.TestBackForward:SecurityExploitBrowserTest.InterstitialCommandFromUnderlyingContent:ServiceWorkerBrowserTest.CrossSiteTransfer:ServiceWorkerBrowserTest.ImportsBustMemcache:ServiceWorkerBrowserTest.Reload:ServiceWorkerBrowserTest.ResponseFromHTTPServiceWorkerIsNotMarkedAsSecure:ServiceWorkerBrowserTest.ResponseFromHTTPSServiceWorkerIsMarkedAsSecure:SessionHistoryTest.CrossFrameFormBackForward:SessionHistoryTest.FrameBackForward:SessionHistoryTest.FrameFormBackForward:SessionHistoryTest.LocationChangeInSubframe:SitePerProcessBrowserTest.CrashSubframe:SitePerProcessBrowserTest.CrossSiteDidStopLoading:SitePerProcessBrowserTest.OpenPopupWithRemoteParent:WebContentsImplBrowserTest.ClearNonVisiblePendingOnFail:WebContentsViewAuraTest.OverscrollScreenshot:WebUIMojoTest.EndToEndPing" + ], + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "content_browsertests" }, { "args": [ "--enable-browser-side-navigation", - "--gtest_filter=-NavigationControllerTest.CopyRestoredStateAndNavigate:RenderFrameHostManagerTest.CancelPendingProperlyDeletesOrSwaps:RenderFrameHostManagerTest.PageDoesBackAndReload:RenderViewHostTest.ResetUnloadOnReload:ResourceDispatcherHostTest.TransferNavigationHtml:ResourceDispatcherHostTest.TransferNavigationText:ResourceDispatcherHostTest.TransferNavigationWithProcessCrash:ResourceDispatcherHostTest.TransferNavigationWithTwoRedirects:ResourceDispatcherHostTest.TransferTwoNavigationsHtml:WebContentsImplTest.CrossSiteNavigationBackPreempted:WebContentsImplTest.CrossSiteNotPreemptedDuringBeforeUnload:WebContentsImplTest.NoEarlyStop:WebContentsImplTest.ShowInterstitialCrashRendererThenGoBack:WebContentsImplTest.ShowInterstitialFromBrowserNewNavigationProceed:WebContentsImplTest.ShowInterstitialThenGoBack" + "--gtest_filter=-NavigationControllerTest.CopyRestoredStateAndNavigate:RenderFrameHostManagerTest.CancelPendingProperlyDeletesOrSwaps:RenderFrameHostManagerTest.PageDoesBackAndReload:RenderViewHostTest.ResetUnloadOnReload:ResourceDispatcherHostTest.TransferNavigationHtml:ResourceDispatcherHostTest.TransferNavigationText:ResourceDispatcherHostTest.TransferNavigationWithProcessCrash:ResourceDispatcherHostTest.TransferNavigationWithTwoRedirects:ResourceDispatcherHostTest.TransferTwoNavigationsHtml:WebContentsImplTest.CrossSiteNavigationBackPreempted:WebContentsImplTest.CrossSiteNotPreemptedDuringBeforeUnload:WebContentsImplTest.NoEarlyStop:WebContentsImplTest.ShowInterstitialCrashRendererThenGoBack:WebContentsImplTest.ShowInterstitialFromBrowserNewNavigationProceed" ], + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "content_unittests" + }, + { + "args": [ + "--enable-browser-side-navigation", + "--gtest_filter=-AutofillDialogViewsTest.SignInFocus:BookmarkInstantExtendedTest.DetachedBookmarkBarOnNTP:BookmarkTest.DetachedBookmarkBarOnNTP:BrowserBookmarkBarTest.StateOnActiveTabChanged:BrowserCommandsTest.BackForwardInNewTab:BrowserCommandsTest.BookmarkCurrentPage:BrowserCommandsTest.DuplicateTab:BrowserCommandsTest.OnDefaultZoomLevelChanged:BrowserCommandsTest.OnMaxZoomIn:BrowserCommandsTest.OnMaxZoomOut:BrowserCommandsTest.OnZoomChangedForActiveTab:BrowserCommandsTest.OnZoomLevelChanged:BrowserCommandsTest.OnZoomReset:BrowserCommandsTest.ViewSource:BrowserInstantControllerTest.DefaultSearchProviderChanged:BrowserInstantControllerTest.GoogleBaseURLUpdated:BrowserListTest.TabContentsIteratorVerifyBrowser:BrowserListTest.TabContentsIteratorVerifyCount:BrowserProcessPowerTest.IncognitoDoesntRecordPowerUsage:BrowserProcessPowerTest.MultipleProfilesRecordSeparately:BrowserProcessPowerTest.MultipleSites:BrowserProcessPowerTest.OneSite:BrowserViewTest.BrowserViewLayout:ChromeContentBrowserClientWindowTest.OpenURL:ChromeLauncherControllerTest.AppPanels:ChromeLauncherControllerTest.BrowserMenuGeneration:ChromeLauncherControllerTest.GmailMatching:ChromeLauncherControllerTest.GmailOfflineMatching:ChromeLauncherControllerTest.PersistLauncherItemPositions:ChromeLauncherControllerTest.PersistPinned:ChromeLauncherControllerTest.V1AppMenuDeletionExecution:ChromeLauncherControllerTest.V1AppMenuExecution:ChromeLauncherControllerTest.V1AppMenuGeneration:DeclarativeContentIsBookmarkedConditionTrackerTest.AddAndRemoveBookmark:DeclarativeContentIsBookmarkedConditionTrackerTest.BookmarkedAtStartOfTracking:DeclarativeContentIsBookmarkedConditionTrackerTest.ExtensiveChanges:DeclarativeContentIsBookmarkedConditionTrackerTest.Navigation:DeclarativeContentPageUrlConditionTrackerTest.AddAndRemoveConditionSets:DeclarativeContentPageUrlConditionTrackerTest.NotifyWebContentsNavigation:DeclarativeContentPageUrlConditionTrackerTest.TrackWebContents:InstantNTPURLRewriteTest.UberURLHandler_InstantExtendedNewTabPage:InstantSearchPrerendererTest.CancelPendingPrerenderRequest:InstantSearchPrerendererTest.CancelPrerenderRequest_EmptySearchQueryCommitted:InstantSearchPrerendererTest.CancelPrerenderRequest_UnsupportedDispositions:InstantSearchPrerendererTest.CancelPrerenderRequestOnTabChangeEvent:InstantSearchPrerendererTest.CanCommitQuery:InstantSearchPrerendererTest.CommitQuery:InstantSearchPrerendererTest.DoNotPrefetchSearchResults:InstantSearchPrerendererTest.PrefetchSearchResults:InstantSearchPrerendererTest.PrerenderingAllowed:InstantSearchPrerendererTest.PrerenderRequestCancelled:InstantSearchPrerendererTest.UsePrerenderedPage_SearchQueryMistmatch:InstantSearchPrerendererTest.UsePrerenderPage:ListChangesTaskTest.UnderTrackedFolder:ListChangesTaskTest.UnrelatedChange:MediaRouterDialogControllerTest.CloseDialogFromDialogController:MediaRouterDialogControllerTest.CloseDialogFromWebUI:MediaRouterDialogControllerTest.CloseInitiator:MediaRouterDialogControllerTest.MultipleMediaRouterDialogs:MediaRouterDialogControllerTest.ShowMediaRouterDialog:OneClickSigninSyncObserverTest.NoSyncService_RedirectsImmediately:OneClickSigninSyncObserverTest.OnSyncStateChanged_SyncConfiguredSuccessfully:PinnedTabCodecTest.NoPinnedTabs:PinnedTabCodecTest.PinnedAndNonPinned:PinnedTabServiceTest.Popup:PopupToolbarModelTest.ShouldDisplayURL:PrintPreviewDialogControllerUnitTest.ClearInitiatorDetails:PrintPreviewDialogControllerUnitTest.GetOrCreatePreviewDialog:PrintPreviewDialogControllerUnitTest.MultiplePreviewDialogs:PrintPreviewUIUnitTest.GetCurrentPrintPreviewStatus:PrintPreviewUIUnitTest.PrintPreviewData:PrintPreviewUIUnitTest.PrintPreviewDraftPages:RecentTabsSubMenuModelTest.RecentlyClosedTabsAndWindowsFromLastSession:RecentTabsSubMenuModelTest.RecentlyClosedTabsFromCurrentSession:ReuseInstantSearchBasePageTest.CanCommitQuery:ReuseInstantSearchBasePageTest.CanCommitQuery_InstantSearchBasePageLoadInProgress:SearchDelegateTest.SearchModel:SearchIPCRouterPolicyTest.AppropriateMessagesSentToIncognitoPages:SearchIPCRouterPolicyTest.DoNotProcessChromeIdentityCheck:SearchIPCRouterPolicyTest.DoNotProcessFocusOmnibox:SearchIPCRouterPolicyTest.DoNotProcessHistorySyncCheck:SearchIPCRouterPolicyTest.DoNotProcessLogEvent:SearchIPCRouterPolicyTest.DoNotProcessMessagesForInactiveTab:SearchIPCRouterPolicyTest.DoNotProcessMessagesForIncognitoPage:SearchIPCRouterPolicyTest.DoNotProcessNavigateToURL:SearchIPCRouterPolicyTest.DoNotProcessPasteIntoOmniboxMsg:SearchIPCRouterPolicyTest.DoNotSendMostVisitedItems:SearchIPCRouterPolicyTest.DoNotSendSetMessagesForIncognitoPage:SearchIPCRouterPolicyTest.DoNotSendSetPromoInformation:SearchIPCRouterPolicyTest.DoNotSendThemeBackgroundInfo:SearchIPCRouterPolicyTest.ProcessChromeIdentityCheck:SearchIPCRouterPolicyTest.ProcessDeleteMostVisitedItem:SearchIPCRouterPolicyTest.ProcessFocusOmnibox:SearchIPCRouterPolicyTest.ProcessHistorySyncCheck:SearchIPCRouterPolicyTest.ProcessLogEvent:SearchIPCRouterPolicyTest.ProcessNavigateToURL:SearchIPCRouterPolicyTest.ProcessPasteIntoOmniboxMsg:SearchIPCRouterPolicyTest.ProcessUndoAllMostVisitedDeletions:SearchIPCRouterPolicyTest.ProcessUndoMostVisitedDeletion:SearchIPCRouterPolicyTest.ProcessVoiceSearchSupportMsg:SearchIPCRouterPolicyTest.SendMostVisitedItems:SearchIPCRouterPolicyTest.SendSetDisplayInstantResults:SearchIPCRouterPolicyTest.SendSetOmniboxStartMargin:SearchIPCRouterPolicyTest.SendSetPromoInformation:SearchIPCRouterPolicyTest.SendSetSuggestionToPrefetch:SearchIPCRouterPolicyTest.SendThemeBackgroundInfo:SearchIPCRouterPolicyTest.SendToggleVoiceSearch:SearchIPCRouterPolicyTest.SubmitQuery:SearchIPCRouterTest.DoNotSendMostVisitedItemsMsg:SearchIPCRouterTest.DoNotSendOmniboxFocusChange:SearchIPCRouterTest.DoNotSendSetDisplayInstantResultsMsg:SearchIPCRouterTest.DoNotSendSetInputInProgress:SearchIPCRouterTest.DoNotSendSetOmniboxStartMargin:SearchIPCRouterTest.DoNotSendSetPromoInformationMsg:SearchIPCRouterTest.DoNotSendSetSuggestionToPrefetch:SearchIPCRouterTest.DoNotSendSubmitMsg:SearchIPCRouterTest.DoNotSendThemeBackgroundInfoMsg:SearchIPCRouterTest.DoNotSendToggleVoiceSearch:SearchIPCRouterTest.HandleTabChangedEvents:SearchIPCRouterTest.IgnoreChromeIdentityCheckMsg:SearchIPCRouterTest.IgnoreDeleteMostVisitedItemMsg:SearchIPCRouterTest.IgnoreFocusOmniboxMsg:SearchIPCRouterTest.IgnoreHistorySyncCheckMsg:SearchIPCRouterTest.IgnoreLogEventMsg:SearchIPCRouterTest.IgnoreMessageIfThePageIsNotActive:SearchIPCRouterTest.IgnoreMessagesFromNonInstantRenderers:SearchIPCRouterTest.IgnoreNavigateToURLMsg:SearchIPCRouterTest.IgnorePasteAndOpenDropdownMsg:SearchIPCRouterTest.IgnoreUndoAllMostVisitedDeletionsMsg:SearchIPCRouterTest.IgnoreUndoMostVisitedDeletionMsg:SearchIPCRouterTest.IgnoreVoiceSearchSupportMsg:SearchIPCRouterTest.ProcessChromeIdentityCheckMsg:SearchIPCRouterTest.ProcessDeleteMostVisitedItemMsg:SearchIPCRouterTest.ProcessFocusOmniboxMsg:SearchIPCRouterTest.ProcessHistorySyncCheckMsg:SearchIPCRouterTest.ProcessLogEventMsg:SearchIPCRouterTest.ProcessLogMostVisitedImpressionMsg:SearchIPCRouterTest.ProcessLogMostVisitedNavigationMsg:SearchIPCRouterTest.ProcessNavigateToURLMsg:SearchIPCRouterTest.ProcessPasteAndOpenDropdownMsg:SearchIPCRouterTest.ProcessUndoAllMostVisitedDeletionsMsg:SearchIPCRouterTest.ProcessUndoMostVisitedDeletionMsg:SearchIPCRouterTest.ProcessVoiceSearchSupportMsg:SearchIPCRouterTest.SendMostVisitedItemsMsg:SearchIPCRouterTest.SendOmniboxFocusChange:SearchIPCRouterTest.SendSetDisplayInstantResultsMsg_DisableInstantOnResultsPage:SearchIPCRouterTest.SendSetDisplayInstantResultsMsg_EnableInstantOnResultsPage:SearchIPCRouterTest.SendSetDisplayInstantResultsMsg_EnableInstantOutsideSearchResultsPage:SearchIPCRouterTest.SendSetInputInProgress:SearchIPCRouterTest.SendSetOmniboxStartMargin:SearchIPCRouterTest.SendSetPromoInformationMsg:SearchIPCRouterTest.SendSetSuggestionToPrefetch:SearchIPCRouterTest.SendSubmitMsg:SearchIPCRouterTest.SendThemeBackgroundInfoMsg:SearchIPCRouterTest.SendToggleVoiceSearch:SearchIPCRouterTest.SpuriousMessageTypesIgnored:SearchTabHelperPrerenderTest.OnOmniboxFocusPrerenderInstantURL:SearchTabHelperPrerenderTest.OnTabActivatedNoPrerenderIfOmniboxBlurred:SearchTabHelperPrerenderTest.OnTabActivatedPrerenderInstantURL:SearchTest.InstantCacheableNTPNavigationEntry:SearchTest.InstantCacheableNTPNavigationEntryNewProfile:SearchTest.InstantNTPCustomNavigationEntry:SearchTest.InstantNTPExtendedEnabled:SearchTest.ProcessIsolation:SearchTest.ProcessIsolation_RendererInitiated:SessionCrashedInfoBarDelegateUnitTest.DetachingTabWithCrashedInfoBar:SessionsSyncManagerTest.AssociateWindowsDontReloadTabs:SessionsSyncManagerTest.CheckPrerenderedWebContentsSwap:SessionsSyncManagerTest.MergeLocalSessionExistingTabs:SessionsSyncManagerTest.MergeWithLocalAndForeignTabs:SessionsSyncManagerTest.OnLocalTabModified:SessionsSyncManagerTest.ProcessRemoteDeleteOfLocalSession:SessionsSyncManagerTest.SwappedOutOnRestore:SessionsSyncManagerTest.UpdatesAfterMixedMerge:SiteEngagementServiceTest.ScoreIncrementsOnPageRequest:TabMenuModelTest.Basics:TestUsePrerenderPage.DoNotUsePrerenderPage:TestUsePrerenderPage.ExtractSearchTermsAndUsePrerenderPage:TestUsePrerenderPage.SetEmbeddedSearchRequestParams:ToolbarActionsBarRedesignUnitTest.ExtensionActionWantsToRunAppearance:ToolbarActionsBarUnitTest.ExtensionActionNormalAppearance:ToolbarModelTest.GoogleBaseURL:ToolbarModelTest.SearchTermsWhileLoading:ToolbarModelTest.ShouldDisplayURL_QueryExtraction" + ], + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "unit_tests" + } + ] + }, + "CFI Linux": { + "gtest_tests": [ + { + "test": "base_unittests" } ] }, @@ -151,6 +184,10 @@ "name": "telemetry_unittests", "script": "telemetry_unittests.py" }, + { + "name": "telemetry_gpu_unittests", + "script": "telemetry_gpu_unittests.py" + }, { "name": "telemetry_perf_unittests", "script": "telemetry_perf_unittests.py" @@ -161,6 +198,143 @@ } ] }, + "Chromium Win 10": { + "gtest_tests": [ + { + "test": "angle_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "base_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "shards": 10 + }, + "test": "browser_tests" + }, + { + "test": "cacheinvalidation_unittests" + }, + { + "test": "chrome_elf_unittests" + }, + { + "test": "components_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "courgette_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "crypto_unittests" + }, + { + "test": "device_unittests" + }, + { + "test": "extensions_unittests" + }, + { + "test": "gcm_unit_tests" + }, + { + "test": "google_apis_unittests" + }, + { + "test": "gpu_unittests" + }, + { + "test": "installer_util_unittests" + }, + { + "test": "ipc_tests" + }, + { + "test": "jingle_unittests" + }, + { + "test": "media_unittests" + }, + { + "test": "midi_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "net_unittests" + }, + { + "test": "ppapi_unittests" + }, + { + "test": "printing_unittests" + }, + { + "test": "remoting_unittests" + }, + { + "test": "sbox_integration_tests" + }, + { + "test": "sbox_unittests" + }, + { + "test": "sbox_validation_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "setup_unittests" + }, + { + "test": "skia_unittests" + }, + { + "test": "sql_unittests" + }, + { + "test": "sync_unit_tests" + }, + { + "test": "ui_base_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "unit_tests" + }, + { + "test": "url_unittests" + }, + { + "test": "views_unittests" + } + ] + }, "ClangToTLinux tester": { "gtest_tests": [ { @@ -209,6 +383,9 @@ "test": "components_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "compositor_unittests" }, { @@ -269,6 +446,9 @@ "test": "mojo_common_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "mojo_public_bindings_unittests" }, { @@ -287,6 +467,9 @@ "test": "nacl_helper_nonsfi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "nacl_loader_unittests" }, { @@ -577,6 +760,9 @@ "test": "mojo_common_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "mojo_public_bindings_unittests" }, { @@ -607,6 +793,9 @@ "test": "remoting_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sandbox_mac_unittests" }, { @@ -639,6 +828,10 @@ "name": "telemetry_unittests", "script": "telemetry_unittests.py" }, + { + "name": "telemetry_gpu_unittests", + "script": "telemetry_gpu_unittests.py" + }, { "name": "telemetry_perf_unittests", "script": "telemetry_perf_unittests.py" @@ -745,6 +938,9 @@ "test": "mojo_common_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "mojo_public_bindings_unittests" }, { @@ -775,6 +971,9 @@ "test": "remoting_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sandbox_mac_unittests" }, { @@ -807,6 +1006,10 @@ "name": "telemetry_unittests", "script": "telemetry_unittests.py" }, + { + "name": "telemetry_gpu_unittests", + "script": "telemetry_gpu_unittests.py" + }, { "name": "telemetry_perf_unittests", "script": "telemetry_perf_unittests.py" @@ -922,6 +1125,12 @@ { "test": "sbox_validation_tests" }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "setup_unittests" + }, { "test": "skia_unittests" }, @@ -1053,6 +1262,12 @@ { "test": "sbox_validation_tests" }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "setup_unittests" + }, { "test": "skia_unittests" }, @@ -1184,6 +1399,12 @@ { "test": "sbox_validation_tests" }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "setup_unittests" + }, { "test": "skia_unittests" }, @@ -1315,6 +1536,12 @@ { "test": "sbox_validation_tests" }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "setup_unittests" + }, { "test": "skia_unittests" }, @@ -1446,6 +1673,12 @@ { "test": "sbox_validation_tests" }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "setup_unittests" + }, { "test": "skia_unittests" }, @@ -1539,6 +1772,9 @@ "test": "gpu_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "installer_util_unittests" }, { @@ -1569,14 +1805,29 @@ "test": "remoting_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sbox_integration_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sbox_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sbox_validation_tests" }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "setup_unittests" + }, { "test": "skia_unittests" }, @@ -1615,15 +1866,24 @@ "test": "base_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "browser_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "cacheinvalidation_unittests" }, { "test": "chrome_elf_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "components_unittests" }, { @@ -1633,6 +1893,9 @@ "test": "content_browsertests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "content_unittests" }, { @@ -1654,66 +1917,126 @@ "test": "extensions_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gcm_unit_tests" }, { "test": "google_apis_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gpu_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "installer_util_unittests" }, { - "test": "ipc_tests" + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "ipc_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "jingle_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "media_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "midi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "net_unittests" }, { "test": "ppapi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "printing_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "remoting_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sbox_integration_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sbox_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sbox_validation_tests" }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "setup_unittests" + }, { "test": "skia_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sql_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sync_unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ui_base_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "url_unittests" }, { @@ -1733,15 +2056,24 @@ "test": "base_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "browser_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "cacheinvalidation_unittests" }, { "test": "chrome_elf_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "components_unittests" }, { @@ -1751,6 +2083,9 @@ "test": "content_browsertests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "content_unittests" }, { @@ -1772,39 +2107,66 @@ "test": "extensions_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gcm_unit_tests" }, { "test": "google_apis_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gpu_unittests" }, { "test": "installer_util_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ipc_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "jingle_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "media_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "midi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "net_unittests" }, { "test": "ppapi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "printing_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "remoting_unittests" }, { @@ -1816,22 +2178,43 @@ { "test": "sbox_validation_tests" }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "setup_unittests" + }, { "test": "skia_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sql_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sync_unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ui_base_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "url_unittests" }, { @@ -1944,6 +2327,12 @@ { "test": "sbox_validation_tests" }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "setup_unittests" + }, { "test": "skia_unittests" }, @@ -2075,6 +2464,12 @@ { "test": "sbox_validation_tests" }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "setup_unittests" + }, { "test": "skia_unittests" }, @@ -2206,6 +2601,12 @@ { "test": "sbox_validation_tests" }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "setup_unittests" + }, { "test": "skia_unittests" }, @@ -2337,6 +2738,12 @@ { "test": "sbox_validation_tests" }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "setup_unittests" + }, { "test": "skia_unittests" }, @@ -2446,6 +2853,12 @@ { "test": "sbox_validation_tests" }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "setup_unittests" + }, { "test": "skia_unittests" }, @@ -2574,6 +2987,12 @@ { "test": "sbox_validation_tests" }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "setup_unittests" + }, { "test": "skia_unittests" }, @@ -2705,6 +3124,12 @@ { "test": "sbox_validation_tests" }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "setup_unittests" + }, { "test": "skia_unittests" }, @@ -2759,39 +3184,75 @@ "test": "app_shell_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "aura_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "base_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "browser_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "cacheinvalidation_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "cast_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "cc_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "chromedriver_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "components_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "compositor_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "content_browsertests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "content_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "crypto_unittests" }, { @@ -2801,18 +3262,30 @@ "test": "device_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "display_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "events_unittests" }, { "test": "extensions_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gcm_unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gfx_unittests" }, { @@ -2822,27 +3295,51 @@ "test": "google_apis_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gpu_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "interactive_ui_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ipc_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "jingle_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "media_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "midi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "mojo_common_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "mojo_public_bindings_unittests" }, { @@ -2861,48 +3358,84 @@ "test": "nacl_helper_nonsfi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "nacl_loader_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "net_unittests" }, { "test": "ppapi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "printing_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "remoting_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sandbox_linux_unittests" }, { "test": "skia_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sql_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sync_unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ui_base_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ui_touch_selection_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "url_unittests" }, { "test": "views_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "wm_unittests" } ], @@ -2911,6 +3444,10 @@ "name": "telemetry_unittests", "script": "telemetry_unittests.py" }, + { + "name": "telemetry_gpu_unittests", + "script": "telemetry_gpu_unittests.py" + }, { "name": "telemetry_perf_unittests", "script": "telemetry_perf_unittests.py" @@ -2975,6 +3512,9 @@ "test": "device_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "display_unittests" }, { @@ -3085,6 +3625,10 @@ "name": "telemetry_unittests", "script": "telemetry_unittests.py" }, + { + "name": "telemetry_gpu_unittests", + "script": "telemetry_gpu_unittests.py" + }, { "name": "telemetry_perf_unittests", "script": "telemetry_perf_unittests.py" @@ -3113,39 +3657,75 @@ "test": "app_shell_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "aura_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "base_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "browser_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "cacheinvalidation_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "cast_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "cc_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "chromedriver_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "components_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "compositor_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "content_browsertests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "content_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "crypto_unittests" }, { @@ -3158,15 +3738,24 @@ "test": "display_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "events_unittests" }, { "test": "extensions_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gcm_unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gfx_unittests" }, { @@ -3176,27 +3765,51 @@ "test": "google_apis_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gpu_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "interactive_ui_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ipc_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "jingle_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "media_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "midi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "mojo_common_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "mojo_public_bindings_unittests" }, { @@ -3215,48 +3828,84 @@ "test": "nacl_helper_nonsfi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "nacl_loader_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "net_unittests" }, { "test": "ppapi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "printing_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "remoting_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sandbox_linux_unittests" }, { "test": "skia_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sql_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sync_unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ui_base_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ui_touch_selection_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "url_unittests" }, { "test": "views_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "wm_unittests" } ], @@ -3265,6 +3914,10 @@ "name": "telemetry_unittests", "script": "telemetry_unittests.py" }, + { + "name": "telemetry_gpu_unittests", + "script": "telemetry_gpu_unittests.py" + }, { "name": "telemetry_perf_unittests", "script": "telemetry_perf_unittests.py" @@ -3439,6 +4092,10 @@ "name": "telemetry_unittests", "script": "telemetry_unittests.py" }, + { + "name": "telemetry_gpu_unittests", + "script": "telemetry_gpu_unittests.py" + }, { "name": "telemetry_perf_unittests", "script": "telemetry_perf_unittests.py" @@ -3454,14 +4111,14 @@ { "args": [ "--site-per-process", - "--gtest_filter=-AppApiTest.*:BlockedAppApiTest.*:BrowserTest.ClearPendingOnFailUnlessNTP:BrowserTest.OtherRedirectsDontForkProcess:BrowserTest.WindowOpenClose:ChromeAppAPITest.*:ChromeRenderProcessHostTest.*:ChromeRenderProcessHostTestWithCommandLine.*:DevToolsExperimentalExtensionTest.*:DevToolsExtensionTest.*:DnsProbeBrowserTest.*:ErrorPageTest.*:ExecuteScriptApiTest.ExecuteScriptPermissions:ExtensionApiTest.ActiveTab:ExtensionApiTest.ChromeRuntimeOpenOptionsPage:ExtensionApiTest.ContentScriptExtensionIframe:ExtensionApiTest.ContentScriptOtherExtensions:ExtensionApiTest.ContentScriptExtensionProcess:ExtensionApiTest.Tabs2:ExtensionApiTest.TabsOnUpdated:ExtensionApiTest.WindowOpenPopupIframe:ExtensionBrowserTest.LoadChromeExtensionsWithOptionsParamWhenEmbedded:ExtensionCrxInstallerTest.InstallDelayedUntilNextUpdate:ExtensionOptionsApiTest.ExtensionCanEmbedOwnOptions:ExtensionWebUITest.CanEmbedExtensionOptions:ExtensionWebUITest.ReceivesExtensionOptionsOnClose:InlineLoginUISafeIframeBrowserTest.*:IsolatedAppTest.*:LaunchWebAuthFlowFunctionTest.*:MimeHandlerViewTest.*:*.NewAvatarMenuEnabledInGuestMode:OptionsUIBrowserTest.*:*PDFExtensionTest.*:PhishingClassifierTest.*:PhishingDOMFeatureExtractorTest.*:PlatformAppUrlRedirectorBrowserTest.*:PopupBlockerBrowserTest.*:PrerenderBrowserTest.*:ProcessManagementTest.*:RedirectTest.*:ReferrerPolicyTest.*:SSLUITest.*:WebNavigationApiTest.CrossProcessFragment:WebNavigationApiTest.ServerRedirectSingleProcess:WebNavigationApiTest.CrossProcessHistory:WebViewCommonTest.*:WebViewDPITest.*:WebViewPluginTest.*:WebViewTest.*:ZoomControllerBrowserTest.*:*.NavigateFromNTPToOptionsInSameTab:*.ProfilesWithoutPagesNotLaunched:*.TabMove:*.WhitelistedExtension:*.NewTabPageURL:*.HomepageLocation:RestoreOnStartupPolicyTest*:PhishingClassifierDelegateTest.*:WebUIWebViewBrowserTest*:WebRtcBrowserTest.RunsAudioVideoWebRTCCallInTwoTabs" + "--gtest_filter=-AppApiTest.OpenAppFromIframe:AppApiTest.OpenWebPopupFromWebIframe:BrowserTest.ClearPendingOnFailUnlessNTP:BrowserTest.OtherRedirectsDontForkProcess:BrowserTest.WindowOpenClose:ChromeRenderProcessHostTest.*:ChromeRenderProcessHostTestWithCommandLine.*:DevToolsExperimentalExtensionTest.*:DevToolsExtensionTest.*:DnsProbeBrowserTest.*:ErrorPageTest.*:ExtensionApiTest.ActiveTab:ExtensionApiTest.ContentScriptExtensionIframe:ExtensionApiTest.ContentScriptOtherExtensions:ExtensionApiTest.ContentScriptExtensionProcess:ExtensionApiTest.Tabs2:ExtensionApiTest.TabsOnUpdated:ExtensionApiTest.WindowOpenPopupIframe:ExtensionOptionsApiTest.ExtensionCanEmbedOwnOptions:ExtensionViewTest.*:InlineLoginUISafeIframeBrowserTest.*:IsolatedAppTest.*:LaunchWebAuthFlowFunctionTest.*:MimeHandlerViewTest.*:*.NewAvatarMenuEnabledInGuestMode:OptionsUIBrowserTest.*:*PDFExtensionTest.*:PhishingClassifierTest.*:PhishingDOMFeatureExtractorTest.*:PopupBlockerBrowserTest.*:PrerenderBrowserTest.*:ProcessManagementTest.*:RedirectTest.*:ReferrerPolicyTest.*:*.RestoreCrossSiteWithExistingSiteInstance:*.RestoreTabWithSpecialURLOnBack:SSLUITest.*:WebNavigationApiTest.CrossProcessFragment:WebNavigationApiTest.ServerRedirectSingleProcess:WebNavigationApiTest.CrossProcessHistory:WebViewDPITest.*:WebViewPluginTest.*:WebViewTest.AcceptTouchEvents:WebViewTest.ExecuteScript:WebViewTest.GeolocationAPICancelGeolocation:WebViewTest.GeolocationAPIEmbedderHasAccessMultipleBridgeIdAllow:WebViewTest.IndexedDBIsolation:WebViewTest.ScreenCoordinates:WebViewTest.ContextMenusAPI_PreventDefault:WebViewTest.TestContextMenu:WebViewFocusTest.*:WebViewNewWindowTest.*:WebViewSizeTest.*:WebViewSpeechAPITest.*:WebViewVisibilityTest.*:ZoomControllerBrowserTest.*:*.NavigateFromNTPToOptionsInSameTab:*.ProfilesWithoutPagesNotLaunched:*.TabMove:*.WhitelistedExtension:*.NewTabPageURL:*.HomepageLocation:RestoreOnStartupPolicyTest*:PhishingClassifierDelegateTest.*:WebUIWebViewBrowserTest*:WebRtcBrowserTest.RunsAudioVideoWebRTCCallInTwoTabs" ], "test": "browser_tests" }, { "args": [ "--site-per-process", - "--gtest_filter=-*.AllowTargetedNavigationsAfterSwap:*.DisownOpener:*.SupportCrossProcessPostMessageWithMessagePort" + "--gtest_filter=-*.PreventSpoofFromSubframeAndReplace:SessionHistoryTest.CrossFrameFormBackForward:SessionHistoryTest.FrameBackForward:*.SupportCrossProcessPostMessageWithMessagePort:DevToolsProtocolTest.NavigationPreservesMessages:NavigationControllerBrowserTest.ReloadOriginalRequest" ], "test": "content_browsertests" }, @@ -3484,14 +4141,14 @@ { "args": [ "--site-per-process", - "--gtest_filter=-AppApiTest.*:BlockedAppApiTest.*:BrowserTest.ClearPendingOnFailUnlessNTP:BrowserTest.OtherRedirectsDontForkProcess:BrowserTest.WindowOpenClose:ChromeAppAPITest.*:ChromeRenderProcessHostTest.*:ChromeRenderProcessHostTestWithCommandLine.*:DevToolsExperimentalExtensionTest.*:DevToolsExtensionTest.*:DnsProbeBrowserTest.*:ErrorPageTest.*:ExecuteScriptApiTest.ExecuteScriptPermissions:ExtensionApiTest.ActiveTab:ExtensionApiTest.ChromeRuntimeOpenOptionsPage:ExtensionApiTest.ContentScriptExtensionIframe:ExtensionApiTest.ContentScriptOtherExtensions:ExtensionApiTest.ContentScriptExtensionProcess:ExtensionApiTest.Tabs2:ExtensionApiTest.TabsOnUpdated:ExtensionApiTest.WindowOpenPopupIframe:ExtensionBrowserTest.LoadChromeExtensionsWithOptionsParamWhenEmbedded:ExtensionCrxInstallerTest.InstallDelayedUntilNextUpdate:ExtensionOptionsApiTest.ExtensionCanEmbedOwnOptions:ExtensionWebUITest.CanEmbedExtensionOptions:ExtensionWebUITest.ReceivesExtensionOptionsOnClose:InlineLoginUISafeIframeBrowserTest.*:IsolatedAppTest.*:LaunchWebAuthFlowFunctionTest.*:MimeHandlerViewTest.*:*.NewAvatarMenuEnabledInGuestMode:OptionsUIBrowserTest.*:*PDFExtensionTest.*:PhishingClassifierTest.*:PhishingDOMFeatureExtractorTest.*:PlatformAppUrlRedirectorBrowserTest.*:PopupBlockerBrowserTest.*:PrerenderBrowserTest.*:ProcessManagementTest.*:RedirectTest.*:ReferrerPolicyTest.*:SSLUITest.*:WebNavigationApiTest.CrossProcessFragment:WebNavigationApiTest.ServerRedirectSingleProcess:WebNavigationApiTest.CrossProcessHistory:WebViewCommonTest.*:WebViewDPITest.*:WebViewPluginTest.*:WebViewTest.*:ZoomControllerBrowserTest.*:*.NavigateFromNTPToOptionsInSameTab:*.ProfilesWithoutPagesNotLaunched:*.TabMove:*.WhitelistedExtension:*.NewTabPageURL:*.HomepageLocation:RestoreOnStartupPolicyTest*:PhishingClassifierDelegateTest.*:WebUIWebViewBrowserTest*:WebRtcBrowserTest.RunsAudioVideoWebRTCCallInTwoTabs" + "--gtest_filter=-AppApiTest.OpenAppFromIframe:AppApiTest.OpenWebPopupFromWebIframe:BrowserTest.ClearPendingOnFailUnlessNTP:BrowserTest.OtherRedirectsDontForkProcess:BrowserTest.WindowOpenClose:ChromeRenderProcessHostTest.*:ChromeRenderProcessHostTestWithCommandLine.*:DevToolsExperimentalExtensionTest.*:DevToolsExtensionTest.*:DnsProbeBrowserTest.*:ErrorPageTest.*:ExtensionApiTest.ActiveTab:ExtensionApiTest.ContentScriptExtensionIframe:ExtensionApiTest.ContentScriptOtherExtensions:ExtensionApiTest.ContentScriptExtensionProcess:ExtensionApiTest.Tabs2:ExtensionApiTest.TabsOnUpdated:ExtensionApiTest.WindowOpenPopupIframe:ExtensionOptionsApiTest.ExtensionCanEmbedOwnOptions:ExtensionViewTest.*:InlineLoginUISafeIframeBrowserTest.*:IsolatedAppTest.*:LaunchWebAuthFlowFunctionTest.*:MimeHandlerViewTest.*:*.NewAvatarMenuEnabledInGuestMode:OptionsUIBrowserTest.*:*PDFExtensionTest.*:PhishingClassifierTest.*:PhishingDOMFeatureExtractorTest.*:PopupBlockerBrowserTest.*:PrerenderBrowserTest.*:ProcessManagementTest.*:RedirectTest.*:ReferrerPolicyTest.*:*.RestoreCrossSiteWithExistingSiteInstance:*.RestoreTabWithSpecialURLOnBack:SSLUITest.*:WebNavigationApiTest.CrossProcessFragment:WebNavigationApiTest.ServerRedirectSingleProcess:WebNavigationApiTest.CrossProcessHistory:WebViewDPITest.*:WebViewPluginTest.*:WebViewTest.AcceptTouchEvents:WebViewTest.ExecuteScript:WebViewTest.GeolocationAPICancelGeolocation:WebViewTest.GeolocationAPIEmbedderHasAccessMultipleBridgeIdAllow:WebViewTest.IndexedDBIsolation:WebViewTest.ScreenCoordinates:WebViewTest.ContextMenusAPI_PreventDefault:WebViewTest.TestContextMenu:WebViewFocusTest.*:WebViewNewWindowTest.*:WebViewSizeTest.*:WebViewSpeechAPITest.*:WebViewVisibilityTest.*:ZoomControllerBrowserTest.*:*.NavigateFromNTPToOptionsInSameTab:*.ProfilesWithoutPagesNotLaunched:*.TabMove:*.WhitelistedExtension:*.NewTabPageURL:*.HomepageLocation:RestoreOnStartupPolicyTest*:PhishingClassifierDelegateTest.*:WebUIWebViewBrowserTest*:WebRtcBrowserTest.RunsAudioVideoWebRTCCallInTwoTabs" ], "test": "browser_tests" }, { "args": [ "--site-per-process", - "--gtest_filter=-*.AllowTargetedNavigationsAfterSwap:*.DisownOpener:*.SupportCrossProcessPostMessageWithMessagePort" + "--gtest_filter=-*.PreventSpoofFromSubframeAndReplace:SessionHistoryTest.CrossFrameFormBackForward:SessionHistoryTest.FrameBackForward:*.SupportCrossProcessPostMessageWithMessagePort:DevToolsProtocolTest.NavigationPreservesMessages:NavigationControllerBrowserTest.ReloadOriginalRequest" ], "test": "content_browsertests" }, diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json index a0d832f16b674..4004bcd37fbac 100644 --- a/testing/buildbot/chromium.linux.json +++ b/testing/buildbot/chromium.linux.json @@ -1,183 +1,233 @@ { "Android GN": { "additional_compile_targets": [ + "chrome_public_apk", + "chrome_public_test_apk", "chrome_shell_apk", + "chrome_shell_test_apk", + "content_shell_apk", "mandoline:all" - ] - }, - "Android GN (dbg)": { - "additional_compile_targets": [ - "chrome_shell_apk", - "mandoline:all" - ] - }, - "Android Tests": { - "scripts": [ + ], + "gtest_tests": [ { - "name": "webview_licenses", - "script": "webview_licenses.py" + "test": "html_viewer_unittests" }, { - "name": "telemetry_perf_unittests", - "script": "telemetry_perf_unittests.py" - } - ] - }, - "Android Tests (dbg)": { - "scripts": [ - { - "name": "webview_licenses", - "script": "webview_licenses.py" + "test": "ipc_mojo_unittests" }, { - "name": "telemetry_perf_unittests", - "script": "telemetry_perf_unittests.py" - } - ] - }, - "Cast Linux": { - "gtest_tests": [ - { - "test": "base_unittests" + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "mojo_common_unittests" }, { - "test": "cacheinvalidation_unittests" + "test": "mojo_public_application_unittests" }, { - "test": "cast_base_unittests" + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "mojo_public_bindings_unittests" }, { - "test": "cast_media_unittests" + "test": "mojo_public_environment_unittests" }, { - "test": "cast_shell_browser_test" + "test": "mojo_public_system_unittests" }, { - "test": "content_unittests" + "test": "mojo_public_utility_unittests" }, { - "test": "crypto_unittests" + "test": "mojo_runner_unittests" }, { - "test": "gpu_unittests" + "test": "mojo_shell_unittests" }, { - "test": "ipc_tests" + "test": "mojo_surfaces_lib_unittests" }, { - "test": "jingle_unittests" + "test": "mojo_system_unittests" }, { - "test": "media_unittests" + "test": "mojo_view_manager_lib_unittests" }, { - "test": "midi_unittests" + "test": "resource_provider_unittests" }, { - "test": "net_unittests" - }, + "test": "view_manager_unittests" + } + ], + "scripts": [ { - "test": "sandbox_linux_unittests" - }, + "name": "gn_check", + "script": "gn_check.py" + } + ] + }, + "Android GN (dbg)": { + "additional_compile_targets": [ + "chrome_public_apk", + "chrome_public_test_apk", + "chrome_shell_apk", + "chrome_shell_test_apk", + "content_shell_apk", + "content_shell_test_apk", + "mandoline:all" + ] + }, + "Android Tests": { + "scripts": [ { - "test": "sql_unittests" + "name": "webview_licenses", + "script": "webview_licenses.py" }, { - "test": "sync_unit_tests" + "name": "telemetry_perf_unittests", + "script": "telemetry_perf_unittests.py" }, { - "test": "ui_base_unittests" + "args": [ + "android_webview_unittests" + ], + "name": "android_webview_unittests", + "script": "android_gtest_test.py" + } + ] + }, + "Android Tests (dbg)": { + "scripts": [ + { + "name": "webview_licenses", + "script": "webview_licenses.py" }, { - "test": "url_unittests" + "name": "telemetry_perf_unittests", + "script": "telemetry_perf_unittests.py" } ] }, - "Linux Clang (dbg)": { + "Cast Linux": { "gtest_tests": [ { "swarming": { "can_use_on_swarming_builders": true }, - "test": "accessibility_unittests" - }, - { - "test": "app_shell_unittests" - }, - { "test": "base_unittests" }, { - "test": "components_unittests" - }, - { - "test": "content_unittests" - }, - { - "test": "crypto_unittests" + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "cacheinvalidation_unittests" }, { - "test": "device_unittests" + "test": "cast_base_unittests" }, { - "test": "display_unittests" + "test": "cast_crash_unittests" }, { - "test": "extensions_unittests" + "test": "cast_media_unittests" }, { - "test": "gn_unittests" + "test": "cast_shell_browser_test" }, { - "test": "google_apis_unittests" + "test": "cast_shell_unittests" }, { - "test": "ipc_mojo_unittests" + "args": [ + "--gtest_filter=-OutOfProcessPPAPITest.TrueTypeFont:OutOfProcessPPAPITest.BrowserFont" + ], + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" }, { - "test": "ipc_tests" + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_unittests" }, { - "test": "mojo_common_unittests" + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "crypto_unittests" }, { - "test": "mojo_public_application_unittests" + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "gpu_unittests" }, { - "test": "mojo_public_bindings_unittests" + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "ipc_tests" }, { - "test": "mojo_public_environment_unittests" + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "jingle_unittests" }, { - "test": "mojo_public_system_unittests" + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "media_unittests" }, { - "test": "mojo_public_utility_unittests" + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "midi_unittests" }, { - "test": "mojo_system_unittests" + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "net_unittests" }, { - "test": "nacl_loader_unittests" + "test": "ppapi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sandbox_linux_unittests" }, { - "test": "skia_unittests" - }, - { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sql_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sync_unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ui_base_unittests" }, { - "test": "unit_tests" + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "url_unittests" } ] }, @@ -197,6 +247,9 @@ "test": "aura_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "base_unittests" }, { @@ -376,10 +429,6 @@ ], "name": "gyp_flag_compare", "script": "gyp_flag_compare.py" - }, - { - "name": "mojo_apptest", - "script": "mojo_apptest.py" } ] }, @@ -453,9 +502,15 @@ "test": "app_list_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "app_shell_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "aura_unittests" }, { @@ -472,6 +527,9 @@ "test": "browser_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "cacheinvalidation_unittests" }, { @@ -487,6 +545,9 @@ "test": "cc_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "chromedriver_unittests" }, { @@ -502,6 +563,9 @@ "test": "components_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "compositor_unittests" }, { @@ -526,9 +590,15 @@ "test": "dbus_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "device_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "display_unittests" }, { @@ -544,9 +614,15 @@ "test": "extensions_browsertests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "extensions_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gcm_unit_tests" }, { @@ -559,6 +635,9 @@ "test": "gl_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gn_unittests" }, { @@ -580,9 +659,15 @@ "test": "ipc_mojo_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ipc_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "jingle_unittests" }, { @@ -598,9 +683,15 @@ "test": "midi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "mojo_common_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "mojo_public_bindings_unittests" }, { @@ -616,6 +707,9 @@ "test": "mojo_system_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "nacl_loader_unittests" }, { @@ -628,18 +722,33 @@ "test": "ppapi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "printing_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "remoting_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sandbox_linux_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "skia_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sql_unittests" }, { @@ -649,6 +758,9 @@ "test": "sync_integration_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sync_unit_tests" }, { @@ -670,12 +782,18 @@ "test": "unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "url_unittests" }, { "test": "views_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "wm_unittests" } ], @@ -696,6 +814,10 @@ "name": "telemetry_unittests", "script": "telemetry_unittests.py" }, + { + "name": "telemetry_gpu_unittests", + "script": "telemetry_gpu_unittests.py" + }, { "name": "telemetry_perf_unittests", "script": "telemetry_perf_unittests.py" @@ -721,9 +843,15 @@ "test": "app_list_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "app_shell_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "aura_unittests" }, { @@ -740,6 +868,9 @@ "test": "browser_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "cacheinvalidation_unittests" }, { @@ -755,6 +886,9 @@ "test": "cc_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "chromedriver_unittests" }, { @@ -764,6 +898,9 @@ "test": "components_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "compositor_unittests" }, { @@ -788,9 +925,15 @@ "test": "dbus_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "device_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "display_unittests" }, { @@ -806,9 +949,15 @@ "test": "extensions_browsertests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "extensions_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gcm_unit_tests" }, { @@ -821,6 +970,9 @@ "test": "gl_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gn_unittests" }, { @@ -843,9 +995,15 @@ "test": "ipc_mojo_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ipc_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "jingle_unittests" }, { @@ -861,9 +1019,15 @@ "test": "midi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "mojo_common_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "mojo_public_bindings_unittests" }, { @@ -879,6 +1043,9 @@ "test": "mojo_system_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "nacl_loader_unittests" }, { @@ -891,21 +1058,36 @@ "test": "ppapi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "printing_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "remoting_unittests" }, { "args": [ "--test-launcher-print-test-stdio=always" ], + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sandbox_linux_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "skia_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sql_unittests" }, { @@ -915,6 +1097,9 @@ "test": "sync_integration_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sync_unit_tests" }, { @@ -936,12 +1121,18 @@ "test": "unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "url_unittests" }, { "test": "views_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "wm_unittests" } ], @@ -950,6 +1141,10 @@ "name": "telemetry_unittests", "script": "telemetry_unittests.py" }, + { + "name": "telemetry_gpu_unittests", + "script": "telemetry_gpu_unittests.py" + }, { "name": "telemetry_perf_unittests", "script": "telemetry_perf_unittests.py" @@ -975,9 +1170,15 @@ "test": "app_list_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "app_shell_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "aura_unittests" }, { @@ -994,6 +1195,9 @@ "test": "browser_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "cacheinvalidation_unittests" }, { @@ -1009,6 +1213,9 @@ "test": "cc_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "chromedriver_unittests" }, { @@ -1018,6 +1225,9 @@ "test": "components_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "compositor_unittests" }, { @@ -1042,9 +1252,15 @@ "test": "dbus_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "device_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "display_unittests" }, { @@ -1060,9 +1276,15 @@ "test": "extensions_browsertests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "extensions_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gcm_unit_tests" }, { @@ -1075,6 +1297,9 @@ "test": "gl_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gn_unittests" }, { @@ -1096,9 +1321,15 @@ "test": "ipc_mojo_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ipc_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "jingle_unittests" }, { @@ -1114,9 +1345,15 @@ "test": "midi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "mojo_common_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "mojo_public_bindings_unittests" }, { @@ -1132,6 +1369,9 @@ "test": "mojo_system_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "nacl_loader_unittests" }, { @@ -1144,18 +1384,33 @@ "test": "ppapi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "printing_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "remoting_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sandbox_linux_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "skia_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sql_unittests" }, { @@ -1165,6 +1420,9 @@ "test": "sync_integration_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sync_unit_tests" }, { @@ -1186,12 +1444,18 @@ "test": "unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "url_unittests" }, { "test": "views_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "wm_unittests" } ], diff --git a/testing/buildbot/chromium.mac.json b/testing/buildbot/chromium.mac.json index 4a5ffab86db77..400370814675d 100644 --- a/testing/buildbot/chromium.mac.json +++ b/testing/buildbot/chromium.mac.json @@ -90,6 +90,9 @@ "test": "base_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "cacheinvalidation_unittests" }, { @@ -105,6 +108,9 @@ "test": "cc_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "chromedriver_unittests" }, { @@ -113,6 +119,12 @@ }, "test": "components_unittests" }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_unittests" + }, { "swarming": { "can_use_on_swarming_builders": true @@ -120,11 +132,20 @@ "test": "crypto_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "extensions_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gcm_unit_tests" }, + { + "test": "gl_unittests" + }, { "test": "google_apis_unittests" }, @@ -135,6 +156,15 @@ "test": "gpu_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "ipc_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "jingle_unittests" }, { @@ -156,9 +186,15 @@ "test": "midi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "mojo_common_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "mojo_public_bindings_unittests" }, { @@ -171,6 +207,9 @@ "test": "mojo_public_utility_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "nacl_loader_unittests" }, { @@ -183,18 +222,33 @@ "test": "ppapi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "printing_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "remoting_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "skia_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sql_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sync_unit_tests" }, { @@ -204,6 +258,15 @@ "test": "ui_base_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "unit_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "url_unittests" } ], @@ -212,6 +275,10 @@ "name": "telemetry_unittests", "script": "telemetry_unittests.py" }, + { + "name": "telemetry_gpu_unittests", + "script": "telemetry_gpu_unittests.py" + }, { "name": "telemetry_perf_unittests", "script": "telemetry_perf_unittests.py" @@ -250,6 +317,9 @@ "test": "browser_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "cacheinvalidation_unittests" }, { @@ -265,6 +335,9 @@ "test": "cc_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "chromedriver_unittests" }, { @@ -298,9 +371,15 @@ "test": "crypto_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "extensions_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gcm_unit_tests" }, { @@ -328,9 +407,15 @@ "test": "interactive_ui_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ipc_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "jingle_unittests" }, { @@ -352,9 +437,15 @@ "test": "midi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "mojo_common_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "mojo_public_bindings_unittests" }, { @@ -370,6 +461,9 @@ "test": "mojo_system_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "nacl_loader_unittests" }, { @@ -382,18 +476,33 @@ "test": "ppapi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "printing_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "remoting_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sandbox_mac_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "skia_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sql_unittests" }, { @@ -403,6 +512,9 @@ "test": "sync_integration_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sync_unit_tests" }, { @@ -418,6 +530,9 @@ "test": "unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "url_unittests" } ], @@ -426,6 +541,10 @@ "name": "telemetry_unittests", "script": "telemetry_unittests.py" }, + { + "name": "telemetry_gpu_unittests", + "script": "telemetry_gpu_unittests.py" + }, { "name": "telemetry_perf_unittests", "script": "telemetry_perf_unittests.py" @@ -464,6 +583,9 @@ "test": "browser_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "cacheinvalidation_unittests" }, { @@ -479,6 +601,9 @@ "test": "cc_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "chromedriver_unittests" }, { @@ -506,9 +631,15 @@ "test": "crypto_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "extensions_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gcm_unit_tests" }, { @@ -536,9 +667,15 @@ "test": "interactive_ui_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ipc_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "jingle_unittests" }, { @@ -560,9 +697,15 @@ "test": "midi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "mojo_common_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "mojo_public_bindings_unittests" }, { @@ -578,6 +721,9 @@ "test": "mojo_system_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "nacl_loader_unittests" }, { @@ -590,18 +736,33 @@ "test": "ppapi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "printing_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "remoting_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sandbox_mac_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "skia_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sql_unittests" }, { @@ -611,6 +772,9 @@ "test": "sync_integration_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sync_unit_tests" }, { @@ -626,6 +790,9 @@ "test": "unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "url_unittests" } ], @@ -634,6 +801,10 @@ "name": "telemetry_unittests", "script": "telemetry_unittests.py" }, + { + "name": "telemetry_gpu_unittests", + "script": "telemetry_gpu_unittests.py" + }, { "name": "telemetry_perf_unittests", "script": "telemetry_perf_unittests.py" @@ -672,6 +843,9 @@ "test": "browser_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "cacheinvalidation_unittests" }, { @@ -687,6 +861,9 @@ "test": "cc_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "chromedriver_unittests" }, { @@ -714,9 +891,15 @@ "test": "crypto_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "extensions_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gcm_unit_tests" }, { @@ -744,9 +927,15 @@ "test": "interactive_ui_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ipc_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "jingle_unittests" }, { @@ -768,9 +957,15 @@ "test": "midi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "mojo_common_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "mojo_public_bindings_unittests" }, { @@ -786,6 +981,9 @@ "test": "mojo_system_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "nacl_loader_unittests" }, { @@ -798,18 +996,33 @@ "test": "ppapi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "printing_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "remoting_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sandbox_mac_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "skia_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sql_unittests" }, { @@ -819,6 +1032,9 @@ "test": "sync_integration_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sync_unit_tests" }, { @@ -834,6 +1050,9 @@ "test": "unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "url_unittests" } ], @@ -842,6 +1061,10 @@ "name": "telemetry_unittests", "script": "telemetry_unittests.py" }, + { + "name": "telemetry_gpu_unittests", + "script": "telemetry_gpu_unittests.py" + }, { "name": "telemetry_perf_unittests", "script": "telemetry_perf_unittests.py" @@ -880,6 +1103,9 @@ "test": "browser_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "cacheinvalidation_unittests" }, { @@ -895,6 +1121,9 @@ "test": "cc_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "chromedriver_unittests" }, { @@ -922,9 +1151,15 @@ "test": "crypto_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "extensions_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gcm_unit_tests" }, { @@ -953,9 +1188,15 @@ "test": "interactive_ui_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ipc_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "jingle_unittests" }, { @@ -977,9 +1218,15 @@ "test": "midi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "mojo_common_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "mojo_public_bindings_unittests" }, { @@ -995,6 +1242,9 @@ "test": "mojo_system_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "nacl_loader_unittests" }, { @@ -1007,18 +1257,33 @@ "test": "ppapi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "printing_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "remoting_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sandbox_mac_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "skia_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sql_unittests" }, { @@ -1028,6 +1293,9 @@ "test": "sync_integration_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sync_unit_tests" }, { @@ -1043,6 +1311,9 @@ "test": "unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "url_unittests" } ], @@ -1051,6 +1322,10 @@ "name": "telemetry_unittests", "script": "telemetry_unittests.py" }, + { + "name": "telemetry_gpu_unittests", + "script": "telemetry_gpu_unittests.py" + }, { "name": "telemetry_perf_unittests", "script": "telemetry_perf_unittests.py" diff --git a/testing/buildbot/chromium.memory.fyi.json b/testing/buildbot/chromium.memory.fyi.json index c577790887d5e..bfc7e0f93ead8 100644 --- a/testing/buildbot/chromium.memory.fyi.json +++ b/testing/buildbot/chromium.memory.fyi.json @@ -14,9 +14,15 @@ "test": "app_list_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "aura_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "base_unittests" }, { @@ -27,51 +33,96 @@ "test": "browser_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "cacheinvalidation_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "cast_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "cc_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "chromedriver_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "components_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "compositor_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "content_browsertests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "content_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "crypto_unittests" }, { "test": "dbus_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "device_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "display_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "events_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "extensions_browsertests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "extensions_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gcm_unit_tests" }, { @@ -81,6 +132,9 @@ "test": "google_apis_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gpu_unittests" }, { @@ -94,21 +148,39 @@ "test": "ipc_mojo_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ipc_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "jingle_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "media_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "midi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "mojo_common_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "mojo_public_bindings_unittests" }, { @@ -124,45 +196,81 @@ "test": "mojo_system_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "nacl_loader_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "net_unittests" }, { "test": "ppapi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "printing_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "remoting_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sandbox_linux_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "skia_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sql_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sync_unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ui_base_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "url_unittests" }, { "test": "views_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "wm_unittests" } ] @@ -182,9 +290,15 @@ "test": "app_list_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "aura_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "base_unittests" }, { @@ -195,54 +309,102 @@ "test": "browser_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "cacheinvalidation_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "cast_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "cc_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "chromedriver_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "components_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "compositor_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "content_browsertests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "content_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "crypto_unittests" }, { "test": "dbus_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "device_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "display_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "events_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "extensions_browsertests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "extensions_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gcm_unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gfx_unittests" }, { @@ -252,6 +414,9 @@ "test": "google_apis_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gpu_unittests" }, { @@ -264,21 +429,39 @@ "test": "ipc_mojo_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ipc_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "jingle_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "media_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "midi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "mojo_common_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "mojo_public_bindings_unittests" }, { @@ -294,48 +477,87 @@ "test": "mojo_system_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "nacl_loader_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "net_unittests" }, { "test": "ppapi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "printing_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "remoting_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sandbox_linux_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "skia_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sql_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sync_unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ui_base_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ui_touch_selection_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "url_unittests" }, { "test": "views_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "wm_unittests" } ] @@ -361,6 +583,9 @@ "test": "app_list_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "aura_unittests" }, { @@ -370,15 +595,27 @@ "test": "base_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "cacheinvalidation_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "cast_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "chromedriver_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "components_unittests" }, { @@ -394,27 +631,48 @@ "test": "content_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "crypto_unittests" }, { "test": "dbus_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "device_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "display_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "events_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "extensions_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gcm_unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gfx_unittests" }, { @@ -424,24 +682,42 @@ "test": "google_apis_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gpu_unittests" }, { "test": "ipc_mojo_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ipc_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "jingle_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "media_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "midi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "mojo_common_unittests" }, { @@ -455,27 +731,51 @@ "test": "ppapi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "printing_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "remoting_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sandbox_linux_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "skia_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sql_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sync_unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ui_base_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ui_touch_selection_unittests" }, { @@ -486,12 +786,18 @@ "test": "unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "url_unittests" }, { "test": "views_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "wm_unittests" } ] diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json index df3f6ac1babe6..7e9b23017555b 100644 --- a/testing/buildbot/chromium.memory.json +++ b/testing/buildbot/chromium.memory.json @@ -21,15 +21,27 @@ "test": "browser_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "cacheinvalidation_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "cast_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "cc_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "components_unittests" }, { @@ -51,21 +63,39 @@ "test": "crypto_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "device_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "display_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "extensions_browsertests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "extensions_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gcm_unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gfx_unittests" }, { @@ -75,6 +105,9 @@ "test": "google_apis_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gpu_unittests" }, { @@ -85,15 +118,27 @@ "test": "interactive_ui_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ipc_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "jingle_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "media_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "midi_unittests" }, { @@ -107,24 +152,45 @@ "test": "ppapi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "printing_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "remoting_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sandbox_linux_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "skia_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sql_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sync_unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ui_base_unittests" }, { @@ -135,6 +201,9 @@ "test": "unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "url_unittests" } ] @@ -183,6 +252,9 @@ "test": "ash_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "aura_unittests" }, { @@ -199,18 +271,33 @@ "test": "browser_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "cacheinvalidation_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "cast_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "chromeos_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "components_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "compositor_unittests" }, { @@ -232,18 +319,33 @@ "test": "crypto_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "device_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "display_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "events_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gcm_unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gfx_unittests" }, { @@ -253,6 +355,9 @@ "test": "google_apis_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gpu_unittests" }, { @@ -263,21 +368,39 @@ "test": "interactive_ui_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ipc_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "jingle_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "media_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "message_center_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "midi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "nacl_loader_unittests" }, { @@ -291,30 +414,54 @@ "test": "ppapi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "printing_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "remoting_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sandbox_linux_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "skia_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sql_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sync_unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ui_base_unittests" }, { "test": "ui_chromeos_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ui_touch_selection_unittests" }, { @@ -325,6 +472,9 @@ "test": "unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "url_unittests" }, { @@ -334,9 +484,6 @@ }, "Mac ASan 64 Tests (1)": { "gtest_tests": [ - { - "test": "base_unittests" - }, { "swarming": { "can_use_on_swarming_builders": true @@ -351,15 +498,27 @@ "test": "browser_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "cacheinvalidation_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "cc_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "chromedriver_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "components_unittests" }, { @@ -382,9 +541,15 @@ "test": "crypto_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gcm_unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gpu_unittests" }, { @@ -395,15 +560,27 @@ "test": "interactive_ui_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ipc_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "jingle_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "media_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "midi_unittests" }, { @@ -415,129 +592,52 @@ { "test": "ppapi_unittests" }, - { - "test": "printing_unittests" - }, - { - "test": "remoting_unittests" - }, - { - "test": "skia_unittests" - }, - { - "test": "sql_unittests" - }, - { - "test": "sync_unit_tests" - }, - { - "test": "ui_base_unittests" - }, { "swarming": { "can_use_on_swarming_builders": true }, - "test": "unit_tests" + "test": "printing_unittests" }, - { - "test": "url_unittests" - } - ] - }, - "Mac ASan Tests (1)": { - "gtest_tests": [ { "swarming": { "can_use_on_swarming_builders": true }, - "test": "base_unittests" + "test": "remoting_unittests" }, { "swarming": { - "can_use_on_swarming_builders": true, - "shards": 10 + "can_use_on_swarming_builders": true }, - "test": "browser_tests" - }, - { - "test": "cacheinvalidation_unittests" - }, - { - "test": "cc_unittests" - }, - { - "test": "chromedriver_unittests" - }, - { - "test": "components_unittests" + "test": "skia_unittests" }, { "swarming": { "can_use_on_swarming_builders": true }, - "test": "content_browsertests" + "test": "sql_unittests" }, { "swarming": { "can_use_on_swarming_builders": true }, - "test": "content_unittests" + "test": "sync_unit_tests" }, { "swarming": { "can_use_on_swarming_builders": true }, - "test": "crypto_unittests" - }, - { - "test": "gcm_unit_tests" - }, - { - "test": "gpu_unittests" + "test": "ui_base_unittests" }, { "swarming": { "can_use_on_swarming_builders": true }, - "test": "interactive_ui_tests" - }, - { - "test": "ipc_tests" - }, - { - "test": "jingle_unittests" - }, - { - "test": "media_unittests" - }, - { - "test": "midi_unittests" + "test": "unit_tests" }, { "swarming": { "can_use_on_swarming_builders": true }, - "test": "net_unittests" - }, - { - "test": "ppapi_unittests" - }, - { - "test": "printing_unittests" - }, - { - "test": "remoting_unittests" - }, - { - "test": "sql_unittests" - }, - { - "test": "sync_unit_tests" - }, - { - "test": "ui_base_unittests" - }, - { "test": "url_unittests" } ] diff --git a/testing/buildbot/chromium.webkit.json b/testing/buildbot/chromium.webkit.json index 80221c99a3f14..4e8a96cd4e8d7 100644 --- a/testing/buildbot/chromium.webkit.json +++ b/testing/buildbot/chromium.webkit.json @@ -14,6 +14,9 @@ "test": "app_list_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "app_shell_unittests" }, { @@ -23,6 +26,9 @@ "test": "ash_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "aura_unittests" }, { @@ -39,18 +45,30 @@ "test": "browser_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "cacheinvalidation_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "chromeos_unittests" }, { "test": "chromevox_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "components_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "compositor_unittests" }, { @@ -65,9 +83,6 @@ }, "test": "content_unittests" }, - { - "test": "content_unittests" - }, { "swarming": { "can_use_on_swarming_builders": true @@ -78,12 +93,21 @@ "test": "dbus_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "device_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "display_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "events_unittests" }, { @@ -93,15 +117,24 @@ "test": "extensions_browsertests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "extensions_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gcm_unit_tests" }, { "test": "google_apis_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gpu_unittests" }, { @@ -111,24 +144,42 @@ "test": "interactive_ui_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ipc_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "jingle_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "media_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "message_center_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "midi_unittests" }, { "test": "nacl_helper_nonsfi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "nacl_loader_unittests" }, { @@ -141,27 +192,51 @@ "test": "ppapi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "printing_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "remoting_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sandbox_linux_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "skia_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sql_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sync_unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ui_base_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ui_touch_selection_unittests" }, { @@ -171,12 +246,18 @@ "test": "unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "url_unittests" }, { "test": "views_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "wm_unittests" } ] @@ -199,6 +280,9 @@ "test": "app_list_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "app_shell_unittests" }, { @@ -208,6 +292,9 @@ "test": "ash_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "aura_unittests" }, { @@ -224,15 +311,27 @@ "test": "browser_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "cacheinvalidation_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "chromeos_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "components_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "compositor_unittests" }, { @@ -258,12 +357,21 @@ "test": "dbus_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "device_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "display_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "events_unittests" }, { @@ -273,15 +381,24 @@ "test": "extensions_browsertests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "extensions_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gcm_unit_tests" }, { "test": "google_apis_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gpu_unittests" }, { @@ -292,24 +409,42 @@ "test": "interactive_ui_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ipc_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "jingle_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "media_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "message_center_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "midi_unittests" }, { "test": "nacl_helper_nonsfi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "nacl_loader_unittests" }, { @@ -322,27 +457,51 @@ "test": "ppapi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "printing_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "remoting_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sandbox_linux_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "skia_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sql_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sync_unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ui_base_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ui_touch_selection_unittests" }, { @@ -352,12 +511,18 @@ "test": "unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "url_unittests" }, { "test": "views_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "wm_unittests" } ] @@ -671,6 +836,32 @@ } ] }, + "WebKit Linux Trusty": { + "gtest_tests": [ + { + "test": "blink_heap_unittests" + }, + { + "test": "blink_platform_unittests" + }, + { + "test": "webkit_unit_tests" + }, + { + "test": "wtf_unittests" + } + ], + "scripts": [ + { + "name": "webkit_lint", + "script": "webkit_lint.py" + }, + { + "name": "webkit_python_tests", + "script": "webkit_python_tests.py" + } + ] + }, "WebKit Mac Oilpan": { "gtest_tests": [ { @@ -723,6 +914,32 @@ } ] }, + "WebKit Mac10.10": { + "gtest_tests": [ + { + "test": "blink_heap_unittests" + }, + { + "test": "blink_platform_unittests" + }, + { + "test": "webkit_unit_tests" + }, + { + "test": "wtf_unittests" + } + ], + "scripts": [ + { + "name": "webkit_lint", + "script": "webkit_lint.py" + }, + { + "name": "webkit_python_tests", + "script": "webkit_python_tests.py" + } + ] + }, "WebKit Mac10.6": { "gtest_tests": [ { @@ -853,7 +1070,7 @@ } ] }, - "WebKit Mac10.8 (retina)": { + "WebKit Mac10.9": { "gtest_tests": [ { "test": "blink_heap_unittests" @@ -879,7 +1096,7 @@ } ] }, - "WebKit Mac10.9": { + "WebKit Mac10.9 (retina)": { "gtest_tests": [ { "test": "blink_heap_unittests" diff --git a/testing/buildbot/chromium.win.json b/testing/buildbot/chromium.win.json index f1fb87904d074..0f760f22f81aa 100644 --- a/testing/buildbot/chromium.win.json +++ b/testing/buildbot/chromium.win.json @@ -8,9 +8,15 @@ "test": "accessibility_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "app_shell_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "aura_unittests" }, { @@ -27,6 +33,9 @@ "test": "browser_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "cacheinvalidation_unittests" }, { @@ -45,6 +54,9 @@ "test": "chrome_elf_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "chromedriver_unittests" }, { @@ -54,6 +66,9 @@ "test": "components_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "compositor_unittests" }, { @@ -81,6 +96,9 @@ "test": "crypto_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "events_unittests" }, { @@ -90,12 +108,21 @@ "test": "extensions_browsertests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "extensions_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gcm_unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gfx_unittests" }, { @@ -111,6 +138,9 @@ "test": "gpu_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "installer_util_unittests" }, { @@ -121,9 +151,15 @@ "test": "interactive_ui_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ipc_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "jingle_unittests" }, { @@ -139,9 +175,15 @@ "test": "midi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "mojo_common_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "mojo_public_bindings_unittests" }, { @@ -157,6 +199,9 @@ "test": "mojo_system_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "nacl_loader_unittests" }, { @@ -169,24 +214,45 @@ "test": "ppapi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "printing_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "remoting_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sbox_integration_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sbox_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sbox_validation_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "skia_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sql_unittests" }, { @@ -196,12 +262,21 @@ "test": "sync_integration_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sync_unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ui_base_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ui_touch_selection_unittests" }, { @@ -211,12 +286,18 @@ "test": "unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "url_unittests" }, { "test": "views_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "wm_unittests" } ], @@ -237,6 +318,9 @@ "test": "app_list_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "app_shell_unittests" }, { @@ -246,6 +330,9 @@ "test": "ash_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "aura_unittests" }, { @@ -262,6 +349,9 @@ "test": "browser_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "cacheinvalidation_unittests" }, { @@ -280,9 +370,15 @@ "test": "chrome_elf_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "chromedriver_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "components_browsertests" }, { @@ -292,6 +388,9 @@ "test": "components_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "compositor_unittests" }, { @@ -319,9 +418,15 @@ "test": "crypto_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "device_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "events_unittests" }, { @@ -331,12 +436,21 @@ "test": "extensions_browsertests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "extensions_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gcm_unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gfx_unittests" }, { @@ -352,6 +466,9 @@ "test": "gpu_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "installer_util_unittests" }, { @@ -362,9 +479,15 @@ "test": "interactive_ui_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ipc_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "jingle_unittests" }, { @@ -377,6 +500,9 @@ "test": "media_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "message_center_unittests" }, { @@ -386,9 +512,15 @@ "test": "midi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "mojo_common_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "mojo_public_bindings_unittests" }, { @@ -404,6 +536,9 @@ "test": "mojo_system_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "nacl_loader_unittests" }, { @@ -416,24 +551,45 @@ "test": "ppapi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "printing_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "remoting_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sbox_integration_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sbox_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sbox_validation_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "skia_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sql_unittests" }, { @@ -443,12 +599,21 @@ "test": "sync_integration_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sync_unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ui_base_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ui_touch_selection_unittests" }, { @@ -458,12 +623,18 @@ "test": "unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "url_unittests" }, { "test": "views_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "wm_unittests" } ], @@ -472,6 +643,10 @@ "name": "telemetry_unittests", "script": "telemetry_unittests.py" }, + { + "name": "telemetry_gpu_unittests", + "script": "telemetry_gpu_unittests.py" + }, { "name": "telemetry_perf_unittests", "script": "telemetry_perf_unittests.py" @@ -603,6 +778,9 @@ "test": "app_list_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "app_shell_unittests" }, { @@ -612,6 +790,9 @@ "test": "ash_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "aura_unittests" }, { @@ -628,6 +809,9 @@ "test": "browser_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "cacheinvalidation_unittests" }, { @@ -646,9 +830,15 @@ "test": "chrome_elf_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "chromedriver_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "components_browsertests" }, { @@ -658,6 +848,9 @@ "test": "components_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "compositor_unittests" }, { @@ -685,9 +878,15 @@ "test": "crypto_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "device_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "events_unittests" }, { @@ -697,12 +896,21 @@ "test": "extensions_browsertests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "extensions_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gcm_unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gfx_unittests" }, { @@ -718,6 +926,9 @@ "test": "gpu_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "installer_util_unittests" }, { @@ -728,9 +939,15 @@ "test": "interactive_ui_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ipc_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "jingle_unittests" }, { @@ -743,6 +960,9 @@ "test": "media_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "message_center_unittests" }, { @@ -752,9 +972,15 @@ "test": "midi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "mojo_common_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "mojo_public_bindings_unittests" }, { @@ -770,6 +996,9 @@ "test": "mojo_system_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "nacl_loader_unittests" }, { @@ -782,24 +1011,45 @@ "test": "ppapi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "printing_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "remoting_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sbox_integration_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sbox_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sbox_validation_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "skia_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sql_unittests" }, { @@ -809,12 +1059,21 @@ "test": "sync_integration_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sync_unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ui_base_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ui_touch_selection_unittests" }, { @@ -824,12 +1083,18 @@ "test": "unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "url_unittests" }, { "test": "views_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "wm_unittests" } ], @@ -838,6 +1103,10 @@ "name": "telemetry_unittests", "script": "telemetry_unittests.py" }, + { + "name": "telemetry_gpu_unittests", + "script": "telemetry_gpu_unittests.py" + }, { "name": "telemetry_perf_unittests", "script": "telemetry_perf_unittests.py" @@ -848,6 +1117,7 @@ } ] }, + "Win7 Tests (ANGLE)": {}, "Win7 Tests (dbg)(1)": { "gtest_tests": [ { @@ -857,6 +1127,9 @@ "test": "accessibility_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "app_shell_unittests" }, { @@ -866,6 +1139,9 @@ "test": "ash_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "aura_unittests" }, { @@ -882,6 +1158,9 @@ "test": "browser_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "cacheinvalidation_unittests" }, { @@ -900,6 +1179,9 @@ "test": "chrome_elf_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "chromedriver_unittests" }, { @@ -909,6 +1191,9 @@ "test": "components_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "compositor_unittests" }, { @@ -937,6 +1222,9 @@ "test": "crypto_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "events_unittests" }, { @@ -946,9 +1234,15 @@ "test": "extensions_browsertests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "extensions_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gcm_unit_tests" }, { @@ -958,6 +1252,9 @@ "test": "gpu_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "installer_util_unittests" }, { @@ -968,9 +1265,15 @@ "test": "interactive_ui_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ipc_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "jingle_unittests" }, { @@ -986,9 +1289,15 @@ "test": "midi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "mojo_common_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "mojo_public_bindings_unittests" }, { @@ -1004,6 +1313,9 @@ "test": "mojo_system_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "nacl_loader_unittests" }, { @@ -1016,24 +1328,45 @@ "test": "ppapi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "printing_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "remoting_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sbox_integration_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sbox_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sbox_validation_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "skia_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sql_unittests" }, { @@ -1044,12 +1377,21 @@ "test": "sync_integration_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sync_unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ui_base_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ui_touch_selection_unittests" }, { @@ -1059,12 +1401,18 @@ "test": "unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "url_unittests" }, { "test": "views_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "wm_unittests" } ], @@ -1073,6 +1421,10 @@ "name": "telemetry_unittests", "script": "telemetry_unittests.py" }, + { + "name": "telemetry_gpu_unittests", + "script": "telemetry_gpu_unittests.py" + }, { "name": "telemetry_perf_unittests", "script": "telemetry_perf_unittests.py" @@ -1255,9 +1607,15 @@ "test": "accessibility_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "app_shell_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "aura_unittests" }, { @@ -1274,6 +1632,9 @@ "test": "browser_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "cacheinvalidation_unittests" }, { @@ -1292,6 +1653,9 @@ "test": "chrome_elf_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "chromedriver_unittests" }, { @@ -1307,6 +1671,9 @@ "test": "components_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "compositor_unittests" }, { @@ -1334,6 +1701,9 @@ "test": "crypto_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "events_unittests" }, { @@ -1343,12 +1713,21 @@ "test": "extensions_browsertests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "extensions_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gcm_unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "gfx_unittests" }, { @@ -1364,6 +1743,9 @@ "test": "gpu_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "installer_util_unittests" }, { @@ -1377,9 +1759,15 @@ "test": "ipc_mojo_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ipc_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "jingle_unittests" }, { @@ -1395,6 +1783,9 @@ "test": "midi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "nacl_loader_unittests" }, { @@ -1407,24 +1798,45 @@ "test": "ppapi_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "printing_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "remoting_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sbox_integration_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sbox_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sbox_validation_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "skia_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sql_unittests" }, { @@ -1434,12 +1846,21 @@ "test": "sync_integration_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sync_unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ui_base_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ui_touch_selection_unittests" }, { @@ -1449,12 +1870,18 @@ "test": "unit_tests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "url_unittests" }, { "test": "views_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "wm_unittests" } ], @@ -1463,6 +1890,10 @@ "name": "telemetry_unittests", "script": "telemetry_unittests.py" }, + { + "name": "telemetry_gpu_unittests", + "script": "telemetry_gpu_unittests.py" + }, { "name": "telemetry_perf_unittests", "script": "telemetry_perf_unittests.py" diff --git a/testing/buildbot/client.v8.fyi.json b/testing/buildbot/client.v8.fyi.json index 2f43da0412d89..d214267dfcf7c 100644 --- a/testing/buildbot/client.v8.fyi.json +++ b/testing/buildbot/client.v8.fyi.json @@ -59,6 +59,12 @@ "views_unittests", "wm_unittests" ], - "gtest_tests": [] + "gtest_tests": [], + "scripts": [ + { + "name": "gn_check", + "script": "gn_check.py" + } + ] } } diff --git a/testing/buildbot/manage.py b/testing/buildbot/manage.py index 98de7ef4b0435..7a39176649a0c 100755 --- a/testing/buildbot/manage.py +++ b/testing/buildbot/manage.py @@ -10,6 +10,7 @@ """ import argparse +import ast import collections import glob import json @@ -38,12 +39,17 @@ # http://crbug.com/480053 'Linux GN', + 'Linux GN (dbg)', 'linux_chromium_gn_rel', # Unmaintained builders on chromium.fyi 'ClangToTMac', 'ClangToTMacASan', + # This builder is fine, but win8_chromium_ng uses GN and this configuration, + # which breaks everything. + 'Win8 Aura', + # One off builders. Note that Swarming does support ARM. 'Linux ARM Cross-Compile', 'Site Isolation Linux', @@ -51,6 +57,15 @@ } +# TODO(GYP): These targets have not been ported to GN yet. +SKIP_NINJA_TO_GN_TARGETS = { + 'cast_media_unittests', + 'cast_shell_browser_test', + 'chromevox_tests', + 'nacl_helper_nonsfi_unittests', +} + + class Error(Exception): """Processing error.""" @@ -61,7 +76,7 @@ def get_isolates(): return [os.path.basename(f) for f in files if f.endswith('.isolate')] -def process_builder_convert(data, filename, builder, test_name): +def process_builder_convert(data, test_name): """Converts 'test_name' to run on Swarming in 'data'. Returns True if 'test_name' was found. @@ -72,7 +87,6 @@ def process_builder_convert(data, filename, builder, test_name): continue test.setdefault('swarming', {}) if not test['swarming'].get('can_use_on_swarming_builders'): - print('- %s: %s' % (filename, builder)) test['swarming']['can_use_on_swarming_builders'] = True result = True return result @@ -90,8 +104,9 @@ def process_builder_remaining(data, filename, builder, tests_location): filename, []).append(builder) -def process_file(mode, test_name, tests_location, filepath): - """Processes a file. +def process_file(mode, test_name, tests_location, filepath, ninja_targets, + ninja_targets_seen): + """Processes a json file describing what tests should be run for each recipe. The action depends on mode. Updates tests_location. @@ -120,12 +135,24 @@ def process_file(mode, test_name, tests_location, filepath): raise Error( '%s: %s is broken: %s' % (filename, builder, data['gtest_tests'])) + for d in data['gtest_tests']: + if (d['test'] not in ninja_targets and + d['test'] not in SKIP_NINJA_TO_GN_TARGETS): + raise Error('%s: %s / %s is not listed in ninja_to_gn.pyl.' % + (filename, builder, d['test'])) + elif d['test'] in ninja_targets: + ninja_targets_seen.add(d['test']) + config[builder]['gtest_tests'] = sorted( data['gtest_tests'], key=lambda x: x['test']) - if mode == 'remaining': + + # The trick here is that process_builder_remaining() is called before + # process_builder_convert() so tests_location can be used to know how many + # tests were converted. + if mode in ('convert', 'remaining'): process_builder_remaining(data, filename, builder, tests_location) - elif mode == 'convert': - process_builder_convert(data, filename, builder, test_name) + if mode == 'convert': + process_builder_convert(data, test_name) expected = json.dumps( config, sort_keys=True, indent=2, separators=(',', ': ')) + '\n' @@ -142,7 +169,26 @@ def process_file(mode, test_name, tests_location, filepath): return True -def print_remaining(test_name,tests_location): +def print_convert(test_name, tests_location): + """Prints statistics for a test being converted for use in a CL description. + """ + data = tests_location[test_name] + print('Convert %s to run exclusively on Swarming' % test_name) + print('') + print('%d configs already ran on Swarming' % data['count_run_on_swarming']) + print('%d used to run locally and were converted:' % data['count_run_local']) + for master, builders in sorted(data['local_configs'].iteritems()): + for builder in builders: + print('- %s: %s' % (master, builder)) + print('') + print('Ran:') + print(' ./manage.py --convert %s' % test_name) + print('') + print('R=') + print('BUG=98637') + + +def print_remaining(test_name, tests_location): """Prints a visual summary of what tests are yet to be converted to run on Swarming. """ @@ -222,13 +268,29 @@ def main(): 'count_run_local': 0, 'count_run_on_swarming': 0, 'local_configs': {} }) + with open(os.path.join(THIS_DIR, "ninja_to_gn.pyl")) as fp: + ninja_targets = ast.literal_eval(fp.read()) + try: result = 0 + ninja_targets_seen = set() for filepath in glob.glob(os.path.join(THIS_DIR, '*.json')): - if not process_file(args.mode, args.test_name, tests_location, filepath): + if not process_file(args.mode, args.test_name, tests_location, filepath, + ninja_targets, ninja_targets_seen): result = 1 - if args.mode == 'remaining': + extra_targets = set(ninja_targets) - ninja_targets_seen + if extra_targets: + if len(extra_targets) > 1: + extra_targets_str = ', '.join(extra_targets) + ' are' + else: + extra_targets_str = list(extra_targets)[0] + ' is' + raise Error('%s listed in ninja_to_gn.pyl but not in any .json files' % + extra_targets_str) + + if args.mode == 'convert': + print_convert(args.test_name, tests_location) + elif args.mode == 'remaining': print_remaining(args.test_name, tests_location) return result except Error as e: diff --git a/testing/buildbot/ninja_to_gn.pyl b/testing/buildbot/ninja_to_gn.pyl new file mode 100644 index 0000000000000..5e26949eb42c3 --- /dev/null +++ b/testing/buildbot/ninja_to_gn.pyl @@ -0,0 +1,102 @@ +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# ninja_to_gn - A mapping of Ninja build target names to GN labels for +# the tests run on the bots. +# +# This mapping is used by MB so that we can uniformly refer to test binaries +# by their Ninja target names in the recipes and not need to worry about how +# they are referred to in GN or GYP specifically (the GYP target name is pretty +# much always the same as the Ninja target name, since GYP target names are not +# hierarchical). + +{ + "base_unittests": "//base:base_unittests", + "accessibility_unittests": "//ui/accessibility:accessibility_unittests", + "angle_unittests": "//gpu:angle_unittests", + "app_list_unittests": "//ui/app_list:app_list_unittests", + "app_shell_unittests": "//extensions/shell:app_shell_unittests", + "ash_unittests": "//ash:ash_unittests", + "aura_unittests": "//ui/aura:aura_unittests", + "blink_heap_unittests": "//third_party/WebKit/public:blink_heap_unittests", + "blink_platform_unittests": "//third_party/WebKit/public:blink_platform_unittests", + "browser_tests": "//chrome/test:browser_tests", + "cacheinvalidation_unittests": "//third_party/cacheinvalidation:cacheinvalidation_unittests", + "cast_base_unittests": "//chromecast/base:cast_base_unittests", + "cast_crash_unittests": "//chromecast/crash:cast_crash_unittests", + "cast_media_unittests": "//chromecast/media:cast_media_unittests", + "cast_shell_unittests": "//chromecast/app:cast_shell_unittests", + "cast_unittests": "//media/cast:cast_unittests", + "cc_unittests": "//cc:cc_unittests", + "chromedriver_unittests": "//chrome/test/chromedriver:chromedriver_unittests", + "chrome_elf_unittests": "//chrome_elf:chrome_elf_unittests", + "chromeos_unittests": "//chromeos:chromeos_unittests", + "components_browsertests": "//components:components_browsertests", + "components_unittests": "//components:components_unittests", + "compositor_unittests": "//ui/compositor:compositor_unittests", + "content_browsertests": "//content/test:content_browsertests", + "content_unittests": "//content/test:content_unittests", + "courgette_unittests": "//courgette:courgette_unittests", + "crypto_unittests": "//crypto:crypto_unittests", + "dbus_unittests": "//dbus:dbus_unittests", + "device_unittests": "//device:device_unittests", + "display_unittests": "//ui/display:display_unittests", + "events_unittests": "//ui/events:events_unittests", + "extensions_browsertests": "//extensions:extensions_browsertests", + "extensions_unittests": "//extensions:extensions_unittests", + "gcm_unit_tests": "//google_apis/gcm:gcm_unit_tests", + "gfx_unittests": "//ui/gfx:gfx_unittests", + "gl_unittests": "//ui/gl:gl_unittests", + "gn_unittests": "//tools/gn:gn_unittests", + "google_apis_unittests": "//google_apis:google_apis_unittests", + "gpu_unittests": "//gpu:gpu_unittests", + "html_viewer_unittests": "//components/html_viewer:html_viewer_unittests", + "installer_util_unittests": "//chrome/installer/util:installer_util_unittests", + "interactive_ui_tests": "//chrome/test:interactive_ui_tests", + "ipc_mojo_unittests": "//ipc/mojo:ipc_mojo_unittests", + "ipc_tests": "//ipc:ipc_tests", + "jingle_unittests": "//jingle:jingle_unittests", + "keyboard_unittests": "//ui/keyboard:keyboard_unittests", + "media_unittests": "//media:media_unittests", + "midi_unittests": "//media:midi_unittests", + "mojo_common_unittests": "//mojo/common:mojo_common_unittests", + "mojo_public_application_unittests": "//third_party/mojo/src/mojo/edk/test:mojo_public_applicaiton_unittests", + "mojo_public_bindings_unittests": "//third_party/mojo/src/mojo/edk/test:mojo_public_bindings_unittests", + "mojo_public_environment_unittests": "//third_party/mojo/src/mojo/edk/test:mojo_public_environment_unittests", + "mojo_public_system_unittests": "//third_party/mojo/src/mojo/edk/test:mojo_public_system_unittests", + "mojo_public_utility_unittests": "//third_party/mojo/src/mojo/edk/test:mojo_public_utility_unittests", + "mojo_runner_unittests": "//mojo/runner:mojo_runner_unittests", + "mojo_shell_unittests": "//mojo/shell:mojo_shell_unittests", + "mojo_surfaces_lib_unittests": "//mojo/converters/surfaces/tests:mojo_surfaces_lib_unittests", + "mojo_system_unittests": "//third_party/mojo/src/mojo/edk/system:mojo_system_unittests", + "mojo_view_manager_lib_unittests": "//components/view_manager/public/cpp/tests:mojo_view_manager_lib_unittests", + "message_center_unittests": "//ui/message_center:message_center_unittests", + "nacl_loader_unittests": "//components/nacl:nacl_loader_unittests", + "net_unittests": "//net:net_unittests", + "ozone_unittests": "//ui/ozone:ozone_unittests", + "ppapi_unittests": "//ppapi:ppapi_unittests", + "printing_unittests": "//printing:printing_unittests", + "remoting_unittests": "//remoting:remoting_unittests", + "resource_provider_unittests": "//components/resource_provider:resource_provider_unittests", + "sandbox_linux_unittests": "//sandbox/linux:sandbox_linux_unittests", + "sandbox_mac_unittests": "//sandbox/mac:sandbox_mac_unittests", + "sbox_integration_tests": "//sandbox/win:sbox_integration_tests", + "sbox_unittests": "//sandbox/win:sbox_unittests", + "sbox_validation_tests": "//sandbox/win:sbox_validation_tests", + "setup_unittests": "//chrome/installer/setup:setup_unittests", + "skia_unittests": "//skia:skia_unittests", + "sql_unittests": "//sql:sql_unittests", + "sync_integration_tests": "//sync:sync_integration_tests", + "sync_unit_tests": "//sync:sync_unit_tests", + "ui_base_unittests": "//ui/base:ui_base_unittests", + "ui_chromeos_unittests": "//ui/chromeos:ui_chromeos_unittests", + "ui_touch_selection_unittests": "//ui/touch_selection:ui_touch_selection_unittests", + "unit_tests": "//chrome/test:unit_tests", + "url_unittests": "//url:url_unittests", + "view_manager_unittests": "//components/view_manager:view_manager_unittests", + "views_unittests": "//ui/views:views_unittests", + "webkit_unit_tests": "//third_party/WebKit/public:webkit_unit_tests", + "wm_unittests": "//ui/wm:wm_unittests", + "wtf_unittests": "//third_party/WebKit/public:wtf_unittests", +} diff --git a/testing/buildbot/trybot_analyze_config.json b/testing/buildbot/trybot_analyze_config.json index 5608ae4b43b70..da3533ee79bde 100644 --- a/testing/buildbot/trybot_analyze_config.json +++ b/testing/buildbot/trybot_analyze_config.json @@ -14,8 +14,10 @@ "build/get_landmines.py", "build/gyp_chromium", "build/linux/sysroot_ld_path.sh", + "infra/.*", "DEPS", "testing/buildbot/.*", + "testing/scripts/.*", "testing/test_env.py", "tools/clang/blink_gc_plugin/CMakeLists.txt", "tools/luci-go/.*", diff --git a/testing/buildbot/tryserver.chromium.linux.json b/testing/buildbot/tryserver.chromium.linux.json index 876d8a50f4226..36fa0c3e477ba 100644 --- a/testing/buildbot/tryserver.chromium.linux.json +++ b/testing/buildbot/tryserver.chromium.linux.json @@ -1,13 +1,22 @@ { "android_chromium_gn_compile_dbg": { "additional_compile_targets": [ + "chrome_public_apk", + "chrome_public_test_apk", "chrome_shell_apk", + "chrome_shell_test_apk", + "content_shell_apk", "mandoline:all" ] }, "android_chromium_gn_compile_rel": { "additional_compile_targets": [ + "chrome_public_apk", + "chrome_public_test_apk", "chrome_shell_apk", + "chrome_shell_test_apk", + "content_shell_apk", + "content_shell_test_apk", "mandoline:all" ] }, @@ -347,10 +356,6 @@ ], "name": "gyp_flag_compare", "script": "gyp_flag_compare.py" - }, - { - "name": "mojo_apptest", - "script": "mojo_apptest.py" } ] } diff --git a/testing/buildbot/tryserver.v8.json b/testing/buildbot/tryserver.v8.json index a0f9adf9fa51f..548606135bf2d 100644 --- a/testing/buildbot/tryserver.v8.json +++ b/testing/buildbot/tryserver.v8.json @@ -60,6 +60,12 @@ "views_unittests", "wm_unittests" ], - "gtest_tests": [] + "gtest_tests": [], + "scripts": [ + { + "name": "gn_check", + "script": "gn_check.py" + } + ] } } diff --git a/testing/chromoting/app_remoting_integration_tests.isolate b/testing/chromoting/app_remoting_integration_tests.isolate new file mode 100644 index 0000000000000..bc0d8241f9b6c --- /dev/null +++ b/testing/chromoting/app_remoting_integration_tests.isolate @@ -0,0 +1,38 @@ +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +{ + 'conditions': [ + ['OS=="linux"', { + 'variables': { + 'command': [ + '../xvfb.py', + '<(PRODUCT_DIR)', + '<(PRODUCT_DIR)/ar_test_driver', + '--username=appremotingtestdriver_chromium_01@lgtestuser.com', + '--environment=staging', + '--refresh-token-file=../../remoting/tools/internal/refresh_tokens.json', + '--show-host-availability', + '--release-hosts-after-tests', + '--verbosity=1', + ], + 'files': [ + '../xvfb.py', + '../test_env.py', + '<(PRODUCT_DIR)/ar_test_driver', + '../../remoting/tools/internal/refresh_tokens.json', + ], + }, + }], + ['OS=="linux" and use_ozone==0', { + 'variables': { + 'files': [ + '<(PRODUCT_DIR)/xdisplaycheck<(EXECUTABLE_SUFFIX)', + ], + }, + }], + ], + 'includes': [ + '../../base/base.isolate', + ], +} diff --git a/testing/chromoting/browser_test_commands_linux.txt b/testing/chromoting/browser_test_commands_linux.txt index dbc386c18b836..4143ad4a14d87 100644 --- a/testing/chromoting/browser_test_commands_linux.txt +++ b/testing/chromoting/browser_test_commands_linux.txt @@ -1,15 +1,11 @@ -/usr/bin/python ../xvfb.py #PROD_DIR# #PROD_DIR#/browser_tests --gtest_filter=RemoteDesktopBrowserTest.MANUAL_Launch:RemoteDesktopBrowserTest.MANUAL_Auth --run-manual --ui-test-action-timeout=100000 --webapp-unpacked=#PROD_DIR#/remoting/remoting.webapp --extension-name=Chromoting --accounts-file=../../remoting/tools/internal/test_accounts.json --account-type=gmail -/usr/bin/python ../xvfb.py #PROD_DIR# #PROD_DIR#/browser_tests --gtest_filter=RemoteDesktopBrowserTest.MANUAL_Auth --run-manual --ui-test-action-timeout=100000 --webapp-unpacked=#PROD_DIR#/remoting/remoting.webapp --extension-name=Chromoting --accounts-file=../../remoting/tools/internal/test_accounts.json --account-type=gafyd -/usr/bin/python ../xvfb.py #PROD_DIR# #PROD_DIR#/browser_tests --gtest_filter=RemoteDesktopBrowserTest.MANUAL_Auth --run-manual --ui-test-action-timeout=100000 --webapp-unpacked=#PROD_DIR#/remoting/remoting.webapp --extension-name=Chromoting --accounts-file=../../remoting/tools/internal/test_accounts.json --account-type=non-gmail /usr/bin/python ../xvfb.py #PROD_DIR# #PROD_DIR#/browser_tests --gtest_filter=RemoteDesktopBrowserTest.MANUAL_Launch:RemoteDesktopBrowserTest.MANUAL_Auth --run-manual --ui-test-action-timeout=100000 --webapp-unpacked=#PROD_DIR#/remoting/remoting.webapp.v2 --extension-name=Chromoting --accounts-file=../../remoting/tools/internal/test_accounts.json --account-type=gmail -/usr/bin/python ../xvfb.py #PROD_DIR# #PROD_DIR#/browser_tests --gtest_filter=Me2MeBrowserTest.MANUAL_Me2Me_Connect_Local_Host --run-manual --ui-test-action-timeout=100000 --webapp-unpacked=#PROD_DIR#/remoting/remoting.webapp --extension-name=Chromoting --accounts-file=../../remoting/tools/internal/test_accounts.json --account-type=gmail --me2me-pin=123456 --override-user-data-dir=/tmp/chromoting_test_profile /usr/bin/python ../xvfb.py #PROD_DIR# #PROD_DIR#/browser_tests --gtest_filter=Me2MeBrowserTest.MANUAL_Me2Me_Connect_Local_Host --run-manual --ui-test-action-timeout=100000 --webapp-unpacked=#PROD_DIR#/remoting/remoting.webapp.v2 --extension-name=Chromoting --accounts-file=../../remoting/tools/internal/test_accounts.json --account-type=gmail --me2me-pin=123456 --override-user-data-dir=/tmp/chromoting_test_profile /usr/bin/python ../xvfb.py #PROD_DIR# #PROD_DIR#/browser_tests --gtest_filter=Me2MeBrowserTest.MANUAL_Me2Me_RetryOnHostOffline --run-manual --ui-test-action-timeout=100000 --webapp-unpacked=#PROD_DIR#/remoting/remoting.webapp.v2 --extension-name=Chromoting --accounts-file=../../remoting/tools/internal/test_accounts.json --account-type=gmail --me2me-pin=123456 --override-user-data-dir=/tmp/chromoting_test_profile /usr/bin/python ../xvfb.py #PROD_DIR# #PROD_DIR#/browser_tests --gtest_filter=Me2MeBrowserTest.MANUAL_Me2Me_v2_Alive_OnLostFocus --run-manual --ui-test-action-timeout=100000 --webapp-unpacked=#PROD_DIR#/remoting/remoting.webapp.v2 --extension-name=Chromoting --accounts-file=../../remoting/tools/internal/test_accounts.json --account-type=gmail --me2me-pin=123456 --override-user-data-dir=/tmp/chromoting_test_profile -/usr/bin/python ../xvfb.py #PROD_DIR# #PROD_DIR#/browser_tests --gtest_filter=It2MeBrowserTest.MANUAL_Connect --run-manual --ui-test-action-timeout=100000 --webapp-unpacked=#PROD_DIR#/remoting/remoting.webapp --extension-name=Chromoting --accounts-file=../../remoting/tools/internal/test_accounts.json --account-type=gmail --override-user-data-dir=/tmp/chromoting_test_profile -/usr/bin/python ../xvfb.py #PROD_DIR# #PROD_DIR#/browser_tests --gtest_filter=It2MeBrowserTest.MANUAL_InvalidAccessCode --run-manual --ui-test-action-timeout=100000 --webapp-unpacked=#PROD_DIR#/remoting/remoting.webapp --extension-name=Chromoting --accounts-file=../../remoting/tools/internal/test_accounts.json --account-type=gmail --override-user-data-dir=/tmp/chromoting_test_profile -/usr/bin/python ../xvfb.py #PROD_DIR# #PROD_DIR#/browser_tests --gtest_filter=It2MeBrowserTest.MANUAL_CancelShare --run-manual --ui-test-action-timeout=100000 --webapp-unpacked=#PROD_DIR#/remoting/remoting.webapp --extension-name=Chromoting --accounts-file=../../remoting/tools/internal/test_accounts.json --account-type=gmail --override-user-data-dir=/tmp/chromoting_test_profile -/usr/bin/python ../xvfb.py #PROD_DIR# #PROD_DIR#/browser_tests --gtest_filter=It2MeBrowserTest.MANUAL_VerifyAccessCodeNonReusable --run-manual --ui-test-action-timeout=100000 --webapp-unpacked=#PROD_DIR#/remoting/remoting.webapp --extension-name=Chromoting --accounts-file=../../remoting/tools/internal/test_accounts.json --account-type=gmail --override-user-data-dir=/tmp/chromoting_test_profile +/usr/bin/python ../xvfb.py #PROD_DIR# #PROD_DIR#/browser_tests --gtest_filter=It2MeBrowserTest.MANUAL_Connect --run-manual --ui-test-action-timeout=100000 --webapp-unpacked=#PROD_DIR#/remoting/remoting.webapp.v2 --extension-name=Chromoting --accounts-file=../../remoting/tools/internal/test_accounts.json --account-type=gmail --override-user-data-dir=/tmp/chromoting_test_profile +/usr/bin/python ../xvfb.py #PROD_DIR# #PROD_DIR#/browser_tests --gtest_filter=It2MeBrowserTest.MANUAL_InvalidAccessCode --run-manual --ui-test-action-timeout=100000 --webapp-unpacked=#PROD_DIR#/remoting/remoting.webapp.v2 --extension-name=Chromoting --accounts-file=../../remoting/tools/internal/test_accounts.json --account-type=gmail --override-user-data-dir=/tmp/chromoting_test_profile +/usr/bin/python ../xvfb.py #PROD_DIR# #PROD_DIR#/browser_tests --gtest_filter=It2MeBrowserTest.MANUAL_CancelShare --run-manual --ui-test-action-timeout=100000 --webapp-unpacked=#PROD_DIR#/remoting/remoting.webapp.v2 --extension-name=Chromoting --accounts-file=../../remoting/tools/internal/test_accounts.json --account-type=gmail --override-user-data-dir=/tmp/chromoting_test_profile +/usr/bin/python ../xvfb.py #PROD_DIR# #PROD_DIR#/browser_tests --gtest_filter=It2MeBrowserTest.MANUAL_VerifyAccessCodeNonReusable --run-manual --ui-test-action-timeout=100000 --webapp-unpacked=#PROD_DIR#/remoting/remoting.webapp.v2 --extension-name=Chromoting --accounts-file=../../remoting/tools/internal/test_accounts.json --account-type=gmail --override-user-data-dir=/tmp/chromoting_test_profile /usr/bin/python ../xvfb.py #PROD_DIR# #PROD_DIR#/browser_tests --gtest_filter=RemoteDesktopBrowserTest.MANUAL_Cancel_PIN --run-manual --ui-test-action-timeout=100000 --webapp-unpacked=#PROD_DIR#/remoting/remoting.webapp.v2 --extension-name=Chromoting --accounts-file=../../remoting/tools/internal/test_accounts.json --account-type=gmail --me2me-pin=123456 --override-user-data-dir=/tmp/chromoting_test_profile /usr/bin/python ../xvfb.py #PROD_DIR# #PROD_DIR#/browser_tests --gtest_filter=RemoteDesktopBrowserTest.MANUAL_Update_PIN --run-manual --ui-test-action-timeout=100000 --webapp-unpacked=#PROD_DIR#/remoting/remoting.webapp.v2 --extension-name=Chromoting --accounts-file=../../remoting/tools/internal/test_accounts.json --account-type=gmail --me2me-pin=123456 --override-user-data-dir=/tmp/chromoting_test_profile /usr/bin/python ../xvfb.py #PROD_DIR# #PROD_DIR#/browser_tests --gtest_filter=RemoteDesktopBrowserTest.MANUAL_Invalid_PIN --run-manual --ui-test-action-timeout=100000 --webapp-unpacked=#PROD_DIR#/remoting/remoting.webapp.v2 --extension-name=Chromoting --accounts-file=../../remoting/tools/internal/test_accounts.json --account-type=gmail --me2me-pin=123457 --override-user-data-dir=/tmp/chromoting_test_profile diff --git a/testing/chromoting/chromoting_test_files.txt b/testing/chromoting/chromoting_test_files.txt new file mode 100644 index 0000000000000..d68d381106e26 --- /dev/null +++ b/testing/chromoting/chromoting_test_files.txt @@ -0,0 +1 @@ +gs://chrome-chromoting-test-data/integration_tests/input/test_accounts.json \ No newline at end of file diff --git a/testing/chromoting/dependencies.gypi b/testing/chromoting/dependencies.gypi index 10013d31f8ced..b2bec1e18be2e 100644 --- a/testing/chromoting/dependencies.gypi +++ b/testing/chromoting/dependencies.gypi @@ -19,6 +19,7 @@ 'dependencies': [ '../../remoting/remoting.gyp:remoting_me2me_host_archive', '../../remoting/internal/app_remoting_all.gyp:app_remoting_all_apps', + '../../remoting/internal/app_remoting_all.gyp:ar_test_driver', ], }], # OS=="linux" ], diff --git a/testing/chromoting/download_test_files.py b/testing/chromoting/download_test_files.py new file mode 100644 index 0000000000000..57fb9a19ed7eb --- /dev/null +++ b/testing/chromoting/download_test_files.py @@ -0,0 +1,57 @@ +# Copyright (c) 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""A script to download files required for Remoting integration tests from GCS. + + The script expects 2 parameters: + + input_files: a file containing the full path in GCS to each file that is to + be downloaded. + output_folder: the folder to which the specified files should be downloaded. + + This scripts expects that its execution is done on a machine where the + credentials are correctly setup to obtain the required permissions for + downloading files from the specified GCS buckets. +""" + +import argparse +import ntpath +import os +import subprocess +import sys + + +def main(): + + parser = argparse.ArgumentParser() + parser.add_argument('-f', '--files', + help='File specifying files to be downloaded .') + parser.add_argument( + '-o', '--output_folder', + help='Folder where specified files should be downloaded .') + + if len(sys.argv) < 3: + parser.print_help() + sys.exit(1) + + args = parser.parse_args() + if not args.files or not args.output_folder: + parser.print_help() + sys.exit(1) + + # Loop through lines in input file specifying source file locations. + with open(args.files) as f: + for line in f: + # Copy the file to the output folder, with same name as source file. + output_file = os.path.join(args.output_folder, ntpath.basename(line)) + # Download specified file from GCS. + cp_cmd = ['gsutil.py', 'cp', line, output_file] + try: + subprocess.check_call(cp_cmd) + except subprocess.CalledProcessError, e: + print e.output + sys.exit(1) + +if __name__ == '__main__': + main() diff --git a/testing/chromoting/integration_tests.gyp b/testing/chromoting/integration_tests.gyp index c3f7912b48eec..23a18ea0fd23f 100644 --- a/testing/chromoting/integration_tests.gyp +++ b/testing/chromoting/integration_tests.gyp @@ -3,8 +3,41 @@ # found in the LICENSE file. { + 'variables': { + 'run_multi_machine_tests%': '0', + }, + 'conditions': [ ['archive_chromoting_tests==1', { + 'conditions': [ + ['OS=="linux"', { + 'targets': [ + { + 'target_name': 'app_remoting_integration_tests_run', + 'includes': [ + './dependencies.gypi', + ], + 'sources': [ + 'app_remoting_integration_tests.isolate', + ], + }, # target_name: 'app_remoting_integration_tests_run' + ], + }], + ['run_multi_machine_tests==1', { + 'targets': [ + { + 'target_name': 'chromoting_multi_machine_example_test', + 'includes': [ + './dependencies.gypi', + ], + 'sources': [ + 'multi_machine_example/example_test_controller.isolate', + 'multi_machine_example/example_task.isolate', + ], + }, # target_name: 'chromoting_multi_machine_example_test' + ], + }], + ], 'targets': [ { 'target_name': 'chromoting_integration_tests_run', @@ -14,17 +47,32 @@ 'sources': [ 'chromoting_integration_tests.isolate', ], - }, # target_name: 'chromoting_integration_tests_run' - { - 'target_name': 'chromoting_multi_machine_example_test', - 'includes': [ - './dependencies.gypi', + 'actions': [ + { + 'action_name': 'download_test_files', + 'variables': { + 'dl_files_script': './download_test_files.py', + 'files_list': './chromoting_test_files.txt', + 'output_folder': './', + }, + 'inputs': [ + '<(files_list)', + ], + 'outputs': [ + '<(output_folder)', + ], + 'action': [ + 'python', + '<(dl_files_script)', + '--files', + '<(files_list)', + '--output_folder', + '<(output_folder)', + ], + 'message': 'Downloading required Remoting test files.', + }, ], - 'sources': [ - 'multi_machine_example/example_test_controller.isolate', - 'multi_machine_example/example_task.isolate', - ], - }, # target_name: 'chromoting_multi_machine_example_test' + }, # target_name: 'chromoting_integration_tests_run' ], }], ], diff --git a/testing/generate_gmock_mutant.py b/testing/generate_gmock_mutant.py index 9c5678c2f296d..45ac4edbbc043 100755 --- a/testing/generate_gmock_mutant.py +++ b/testing/generate_gmock_mutant.py @@ -66,7 +66,7 @@ // // Will invoke mock.HandleFlowers("orchids", n, request) // // "orchids" is a pre-bound argument, and and are call-time // // arguments - they are not known until the OnRequest mock is invoked. -// EXPECT_CALL(mock, OnRequest(Ge(5), StartsWith("flower")) +// EXPECT_CALL(mock, OnRequest(Ge(5), base::StartsWith("flower")) // .Times(1) // .WillOnce(Invoke(CreateFunctor(&mock, &Mock::HandleFlowers, // string("orchids")))); diff --git a/testing/gmock_mutant.h b/testing/gmock_mutant.h index acc1ae9249629..6049d1d2927a5 100644 --- a/testing/gmock_mutant.h +++ b/testing/gmock_mutant.h @@ -57,7 +57,7 @@ // // Will invoke mock.HandleFlowers("orchids", n, request) // // "orchids" is a pre-bound argument, and and are call-time // // arguments - they are not known until the OnRequest mock is invoked. -// EXPECT_CALL(mock, OnRequest(Ge(5), StartsWith("flower")) +// EXPECT_CALL(mock, OnRequest(Ge(5), base::StartsWith("flower")) // .Times(1) // .WillOnce(Invoke(CreateFunctor(&mock, &Mock::HandleFlowers, // string("orchids")))); diff --git a/testing/gtest.gyp b/testing/gtest.gyp index d61772ecbe233..79d7e669800e3 100644 --- a/testing/gtest.gyp +++ b/testing/gtest.gyp @@ -191,6 +191,14 @@ ], 'msvs_disabled_warnings': [4800], }, + 'variables': { + 'clang_warning_flags': [ + # The Mutex constructor initializer list in gtest-port.cc is + # incorrectly ordered. See + # https://groups.google.com/d/msg/googletestframework/S5uSV8L2TX8/U1FaTDa6J6sJ. + '-Wno-reorder', + ] + }, }, { 'target_name': 'gtest_main', diff --git a/testing/gtest_mac.h b/testing/gtest_mac.h index aa48c945431c8..0a9af4323af5f 100644 --- a/testing/gtest_mac.h +++ b/testing/gtest_mac.h @@ -16,19 +16,51 @@ namespace testing { namespace internal { // This overloaded version allows comparison between ObjC objects that conform -// to the NSObject protocol. Used to implement {ASSERT|EXPECT}_EQ(). +// to the NSObject protocol. Used to implement {ASSERT|EXPECT}_NSEQ(). GTEST_API_ AssertionResult CmpHelperNSEQ(const char* expected_expression, const char* actual_expression, id expected, id actual); // This overloaded version allows comparison between ObjC objects that conform -// to the NSObject protocol. Used to implement {ASSERT|EXPECT}_NE(). +// to the NSObject protocol. Used to implement {ASSERT|EXPECT}_NSNE(). GTEST_API_ AssertionResult CmpHelperNSNE(const char* expected_expression, const char* actual_expression, id expected, id actual); +#if !defined(GTEST_OS_IOS) + +// This overloaded version allows comparison between NSRect objects using +// NSEqualRects. Used to implement {ASSERT|EXPECT}_NSEQ(). +GTEST_API_ AssertionResult CmpHelperNSEQ(const char* expected_expression, + const char* actual_expression, + const NSRect& expected, + const NSRect& actual); + +// This overloaded version allows comparison between NSRect objects using +// NSEqualRects. Used to implement {ASSERT|EXPECT}_NSNE(). +GTEST_API_ AssertionResult CmpHelperNSNE(const char* expected_expression, + const char* actual_expression, + const NSRect& expected, + const NSRect& actual); + +// This overloaded version allows comparison between NSPoint objects using +// NSEqualPoints. Used to implement {ASSERT|EXPECT}_NSEQ(). +GTEST_API_ AssertionResult CmpHelperNSEQ(const char* expected_expression, + const char* actual_expression, + const NSPoint& expected, + const NSPoint& actual); + +// This overloaded version allows comparison between NSPoint objects using +// NSEqualPoints. Used to implement {ASSERT|EXPECT}_NSNE(). +GTEST_API_ AssertionResult CmpHelperNSNE(const char* expected_expression, + const char* actual_expression, + const NSPoint& expected, + const NSPoint& actual); + +#endif // !GTEST_OS_IOS + } // namespace internal } // namespace testing diff --git a/testing/gtest_mac.mm b/testing/gtest_mac.mm index 6aee98901331a..62b51c5a5ad1d 100644 --- a/testing/gtest_mac.mm +++ b/testing/gtest_mac.mm @@ -55,6 +55,70 @@ GTEST_API_ AssertionResult CmpHelperNSNE(const char* expected_expression, return AssertionFailure(msg); } +#if !defined(GTEST_OS_IOS) + +GTEST_API_ AssertionResult CmpHelperNSEQ(const char* expected_expression, + const char* actual_expression, + const NSRect& expected, + const NSRect& actual) { + if (NSEqualRects(expected, actual)) { + return AssertionSuccess(); + } + return EqFailure(expected_expression, + actual_expression, + [NSStringFromRect(expected) UTF8String], + [NSStringFromRect(actual) UTF8String], + false); + +} + +GTEST_API_ AssertionResult CmpHelperNSNE(const char* expected_expression, + const char* actual_expression, + const NSRect& expected, + const NSRect& actual) { + if (!NSEqualRects(expected, actual)) { + return AssertionSuccess(); + } + Message msg; + msg << "Expected: (" << expected_expression << ") != (" << actual_expression + << "), actual: " << [NSStringFromRect(expected) UTF8String] + << " vs " << [NSStringFromRect(actual) UTF8String]; + return AssertionFailure(msg); + +} + +GTEST_API_ AssertionResult CmpHelperNSEQ(const char* expected_expression, + const char* actual_expression, + const NSPoint& expected, + const NSPoint& actual) { + if (NSEqualPoints(expected, actual)) { + return AssertionSuccess(); + } + return EqFailure(expected_expression, + actual_expression, + [NSStringFromPoint(expected) UTF8String], + [NSStringFromPoint(actual) UTF8String], + false); + +} + +GTEST_API_ AssertionResult CmpHelperNSNE(const char* expected_expression, + const char* actual_expression, + const NSPoint& expected, + const NSPoint& actual) { + if (!NSEqualPoints(expected, actual)) { + return AssertionSuccess(); + } + Message msg; + msg << "Expected: (" << expected_expression << ") != (" << actual_expression + << "), actual: " << [NSStringFromPoint(expected) UTF8String] + << " vs " << [NSStringFromPoint(actual) UTF8String]; + return AssertionFailure(msg); + +} + +#endif // !GTEST_OS_IOS + } // namespace internal } // namespace testing diff --git a/testing/gtest_mac_unittest.mm b/testing/gtest_mac_unittest.mm index 01f14979fefc3..2dfa24e8d8b22 100644 --- a/testing/gtest_mac_unittest.mm +++ b/testing/gtest_mac_unittest.mm @@ -55,3 +55,55 @@ // TODO(shess): Test that EXPECT_NSNE(nil, nil) fails. } + +#if !defined(GTEST_OS_IOS) + +TEST(GTestMac, ExpectNSEQRect) { + base::mac::ScopedNSAutoreleasePool pool; + + EXPECT_NSEQ(NSMakeRect(1, 2, 3, 4), NSMakeRect(1, 2, 3, 4)); +} + +TEST(GTestMac, AssertNSEQRect) { + base::mac::ScopedNSAutoreleasePool pool; + + ASSERT_NSEQ(NSMakeRect(1, 2, 3, 4), NSMakeRect(1, 2, 3, 4)); +} + +TEST(GTestMac, ExpectNSNERect) { + base::mac::ScopedNSAutoreleasePool pool; + + EXPECT_NSNE(NSMakeRect(1, 2, 3, 4), NSMakeRect(5, 6, 7, 8)); +} + +TEST(GTestMac, AssertNSNERect) { + base::mac::ScopedNSAutoreleasePool pool; + + ASSERT_NSNE(NSMakeRect(1, 2, 3, 4), NSMakeRect(5, 6, 7, 8)); +} + +TEST(GTestMac, ExpectNSEQPoint) { + base::mac::ScopedNSAutoreleasePool pool; + + EXPECT_NSEQ(NSMakePoint(1, 2), NSMakePoint(1, 2)); +} + +TEST(GTestMac, AssertNSEQPoint) { + base::mac::ScopedNSAutoreleasePool pool; + + ASSERT_NSEQ(NSMakePoint(1, 2), NSMakePoint(1, 2)); +} + +TEST(GTestMac, ExpectNSNEPoint) { + base::mac::ScopedNSAutoreleasePool pool; + + EXPECT_NSNE(NSMakePoint(1, 2), NSMakePoint(3, 4)); +} + +TEST(GTestMac, AssertNSNEPoint) { + base::mac::ScopedNSAutoreleasePool pool; + + ASSERT_NSNE(NSMakePoint(1, 2), NSMakePoint(3, 4)); +} + +#endif // !GTEST_OS_IOS diff --git a/testing/iossim/iossim.mm b/testing/iossim/iossim.mm index 3910ba5d60435..4d557ac8a875a 100644 --- a/testing/iossim/iossim.mm +++ b/testing/iossim/iossim.mm @@ -32,6 +32,7 @@ // (crbug.com/385030). #if defined(IOSSIM_USE_XCODE_6) @protocol SimBridge; +@class DVTSimulatorApplication; @class SimDeviceSet; @class SimDeviceType; @class SimRuntime; @@ -631,7 +632,18 @@ - (void)session:(DTiPhoneSimulatorSession*)session // valid. DTiPhoneSimulatorSystemRoot* BuildSystemRoot(NSString* sdkVersion) { Class systemRootClass = FindClassByName(@"DTiPhoneSimulatorSystemRoot"); +#if defined(IOSSIM_USE_XCODE_6) + Class simRuntimeClass = FindClassByName(@"SimRuntime"); + NSArray* sorted = + [[simRuntimeClass supportedRuntimes] sortedArrayUsingDescriptors:@[ + [NSSortDescriptor sortDescriptorWithKey:@"version" ascending:YES] + ]]; + NSString* versionString = [[sorted lastObject] versionString]; + DTiPhoneSimulatorSystemRoot* systemRoot = + [systemRootClass rootWithSDKVersion:versionString]; +#else DTiPhoneSimulatorSystemRoot* systemRoot = [systemRootClass defaultRoot]; +#endif if (sdkVersion) systemRoot = [systemRootClass rootWithSDKVersion:sdkVersion]; @@ -665,7 +677,7 @@ - (void)session:(DTiPhoneSimulatorSession*)session #if defined(IOSSIM_USE_XCODE_6) Class simDeviceTypeClass = FindClassByName(@"SimDeviceType"); id simDeviceType = - [simDeviceTypeClass supportedDeviceTypesByName][deviceName]; + [simDeviceTypeClass supportedDeviceTypesByAlias][deviceName]; Class simRuntimeClass = FindClassByName(@"SimRuntime"); NSString* identifier = systemRoot.runtime.identifier; id simRuntime = [simRuntimeClass supportedRuntimesByIdentifier][identifier]; @@ -955,7 +967,7 @@ int main(int argc, char* const argv[]) { if (IsRunningWithXcode6OrLater()) { #if defined(IOSSIM_USE_XCODE_6) Class simDeviceTypeClass = FindClassByName(@"SimDeviceType"); - if ([simDeviceTypeClass supportedDeviceTypesByName][deviceName] == nil) { + if ([simDeviceTypeClass supportedDeviceTypesByAlias][deviceName] == nil) { LogError(@"Invalid device name: %@.", deviceName); PrintSupportedDevices(); exit(kExitInvalidArguments); diff --git a/testing/legion/SimpleJSONRPCServer.py b/testing/legion/SimpleJSONRPCServer.py new file mode 100644 index 0000000000000..4dbfd6e825c5f --- /dev/null +++ b/testing/legion/SimpleJSONRPCServer.py @@ -0,0 +1,195 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Module to implement the SimpleXMLRPCServer module using JSON-RPC. + +This module uses SimpleXMLRPCServer as the base and only overrides those +portions that implement the XML-RPC protocol. These portions are rewritten +to use the JSON-RPC protocol instead. + +When large portions of code need to be rewritten the original code and +comments are preserved. The intention here is to keep the amount of code +change to a minimum. + +This module only depends on default Python modules, as well as jsonrpclib +which also uses only default modules. No third party code is required to +use this module. +""" +import fcntl +import json +import SimpleXMLRPCServer as _base +import SocketServer +import sys +import traceback +try: + import gzip +except ImportError: + gzip = None #python can be built without zlib/gzip support + +#pylint: disable=relative-import +import jsonrpclib + + +class SimpleJSONRPCRequestHandler(_base.SimpleXMLRPCRequestHandler): + """Request handler class for received requests. + + This class extends the functionality of SimpleXMLRPCRequestHandler and only + overrides the operations needed to change the protocol from XML-RPC to + JSON-RPC. + """ + + def do_POST(self): + """Handles the HTTP POST request. + + Attempts to interpret all HTTP POST requests as JSON-RPC calls, + which are forwarded to the server's _dispatch method for handling. + """ + # Check that the path is legal + if not self.is_rpc_path_valid(): + self.report_404() + return + + try: + # Get arguments by reading body of request. + # We read this in chunks to avoid straining + # socket.read(); around the 10 or 15Mb mark, some platforms + # begin to have problems (bug #792570). + max_chunk_size = 10*1024*1024 + size_remaining = int(self.headers['content-length']) + data = [] + while size_remaining: + chunk_size = min(size_remaining, max_chunk_size) + chunk = self.rfile.read(chunk_size) + if not chunk: + break + data.append(chunk) + size_remaining -= len(data[-1]) + data = ''.join(data) + data = self.decode_request_content(data) + + if data is None: + return # response has been sent + + # In previous versions of SimpleXMLRPCServer, _dispatch + # could be overridden in this class, instead of in + # SimpleXMLRPCDispatcher. To maintain backwards compatibility, + # check to see if a subclass implements _dispatch and dispatch + # using that method if present. + response = self.server._marshaled_dispatch( + data, getattr(self, '_dispatch', None), self.path) + + except Exception, e: # This should only happen if the module is buggy + # internal error, report as HTTP server error + self.send_response(500) + # Send information about the exception if requested + if (hasattr(self.server, '_send_traceback_header') and + self.server._send_traceback_header): + self.send_header('X-exception', str(e)) + self.send_header('X-traceback', traceback.format_exc()) + + self.send_header('Content-length', '0') + self.end_headers() + else: + # got a valid JSON RPC response + self.send_response(200) + self.send_header('Content-type', 'application/json') + + if self.encode_threshold is not None: + if len(response) > self.encode_threshold: + q = self.accept_encodings().get('gzip', 0) + if q: + try: + response = jsonrpclib.gzip_encode(response) + self.send_header('Content-Encoding', 'gzip') + except NotImplementedError: + pass + + self.send_header('Content-length', str(len(response))) + self.end_headers() + self.wfile.write(response) + + +class SimpleJSONRPCDispatcher(_base.SimpleXMLRPCDispatcher): + """Dispatcher for received JSON-RPC requests. + + This class extends the functionality of SimpleXMLRPCDispatcher and only + overrides the operations needed to change the protocol from XML-RPC to + JSON-RPC. + """ + + def _marshaled_dispatch(self, data, dispatch_method=None, path=None): + """Dispatches an JSON-RPC method from marshalled (JSON) data. + + JSON-RPC methods are dispatched from the marshalled (JSON) data + using the _dispatch method and the result is returned as + marshalled data. For backwards compatibility, a dispatch + function can be provided as an argument (see comment in + SimpleJSONRPCRequestHandler.do_POST) but overriding the + existing method through subclassing is the preferred means + of changing method dispatch behavior. + + Returns: + The JSON-RPC string to return. + """ + method = '' + params = [] + ident = '' + try: + request = json.loads(data) + jsonrpclib.ValidateRequest(request) + method = request['method'] + params = request['params'] + ident = request['id'] + + # generate response + if dispatch_method is not None: + response = dispatch_method(method, params) + else: + response = self._dispatch(method, params) + response = jsonrpclib.CreateResponseString(response, ident) + + except jsonrpclib.Fault as fault: + response = jsonrpclib.CreateResponseString(fault, ident) + + # Catch all exceptions here as they should be raised on the caller side. + except: #pylint: disable=bare-except + # report exception back to server + exc_type, exc_value, _ = sys.exc_info() + response = jsonrpclib.CreateResponseString( + jsonrpclib.Fault(1, '%s:%s' % (exc_type, exc_value)), ident) + return response + + +class SimpleJSONRPCServer(SocketServer.TCPServer, + SimpleJSONRPCDispatcher): + """Simple JSON-RPC server. + + This class mimics the functionality of SimpleXMLRPCServer and only + overrides the operations needed to change the protocol from XML-RPC to + JSON-RPC. + """ + + allow_reuse_address = True + + # Warning: this is for debugging purposes only! Never set this to True in + # production code, as will be sending out sensitive information (exception + # and stack trace details) when exceptions are raised inside + # SimpleJSONRPCRequestHandler.do_POST + _send_traceback_header = False + + def __init__(self, addr, requestHandler=SimpleJSONRPCRequestHandler, + logRequests=True, allow_none=False, encoding=None, + bind_and_activate=True): + self.logRequests = logRequests + SimpleJSONRPCDispatcher.__init__(self, allow_none, encoding) + SocketServer.TCPServer.__init__(self, addr, requestHandler, + bind_and_activate) + + # [Bug #1222790] If possible, set close-on-exec flag; if a + # method spawns a subprocess, the subprocess shouldn't have + # the listening socket open. + if fcntl is not None and hasattr(fcntl, 'FD_CLOEXEC'): + flags = fcntl.fcntl(self.fileno(), fcntl.F_GETFD) + flags |= fcntl.FD_CLOEXEC + fcntl.fcntl(self.fileno(), fcntl.F_SETFD, flags) diff --git a/testing/legion/common_lib.py b/testing/legion/common_lib.py index 6e7954bbeeb2a..863f88730da9e 100644 --- a/testing/legion/common_lib.py +++ b/testing/legion/common_lib.py @@ -8,7 +8,6 @@ import logging import os import socket -import xmlrpclib LOGGING_LEVELS = ['DEBUG', 'INFO', 'WARNING', 'WARN', 'ERROR'] MY_IP = socket.gethostbyname(socket.gethostname()) @@ -36,8 +35,9 @@ def InitLogging(): datefmt='%H:%M:%S', level=args.verbosity) -def ConnectToServer(server): - """Connect to an RPC server.""" - addr = 'http://%s:%d' % (server, SERVER_PORT) - logging.debug('Connecting to RPC server at %s', addr) - return xmlrpclib.Server(addr, allow_none=True) +def GetOutputDir(): + """Get the isolated output directory specified on the command line.""" + parser = argparse.ArgumentParser() + parser.add_argument('--output-dir') + args, _ = parser.parse_known_args() + return args.output_dir diff --git a/testing/legion/examples/subprocess/subprocess_test.py b/testing/legion/examples/subprocess/subprocess_test.py index cea871a4051f9..4b7fb6feec9ee 100755 --- a/testing/legion/examples/subprocess/subprocess_test.py +++ b/testing/legion/examples/subprocess/subprocess_test.py @@ -19,6 +19,7 @@ sys.path.append(TESTING_DIR) from legion import legion_test_case +from legion import jsonrpclib class ExampleTestController(legion_test_case.TestCase): @@ -90,6 +91,41 @@ def testLs(self): self.assertEqual(ls.GetReturncode(), 0) self.assertIn('task.isolate', ls.ReadStdout()) + def testProcessOutput(self): + """Tests that a process's output gets logged to a file in the output-dir.""" + code = ('import sys\n' + 'sys.stdout.write("Hello stdout")\n' + 'sys.stderr.write("Hello stderr")') + self.task.rpc.WriteFile('test.py', code) + proc = self.task.Process(['python', 'test.py'],) + + self.CheckProcessOutput('stdout', proc.key, 'Hello stdout') + self.CheckProcessOutput('stderr', proc.key, 'Hello stderr') + + def testCustomKey(self): + """Tests that a custom key passed to a process works correctly.""" + code = ('import sys\n' + 'sys.stdout.write("Hello CustomKey stdout")\n' + 'sys.stderr.write("Hello CustomKey stderr")') + self.task.rpc.WriteFile('test.py', code) + self.task.Process(['python', 'test.py'], key='CustomKey') + + self.CheckProcessOutput('stdout', 'CustomKey', 'Hello CustomKey stdout') + self.CheckProcessOutput('stderr', 'CustomKey', 'Hello CustomKey stderr') + + def testKeyReuse(self): + """Tests that a key cannot be reused.""" + self.task.Process(['ls'], key='KeyReuse') + self.assertRaises(jsonrpclib.Fault, self.task.Process, ['ls'], + key='KeyReuse') + + def CheckProcessOutput(self, pipe, key, expected): + """Checks that a process' output files are correct.""" + logging.info('Reading output file') + output_dir = self.task.rpc.GetOutputDir() + path = self.task.rpc.PathJoin(output_dir, '%s.%s' % (key, pipe)) + actual = self.task.rpc.ReadFile(path) + self.assertEqual(expected, actual) if __name__ == '__main__': legion_test_case.main() diff --git a/testing/legion/jsonrpclib.py b/testing/legion/jsonrpclib.py new file mode 100644 index 0000000000000..56b30e8dc3bff --- /dev/null +++ b/testing/legion/jsonrpclib.py @@ -0,0 +1,370 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Module to implement the JSON-RPC protocol. + +This module uses xmlrpclib as the base and only overrides those +portions that implement the XML-RPC protocol. These portions are rewritten +to use the JSON-RPC protocol instead. + +When large portions of code need to be rewritten the original code and +comments are preserved. The intention here is to keep the amount of code +change to a minimum. + +This module only depends on default Python modules. No third party code is +required to use this module. +""" +import json +import urllib +import xmlrpclib as _base + +__version__ = '1.0.0' +gzip_encode = _base.gzip_encode +gzip = _base.gzip + + +class Error(Exception): + + def __str__(self): + return repr(self) + + +class ProtocolError(Error): + """Indicates a JSON protocol error.""" + + def __init__(self, url, errcode, errmsg, headers): + Error.__init__(self) + self.url = url + self.errcode = errcode + self.errmsg = errmsg + self.headers = headers + + def __repr__(self): + return ( + '' % + (self.url, self.errcode, self.errmsg)) + + +class ResponseError(Error): + """Indicates a broken response package.""" + pass + + +class Fault(Error): + """Indicates a JSON-RPC fault package.""" + + def __init__(self, code, message): + Error.__init__(self) + if not isinstance(code, int): + raise ProtocolError('Fault code must be an integer.') + self.code = code + self.message = message + + def __repr__(self): + return ( + '' % + (self.code, repr(self.message)) + ) + + +def CreateRequest(methodname, params, ident=''): + """Create a valid JSON-RPC request. + + Args: + methodname: The name of the remote method to invoke. + params: The parameters to pass to the remote method. This should be a + list or tuple and able to be encoded by the default JSON parser. + + Returns: + A valid JSON-RPC request object. + """ + request = { + 'jsonrpc': '2.0', + 'method': methodname, + 'params': params, + 'id': ident + } + + return request + + +def CreateRequestString(methodname, params, ident=''): + """Create a valid JSON-RPC request string. + + Args: + methodname: The name of the remote method to invoke. + params: The parameters to pass to the remote method. + These parameters need to be encode-able by the default JSON parser. + ident: The request identifier. + + Returns: + A valid JSON-RPC request string. + """ + return json.dumps(CreateRequest(methodname, params, ident)) + + +def CreateResponse(data, ident): + """Create a JSON-RPC response. + + Args: + data: The data to return. + ident: The response identifier. + + Returns: + A valid JSON-RPC response object. + """ + if isinstance(data, Fault): + response = { + 'jsonrpc': '2.0', + 'error': { + 'code': data.code, + 'message': data.message}, + 'id': ident + } + else: + response = { + 'jsonrpc': '2.0', + 'response': data, + 'id': ident + } + + return response + + +def CreateResponseString(data, ident): + """Create a JSON-RPC response string. + + Args: + data: The data to return. + ident: The response identifier. + + Returns: + A valid JSON-RPC response object. + """ + return json.dumps(CreateResponse(data, ident)) + + +def ParseHTTPResponse(response): + """Parse an HTTP response object and return the JSON object. + + Args: + response: An HTTP response object. + + Returns: + The returned JSON-RPC object. + + Raises: + ProtocolError: if the object format is not correct. + Fault: If a Fault error is returned from the server. + """ + # Check for new http response object, else it is a file object + if hasattr(response, 'getheader'): + if response.getheader('Content-Encoding', '') == 'gzip': + stream = _base.GzipDecodedResponse(response) + else: + stream = response + else: + stream = response + + data = '' + while 1: + chunk = stream.read(1024) + if not chunk: + break + data += chunk + + response = json.loads(data) + ValidateBasicJSONRPCData(response) + + if 'response' in response: + ValidateResponse(response) + return response['response'] + elif 'error' in response: + ValidateError(response) + code = response['error']['code'] + message = response['error']['message'] + raise Fault(code, message) + else: + raise ProtocolError('No valid JSON returned') + + +def ValidateRequest(data): + """Validate a JSON-RPC request object. + + Args: + data: The JSON-RPC object (dict). + + Raises: + ProtocolError: if the object format is not correct. + """ + ValidateBasicJSONRPCData(data) + if 'method' not in data or 'params' not in data: + raise ProtocolError('JSON is not a valid request') + + +def ValidateResponse(data): + """Validate a JSON-RPC response object. + + Args: + data: The JSON-RPC object (dict). + + Raises: + ProtocolError: if the object format is not correct. + """ + ValidateBasicJSONRPCData(data) + if 'response' not in data: + raise ProtocolError('JSON is not a valid response') + + +def ValidateError(data): + """Validate a JSON-RPC error object. + + Args: + data: The JSON-RPC object (dict). + + Raises: + ProtocolError: if the object format is not correct. + """ + ValidateBasicJSONRPCData(data) + if ('error' not in data or + 'code' not in data['error'] or + 'message' not in data['error']): + raise ProtocolError('JSON is not a valid error response') + + +def ValidateBasicJSONRPCData(data): + """Validate a basic JSON-RPC object. + + Args: + data: The JSON-RPC object (dict). + + Raises: + ProtocolError: if the object format is not correct. + """ + error = None + if not isinstance(data, dict): + error = 'JSON data is not a dictionary' + elif 'jsonrpc' not in data or data['jsonrpc'] != '2.0': + error = 'JSON is not a valid JSON RPC 2.0 message' + elif 'id' not in data: + error = 'JSON data missing required id entry' + if error: + raise ProtocolError(error) + + +class Transport(_base.Transport): + """RPC transport class. + + This class extends the functionality of xmlrpclib.Transport and only + overrides the operations needed to change the protocol from XML-RPC to + JSON-RPC. + """ + + user_agent = 'jsonrpclib.py/' + __version__ + + def send_content(self, connection, request_body): + """Send the request.""" + connection.putheader('Content-Type','application/json') + + #optionally encode the request + if (self.encode_threshold is not None and + self.encode_threshold < len(request_body) and + gzip): + connection.putheader('Content-Encoding', 'gzip') + request_body = gzip_encode(request_body) + + connection.putheader('Content-Length', str(len(request_body))) + connection.endheaders(request_body) + + def single_request(self, host, handler, request_body, verbose=0): + """Issue a single JSON-RPC request.""" + + h = self.make_connection(host) + if verbose: + h.set_debuglevel(1) + try: + self.send_request(h, handler, request_body) + self.send_host(h, host) + self.send_user_agent(h) + self.send_content(h, request_body) + + response = h.getresponse(buffering=True) + if response.status == 200: + self.verbose = verbose #pylint: disable=attribute-defined-outside-init + + return self.parse_response(response) + + except Fault: + raise + except Exception: + # All unexpected errors leave connection in + # a strange state, so we clear it. + self.close() + raise + + # discard any response data and raise exception + if response.getheader('content-length', 0): + response.read() + raise ProtocolError( + host + handler, + response.status, response.reason, + response.msg, + ) + + def parse_response(self, response): + """Parse the HTTP resoponse from the server.""" + return ParseHTTPResponse(response) + + +class SafeTransport(_base.SafeTransport): + """Transport class for HTTPS servers. + + This class extends the functionality of xmlrpclib.SafeTransport and only + overrides the operations needed to change the protocol from XML-RPC to + JSON-RPC. + """ + + def parse_response(self, response): + return ParseHTTPResponse(response) + + +class ServerProxy(_base.ServerProxy): + """Proxy class to the RPC server. + + This class extends the functionality of xmlrpclib.ServerProxy and only + overrides the operations needed to change the protocol from XML-RPC to + JSON-RPC. + """ + + def __init__(self, uri, transport=None, encoding=None, verbose=0, + allow_none=0, use_datetime=0): + urltype, _ = urllib.splittype(uri) + if urltype not in ('http', 'https'): + raise IOError('unsupported JSON-RPC protocol') + + _base.ServerProxy.__init__(self, uri, transport, encoding, verbose, + allow_none, use_datetime) + transport_type, uri = urllib.splittype(uri) + if transport is None: + if transport_type == 'https': + transport = SafeTransport(use_datetime=use_datetime) + else: + transport = Transport(use_datetime=use_datetime) + self.__transport = transport + + def __request(self, methodname, params): + """Call a method on the remote server.""" + request = CreateRequestString(methodname, params) + + response = self.__transport.request( + self.__host, + self.__handler, + request, + verbose=self.__verbose + ) + + return response + + +Server = ServerProxy diff --git a/testing/legion/legion.isolate b/testing/legion/legion.isolate index 18e0b3b092d6a..63e3fc88d368f 100644 --- a/testing/legion/legion.isolate +++ b/testing/legion/legion.isolate @@ -7,15 +7,18 @@ 'files': [ '__init__.py', 'common_lib.py', + 'jsonrpclib.py', 'legion_test_case.py', 'legion.isolate', 'process.py', 'rpc_methods.py', 'rpc_server.py', 'run_task.py', + 'ssl_util.py', 'task_controller.py', 'task_registration_server.py', 'test_controller.py', + 'SimpleJSONRPCServer.py', '../../tools/swarming_client/', ], }, diff --git a/testing/legion/legion_test_case.py b/testing/legion/legion_test_case.py index 9514e8e19be7c..c70d154919c22 100644 --- a/testing/legion/legion_test_case.py +++ b/testing/legion/legion_test_case.py @@ -36,6 +36,13 @@ def __init__(self, test_name='runTest'): # Install the _RunTest method self._TestMethod = method setattr(self, test_name, self._RunTest) + self._output_dir = None + + @property + def output_dir(self): + if not self._output_dir: + self._output_dir = self.rpc.GetOutputDir() + return self._output_dir def _RunTest(self): """Runs the test method and provides banner info and error reporting.""" diff --git a/testing/legion/process.py b/testing/legion/process.py index 356db6131bfa1..f3cabb5d94b4a 100644 --- a/testing/legion/process.py +++ b/testing/legion/process.py @@ -9,6 +9,7 @@ """ import logging +import os import subprocess import sys import threading @@ -29,30 +30,37 @@ class ControllerProcessWrapper(object): than calling the methods directly using the RPC object. """ - def __init__(self, rpc, cmd, verbose=False, detached=False, cwd=None): + def __init__(self, rpc, cmd, verbose=False, detached=False, cwd=None, + key=None): + logging.info('Creating a process with cmd=%s', cmd) self._rpc = rpc - self._id = rpc.subprocess.Process(cmd) + self._key = rpc.subprocess.Process(cmd, key) + logging.info('Process created with key=%s', self._key) if verbose: - self._rpc.subprocess.SetVerbose(self._id) + self._rpc.subprocess.SetVerbose(self._key) if detached: - self._rpc.subprocess.SetDetached(self._id) + self._rpc.subprocess.SetDetached(self._key) if cwd: self._rpc.subprocess.SetCwd(self._rpc, cwd) - self._rpc.subprocess.Start(self._id) + self._rpc.subprocess.Start(self._key) + + @property + def key(self): + return self._key def Terminate(self): - logging.debug('Terminating process %s', self._id) - return self._rpc.subprocess.Terminate(self._id) + logging.debug('Terminating process %s', self._key) + return self._rpc.subprocess.Terminate(self._key) def Kill(self): - logging.debug('Killing process %s', self._id) - self._rpc.subprocess.Kill(self._id) + logging.debug('Killing process %s', self._key) + self._rpc.subprocess.Kill(self._key) def Delete(self): - return self._rpc.subprocess.Delete(self._id) + return self._rpc.subprocess.Delete(self._key) def GetReturncode(self): - return self._rpc.subprocess.GetReturncode(self._id) + return self._rpc.subprocess.GetReturncode(self._key) def ReadStdout(self): """Returns all stdout since the last call to ReadStdout. @@ -62,30 +70,30 @@ def ReadStdout(self): multiple calls to ReadStdout and to retain the entire output the results of this call will need to be buffered in the calling code. """ - return self._rpc.subprocess.ReadStdout(self._id) + return self._rpc.subprocess.ReadStdout(self._key) def ReadStderr(self): """Returns all stderr read since the last call to ReadStderr. See ReadStdout for additional details. """ - return self._rpc.subprocess.ReadStderr(self._id) + return self._rpc.subprocess.ReadStderr(self._key) def ReadOutput(self): """Returns the (stdout, stderr) since the last Read* call. See ReadStdout for additional details. """ - return self._rpc.subprocess.ReadOutput(self._id) + return self._rpc.subprocess.ReadOutput(self._key) def Wait(self): - return self._rpc.subprocess.Wait(self._id) + return self._rpc.subprocess.Wait(self._key) def Poll(self): - return self._rpc.subprocess.Poll(self._id) + return self._rpc.subprocess.Poll(self._key) def GetPid(self): - return self._rpc.subprocess.GetPid(self._id) + return self._rpc.subprocess.GetPid(self._key) @@ -105,15 +113,21 @@ class Process(object): _process_next_id = 0 _creation_lock = threading.Lock() - def __init__(self, cmd): + def __init__(self, cmd, key): self.stdout = '' self.stderr = '' + self.key = key self.cmd = cmd self.proc = None self.cwd = None self.verbose = False self.detached = False self.data_lock = threading.Lock() + self.stdout_file = open(self._CreateOutputFilename('stdout'), 'wb+') + self.stderr_file = open(self._CreateOutputFilename('stderr'), 'wb+') + + def _CreateOutputFilename(self, fname): + return os.path.join(common_lib.GetOutputDir(), '%s.%s' % (self.key, fname)) def __str__(self): return '%r, cwd=%r, verbose=%r, detached=%r' % ( @@ -124,10 +138,14 @@ def _reader(self): with self.data_lock: if pipe == 'stdout': self.stdout += data + self.stdout_file.write(data) + self.stdout_file.flush() if self.verbose: sys.stdout.write(data) else: self.stderr += data + self.stderr_file.write(data) + self.stderr_file.flush() if self.verbose: sys.stderr.write(data) @@ -137,13 +155,15 @@ def KillAll(cls): cls.Kill(key) @classmethod - def Process(cls, cmd): + def Process(cls, cmd, key=None): with cls._creation_lock: - key = 'Process%d' % cls._process_next_id - cls._process_next_id += 1 - logging.debug('Creating process %s with cmd %r', key, cmd) - process = cls(cmd) - cls._processes[key] = process + if not key: + key = 'Process%d' % cls._process_next_id + cls._process_next_id += 1 + if key in cls._processes: + raise KeyError('Key %s already in use' % key) + logging.debug('Creating process %s with cmd %r', key, cmd) + cls._processes[key] = cls(cmd, key) return key def _Start(self): diff --git a/testing/legion/rpc_methods.py b/testing/legion/rpc_methods.py index 24d0312c252b5..aaab7e018e778 100644 --- a/testing/legion/rpc_methods.py +++ b/testing/legion/rpc_methods.py @@ -10,6 +10,7 @@ import threading #pylint: disable=relative-import +import common_lib import process @@ -49,3 +50,30 @@ def Quit(self): """ t = threading.Thread(target=self._server.shutdown) t.start() + + def GetOutputDir(self): + """Returns the isolated output directory on the task machine.""" + return common_lib.GetOutputDir() + + def WriteFile(self, path, text, mode='wb+'): + """Writes a file on the task machine.""" + with open(path, mode) as fh: + fh.write(text) + + def ReadFile(self, path, mode='rb'): + """Reads a file from the local task machine.""" + with open(path, mode) as fh: + return fh.read() + + def PathJoin(self, *parts): + """Performs an os.path.join on the task machine. + + This is needed due to the fact that there is no guarantee that os.sep will + be the same across all machines in a particular test. This method will + join the path parts locally to ensure the correct separator is used. + """ + return os.path.join(*parts) + + def ListDir(self, path): + """Returns the results of os.listdir.""" + return os.listdir(path) diff --git a/testing/legion/rpc_server.py b/testing/legion/rpc_server.py index 43b431707e851..24ebe250d6c5e 100644 --- a/testing/legion/rpc_server.py +++ b/testing/legion/rpc_server.py @@ -17,16 +17,16 @@ import logging import threading import time -import xmlrpclib -import SimpleXMLRPCServer import SocketServer #pylint: disable=relative-import import common_lib import rpc_methods +import ssl_util +import SimpleJSONRPCServer -class RequestHandler(SimpleXMLRPCServer.SimpleXMLRPCRequestHandler): +class RequestHandler(SimpleJSONRPCServer.SimpleJSONRPCRequestHandler): """Restricts access to only specified IP address. This call assumes the server is RPCServer. @@ -44,20 +44,19 @@ def do_POST(self): self.end_headers() self.wfile.write(response) else: - return SimpleXMLRPCServer.SimpleXMLRPCRequestHandler.do_POST(self) + return SimpleJSONRPCServer.SimpleJSONRPCRequestHandler.do_POST(self) -class RPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer, +class RpcServer(ssl_util.SslRpcServer, SocketServer.ThreadingMixIn): """Restricts all endpoints to only specified IP addresses.""" def __init__(self, authorized_address, idle_timeout_secs=common_lib.DEFAULT_TIMEOUT_SECS): - SimpleXMLRPCServer.SimpleXMLRPCServer.__init__( + ssl_util.SslRpcServer.__init__( self, (common_lib.SERVER_ADDRESS, common_lib.SERVER_PORT), allow_none=True, logRequests=False, requestHandler=RequestHandler) - self.authorized_address = authorized_address self.idle_timeout_secs = idle_timeout_secs self.register_instance(rpc_methods.RPCMethods(self)) @@ -73,7 +72,7 @@ def shutdown(self): idle timeout thread to quit. """ self._shutdown_requested_event.set() - SimpleXMLRPCServer.SimpleXMLRPCServer.shutdown(self) + SimpleJSONRPCServer.SimpleJSONRPCServer.shutdown(self) logging.info('Server shutdown complete') def serve_forever(self, poll_interval=0.5): @@ -88,7 +87,7 @@ def serve_forever(self, poll_interval=0.5): """ logging.info('RPC server starting') self._idle_thread.start() - SimpleXMLRPCServer.SimpleXMLRPCServer.serve_forever(self, poll_interval) + SimpleJSONRPCServer.SimpleJSONRPCServer.serve_forever(self, poll_interval) def _dispatch(self, method, params): """Dispatch the call to the correct method with the provided params. @@ -105,7 +104,8 @@ def _dispatch(self, method, params): """ logging.debug('Calling %s%s', method, params) self._rpc_received_event.set() - return SimpleXMLRPCServer.SimpleXMLRPCServer._dispatch(self, method, params) + return SimpleJSONRPCServer.SimpleJSONRPCServer._dispatch( + self, method, params) def _CheckForIdleQuit(self): """Check for, and exit, if the server is idle for too long. diff --git a/testing/legion/run_task.py b/testing/legion/run_task.py index 26c6e5c877ca9..cb0b90fefd6a6 100755 --- a/testing/legion/run_task.py +++ b/testing/legion/run_task.py @@ -14,6 +14,7 @@ #pylint: disable=relative-import import common_lib import rpc_server +import ssl_util def main(): @@ -34,10 +35,10 @@ def main(): logging.info( 'Registering with registration server at %s using OTP "%s"', args.controller, args.otp) - common_lib.ConnectToServer(args.controller).RegisterTask( + ssl_util.SslRpcServer.Connect(args.controller).RegisterTask( args.otp, common_lib.MY_IP) - server = rpc_server.RPCServer(args.controller, args.idle_timeout) + server = rpc_server.RpcServer(args.controller, args.idle_timeout) server.serve_forever() logging.info('Server shutdown complete') diff --git a/testing/legion/ssl_util.py b/testing/legion/ssl_util.py new file mode 100644 index 0000000000000..41e1e75b2ddc0 --- /dev/null +++ b/testing/legion/ssl_util.py @@ -0,0 +1,103 @@ +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Utility library to add SSL support to the RPC server.""" + +import logging +import ssl +import subprocess +import tempfile + +#pylint: disable=relative-import +import common_lib +import jsonrpclib +import SimpleJSONRPCServer + + +class Error(Exception): + pass + + +def CreateKeyFile(): + """Creates an SSL keyfile and returns the path.""" + keyfile = tempfile.mkstemp()[1] + cmd = [ + 'openssl', + 'genrsa', + '-out', keyfile, + '2048' + ] + _RunCommand(cmd) + return keyfile + + +def CreateCsrFile(keyfile): + """Creates an SSL CSR file and returns the path.""" + csrfile = tempfile.mkstemp()[1] + cmd = [ + 'openssl', + 'req', + '-new', + '-key', keyfile, + '-out', csrfile, + '-subj', '/C=NA/ST=NA/L=NA/O=Chromium/OU=Test/CN=chromium.org' + ] + _RunCommand(cmd) + return csrfile + + +def CreateCrtFile(keyfile, csrfile): + """Creates an SSL CRT file and returns the path.""" + crtfile = tempfile.mkstemp()[1] + cmd = [ + 'openssl', + 'x509', + '-req', + '-days', '1', + '-in', csrfile, + '-signkey', keyfile, + '-out', crtfile + ] + _RunCommand(cmd) + return crtfile + + +def CreatePemFile(): + """Creates an SSL PEM file and returns the path.""" + keyfile = CreateKeyFile() + csrfile = CreateCsrFile(keyfile) + crtfile = CreateCrtFile(keyfile, csrfile) + pemfile = tempfile.mkstemp()[1] + with open(keyfile) as k: + with open(crtfile) as c: + with open(pemfile, 'wb') as p: + p.write('%s\n%s' % (k.read(), c.read())) + return pemfile + + +def _RunCommand(cmd): + try: + p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + except OSError as e: + raise Error('Failed to run %s: %s' % (' '.join(cmd), e)) + out, err = p.communicate() + if p.returncode != 0: + raise Error(err) + return out + + +class SslRpcServer(SimpleJSONRPCServer.SimpleJSONRPCServer): + """Class to add SSL support to the RPC server.""" + + def __init__(self, *args, **kwargs): + SimpleJSONRPCServer.SimpleJSONRPCServer.__init__(self, *args, **kwargs) + self.socket = ssl.wrap_socket(self.socket, certfile=CreatePemFile(), + server_side=True) + + @staticmethod + def Connect(server, port=common_lib.SERVER_PORT): + """Creates and returns a connection to an SSL RPC server.""" + addr = 'https://%s:%d' % (server, port) + logging.debug('Connecting to RPC server at %s', addr) + return jsonrpclib.ServerProxy(addr, allow_none=True) diff --git a/testing/legion/task_controller.py b/testing/legion/task_controller.py index 9514f44fddd89..7e0aa99bba43c 100644 --- a/testing/legion/task_controller.py +++ b/testing/legion/task_controller.py @@ -13,11 +13,12 @@ import sys import tempfile import threading -import xmlrpclib #pylint: disable=relative-import import common_lib import process +import ssl_util +import jsonrpclib ISOLATE_PY = os.path.join(common_lib.SWARMING_DIR, 'isolate.py') SWARMING_PY = os.path.join(common_lib.SWARMING_DIR, 'swarming.py') @@ -68,6 +69,7 @@ def __init__(self, isolated_hash, dimensions, priority=100, self._ip_address = None self._otp = self._CreateOTP() self._rpc = None + self._output_dir = None run_id = run_id or datetime.datetime.now().strftime('%Y-%m-%d-%H-%M-%S') self._task_name = '%s/%s/%s' % ( @@ -121,14 +123,19 @@ def verbosity(self, level): level = logging.getLevelName(level) self._verbosity = level #pylint: disable=attribute-defined-outside-init + @property + def output_dir(self): + if not self._output_dir: + self._output_dir = self.rpc.GetOutputDir() + return self._output_dir + @classmethod def ReleaseAllTasks(cls): for task in cls._tasks: task.Release() - def Process(self, cmd, verbose=False, detached=False, cwd=None): - return process.ControllerProcessWrapper( - self.rpc, cmd, verbose, detached, cwd) + def Process(self, cmd, *args, **kwargs): + return process.ControllerProcessWrapper(self.rpc, cmd, *args, **kwargs) def _CreateOTP(self): """Creates the OTP.""" @@ -160,10 +167,12 @@ def WaitForConnection(self): def Release(self): """Quits the task's RPC server so it can release the machine.""" if self._rpc is not None and self._connected: + logging.info('Copying output-dir files to controller') + self.RetrieveOutputFiles() logging.info('Releasing %s', self._name) try: self._rpc.Quit() - except (socket.error, xmlrpclib.Fault): + except (socket.error, jsonrpclib.Fault): logging.error('Unable to connect to %s to call Quit', self.name) self._rpc = None self._connected = False @@ -192,6 +201,7 @@ def _ExecuteSwarming(self): '--otp', self._otp, '--verbosity', self._verbosity, '--idle-timeout', str(self._idle_timeout_secs), + '--output-dir', '${ISOLATED_OUTDIR}' ]) self._ExecuteProcess(cmd) @@ -208,6 +218,17 @@ def OnConnect(self, ip_address): """Receives task ip address on connection.""" self._ip_address = ip_address self._connected = True - self._rpc = common_lib.ConnectToServer(self._ip_address) + self._rpc = ssl_util.SslRpcServer.Connect(self._ip_address) logging.info('%s connected from %s', self._name, ip_address) self._connect_event.set() + + def RetrieveOutputFiles(self): + """Retrieves all files in the output-dir.""" + files = self.rpc.ListDir(self.output_dir) + for fname in files: + remote_path = self.rpc.PathJoin(self.output_dir, fname) + local_name = os.path.join(common_lib.GetOutputDir(), + '%s.%s' % (self.name, fname)) + contents = self.rpc.ReadFile(remote_path) + with open(local_name, 'wb+') as fh: + fh.write(contents) diff --git a/testing/legion/task_registration_server.py b/testing/legion/task_registration_server.py index fe92dcd5fc793..1b1595224947a 100644 --- a/testing/legion/task_registration_server.py +++ b/testing/legion/task_registration_server.py @@ -11,11 +11,10 @@ import logging import threading -import xmlrpclib -import SimpleXMLRPCServer #pylint: disable=relative-import import common_lib +import ssl_util class TaskRegistrationServer(object): @@ -40,7 +39,7 @@ def RegisterTaskCallback(self, otp, callback): def Start(self): """Starts the registration server.""" logging.info('Starting task registration server') - self._rpc_server = SimpleXMLRPCServer.SimpleXMLRPCServer( + self._rpc_server = ssl_util.SslRpcServer( (common_lib.SERVER_ADDRESS, common_lib.SERVER_PORT), allow_none=True, logRequests=False) self._rpc_server.register_function( diff --git a/testing/legion/tools/legion.py b/testing/legion/tools/legion.py index 7b671335eeb86..4ddfc5e44ad7f 100755 --- a/testing/legion/tools/legion.py +++ b/testing/legion/tools/legion.py @@ -133,6 +133,8 @@ def GetSwarmingCommandLine(args): cmd.append('--') + # Specify the output dir + cmd.extend(['--output-dir', '${ISOLATED_OUTDIR}']) # Task name/hash values for name, isolated in args.tasks: cmd.extend(['--' + name, Archive(isolated, args.isolate_server)]) diff --git a/testing/scripts/android_gtest_test.py b/testing/scripts/android_gtest_test.py new file mode 100755 index 0000000000000..998a354135e80 --- /dev/null +++ b/testing/scripts/android_gtest_test.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import json +import os +import sys + + +import common + + +def main_run(args): + filter_tests = [] + if args.filter_file: + filter_tests = json.load(args.filter_file) + + script_args = args.args + test_suite = script_args[0] + + with common.temporary_file() as tempfile_path: + cmd = [ + os.path.join( + args.paths['checkout'], 'build', 'android', 'test_runner.py'), + 'gtest', + '--release' if 'release' in args.build_config_fs.lower() else '--debug', + '--suite', test_suite, + '--verbose', + '--flakiness-dashboard-server=http://test-results.appspot.com', + '--json-results-file', tempfile_path, + ] + if filter_tests: + cmd.extend(['--gtest-filter', ':'.join(filter_tests)]) + + rc = common.run_command(cmd) + + with open(tempfile_path) as f: + results = json.load(f) + + parsed_results = common.parse_gtest_test_results(results) + + json.dump({ + 'valid': True, + 'failures': parsed_results['failures'], + }, args.output) + + return rc + + +def main_compile_targets(args): + json.dump(['${name}_apk'], args.output) + + +if __name__ == '__main__': + funcs = { + 'run': main_run, + 'compile_targets': main_compile_targets, + } + sys.exit(common.run_script(sys.argv[1:], funcs)) diff --git a/testing/scripts/common.py b/testing/scripts/common.py index 1aefcd5b79557..3697c4b737386 100644 --- a/testing/scripts/common.py +++ b/testing/scripts/common.py @@ -37,6 +37,11 @@ def parse_json(path): # behavior of the script. parser.add_argument('--args', type=parse_json, default=[]) + parser.add_argument( + '--use-src-side-runtest-py', action='store_true', + help='Use the src-side copy of runtest.py, as opposed to the build-side ' + 'one') + subparsers = parser.add_subparsers() run_parser = subparsers.add_parser('run') @@ -62,12 +67,23 @@ def run_command(argv): def run_runtest(cmd_args, runtest_args): - return run_command([ + if cmd_args.use_src_side_runtest_py: + cmd = [ + sys.executable, + os.path.join( + cmd_args.paths['checkout'], 'infra', 'scripts', 'runtest_wrapper.py'), + '--path-build', cmd_args.paths['build'], + '--', + ] + else: + cmd = [ sys.executable, os.path.join(cmd_args.paths['build'], 'scripts', 'tools', 'runit.py'), '--show-path', sys.executable, os.path.join(cmd_args.paths['build'], 'scripts', 'slave', 'runtest.py'), + ] + return run_command(cmd + [ '--target', cmd_args.build_config_fs, '--xvfb', '--builder-name', cmd_args.properties['buildername'], @@ -137,3 +153,19 @@ def convert_trie_to_flat_paths(trie, prefix=None): results[key][test] = data return results + + +def parse_gtest_test_results(json_results): + failures = set() + for cur_iteration_data in json_results.get('per_iteration_data', []): + for test_fullname, results in cur_iteration_data.iteritems(): + # Results is a list with one entry per test try. Last one is the final + # result, the only we care about here. + last_result = results[-1] + + if last_result['status'] != 'SUCCESS': + failures.add(test_fullname) + + return { + 'failures': sorted(failures), + } diff --git a/testing/scripts/mojo_apptest.py b/testing/scripts/mojo_apptests.py similarity index 88% rename from testing/scripts/mojo_apptest.py rename to testing/scripts/mojo_apptests.py index 09e3f234fd1fb..49b855da2faa8 100755 --- a/testing/scripts/mojo_apptest.py +++ b/testing/scripts/mojo_apptests.py @@ -13,11 +13,10 @@ def main_run(args): runner = os.path.join(common.SRC_DIR, 'mojo', 'tools', 'apptest_runner.py') - tests = os.path.join(common.SRC_DIR, 'mojo', 'tools', 'data', 'apptests') build_dir = os.path.join(common.SRC_DIR, 'out', args.build_config_fs) with common.temporary_file() as tempfile_path: - rc = common.run_command([runner, tests, build_dir, '--verbose', + rc = common.run_command([runner, build_dir, '--verbose', '--write-full-results-to', tempfile_path]) with open(tempfile_path) as f: results = json.load(f) diff --git a/testing/scripts/telemetry_gpu_unittests.py b/testing/scripts/telemetry_gpu_unittests.py new file mode 100755 index 0000000000000..cf9862e3e2405 --- /dev/null +++ b/testing/scripts/telemetry_gpu_unittests.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import json +import os +import sys + + +import common + + +def main_run(args): + filter_tests = [] + if args.filter_file: + filter_tests = json.load(args.filter_file) + + with common.temporary_file() as tempfile_path: + rc = common.run_runtest(args, [ + '--test-type', 'telemetry_gpu_unittests', + '--run-python-script', + os.path.join(common.SRC_DIR, + 'content', 'test', 'gpu', 'run_unittests.py'), + '--retry-limit', '3', + '--write-full-results-to', tempfile_path, + ] + filter_tests) + + with open(tempfile_path) as f: + results = json.load(f) + + parsed_results = common.parse_common_test_results(results, test_separator='.') + failures = parsed_results['unexpected_failures'] + + json.dump({ + 'valid': bool(rc <= common.MAX_FAILURES_EXIT_STATUS and + ((rc == 0) or failures)), + 'failures': failures.keys(), + }, args.output) + + return rc + + +def main_compile_targets(args): + json.dump([], args.output) + + +if __name__ == '__main__': + funcs = { + 'run': main_run, + 'compile_targets': main_compile_targets, + } + sys.exit(common.run_script(sys.argv[1:], funcs)) diff --git a/testing/scripts/telemetry_perf_unittests.py b/testing/scripts/telemetry_perf_unittests.py index 06e018136c165..0c6f08981ee7a 100755 --- a/testing/scripts/telemetry_perf_unittests.py +++ b/testing/scripts/telemetry_perf_unittests.py @@ -25,7 +25,6 @@ def main_run(args): with common.temporary_file() as tempfile_path: test_args += ['--write-full-results-to', tempfile_path] rc = common.run_runtest(args, [ - '--annotate', 'gtest', '--test-type', 'telemetry_perf_unittests', '--run-python-script', os.path.join(common.SRC_DIR, 'tools', 'perf', 'run_tests') diff --git a/testing/scripts/telemetry_unittests.py b/testing/scripts/telemetry_unittests.py index 50af0c08bf6fd..ad7e66f1bfdd9 100755 --- a/testing/scripts/telemetry_unittests.py +++ b/testing/scripts/telemetry_unittests.py @@ -18,7 +18,6 @@ def main_run(args): with common.temporary_file() as tempfile_path: rc = common.run_runtest(args, [ - '--annotate', 'gtest', '--test-type', 'telemetry_unittests', '--run-python-script', os.path.join(common.SRC_DIR, 'tools', 'telemetry', 'run_tests'), diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json deleted file mode 100644 index 9e26dfeeb6e64..0000000000000 --- a/testing/variations/fieldtrial_testing_config.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/testing/variations/fieldtrial_testing_config_android.json b/testing/variations/fieldtrial_testing_config_android.json new file mode 100644 index 0000000000000..cdfc62c58757d --- /dev/null +++ b/testing/variations/fieldtrial_testing_config_android.json @@ -0,0 +1,62 @@ +{ + "EnhancedBookmarks": [ + { + "group_name": "EnableEnhancedBookmarks", + "params": { + "id": "Fake_id_to_trigger_experiment_code" + } + }, + { + "group_name": "EnableEnhancedBookmarksGrid", + "params": { + "DefaultViewMode": "Grid", + "id": "Fake_id_to_trigger_experiment_code" + } + }, + { + "group_name": "EnableEnhancedBookmarksList", + "params": { + "DefaultViewMode": "List", + "id": "Fake_id_to_trigger_experiment_code" + } + } + ], + "CustomTabs": [ + { + "group_name": "Enabled" + }, + { + "group_name": "DisablePrerender" + }, + { + "group_name": "Disabled" + } + ], + "DataReductionProxyUseQuic": [ + { + "group_name": "Enabled" + } + ], + "LimitSyncPassphrasePrompt": [ + { + "group_name": "Enabled" + } + ], + "ReaderModeUIFeedback": [ + { + "group_name": "Show" + }, + { + "group_name": "DoNotShow" + } + ], + "ContextualSearch": [ + { + "group_name": "OptOut", + "params": { + "enabled": "true", + "promo_opt_out": "true" + } + } + ] +} diff --git a/testing/variations/fieldtrial_testing_config_chromeos.json b/testing/variations/fieldtrial_testing_config_chromeos.json new file mode 100644 index 0000000000000..0967ef424bce6 --- /dev/null +++ b/testing/variations/fieldtrial_testing_config_chromeos.json @@ -0,0 +1 @@ +{} diff --git a/testing/variations/fieldtrial_testing_config_ios.json b/testing/variations/fieldtrial_testing_config_ios.json new file mode 100644 index 0000000000000..0967ef424bce6 --- /dev/null +++ b/testing/variations/fieldtrial_testing_config_ios.json @@ -0,0 +1 @@ +{} diff --git a/testing/variations/fieldtrial_testing_config_linux.json b/testing/variations/fieldtrial_testing_config_linux.json new file mode 100644 index 0000000000000..0967ef424bce6 --- /dev/null +++ b/testing/variations/fieldtrial_testing_config_linux.json @@ -0,0 +1 @@ +{} diff --git a/testing/variations/fieldtrial_testing_config_mac.json b/testing/variations/fieldtrial_testing_config_mac.json new file mode 100644 index 0000000000000..0967ef424bce6 --- /dev/null +++ b/testing/variations/fieldtrial_testing_config_mac.json @@ -0,0 +1 @@ +{} diff --git a/testing/variations/fieldtrial_testing_config_win.json b/testing/variations/fieldtrial_testing_config_win.json index c80a14e1e22cf..adb7a4076694b 100644 --- a/testing/variations/fieldtrial_testing_config_win.json +++ b/testing/variations/fieldtrial_testing_config_win.json @@ -4,11 +4,6 @@ "group_name": "Enabled" } ], - "CTRequiredForEVTrial": [ - { - "group_name": "RequirementEnforced" - } - ], "ChildAccountDetection": [ { "group_name": "Disabled" @@ -19,6 +14,11 @@ "group_name": "Default" } ], + "EnableSessionCrashedBubbleUI": [ + { + "group_name": "Enabled" + } + ], "ExtensionContentVerification": [ { "group_name": "Enforce" @@ -54,21 +54,6 @@ "group_name": "Enabled" } ], - "SHA1IdentityUIWarning": [ - { - "group_name": "Enabled" - } - ], - "SHA1ToolbarUIJanuary2016": [ - { - "group_name": "Warning" - } - ], - "SHA1ToolbarUIJanuary2017": [ - { - "group_name": "Error" - } - ], "SRTPromptFieldTrial": [ { "group_name": "Default" @@ -78,20 +63,5 @@ { "group_name": "enforce_always_with_extensions_and_dse" } - ], - "ShowAppLauncherPromo": [ - { - "group_name": "ShowPromoUntilDismissed" - } - ], - "UwSInterstitialStatus": [ - { - "group_name": "On" - } - ], - "VoiceTrigger": [ - { - "group_name": "Install" - } ] } diff --git a/testing/xvfb.py b/testing/xvfb.py index e7280f4d314a1..67ef729fb7753 100755 --- a/testing/xvfb.py +++ b/testing/xvfb.py @@ -3,11 +3,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Runs the test with xvfb on linux. Runs the test normally on other platforms. - -For simplicity in gyp targets, this script just runs the test normal on -non-linux platforms. -""" +"""Runs tests with Xvfb and Openbox on Linux and normally on other platforms.""" import os import platform @@ -18,120 +14,101 @@ import test_env -def kill(pid): - """Kills a process and traps exception if the process doesn't exist anymore. - """ - # If the process doesn't exist, it raises an exception that we can ignore. +def kill(proc): + """Kills |proc| and ignores exceptions thrown for non-existent processes.""" try: - os.kill(pid, signal.SIGKILL) + if proc and proc.pid: + os.kill(proc.pid, signal.SIGKILL) except OSError: pass -def get_xvfb_path(server_dir): - """Figures out which X server to use.""" - xvfb_path = os.path.join(server_dir, 'Xvfb.' + platform.architecture()[0]) - if not os.path.exists(xvfb_path): - xvfb_path = os.path.join(server_dir, 'Xvfb') - if not os.path.exists(xvfb_path): - print >> sys.stderr, ( - 'No Xvfb found in designated server path: %s' % server_dir) - raise Exception('No virtual server') - return xvfb_path - - -def start_xvfb(xvfb_path, display): - """Starts a virtual X server that we run the tests in. - - This makes it so we can run the tests even if we didn't start the tests from - an X session. - - Args: - xvfb_path: Path to Xvfb. - """ - cmd = [xvfb_path, display, '-screen', '0', '1024x768x24', '-ac', - '-nolisten', 'tcp', '-dpi', '96'] - try: - proc = subprocess.Popen( - cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - except OSError: - print >> sys.stderr, 'Failed to run %s' % ' '.join(cmd) - return - return proc - - def wait_for_xvfb(xdisplaycheck, env): """Waits for xvfb to be fully initialized by using xdisplaycheck.""" try: - _logs = subprocess.check_output( - [xdisplaycheck], - stderr=subprocess.STDOUT, - env=env) + subprocess.check_output([xdisplaycheck], stderr=subprocess.STDOUT, env=env) except OSError: print >> sys.stderr, 'Failed to load %s with cwd=%s' % ( xdisplaycheck, os.getcwd()) return False except subprocess.CalledProcessError as e: - print >> sys.stderr, ( - 'Xvfb failed to load properly (code %d) according to %s' % - (e.returncode, xdisplaycheck)) + print >> sys.stderr, ('Xvfb failed to load (code %d) according to %s' % + (e.returncode, xdisplaycheck)) return False return True -def run_executable(cmd, build_dir, env): - """Runs an executable within a xvfb buffer on linux or normally on other - platforms. +def should_start_xvfb(env): + """Xvfb is only used on Linux and shouldn't be invoked recursively.""" + return sys.platform == 'linux2' and env.get('_CHROMIUM_INSIDE_XVFB') != '1' + - Requires that both xvfb and openbox are installed on linux. +def start_xvfb(env, build_dir, xvfb_path='Xvfb', display=':9'): + """Start a virtual X server that can run tests without an existing X session. - Detects recursion with an environment variable and do not create a recursive X - buffer if present. + Returns the Xvfb and Openbox process Popen objects, or None on failure. + The |env| dictionary is modified to set the DISPLAY and prevent re-entry. + + Args: + env: The os.environ dictionary [copy] to check for re-entry. + build_dir: The path of the build directory, used for xdisplaycheck. + xvfb_path: The path to Xvfb. + display: The X display number to use. """ - # First look if we are inside a display. - if env.get('_CHROMIUM_INSIDE_XVFB') == '1': - # No need to recurse. - return test_env.run_executable(cmd, env) + assert should_start_xvfb(env) + assert env.get('_CHROMIUM_INSIDE_XVFB') != '1' + env['_CHROMIUM_INSIDE_XVFB'] = '1' + env['DISPLAY'] = display + xvfb_proc = None + openbox_proc = None - pid = None - xvfb = 'Xvfb' try: - if sys.platform == 'linux2': - # Defaults to X display 9. - display = ':9' - xvfb_proc = start_xvfb(xvfb, display) - if not xvfb_proc or not xvfb_proc.pid: - return 1 - env['DISPLAY'] = display - if not wait_for_xvfb(os.path.join(build_dir, 'xdisplaycheck'), env): - rc = xvfb_proc.poll() - if rc is None: - print 'Xvfb still running, stopping.' - xvfb_proc.terminate() - else: - print 'Xvfb exited, code %d' % rc - - print 'Xvfb output:' - for l in xvfb_proc.communicate()[0].splitlines(): - print '> %s' % l - - return 3 - # Inhibit recursion. - env['_CHROMIUM_INSIDE_XVFB'] = '1' - # Some ChromeOS tests need a window manager. Technically, it could be - # another script but that would be overkill. - try: - wm_cmd = ['openbox'] - subprocess.Popen( - wm_cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=env) - except OSError: - print >> sys.stderr, 'Failed to run %s' % ' '.join(wm_cmd) - return 1 + xvfb_cmd = [xvfb_path, display, '-screen', '0', '1024x768x24', '-ac', + '-nolisten', 'tcp', '-dpi', '96'] + xvfb_proc = subprocess.Popen(xvfb_cmd, stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + + if not wait_for_xvfb(os.path.join(build_dir, 'xdisplaycheck'), env): + rc = xvfb_proc.poll() + if rc is None: + print 'Xvfb still running after xdisplaycheck failure, stopping.' + kill(xvfb_proc) + else: + print 'Xvfb exited (code %d) after xdisplaycheck failure.' % rc + print 'Xvfb output:' + for l in xvfb_proc.communicate()[0].splitlines(): + print '> %s' % l + return (None, None) + + # Some ChromeOS tests need a window manager. + openbox_proc = subprocess.Popen('openbox', stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, env=env) + except OSError as e: + print >> sys.stderr, 'Failed to start Xvfb or Openbox: %s' % str(e) + kill(xvfb_proc) + kill(openbox_proc) + return (None, None) + + return (xvfb_proc, openbox_proc) + + +def run_executable(cmd, build_dir, env): + """Runs an executable within Xvfb on Linux or normally on other platforms. + + Returns the exit code of the specified commandline, or 1 on failure. + """ + xvfb = None + openbox = None + if should_start_xvfb(env): + (xvfb, openbox) = start_xvfb(env, build_dir) + if not xvfb or not xvfb.pid or not openbox or not openbox.pid: + return 1 + try: return test_env.run_executable(cmd, env) finally: - if pid: - kill(pid) + kill(xvfb) + kill(openbox) def main(): diff --git a/third_party/android_platform/BUILD.gn b/third_party/android_platform/BUILD.gn new file mode 100644 index 0000000000000..6cc665107429f --- /dev/null +++ b/third_party/android_platform/BUILD.gn @@ -0,0 +1,31 @@ +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("config.gni") + +gypi_values = exec_script("//build/gypi_to_gn.py", + [ rebase_path("relocation_packer.gyp") ], + "scope", + [ "relocation_packer.gyp" ]) + +if (current_toolchain == host_toolchain) { + # GYP: //third_party/android_platform/relocation_packer.gyp:android_lib_relocation_packer + source_set("android_lib_relocation_packer") { + deps = [ + "//third_party/elfutils:libelf", + ] + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + sources = gypi_values.relocation_packer_sources + } + + # GYP: //third_party/android_platform/relocation_packer.gyp:android_relocation_packer + executable("android_relocation_packer") { + deps = [ + ":android_lib_relocation_packer", + "//third_party/elfutils:libelf", + ] + sources = gypi_values.relocation_packer_main_source + } +} diff --git a/third_party/android_platform/README.chromium b/third_party/android_platform/README.chromium index c34702ff6cce5..854a36b583258 100644 --- a/third_party/android_platform/README.chromium +++ b/third_party/android_platform/README.chromium @@ -11,14 +11,43 @@ Security Critical: no Description: Android Platform engineering tools, specifically stack symbolization scripts and a jar containing the AOSP framework to compile the Android WebView -glue layer against. The sources used to build the AOSP framework jar can be -checked out using repo on the corresponding manifest file. +glue layer against. The AOSP framework is built from the Android release tag +after which it is named, and the jar can be built by invoking make on the +android_system_stubs target. + +Also includes a ported copy of the Android relocation packing tool source, +along with the files required to build it in the chromium tree. Local Modifications: Only picked the few scripts needed by chrome. + +The scripts have been modified to better suit Chromium development. Changes +include, but are not limited to, the following: +Added memoization of addr2line and objdump. +Added option to change the amount of symbolization done. Updated output directories to use environment variable. -When calling addr2line, check the symbol is a file (and not a directory). +When calling addr2line, check the symbol is a file that looks like it contains + symbols. Added support for parsing LOG(FATAL) and DCHECK errors and their stack traces, as emitted by src/base/debug/stack_trace_android.cc Added support for finding symbols when library is loaded directly from the APK. Changed the toolchain to remove references to 4.6 toolchains. +Added support for arch=x64 as an alias to arch=x86_64 +Added debug logging and --verbose parameter. + +Android relocation packing tool details: + Copy sources from AOSP bionic/tools/relocation_packer + Remove scripts that regenerate golden test data (not relevant here) + Create a nativehelper/ScopedFd.h to satisfy inclusion from main.cc + Create gyp build + Create gn build (currently packer only; no unit tests) + List of bionic changes currently included: + Refresh: https://android-review.googlesource.com/#/c/143878/ + Refresh: https://android-review.googlesource.com/#/c/147620/ + https://android-review.googlesource.com/#/c/147745/ + https://android-review.googlesource.com/#/c/148073/ + Refresh: https://android-review.googlesource.com/#/c/151901/ + https://android-review.googlesource.com/#/c/149300/ + https://android-review.googlesource.com/#/c/148822/ + https://android-review.googlesource.com/#/c/148492/ + https://android-review.googlesource.com/#/c/148175/ diff --git a/third_party/android_platform/bionic/tools/relocation_packer/Android.mk b/third_party/android_platform/bionic/tools/relocation_packer/Android.mk new file mode 100644 index 0000000000000..94c946cda4f65 --- /dev/null +++ b/third_party/android_platform/bionic/tools/relocation_packer/Android.mk @@ -0,0 +1,103 @@ +# +# Copyright (C) 2015 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +common_cppflags := -Wall -Wextra -Wunused -Werror -Wold-style-cast + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_CPP_EXTENSION := .cc + +LOCAL_SRC_FILES := \ + src/debug.cc \ + src/delta_encoder.cc \ + src/elf_file.cc \ + src/packer.cc \ + src/sleb128.cc \ + +LOCAL_STATIC_LIBRARIES := libelf +LOCAL_C_INCLUDES := external/elfutils/src/libelf +LOCAL_MODULE := lib_relocation_packer + +LOCAL_CPPFLAGS := $(common_cppflags) + +LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk + +include $(BUILD_HOST_STATIC_LIBRARY) + +include $(CLEAR_VARS) + +LOCAL_CPP_EXTENSION := .cc + +LOCAL_SRC_FILES := src/main.cc +LOCAL_STATIC_LIBRARIES := lib_relocation_packer libelf + +# Statically linking libc++ to make it work from prebuilts +LOCAL_CXX_STL := libc++_static +LOCAL_C_INCLUDES := external/elfutils/src/libelf libnativehelper/include + +LOCAL_MODULE := relocation_packer + +LOCAL_CPPFLAGS := $(common_cppflags) + +LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk + +include $(BUILD_HOST_EXECUTABLE) + +include $(CLEAR_VARS) + +LOCAL_CPP_EXTENSION := .cc + +LOCAL_SRC_FILES := \ + src/debug_unittest.cc \ + src/delta_encoder_unittest.cc \ + src/elf_file_unittest.cc \ + src/sleb128_unittest.cc \ + src/packer_unittest.cc \ + +LOCAL_STATIC_LIBRARIES := lib_relocation_packer libelf +LOCAL_C_INCLUDES := external/elfutils/src/libelf + +LOCAL_CPPFLAGS := $(common_cppflags) + +LOCAL_MODULE := relocation_packer_unit_tests +LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk + +include $(BUILD_HOST_NATIVE_TEST) + +# $(1) library name +define copy-test-library +include $(CLEAR_VARS) +LOCAL_IS_HOST_MODULE := true +LOCAL_MODULE := $(1) +LOCAL_MODULE_CLASS := SHARED_LIBRARIES +LOCAL_MODULE_PATH := $(HOST_OUT_EXECUTABLES) +LOCAL_STRIP_MODULE := false +LOCAL_SRC_FILES := test_data/$(1) +include $(BUILD_PREBUILT) +endef + +$(eval $(call copy-test-library,elf_file_unittest_relocs_arm32.so)) +$(eval $(call copy-test-library,elf_file_unittest_relocs_arm32_packed.so)) +$(eval $(call copy-test-library,elf_file_unittest_relocs_arm64.so)) +$(eval $(call copy-test-library,elf_file_unittest_relocs_arm64_packed.so)) +$(eval $(call copy-test-library,elf_file_unittest_relocs_ia32.so)) +$(eval $(call copy-test-library,elf_file_unittest_relocs_ia32_packed.so)) +$(eval $(call copy-test-library,elf_file_unittest_relocs_x64.so)) +$(eval $(call copy-test-library,elf_file_unittest_relocs_x64_packed.so)) +$(eval $(call copy-test-library,elf_file_unittest_relocs_mips32.so)) +$(eval $(call copy-test-library,elf_file_unittest_relocs_mips32_packed.so)) diff --git a/third_party/android_platform/bionic/tools/relocation_packer/LICENSE b/third_party/android_platform/bionic/tools/relocation_packer/LICENSE new file mode 100644 index 0000000000000..972bb2edb099e --- /dev/null +++ b/third_party/android_platform/bionic/tools/relocation_packer/LICENSE @@ -0,0 +1,27 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/third_party/android_platform/bionic/tools/relocation_packer/src/DEPS b/third_party/android_platform/bionic/tools/relocation_packer/src/DEPS new file mode 100644 index 0000000000000..61d0fe46d0c79 --- /dev/null +++ b/third_party/android_platform/bionic/tools/relocation_packer/src/DEPS @@ -0,0 +1,5 @@ +include_rules = [ + '+gtest', + '+nativehelper', + '+testing', +] diff --git a/third_party/android_platform/bionic/tools/relocation_packer/src/debug.cc b/third_party/android_platform/bionic/tools/relocation_packer/src/debug.cc new file mode 100644 index 0000000000000..29d7ab0674454 --- /dev/null +++ b/third_party/android_platform/bionic/tools/relocation_packer/src/debug.cc @@ -0,0 +1,55 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "debug.h" + +#include +#include +#include + +namespace relocation_packer { + +// Construct a new message logger. Prints if level is less than or equal to +// the level set with SetVerbose() and predicate is true. +Logger::Logger(Severity severity, int level, bool predicate) { + severity_ = severity; + level_ = level; + predicate_ = predicate; +} + +// On destruction, flush and print the strings accumulated. Abort if FATAL. +Logger::~Logger() { + if (predicate_) { + if (level_ <= max_level_) { + std::ostream* log = severity_ == INFO ? info_stream_ : error_stream_; + std::string tag; + switch (severity_) { + case INFO: tag = "INFO"; break; + case WARNING: tag = "WARNING"; break; + case ERROR: tag = "ERROR"; break; + case FATAL: tag = "FATAL"; break; + } + stream_.flush(); + *log << tag << ": " << stream_.str() << std::endl; + } + if (severity_ == FATAL) + abort(); + } +} + +// Reset to initial state. +void Logger::Reset() { + max_level_ = -1; + info_stream_ = &std::cout; + error_stream_ = &std::cerr; +} + +// Verbosity. Not thread-safe. +int Logger::max_level_ = -1; + +// Logging streams. Not thread-safe. +std::ostream* Logger::info_stream_ = &std::cout; +std::ostream* Logger::error_stream_ = &std::cerr; + +} // namespace relocation_packer diff --git a/third_party/android_platform/bionic/tools/relocation_packer/src/debug.h b/third_party/android_platform/bionic/tools/relocation_packer/src/debug.h new file mode 100644 index 0000000000000..48be6c19b02b9 --- /dev/null +++ b/third_party/android_platform/bionic/tools/relocation_packer/src/debug.h @@ -0,0 +1,115 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Logging and checks. Avoids a dependency on base. +// +// LOG(tag) prints messages. Tags are INFO, WARNING, ERROR and FATAL. +// INFO prints to stdout, the others to stderr. FATAL aborts after printing. +// +// LOG_IF(tag, predicate) logs if predicate evaluates to true, else silent. +// +// VLOG(level) logs INFO messages where level is less than or equal to the +// verbosity level set with SetVerbose(). +// +// VLOG_IF(level, predicate) logs INFO if predicate evaluates to true, +// else silent. +// +// CHECK(predicate) logs a FATAL error if predicate is false. +// NOTREACHED() always aborts. +// Log streams can be changed with SetStreams(). Logging is not thread-safe. +// + +#ifndef TOOLS_RELOCATION_PACKER_SRC_DEBUG_H_ +#define TOOLS_RELOCATION_PACKER_SRC_DEBUG_H_ + +#include +#include +#include + +namespace relocation_packer { + +class Logger { + public: + enum Severity {INFO = 0, WARNING, ERROR, FATAL}; + + // Construct a new message logger. Prints if level is less than or + // equal to the level set with SetVerbose() and predicate is true. + // |severity| is an enumerated severity. + // |level| is the verbosity level. + // |predicate| controls if the logger prints or is silent. + Logger(Severity severity, int level, bool predicate); + + // On destruction, flush and print the strings accumulated in stream_. + ~Logger(); + + // Return the stream for this logger. + std::ostream& GetStream() { return stream_; } + + // Set verbosity level. Messages with a level less than or equal to + // this level are printed, others are discarded. Static, not thread-safe. + static void SetVerbose(int level) { max_level_ = level; } + + // Set info and error logging streams. Static, not thread-safe. + static void SetStreams(std::ostream* info_stream, + std::ostream* error_stream) { + info_stream_ = info_stream; + error_stream_ = error_stream; + } + + // Reset to initial state. + static void Reset(); + + private: + // Message severity, verbosity level, and predicate. + Severity severity_; + int level_; + bool predicate_; + + // String stream, accumulates message text. + std::ostringstream stream_; + + // Verbosity for INFO messages. Not thread-safe. + static int max_level_; + + // Logging streams. Not thread-safe. + static std::ostream* info_stream_; + static std::ostream* error_stream_; +}; + +} // namespace relocation_packer + +// Make logging severities visible globally. +typedef relocation_packer::Logger::Severity LogSeverity; +using LogSeverity::INFO; +using LogSeverity::WARNING; +using LogSeverity::ERROR; +using LogSeverity::FATAL; + +// LOG(severity) prints a message with the given severity, and aborts if +// severity is FATAL. LOG_IF(severity, predicate) does the same but only if +// predicate is true. INT_MIN is guaranteed to be less than or equal to +// any verbosity level. +#define LOG(severity) \ + (relocation_packer::Logger(severity, INT_MIN, true).GetStream()) +#define LOG_IF(severity, predicate) \ + (relocation_packer::Logger(severity, INT_MIN, (predicate)).GetStream()) + +// VLOG(level) prints its message as INFO if level is less than or equal to +// the current verbosity level. +#define VLOG(level) \ + (relocation_packer::Logger(INFO, (level), true).GetStream()) +#define VLOG_IF(level, predicate) \ + (relocation_packer::Logger(INFO, (level), (predicate)).GetStream()) + +// CHECK(predicate) fails with a FATAL log message if predicate is false. +#define CHECK(predicate) (LOG_IF(FATAL, !(predicate)) \ + << __FILE__ << ":" << __LINE__ << ": " \ + << __FUNCTION__ << ": CHECK '" #predicate "' failed") + +// NOTREACHED() always fails with a FATAL log message. +#define NOTREACHED(_) (LOG(FATAL) \ + << __FILE__ << ":" << __LINE__ << ": " \ + << __FUNCTION__ << ": NOTREACHED() hit") + +#endif // TOOLS_RELOCATION_PACKER_SRC_DEBUG_H_ diff --git a/third_party/android_platform/bionic/tools/relocation_packer/src/debug_unittest.cc b/third_party/android_platform/bionic/tools/relocation_packer/src/debug_unittest.cc new file mode 100644 index 0000000000000..b31e2ae7eeb0f --- /dev/null +++ b/third_party/android_platform/bionic/tools/relocation_packer/src/debug_unittest.cc @@ -0,0 +1,122 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "debug.h" + +#include +#include "gtest/gtest.h" + +namespace relocation_packer { + +TEST(Debug, Log) { + Logger::Reset(); + std::ostringstream info; + std::ostringstream error; + Logger::SetStreams(&info, &error); + + LOG(INFO) << "INFO log message"; + LOG(WARNING) << "WARNING log message"; + LOG(ERROR) << "ERROR log message"; + + EXPECT_EQ("INFO: INFO log message\n", info.str()); + EXPECT_EQ("WARNING: WARNING log message\n" + "ERROR: ERROR log message\n", error.str()); + Logger::Reset(); +} + +TEST(Debug, LogIf) { + Logger::Reset(); + std::ostringstream info; + std::ostringstream error; + Logger::SetStreams(&info, &error); + + LOG_IF(INFO, true) << "INFO log message"; + LOG_IF(INFO, false) << "INFO log message, SHOULD NOT PRINT"; + LOG_IF(WARNING, true) << "WARNING log message"; + LOG_IF(WARNING, false) << "WARNING log message, SHOULD NOT PRINT"; + LOG_IF(ERROR, true) << "ERROR log message"; + LOG_IF(ERROR, false) << "ERROR log message, SHOULD NOT PRINT"; + LOG_IF(FATAL, false) << "FATAL log message, SHOULD NOT PRINT"; + + EXPECT_EQ("INFO: INFO log message\n", info.str()); + EXPECT_EQ("WARNING: WARNING log message\n" + "ERROR: ERROR log message\n", error.str()); + Logger::Reset(); +} + +TEST(Debug, Vlog) { + Logger::Reset(); + std::ostringstream info; + std::ostringstream error; + Logger::SetStreams(&info, &error); + + VLOG(0) << "VLOG 0 INFO log message, SHOULD NOT PRINT"; + VLOG(1) << "VLOG 1 INFO log message, SHOULD NOT PRINT"; + VLOG(2) << "VLOG 2 INFO log message, SHOULD NOT PRINT"; + + EXPECT_EQ("", info.str()); + EXPECT_EQ("", error.str()); + + Logger::SetVerbose(1); + + VLOG(0) << "VLOG 0 INFO log message"; + VLOG(1) << "VLOG 1 INFO log message"; + VLOG(2) << "VLOG 2 INFO log message, SHOULD NOT PRINT"; + + EXPECT_EQ("INFO: VLOG 0 INFO log message\n" + "INFO: VLOG 1 INFO log message\n", info.str()); + EXPECT_EQ("", error.str()); + Logger::Reset(); +} + +TEST(Debug, VlogIf) { + Logger::Reset(); + std::ostringstream info; + std::ostringstream error; + Logger::SetStreams(&info, &error); + + VLOG_IF(0, true) << "VLOG 0 INFO log message, SHOULD NOT PRINT"; + VLOG_IF(1, true) << "VLOG 1 INFO log message, SHOULD NOT PRINT"; + VLOG_IF(2, true) << "VLOG 2 INFO log message, SHOULD NOT PRINT"; + + EXPECT_EQ("", info.str()); + EXPECT_EQ("", error.str()); + + Logger::SetVerbose(1); + + VLOG_IF(0, true) << "VLOG 0 INFO log message"; + VLOG_IF(0, false) << "VLOG 0 INFO log message, SHOULD NOT PRINT"; + VLOG_IF(1, true) << "VLOG 1 INFO log message"; + VLOG_IF(1, false) << "VLOG 1 INFO log message, SHOULD NOT PRINT"; + VLOG_IF(2, true) << "VLOG 2 INFO log message, SHOULD NOT PRINT"; + VLOG_IF(2, false) << "VLOG 2 INFO log message, SHOULD NOT PRINT"; + + EXPECT_EQ("INFO: VLOG 0 INFO log message\n" + "INFO: VLOG 1 INFO log message\n", info.str()); + EXPECT_EQ("", error.str()); + Logger::Reset(); +} + +TEST(DebugDeathTest, Fatal) { + ::testing::FLAGS_gtest_death_test_style = "threadsafe"; + Logger::Reset(); + EXPECT_DEATH(LOG(FATAL) << "FATAL log message", "FATAL: FATAL log message"); + EXPECT_DEATH( + LOG_IF(FATAL, true) << "FATAL log message", "FATAL: FATAL log message"); +} + +TEST(DebugDeathTest, Check) { + ::testing::FLAGS_gtest_death_test_style = "threadsafe"; + Logger::Reset(); + CHECK(0 == 0); + EXPECT_DEATH(CHECK(0 == 1), "FATAL: .*:.*: .*: CHECK '0 == 1' failed"); +} + +TEST(DebugDeathTest, NotReached) { + ::testing::FLAGS_gtest_death_test_style = "threadsafe"; + Logger::Reset(); + EXPECT_DEATH(NOTREACHED(), "FATAL: .*:.*: .*: NOTREACHED\\(\\) hit"); +} + +} // namespace relocation_packer diff --git a/third_party/android_platform/bionic/tools/relocation_packer/src/delta_encoder.cc b/third_party/android_platform/bionic/tools/relocation_packer/src/delta_encoder.cc new file mode 100644 index 0000000000000..8349d7c64e552 --- /dev/null +++ b/third_party/android_platform/bionic/tools/relocation_packer/src/delta_encoder.cc @@ -0,0 +1,307 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "delta_encoder.h" + +#include + +#include "debug.h" + +static constexpr uint32_t RELOCATION_GROUPED_BY_INFO_FLAG = 1; +static constexpr uint32_t RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG = 2; +static constexpr uint32_t RELOCATION_GROUPED_BY_ADDEND_FLAG = 4; +static constexpr uint32_t RELOCATION_GROUP_HAS_ADDEND_FLAG = 8; + +static bool is_relocation_grouped_by_info(uint64_t flags) { + return (flags & RELOCATION_GROUPED_BY_INFO_FLAG) != 0; +} + +static bool is_relocation_grouped_by_offset_delta(uint64_t flags) { + return (flags & RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG) != 0; +} + +static bool is_relocation_grouped_by_addend(uint64_t flags) { + return (flags & RELOCATION_GROUPED_BY_ADDEND_FLAG) != 0; +} + +static bool is_relocation_group_has_addend(uint64_t flags) { + return (flags & RELOCATION_GROUP_HAS_ADDEND_FLAG) != 0; +} + +namespace relocation_packer { + +// Encode relocations into a delta encoded (packed) representation. +template +void RelocationDeltaCodec::Encode(const std::vector& relocations, + std::vector* packed) { + if (relocations.size() == 0) + return; + + // Start with the relocation count, then append groups + // TODO(dimitry): we might want to move it to DT_ANDROID_RELCOUNT section + packed->push_back(static_cast(relocations.size())); + + // lets write starting offset (offset of the first reloc - first delta) + ElfAddr start_offset = relocations.size() > 1 ? + relocations[0].r_offset - (relocations[1].r_offset - relocations[0].r_offset) : + relocations[0].r_offset; + + packed->push_back(start_offset); + + // this one is used to calculate delta + ElfAddr previous_addend = 0; + ElfAddr previous_offset = start_offset; + + for (size_t group_start = 0; group_start < relocations.size(); ) { + ElfAddr group_flags = 0; + ElfAddr group_offset_delta = 0; + ElfAddr group_addend = 0; + ElfAddr group_info = 0; + + ElfAddr group_size = 0; + + DetectGroup(relocations, group_start, previous_offset, &group_size, &group_flags, + &group_offset_delta, &group_info, &group_addend); + + // write the group header + packed->push_back(group_size); + packed->push_back(group_flags); + + if (is_relocation_grouped_by_offset_delta(group_flags)) { + packed->push_back(group_offset_delta); + } + + if (is_relocation_grouped_by_info(group_flags)) { + packed->push_back(group_info); + } + + if (is_relocation_group_has_addend(group_flags) && + is_relocation_grouped_by_addend(group_flags)) { + packed->push_back(group_addend - previous_addend); + previous_addend = group_addend; + } + + for (size_t i = 0; i < static_cast(group_size); ++i) { + CHECK((group_start + i) < relocations.size()); + const ElfRela* relocation = &relocations[group_start + i]; + + if (!is_relocation_grouped_by_offset_delta(group_flags)) { + packed->push_back(relocation->r_offset - previous_offset); + } + previous_offset = relocation->r_offset; + + if (!is_relocation_grouped_by_info(group_flags)) { + packed->push_back(relocation->r_info); + } + + if (is_relocation_group_has_addend(group_flags) && + !is_relocation_grouped_by_addend(group_flags)) { + packed->push_back(relocation->r_addend - previous_addend); + previous_addend = relocation->r_addend; + } + } + + // If the relocation group does not have an addend - reset it to 0 + // to simplify addend computation for the group following this one. + if (!is_relocation_group_has_addend(group_flags)) { + previous_addend = 0; + } + + group_start += group_size; + } +} + +// Decode relocations from a delta encoded (packed) representation. +template +void RelocationDeltaCodec::Decode(const std::vector& packed, + std::vector* relocations) { + if (packed.size() < 5) { + return; + } + + size_t ndx = 0; + ElfAddr current_count = 0; + ElfAddr total_count = packed[ndx++]; + + ElfAddr offset = packed[ndx++]; + ElfAddr info = 0; + ElfAddr addend = 0; + + while(current_count < total_count) { + // read group + ElfAddr group_size = packed[ndx++]; + ElfAddr group_flags = packed[ndx++]; + ElfAddr group_offset_delta = 0; + + if (is_relocation_grouped_by_offset_delta(group_flags)) { + group_offset_delta = packed[ndx++]; + } + + if (is_relocation_grouped_by_info(group_flags)) { + info = packed[ndx++]; + } + + if (is_relocation_group_has_addend(group_flags) && + is_relocation_grouped_by_addend(group_flags)) { + addend += packed[ndx++]; + } + + // now read not grouped info + for (ElfAddr i = 0; ipush_back(reloc); + } + + if (!is_relocation_group_has_addend(group_flags)) { + addend = 0; + } + + current_count += group_size; + } +} + +// This function detects a way to group reloc_one and reloc_two, sets up group_flags +// and initializes values for corresponding group_ fields. For example if relocations +// can be grouped by r_info the function will set group_info variable. +template +void RelocationDeltaCodec::DetectGroupFields(const ElfRela& reloc_one, + const ElfRela& reloc_two, + ElfAddr current_offset_delta, + ElfAddr* group_flags, + ElfAddr* group_offset_delta, + ElfAddr* group_info, + ElfAddr* group_addend) { + *group_flags = 0; + + const ElfAddr offset_delta = static_cast(reloc_two.r_offset) - + static_cast(reloc_one.r_offset); + + if (offset_delta == current_offset_delta) { + *group_flags |= RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG; + if (group_offset_delta != nullptr) { + *group_offset_delta = current_offset_delta; + } + } + + if (reloc_one.r_info == reloc_two.r_info) { + *group_flags |= RELOCATION_GROUPED_BY_INFO_FLAG; + if (group_info != nullptr) { + *group_info = reloc_one.r_info; + } + } + + if (reloc_one.r_addend != 0 || reloc_two.r_addend != 0) { + *group_flags |= RELOCATION_GROUP_HAS_ADDEND_FLAG; + if (reloc_one.r_addend == reloc_two.r_addend) { + *group_flags |= RELOCATION_GROUPED_BY_ADDEND_FLAG; + if (group_addend != nullptr) { + *group_addend = reloc_one.r_addend; + } + } + } +} + +// This function is used to detect if there is better group available +// during RelocationDeltaCodec::DetectGroup processing. +// Current implementation prefers having groups without addend (== zero addend) +// to any other groups field with the ratio 3:1. This is because addend tends +// to be more unevenly distributed than other fields. +static uint32_t group_weight(uint64_t flags) { + uint32_t weight = 0; + if (!is_relocation_group_has_addend(flags)) { + weight += 3; + } else if (is_relocation_grouped_by_addend(flags)) { + weight += 1; + } + + if (is_relocation_grouped_by_offset_delta(flags)) { + weight += 1; + } + + if (is_relocation_grouped_by_info(flags)) { + weight += 1; + } + + return weight; +} + +template +void RelocationDeltaCodec::DetectGroup(const std::vector& relocations, + size_t group_starts_with, ElfAddr previous_offset, + ElfAddr* group_size, ElfAddr* group_flags, + ElfAddr* group_offset_delta, ElfAddr* group_info, + ElfAddr* group_addend) { + CHECK(group_starts_with < relocations.size()); + CHECK(group_flags != nullptr); + + const ElfRela& reloc_one = relocations[group_starts_with++]; + if (group_starts_with == relocations.size()) { + *group_flags = reloc_one.r_addend == 0 ? 0 : RELOCATION_GROUP_HAS_ADDEND_FLAG; + *group_size = 1; + return; + } + + const ElfAddr offset_delta = reloc_one.r_offset - previous_offset; + + // detect group_flags + DetectGroupFields(reloc_one, relocations[group_starts_with], offset_delta, group_flags, + group_offset_delta, group_info, group_addend); + + if (group_starts_with + 1 == relocations.size()) { + *group_size = 2; + return; + } + + ElfAddr cnt = 1; + for (size_t i = group_starts_with; i < relocations.size() - 1; ++i) { + ElfAddr candidate_flags; + // check if next group (reloc_current; reloc_next) has better grouped_by flags + DetectGroupFields(relocations[i], relocations[i+1], offset_delta, &candidate_flags, + nullptr, nullptr, nullptr); + + if (group_weight(*group_flags) < group_weight(candidate_flags)) { + break; + } + cnt++; + + if (candidate_flags != *group_flags) { + break; + } + + if (i + 1 == relocations.size() - 1) { // last one + cnt++; + } + } + + // if as a result of checking candidates we ended up with cnt == 1 + // reset flags to the default state + if (cnt == 1) { + *group_flags = reloc_one.r_addend == 0 ? 0 : RELOCATION_GROUP_HAS_ADDEND_FLAG; + } + + *group_size = cnt; +} + +template class RelocationDeltaCodec; +template class RelocationDeltaCodec; + +} // namespace relocation_packer diff --git a/third_party/android_platform/bionic/tools/relocation_packer/src/delta_encoder.h b/third_party/android_platform/bionic/tools/relocation_packer/src/delta_encoder.h new file mode 100644 index 0000000000000..46c324c490599 --- /dev/null +++ b/third_party/android_platform/bionic/tools/relocation_packer/src/delta_encoder.h @@ -0,0 +1,132 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Delta encode and decode REL/RELA section of elf file. +// +// The encoded data format is sequence of elements of ElfAddr type (unsigned long): +// +// [00] relocation_count - the total count of relocations +// [01] initial r_offset - this is initial r_offset for the +// relocation table. +// followed by group structures: +// [02] group +// ... +// [nn] group + +// the generalized format of the group is (! - always present ? - depends on group_flags): +// -------------- +// ! group_size +// ! group_flags +// ? group_r_offset_delta when RELOCATION_GROUPED_BY_OFFSET_DELTA flag is set +// ? group_r_info when RELOCATION_GROUPED_BY_INFO flag is set +// ? group_r_addend_group_delta when RELOCATION_GROUP_HAS_ADDEND and RELOCATION_GROUPED_BY_ADDEND +// flag is set +// +// The group description is followed by individual relocations. +// please note that there is a case when individual relocation +// section could be empty - that is if every field ends up grouped. +// +// The format for individual relocations section is: +// ? r_offset_delta - when RELOCATION_GROUPED_BY_OFFSET_DELTA is not set +// ? r_info - when RELOCATION_GROUPED_BY_INFO flag is not set +// ? r_addend_delta - RELOCATION_GROUP_HAS_ADDEND is set and RELOCATION_GROUPED_BY_ADDEND is not set +// +// For example lets pack the following relocations: +// +// Relocation section '.rela.dyn' at offset 0xbf58 contains 939 entries: +// Offset Info Type Symbol's Value Symbol's Name + Addend +// 00000000000a2178 0000000000000403 R_AARCH64_RELATIVE 177a8 +// 00000000000a2180 0000000000000403 R_AARCH64_RELATIVE 177cc +// 00000000000a2188 0000000000000403 R_AARCH64_RELATIVE 177e0 +// 00000000000a2190 0000000000000403 R_AARCH64_RELATIVE 177f4 +// 00000000000a2198 0000000000000403 R_AARCH64_RELATIVE 17804 +// 00000000000a21a0 0000000000000403 R_AARCH64_RELATIVE 17818 +// 00000000000a21a8 0000000000000403 R_AARCH64_RELATIVE 1782c +// 00000000000a21b0 0000000000000403 R_AARCH64_RELATIVE 17840 +// 00000000000a21b8 0000000000000403 R_AARCH64_RELATIVE 17854 +// 00000000000a21c0 0000000000000403 R_AARCH64_RELATIVE 17868 +// 00000000000a21c8 0000000000000403 R_AARCH64_RELATIVE 1787c +// 00000000000a21d0 0000000000000403 R_AARCH64_RELATIVE 17890 +// 00000000000a21d8 0000000000000403 R_AARCH64_RELATIVE 178a4 +// 00000000000a21e8 0000000000000403 R_AARCH64_RELATIVE 178b8 +// +// The header is going to be +// [00] 14 <- count +// [01] 0x00000000000a2170 <- initial relocation (first relocation - delta, +// the delta is 8 in this case) +// -- starting the first and only group +// [03] 14 <- group size +// [03] 0xb <- flags RELOCATION_GROUP_HAS_ADDEND | RELOCATION_GROUPED_BY_OFFSET_DELTA +// | RELOCATION_GROUPED_BY_INFO +// [04] 8 <- offset delta +// [05] 0x403 <- r_info +// -- end of group definition, starting list of r_addend deltas +// [06] 0x177a8 +// [07] 0x24 = 177cc - 177a8 +// [08] 0x14 = 177e0 - 177cc +// [09] 0x14 = 177f4 - 177e0 +// [10] 0x10 = 17804 - 177f4 +// [11] 0x14 = 17818 - 17804 +// [12] 0x14 = 1782c - 17818 +// [13] 0x14 = 17840 - 1782c +// [14] 0x14 = 17854 - 17840 +// [15] 0x14 = 17868 - 17854 +// [16] 0x14 = 1787c - 17868 +// [17] 0x14 = 17890 - 1787c +// [18] 0x14 = 178a4 - 17890 +// [19] 0x14 = 178b8 - 178a4 +// -- the end. + +// TODO (dimitry): consider using r_addend_group_delta in the way we use group offset delta, it can +// save us more bytes... + +// The input ends when sum(group_size) == relocation_count + +#ifndef TOOLS_RELOCATION_PACKER_SRC_DELTA_ENCODER_H_ +#define TOOLS_RELOCATION_PACKER_SRC_DELTA_ENCODER_H_ + +#include + +#include "elf.h" +#include "elf_traits.h" + +namespace relocation_packer { + +// A RelocationDeltaCodec packs vectors of relative relocations with +// addends into more compact forms, and unpacks them to reproduce the +// pre-packed data. +template +class RelocationDeltaCodec { + public: + typedef typename ELF::Addr ElfAddr; + typedef typename ELF::Rela ElfRela; + + // Encode relocations with addends into a more compact form. + // |relocations| is a vector of relative relocation with addend structs. + // |packed| is the vector of packed words into which relocations are packed. + static void Encode(const std::vector& relocations, + std::vector* packed); + + // Decode relative relocations with addends from their more compact form. + // |packed| is the vector of packed relocations. + // |relocations| is a vector of unpacked relative relocations. + static void Decode(const std::vector& packed, + std::vector* relocations); + + private: + static void DetectGroup(const std::vector& relocations, + size_t group_starts_with, ElfAddr previous_offset, + ElfAddr* group_size, ElfAddr* group_flags, + ElfAddr* group_offset_delta, ElfAddr* group_info, + ElfAddr* group_addend); + + static void DetectGroupFields(const ElfRela& reloc_one, const ElfRela& reloc_two, + ElfAddr current_offset_delta, ElfAddr* group_flags, + ElfAddr* group_offset_delta, ElfAddr* group_info, + ElfAddr* group_addend); +}; + +} // namespace relocation_packer + +#endif // TOOLS_RELOCATION_PACKER_SRC_DELTA_ENCODER_H_ diff --git a/third_party/android_platform/bionic/tools/relocation_packer/src/delta_encoder_unittest.cc b/third_party/android_platform/bionic/tools/relocation_packer/src/delta_encoder_unittest.cc new file mode 100644 index 0000000000000..06d9c967314f7 --- /dev/null +++ b/third_party/android_platform/bionic/tools/relocation_packer/src/delta_encoder_unittest.cc @@ -0,0 +1,223 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "delta_encoder.h" + +#include +#include "elf.h" +#include "gtest/gtest.h" + +namespace { + +template +void AddRelocation(uint32_t addr, + uint32_t info, + int32_t addend, + std::vector* relocations) { + T relocation; + relocation.r_offset = addr; + relocation.r_info = info; + relocation.r_addend = addend; + relocations->push_back(relocation); +} + +template +bool CheckRelocation(uint32_t addr, + uint32_t info, + int32_t addend, + const T& relocation) { + return relocation.r_offset == addr && + relocation.r_info == info && + relocation.r_addend == addend; +} + +} // namespace + +namespace relocation_packer { + +template +static void encode() { + std::vector relocations; + std::vector packed; + + RelocationDeltaCodec codec; + + codec.Encode(relocations, &packed); + + ASSERT_EQ(0U, packed.size()); + + // Initial relocation. + AddRelocation(0xf00d0000, 11U, 10000, &relocations); + + codec.Encode(relocations, &packed); + + // size of reloc table, size of group, flags, 3 fields, zero + EXPECT_EQ(7U, packed.size()); + // One pair present. + size_t ndx = 0; + EXPECT_EQ(1U, packed[ndx++]); + EXPECT_EQ(0xf00d0000, packed[ndx++]); + EXPECT_EQ(1U, packed[ndx++]); // group_size + EXPECT_EQ(8U, packed[ndx++]); // flags + // Delta from the neutral element is zero + EXPECT_EQ(0U, packed[ndx++]); // offset_delta + EXPECT_EQ(11U, packed[ndx++]); // info + EXPECT_EQ(10000U, packed[ndx++]); // addend_delta + + // Add a second relocation, 4 byte offset delta, 12 byte addend delta. + // same info + AddRelocation(0xf00d0004, 11U, 10012, &relocations); + + packed.clear(); + codec.Encode(relocations, &packed); + + ndx = 0; + EXPECT_EQ(8U, packed.size()); + + EXPECT_EQ(2U, packed[ndx++]); // relocs count + EXPECT_EQ(0xf00cfffc, packed[ndx++]); // initial offset + EXPECT_EQ(2U, packed[ndx++]); // group count + EXPECT_EQ(11U, packed[ndx++]); // flags + EXPECT_EQ(4U, packed[ndx++]); // group offset delta + EXPECT_EQ(11U, packed[ndx++]); // info + + EXPECT_EQ(10000U, packed[ndx++]); // addend delta + EXPECT_EQ(12U, packed[ndx++]); // addend delta + + // Add a third relocation, 4 byte offset delta, 12 byte addend delta. + // different info + AddRelocation(0xf00d0008, 41U, 10024, &relocations); + + // Add three more relocations, 8 byte offset deltas, -24 byte addend deltas. + AddRelocation(0xf00d0010, 42U, 10000, &relocations); + AddRelocation(0xf00d0018, 42U, 9976, &relocations); + AddRelocation(0xf00d0020, 42U, 9952, &relocations); + + AddRelocation(0xf00d2028, 1042U, 0, &relocations); + AddRelocation(0xf00d2030, 3442U, 0, &relocations); + + packed.clear(); + codec.Encode(relocations, &packed); + + ndx = 0; + EXPECT_EQ(26U, packed.size()); + // Total number of relocs + EXPECT_EQ(8U, packed[ndx++]); + EXPECT_EQ(0xf00cfffc, packed[ndx++]); + // 2 in first group + EXPECT_EQ(2U, packed[ndx++]); + EXPECT_EQ(11U, packed[ndx++]); //flags + EXPECT_EQ(4U, packed[ndx++]); // group offset delta + EXPECT_EQ(11U, packed[ndx++]); // info + + // Initial relocation. + EXPECT_EQ(10000U, packed[ndx++]); // addend delta + // Two relocations, 4 byte offset deltas, 12 byte addend deltas. + EXPECT_EQ(12U, packed[ndx++]); // addend delta + + // second group has only one reloc + EXPECT_EQ(1U, packed[ndx++]); // count + EXPECT_EQ(8U, packed[ndx++]); // flags + + EXPECT_EQ(4U, packed[ndx++]); // offset delta + EXPECT_EQ(41U, packed[ndx++]); // info + EXPECT_EQ(12U, packed[ndx++]); // addend delta + + // next - 3 relocs grouped by info + EXPECT_EQ(3U, packed[ndx++]); // count + EXPECT_EQ(11U, packed[ndx++]); // flags + EXPECT_EQ(8U, packed[ndx++]); // group offset delta + EXPECT_EQ(42U, packed[ndx++]); // info + // Three relocations, 8 byte offset deltas, -24 byte addend deltas. + EXPECT_EQ(static_cast(-24), packed[ndx++]); + EXPECT_EQ(static_cast(-24), packed[ndx++]); + EXPECT_EQ(static_cast(-24), packed[ndx++]); + + // and last - 2 relocations without addend + EXPECT_EQ(2U, packed[ndx++]); + EXPECT_EQ(0U, packed[ndx++]); // flags + // offset_deltas and r_infos for next 2 relocations + EXPECT_EQ(0x2008U, packed[ndx++]); // offset delta + EXPECT_EQ(1042U, packed[ndx++]); // r_info + EXPECT_EQ(0x8U, packed[ndx++]); // offset delta + EXPECT_EQ(3442U, packed[ndx++]); // r_info + + EXPECT_EQ(packed.size(), ndx); +} + +TEST(Delta, Encode32) { + encode(); +} + +TEST(Delta, Encode64) { + encode(); +} + +template +static void decode() { + std::vector packed; + std::vector relocations; + + RelocationDeltaCodec codec; + codec.Decode(packed, &relocations); + + EXPECT_EQ(0U, relocations.size()); + + // Six pairs. + packed.push_back(6U); // count + packed.push_back(0xc0ddfffc); // base offset + packed.push_back(3U); // group count + packed.push_back(11U); // flags + packed.push_back(4U); // offset delta + packed.push_back(11U); // info + // Initial relocation. + packed.push_back(10000U); + // Two relocations, 4 byte offset deltas, 12 byte addend deltas. + packed.push_back(12U); // addend + packed.push_back(12U); // addend + + // Three relocations, 8 byte offset deltas, -24 byte addend deltas. + packed.push_back(1U); // group count + packed.push_back(9U); // flags + packed.push_back(11U); // info + + packed.push_back(8U); + packed.push_back(static_cast(-24)); + // next group with 2 relocs + packed.push_back(2U); // group count + packed.push_back(11U); // flags + packed.push_back(8U); // offset + packed.push_back(42U); // info + + packed.push_back(static_cast(-24)); // addend + packed.push_back(static_cast(-24)); // addend + + relocations.clear(); + codec.Decode(packed, &relocations); + + EXPECT_EQ(6U, relocations.size()); + // Initial relocation. + EXPECT_TRUE(CheckRelocation(0xc0de0000, 11U, 10000, relocations[0])); + // Two relocations, 4 byte offset deltas, 12 byte addend deltas. + EXPECT_TRUE(CheckRelocation(0xc0de0004, 11U, 10012, relocations[1])); + EXPECT_TRUE(CheckRelocation(0xc0de0008, 11U, 10024, relocations[2])); + // Three relocations, 8 byte offset deltas, -24 byte addend deltas. + EXPECT_TRUE(CheckRelocation(0xc0de0010, 11U, 10000, relocations[3])); + EXPECT_TRUE(CheckRelocation(0xc0de0018, 42U, 9976, relocations[4])); + EXPECT_TRUE(CheckRelocation(0xc0de0020, 42U, 9952, relocations[5])); +} + +TEST(Delta, Decode32) { + decode(); +} + +TEST(Delta, Decode64) { + decode(); +} + +// TODO (dimitry): add more tests (fix by 19 January 2038 03:14:07 UTC) +// TODO (dimtiry): 1. Incorrect packed array for decode +// TODO (dimtiry): 2. Try to catch situation where it is likely to get series of groups with size 1 + +} // namespace relocation_packer diff --git a/third_party/android_platform/bionic/tools/relocation_packer/src/elf_file.cc b/third_party/android_platform/bionic/tools/relocation_packer/src/elf_file.cc new file mode 100644 index 0000000000000..4004239213a6a --- /dev/null +++ b/third_party/android_platform/bionic/tools/relocation_packer/src/elf_file.cc @@ -0,0 +1,993 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Implementation notes: +// +// We need to remove a piece from the ELF shared library. However, we also +// want to avoid fixing DWARF cfi data and relative relocation addresses. +// So after packing we shift offets and starting address of the RX segment +// while preserving code/data vaddrs location. +// This requires some fixups for symtab/hash/gnu_hash dynamic section addresses. + +#include "elf_file.h" + +#include +#include +#include +#include +#include +#include + +#include "debug.h" +#include "elf_traits.h" +#include "libelf.h" +#include "packer.h" + +namespace relocation_packer { + +// Out-of-band dynamic tags used to indicate the offset and size of the +// android packed relocations section. +static constexpr int32_t DT_ANDROID_REL = DT_LOOS + 2; +static constexpr int32_t DT_ANDROID_RELSZ = DT_LOOS + 3; + +static constexpr int32_t DT_ANDROID_RELA = DT_LOOS + 4; +static constexpr int32_t DT_ANDROID_RELASZ = DT_LOOS + 5; + +static constexpr uint32_t SHT_ANDROID_REL = SHT_LOOS + 1; +static constexpr uint32_t SHT_ANDROID_RELA = SHT_LOOS + 2; + +static const size_t kPageSize = 4096; + +// Alignment to preserve, in bytes. This must be at least as large as the +// largest d_align and sh_addralign values found in the loaded file. +// Out of caution for RELRO page alignment, we preserve to a complete target +// page. See http://www.airs.com/blog/archives/189. +static const size_t kPreserveAlignment = kPageSize; + +// Get section data. Checks that the section has exactly one data entry, +// so that the section size and the data size are the same. True in +// practice for all sections we resize when packing or unpacking. Done +// by ensuring that a call to elf_getdata(section, data) returns NULL as +// the next data entry. +static Elf_Data* GetSectionData(Elf_Scn* section) { + Elf_Data* data = elf_getdata(section, NULL); + CHECK(data && elf_getdata(section, data) == NULL); + return data; +} + +// Rewrite section data. Allocates new data and makes it the data element's +// buffer. Relies on program exit to free allocated data. +static void RewriteSectionData(Elf_Scn* section, + const void* section_data, + size_t size) { + Elf_Data* data = GetSectionData(section); + CHECK(size == data->d_size); + uint8_t* area = new uint8_t[size]; + memcpy(area, section_data, size); + data->d_buf = area; +} + +// Verbose ELF header logging. +template +static void VerboseLogElfHeader(const Ehdr* elf_header) { + VLOG(1) << "e_phoff = " << elf_header->e_phoff; + VLOG(1) << "e_shoff = " << elf_header->e_shoff; + VLOG(1) << "e_ehsize = " << elf_header->e_ehsize; + VLOG(1) << "e_phentsize = " << elf_header->e_phentsize; + VLOG(1) << "e_phnum = " << elf_header->e_phnum; + VLOG(1) << "e_shnum = " << elf_header->e_shnum; + VLOG(1) << "e_shstrndx = " << elf_header->e_shstrndx; +} + +// Verbose ELF program header logging. +template +static void VerboseLogProgramHeader(size_t program_header_index, + const Phdr* program_header) { + std::string type; + switch (program_header->p_type) { + case PT_NULL: type = "NULL"; break; + case PT_LOAD: type = "LOAD"; break; + case PT_DYNAMIC: type = "DYNAMIC"; break; + case PT_INTERP: type = "INTERP"; break; + case PT_PHDR: type = "PHDR"; break; + case PT_GNU_RELRO: type = "GNU_RELRO"; break; + case PT_GNU_STACK: type = "GNU_STACK"; break; + case PT_ARM_EXIDX: type = "EXIDX"; break; + default: type = "(OTHER)"; break; + } + VLOG(1) << "phdr[" << program_header_index << "] : " << type; + VLOG(1) << " p_offset = " << program_header->p_offset; + VLOG(1) << " p_vaddr = " << program_header->p_vaddr; + VLOG(1) << " p_paddr = " << program_header->p_paddr; + VLOG(1) << " p_filesz = " << program_header->p_filesz; + VLOG(1) << " p_memsz = " << program_header->p_memsz; + VLOG(1) << " p_flags = " << program_header->p_flags; + VLOG(1) << " p_align = " << program_header->p_align; +} + +// Verbose ELF section header logging. +template +static void VerboseLogSectionHeader(const std::string& section_name, + const Shdr* section_header) { + VLOG(1) << "section " << section_name; + VLOG(1) << " sh_addr = " << section_header->sh_addr; + VLOG(1) << " sh_offset = " << section_header->sh_offset; + VLOG(1) << " sh_size = " << section_header->sh_size; + VLOG(1) << " sh_entsize = " << section_header->sh_entsize; + VLOG(1) << " sh_addralign = " << section_header->sh_addralign; +} + +// Verbose ELF section data logging. +static void VerboseLogSectionData(const Elf_Data* data) { + VLOG(1) << " data"; + VLOG(1) << " d_buf = " << data->d_buf; + VLOG(1) << " d_off = " << data->d_off; + VLOG(1) << " d_size = " << data->d_size; + VLOG(1) << " d_align = " << data->d_align; +} + +// Load the complete ELF file into a memory image in libelf, and identify +// the .rel.dyn or .rela.dyn, .dynamic, and .android.rel.dyn or +// .android.rela.dyn sections. No-op if the ELF file has already been loaded. +template +bool ElfFile::Load() { + if (elf_) + return true; + + Elf* elf = elf_begin(fd_, ELF_C_RDWR, NULL); + CHECK(elf); + + if (elf_kind(elf) != ELF_K_ELF) { + LOG(ERROR) << "File not in ELF format"; + return false; + } + + auto elf_header = ELF::getehdr(elf); + if (!elf_header) { + LOG(ERROR) << "Failed to load ELF header: " << elf_errmsg(elf_errno()); + return false; + } + + if (elf_header->e_type != ET_DYN) { + LOG(ERROR) << "ELF file is not a shared object"; + return false; + } + + // Require that our endianness matches that of the target, and that both + // are little-endian. Safe for all current build/target combinations. + const int endian = elf_header->e_ident[EI_DATA]; + CHECK(endian == ELFDATA2LSB); + CHECK(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__); + + const int file_class = elf_header->e_ident[EI_CLASS]; + VLOG(1) << "endian = " << endian << ", file class = " << file_class; + VerboseLogElfHeader(elf_header); + + auto elf_program_header = ELF::getphdr(elf); + CHECK(elf_program_header != nullptr); + + const typename ELF::Phdr* dynamic_program_header = NULL; + for (size_t i = 0; i < elf_header->e_phnum; ++i) { + auto program_header = &elf_program_header[i]; + VerboseLogProgramHeader(i, program_header); + + if (program_header->p_type == PT_DYNAMIC) { + CHECK(dynamic_program_header == NULL); + dynamic_program_header = program_header; + } + } + CHECK(dynamic_program_header != nullptr); + + size_t string_index; + elf_getshdrstrndx(elf, &string_index); + + // Notes of the dynamic relocations, packed relocations, and .dynamic + // sections. Found while iterating sections, and later stored in class + // attributes. + Elf_Scn* found_relocations_section = nullptr; + Elf_Scn* found_dynamic_section = nullptr; + + // Notes of relocation section types seen. We require one or the other of + // these; both is unsupported. + bool has_rel_relocations = false; + bool has_rela_relocations = false; + bool has_android_relocations = false; + + Elf_Scn* section = NULL; + while ((section = elf_nextscn(elf, section)) != nullptr) { + auto section_header = ELF::getshdr(section); + std::string name = elf_strptr(elf, string_index, section_header->sh_name); + VerboseLogSectionHeader(name, section_header); + + // Note relocation section types. + if (section_header->sh_type == SHT_REL || section_header->sh_type == SHT_ANDROID_REL) { + has_rel_relocations = true; + } + if (section_header->sh_type == SHT_RELA || section_header->sh_type == SHT_ANDROID_RELA) { + has_rela_relocations = true; + } + + // Note special sections as we encounter them. + if ((name == ".rel.dyn" || name == ".rela.dyn") && + section_header->sh_size > 0) { + found_relocations_section = section; + + // Note if relocation section is already packed + has_android_relocations = + section_header->sh_type == SHT_ANDROID_REL || + section_header->sh_type == SHT_ANDROID_RELA; + } + + if (section_header->sh_offset == dynamic_program_header->p_offset) { + found_dynamic_section = section; + } + + // Ensure we preserve alignment, repeated later for the data block(s). + CHECK(section_header->sh_addralign <= kPreserveAlignment); + + Elf_Data* data = NULL; + while ((data = elf_getdata(section, data)) != NULL) { + CHECK(data->d_align <= kPreserveAlignment); + VerboseLogSectionData(data); + } + } + + // Loading failed if we did not find the required special sections. + if (!found_relocations_section) { + LOG(ERROR) << "Missing or empty .rel.dyn or .rela.dyn section"; + return false; + } + if (!found_dynamic_section) { + LOG(ERROR) << "Missing .dynamic section"; + return false; + } + + // Loading failed if we could not identify the relocations type. + if (!has_rel_relocations && !has_rela_relocations) { + LOG(ERROR) << "No relocations sections found"; + return false; + } + if (has_rel_relocations && has_rela_relocations) { + LOG(ERROR) << "Multiple relocations sections with different types found, " + << "not currently supported"; + return false; + } + + elf_ = elf; + relocations_section_ = found_relocations_section; + dynamic_section_ = found_dynamic_section; + relocations_type_ = has_rel_relocations ? REL : RELA; + has_android_relocations_ = has_android_relocations; + return true; +} + +// Helper for ResizeSection(). Adjust the main ELF header for the hole. +template +static void AdjustElfHeaderForHole(typename ELF::Ehdr* elf_header, + typename ELF::Off hole_start, + ssize_t hole_size) { + if (elf_header->e_phoff > hole_start) { + elf_header->e_phoff += hole_size; + VLOG(1) << "e_phoff adjusted to " << elf_header->e_phoff; + } + if (elf_header->e_shoff > hole_start) { + elf_header->e_shoff += hole_size; + VLOG(1) << "e_shoff adjusted to " << elf_header->e_shoff; + } +} + +// Helper for ResizeSection(). Adjust all section headers for the hole. +template +static void AdjustSectionHeadersForHole(Elf* elf, + typename ELF::Off hole_start, + ssize_t hole_size) { + size_t string_index; + elf_getshdrstrndx(elf, &string_index); + + Elf_Scn* section = NULL; + while ((section = elf_nextscn(elf, section)) != NULL) { + auto section_header = ELF::getshdr(section); + std::string name = elf_strptr(elf, string_index, section_header->sh_name); + + if (section_header->sh_offset > hole_start) { + section_header->sh_offset += hole_size; + VLOG(1) << "section " << name + << " sh_offset adjusted to " << section_header->sh_offset; + } else { + section_header->sh_addr -= hole_size; + VLOG(1) << "section " << name + << " sh_addr adjusted to " << section_header->sh_addr; + } + } +} + +// Helpers for ResizeSection(). On packing, reduce p_align for LOAD segments +// to 4kb if larger. On unpacking, restore p_align for LOAD segments if +// packing reduced it to 4kb. Return true if p_align was changed. +template +static bool ClampLoadSegmentAlignment(typename ELF::Phdr* program_header) { + CHECK(program_header->p_type == PT_LOAD); + + // If large, reduce p_align for a LOAD segment to page size on packing. + if (program_header->p_align > kPageSize) { + program_header->p_align = kPageSize; + return true; + } + return false; +} + +template +static bool RestoreLoadSegmentAlignment(typename ELF::Phdr* program_headers, + size_t count, + typename ELF::Phdr* program_header) { + CHECK(program_header->p_type == PT_LOAD); + + // If p_align was reduced on packing, restore it to its previous value + // on unpacking. We do this by searching for a different LOAD segment + // and setting p_align to that of the other LOAD segment found. + // + // Relies on the following observations: + // - a packable ELF executable has more than one LOAD segment; + // - before packing all LOAD segments have the same p_align; + // - on packing we reduce only one LOAD segment's p_align. + if (program_header->p_align == kPageSize) { + for (size_t i = 0; i < count; ++i) { + typename ELF::Phdr* other_header = &program_headers[i]; + if (other_header->p_type == PT_LOAD && other_header != program_header) { + program_header->p_align = other_header->p_align; + return true; + } + } + LOG(WARNING) << "Cannot find a LOAD segment from which to restore p_align"; + } + return false; +} + +template +static bool AdjustLoadSegmentAlignment(typename ELF::Phdr* program_headers, + size_t count, + typename ELF::Phdr* program_header, + ssize_t hole_size) { + CHECK(program_header->p_type == PT_LOAD); + + bool status = false; + if (hole_size < 0) { + status = ClampLoadSegmentAlignment(program_header); + } else if (hole_size > 0) { + status = RestoreLoadSegmentAlignment(program_headers, + count, + program_header); + } + return status; +} + +// Helper for ResizeSection(). Adjust the offsets of any program headers +// that have offsets currently beyond the hole start, and adjust the +// virtual and physical addrs (and perhaps alignment) of the others. +template +static void AdjustProgramHeaderFields(typename ELF::Phdr* program_headers, + size_t count, + typename ELF::Off hole_start, + ssize_t hole_size) { + int alignment_changes = 0; + for (size_t i = 0; i < count; ++i) { + typename ELF::Phdr* program_header = &program_headers[i]; + + // Do not adjust PT_GNU_STACK - it confuses gdb and results + // in incorrect unwinding if the executable is stripped after + // packing. + if (program_header->p_type == PT_GNU_STACK) { + continue; + } + + if (program_header->p_offset > hole_start) { + // The hole start is past this segment, so adjust offset. + program_header->p_offset += hole_size; + VLOG(1) << "phdr[" << i + << "] p_offset adjusted to "<< program_header->p_offset; + } else { + program_header->p_vaddr -= hole_size; + program_header->p_paddr -= hole_size; + + // If packing, clamp LOAD segment alignment to 4kb to prevent strip + // from adjusting it unnecessarily if run on a packed file. If + // unpacking, attempt to restore a reduced alignment to its previous + // value. Ensure that we do this on at most one LOAD segment. + if (program_header->p_type == PT_LOAD) { + alignment_changes += AdjustLoadSegmentAlignment(program_headers, + count, + program_header, + hole_size); + LOG_IF(FATAL, alignment_changes > 1) + << "Changed p_align on more than one LOAD segment"; + } + + VLOG(1) << "phdr[" << i + << "] p_vaddr adjusted to "<< program_header->p_vaddr + << "; p_paddr adjusted to "<< program_header->p_paddr + << "; p_align adjusted to "<< program_header->p_align; + } + } +} + +// Helper for ResizeSection(). Find the first loadable segment in the +// file. We expect it to map from file offset zero. +template +static typename ELF::Phdr* FindLoadSegmentForHole(typename ELF::Phdr* program_headers, + size_t count, + typename ELF::Off hole_start) { + for (size_t i = 0; i < count; ++i) { + typename ELF::Phdr* program_header = &program_headers[i]; + + if (program_header->p_type == PT_LOAD && + program_header->p_offset <= hole_start && + (program_header->p_offset + program_header->p_filesz) >= hole_start ) { + return program_header; + } + } + LOG(FATAL) << "Cannot locate a LOAD segment with hole_start=0x" << std::hex << hole_start; + NOTREACHED(); + + return nullptr; +} + +// Helper for ResizeSection(). Rewrite program headers. +template +static void RewriteProgramHeadersForHole(Elf* elf, + typename ELF::Off hole_start, + ssize_t hole_size) { + const typename ELF::Ehdr* elf_header = ELF::getehdr(elf); + CHECK(elf_header); + + typename ELF::Phdr* elf_program_header = ELF::getphdr(elf); + CHECK(elf_program_header); + + const size_t program_header_count = elf_header->e_phnum; + + // Locate the segment that we can overwrite to form the new LOAD entry, + // and the segment that we are going to split into two parts. + typename ELF::Phdr* target_load_header = + FindLoadSegmentForHole(elf_program_header, program_header_count, hole_start); + + VLOG(1) << "phdr[" << target_load_header - elf_program_header << "] adjust"; + // Adjust PT_LOAD program header memsz and filesz + target_load_header->p_filesz += hole_size; + target_load_header->p_memsz += hole_size; + + // Adjust the offsets and p_vaddrs + AdjustProgramHeaderFields(elf_program_header, + program_header_count, + hole_start, + hole_size); +} + +// Helper for ResizeSection(). Locate and return the dynamic section. +template +static Elf_Scn* GetDynamicSection(Elf* elf) { + const typename ELF::Ehdr* elf_header = ELF::getehdr(elf); + CHECK(elf_header); + + const typename ELF::Phdr* elf_program_header = ELF::getphdr(elf); + CHECK(elf_program_header); + + // Find the program header that describes the dynamic section. + const typename ELF::Phdr* dynamic_program_header = NULL; + for (size_t i = 0; i < elf_header->e_phnum; ++i) { + const typename ELF::Phdr* program_header = &elf_program_header[i]; + + if (program_header->p_type == PT_DYNAMIC) { + dynamic_program_header = program_header; + } + } + CHECK(dynamic_program_header); + + // Now find the section with the same offset as this program header. + Elf_Scn* dynamic_section = NULL; + Elf_Scn* section = NULL; + while ((section = elf_nextscn(elf, section)) != NULL) { + typename ELF::Shdr* section_header = ELF::getshdr(section); + + if (section_header->sh_offset == dynamic_program_header->p_offset) { + dynamic_section = section; + } + } + CHECK(dynamic_section != NULL); + + return dynamic_section; +} + +// Helper for ResizeSection(). Adjust the .dynamic section for the hole. +template +void ElfFile::AdjustDynamicSectionForHole(Elf_Scn* dynamic_section, + typename ELF::Off hole_start, + ssize_t hole_size, + relocations_type_t relocations_type) { + CHECK(relocations_type != NONE); + Elf_Data* data = GetSectionData(dynamic_section); + + auto dynamic_base = reinterpret_cast(data->d_buf); + std::vector dynamics( + dynamic_base, + dynamic_base + data->d_size / sizeof(dynamics[0])); + + if (hole_size > 0) { // expanding + hole_start += hole_size; + } + + for (size_t i = 0; i < dynamics.size(); ++i) { + typename ELF::Dyn* dynamic = &dynamics[i]; + const typename ELF::Sword tag = dynamic->d_tag; + + // Any tags that hold offsets are adjustment candidates. + const bool is_adjustable = (tag == DT_PLTGOT || + tag == DT_HASH || + tag == DT_GNU_HASH || + tag == DT_STRTAB || + tag == DT_SYMTAB || + tag == DT_RELA || + tag == DT_INIT || + tag == DT_FINI || + tag == DT_REL || + tag == DT_JMPREL || + tag == DT_INIT_ARRAY || + tag == DT_FINI_ARRAY || + tag == DT_VERSYM || + tag == DT_VERNEED || + tag == DT_VERDEF || + tag == DT_ANDROID_REL|| + tag == DT_ANDROID_RELA); + + if (is_adjustable && dynamic->d_un.d_ptr <= hole_start) { + dynamic->d_un.d_ptr -= hole_size; + VLOG(1) << "dynamic[" << i << "] " << dynamic->d_tag + << " d_ptr adjusted to " << dynamic->d_un.d_ptr; + } + + // DT_RELSZ or DT_RELASZ indicate the overall size of relocations. + // Only one will be present. Adjust by hole size. + if (tag == DT_RELSZ || tag == DT_RELASZ || tag == DT_ANDROID_RELSZ || tag == DT_ANDROID_RELASZ) { + dynamic->d_un.d_val += hole_size; + VLOG(1) << "dynamic[" << i << "] " << dynamic->d_tag + << " d_val adjusted to " << dynamic->d_un.d_val; + } + + // Special case: DT_MIPS_RLD_MAP2 stores the difference between dynamic + // entry address and the address of the _r_debug (used by GDB) + // since the dynamic section and target address are on the + // different sides of the hole it needs to be adjusted accordingly + if (tag == DT_MIPS_RLD_MAP2) { + dynamic->d_un.d_val += hole_size; + VLOG(1) << "dynamic[" << i << "] " << dynamic->d_tag + << " d_val adjusted to " << dynamic->d_un.d_val; + } + + // Ignore DT_RELCOUNT and DT_RELACOUNT: (1) nobody uses them and + // technically (2) the relative relocation count is not changed. + + // DT_RELENT and DT_RELAENT don't change, ignore them as well. + } + + void* section_data = &dynamics[0]; + size_t bytes = dynamics.size() * sizeof(dynamics[0]); + RewriteSectionData(dynamic_section, section_data, bytes); +} + +// Resize a section. If the new size is larger than the current size, open +// up a hole by increasing file offsets that come after the hole. If smaller +// than the current size, remove the hole by decreasing those offsets. +template +void ElfFile::ResizeSection(Elf* elf, Elf_Scn* section, size_t new_size, + typename ELF::Word new_sh_type, + relocations_type_t relocations_type) { + + size_t string_index; + elf_getshdrstrndx(elf, &string_index); + auto section_header = ELF::getshdr(section); + std::string name = elf_strptr(elf, string_index, section_header->sh_name); + + if (section_header->sh_size == new_size) { + return; + } + + // Require that the section size and the data size are the same. True + // in practice for all sections we resize when packing or unpacking. + Elf_Data* data = GetSectionData(section); + CHECK(data->d_off == 0 && data->d_size == section_header->sh_size); + + // Require that the section is not zero-length (that is, has allocated + // data that we can validly expand). + CHECK(data->d_size && data->d_buf); + + const auto hole_start = section_header->sh_offset; + const ssize_t hole_size = new_size - data->d_size; + + VLOG_IF(1, (hole_size > 0)) << "expand section (" << name << ") size: " << + data->d_size << " -> " << (data->d_size + hole_size); + VLOG_IF(1, (hole_size < 0)) << "shrink section (" << name << ") size: " << + data->d_size << " -> " << (data->d_size + hole_size); + + // libelf overrides sh_entsize for known sh_types, so it does not matter what we set + // for SHT_REL/SHT_RELA. + typename ELF::Xword new_entsize = + (new_sh_type == SHT_ANDROID_REL || new_sh_type == SHT_ANDROID_RELA) ? 1 : 0; + + VLOG(1) << "Update section (" << name << ") entry size: " << + section_header->sh_entsize << " -> " << new_entsize; + + // Resize the data and the section header. + data->d_size += hole_size; + section_header->sh_size += hole_size; + section_header->sh_entsize = new_entsize; + section_header->sh_type = new_sh_type; + + // Add the hole size to all offsets in the ELF file that are after the + // start of the hole. If the hole size is positive we are expanding the + // section to create a new hole; if negative, we are closing up a hole. + + // Start with the main ELF header. + typename ELF::Ehdr* elf_header = ELF::getehdr(elf); + AdjustElfHeaderForHole(elf_header, hole_start, hole_size); + + // Adjust all section headers. + AdjustSectionHeadersForHole(elf, hole_start, hole_size); + + // Rewrite the program headers to either split or coalesce segments, + // and adjust dynamic entries to match. + RewriteProgramHeadersForHole(elf, hole_start, hole_size); + + Elf_Scn* dynamic_section = GetDynamicSection(elf); + AdjustDynamicSectionForHole(dynamic_section, hole_start, hole_size, relocations_type); +} + +// Find the first slot in a dynamics array with the given tag. The array +// always ends with a free (unused) element, and which we exclude from the +// search. Returns dynamics->size() if not found. +template +static size_t FindDynamicEntry(typename ELF::Sword tag, + std::vector* dynamics) { + // Loop until the penultimate entry. We exclude the end sentinel. + for (size_t i = 0; i < dynamics->size() - 1; ++i) { + if (dynamics->at(i).d_tag == tag) { + return i; + } + } + + // The tag was not found. + return dynamics->size(); +} + +// Replace dynamic entry. +template +static void ReplaceDynamicEntry(typename ELF::Sword tag, + const typename ELF::Dyn& dyn, + std::vector* dynamics) { + const size_t slot = FindDynamicEntry(tag, dynamics); + if (slot == dynamics->size()) { + LOG(FATAL) << "Dynamic slot is not found for tag=" << tag; + } + + // Replace this entry with the one supplied. + dynamics->at(slot) = dyn; + VLOG(1) << "dynamic[" << slot << "] overwritten with " << dyn.d_tag; +} + +// Remove relative entries from dynamic relocations and write as packed +// data into android packed relocations. +template +bool ElfFile::PackRelocations() { + // Load the ELF file into libelf. + if (!Load()) { + LOG(ERROR) << "Failed to load as ELF"; + return false; + } + + // Retrieve the current dynamic relocations section data. + Elf_Data* data = GetSectionData(relocations_section_); + // we always pack rela, because packed format is pretty much the same + std::vector relocations; + + if (relocations_type_ == REL) { + // Convert data to a vector of relocations. + const typename ELF::Rel* relocations_base = reinterpret_cast(data->d_buf); + ConvertRelArrayToRelaVector(relocations_base, + data->d_size / sizeof(typename ELF::Rel), &relocations); + VLOG(1) << "Relocations : REL"; + } else if (relocations_type_ == RELA) { + // Convert data to a vector of relocations with addends. + const typename ELF::Rela* relocations_base = reinterpret_cast(data->d_buf); + relocations = std::vector( + relocations_base, + relocations_base + data->d_size / sizeof(relocations[0])); + + VLOG(1) << "Relocations : RELA"; + } else { + NOTREACHED(); + } + + return PackTypedRelocations(&relocations); +} + +// Helper for PackRelocations(). Rel type is one of ELF::Rel or ELF::Rela. +template +bool ElfFile::PackTypedRelocations(std::vector* relocations) { + typedef typename ELF::Rela Rela; + + if (has_android_relocations_) { + LOG(INFO) << "Relocation table is already packed"; + return true; + } + + // If no relocations then we have nothing packable. Perhaps + // the shared object has already been packed? + if (relocations->empty()) { + LOG(ERROR) << "No relocations found"; + return false; + } + + const size_t rel_size = + relocations_type_ == RELA ? sizeof(typename ELF::Rela) : sizeof(typename ELF::Rel); + const size_t initial_bytes = relocations->size() * rel_size; + + VLOG(1) << "Unpacked : " << initial_bytes << " bytes"; + std::vector packed; + RelocationPacker packer; + + // Pack relocations: dry run to estimate memory savings. + packer.PackRelocations(*relocations, &packed); + const size_t packed_bytes_estimate = packed.size() * sizeof(packed[0]); + VLOG(1) << "Packed (no padding): " << packed_bytes_estimate << " bytes"; + + if (packed.empty()) { + LOG(INFO) << "Too few relocations to pack"; + return true; + } + + // Pre-calculate the size of the hole we will close up when we rewrite + // dynamic relocations. We have to adjust relocation addresses to + // account for this. + typename ELF::Shdr* section_header = ELF::getshdr(relocations_section_); + ssize_t hole_size = initial_bytes - packed_bytes_estimate; + + // hole_size needs to be page_aligned. + hole_size -= hole_size % kPreserveAlignment; + + LOG(INFO) << "Compaction : " << hole_size << " bytes"; + + // Adjusting for alignment may have removed any packing benefit. + if (hole_size == 0) { + LOG(INFO) << "Too few relocations to pack after alignment"; + return true; + } + + if (hole_size <= 0) { + LOG(INFO) << "Packing relocations saves no space"; + return true; + } + + size_t data_padding_bytes = is_padding_relocations_ ? + initial_bytes - packed_bytes_estimate : + initial_bytes - hole_size - packed_bytes_estimate; + + // pad data + std::vector padding(data_padding_bytes, 0); + packed.insert(packed.end(), padding.begin(), padding.end()); + + const void* packed_data = &packed[0]; + + // Run a loopback self-test as a check that packing is lossless. + std::vector unpacked; + packer.UnpackRelocations(packed, &unpacked); + CHECK(unpacked.size() == relocations->size()); + CHECK(!memcmp(&unpacked[0], + &relocations->at(0), + unpacked.size() * sizeof(unpacked[0]))); + + // Rewrite the current dynamic relocations section with packed one then shrink it to size. + const size_t bytes = packed.size() * sizeof(packed[0]); + ResizeSection(elf_, relocations_section_, bytes, + relocations_type_ == REL ? SHT_ANDROID_REL : SHT_ANDROID_RELA, relocations_type_); + RewriteSectionData(relocations_section_, packed_data, bytes); + + // TODO (dimitry): fix string table and replace .rel.dyn/plt with .android.rel.dyn/plt + + // Rewrite .dynamic and rename relocation tags describing the packed android + // relocations. + Elf_Data* data = GetSectionData(dynamic_section_); + const typename ELF::Dyn* dynamic_base = reinterpret_cast(data->d_buf); + std::vector dynamics( + dynamic_base, + dynamic_base + data->d_size / sizeof(dynamics[0])); + section_header = ELF::getshdr(relocations_section_); + { + typename ELF::Dyn dyn; + dyn.d_tag = relocations_type_ == REL ? DT_ANDROID_REL : DT_ANDROID_RELA; + dyn.d_un.d_ptr = section_header->sh_addr; + ReplaceDynamicEntry(relocations_type_ == REL ? DT_REL : DT_RELA, dyn, &dynamics); + } + { + typename ELF::Dyn dyn; + dyn.d_tag = relocations_type_ == REL ? DT_ANDROID_RELSZ : DT_ANDROID_RELASZ; + dyn.d_un.d_val = section_header->sh_size; + ReplaceDynamicEntry(relocations_type_ == REL ? DT_RELSZ : DT_RELASZ, dyn, &dynamics); + } + + const void* dynamics_data = &dynamics[0]; + const size_t dynamics_bytes = dynamics.size() * sizeof(dynamics[0]); + RewriteSectionData(dynamic_section_, dynamics_data, dynamics_bytes); + + Flush(); + return true; +} + +// Find packed relative relocations in the packed android relocations +// section, unpack them, and rewrite the dynamic relocations section to +// contain unpacked data. +template +bool ElfFile::UnpackRelocations() { + // Load the ELF file into libelf. + if (!Load()) { + LOG(ERROR) << "Failed to load as ELF"; + return false; + } + + typename ELF::Shdr* section_header = ELF::getshdr(relocations_section_); + // Retrieve the current packed android relocations section data. + Elf_Data* data = GetSectionData(relocations_section_); + + // Convert data to a vector of bytes. + const uint8_t* packed_base = reinterpret_cast(data->d_buf); + std::vector packed( + packed_base, + packed_base + data->d_size / sizeof(packed[0])); + + if ((section_header->sh_type == SHT_ANDROID_RELA || section_header->sh_type == SHT_ANDROID_REL) && + packed.size() > 3 && + packed[0] == 'A' && + packed[1] == 'P' && + packed[2] == 'S' && + packed[3] == '2') { + LOG(INFO) << "Relocations : " << (relocations_type_ == REL ? "REL" : "RELA"); + } else { + LOG(ERROR) << "Packed relocations not found (not packed?)"; + return false; + } + + return UnpackTypedRelocations(packed); +} + +// Helper for UnpackRelocations(). Rel type is one of ELF::Rel or ELF::Rela. +template +bool ElfFile::UnpackTypedRelocations(const std::vector& packed) { + // Unpack the data to re-materialize the relative relocations. + const size_t packed_bytes = packed.size() * sizeof(packed[0]); + LOG(INFO) << "Packed : " << packed_bytes << " bytes"; + std::vector unpacked_relocations; + RelocationPacker packer; + packer.UnpackRelocations(packed, &unpacked_relocations); + + const size_t relocation_entry_size = + relocations_type_ == REL ? sizeof(typename ELF::Rel) : sizeof(typename ELF::Rela); + const size_t unpacked_bytes = unpacked_relocations.size() * relocation_entry_size; + LOG(INFO) << "Unpacked : " << unpacked_bytes << " bytes"; + + // Retrieve the current dynamic relocations section data. + Elf_Data* data = GetSectionData(relocations_section_); + + LOG(INFO) << "Relocations : " << unpacked_relocations.size() << " entries"; + + // If we found the same number of null relocation entries in the dynamic + // relocations section as we hold as unpacked relative relocations, then + // this is a padded file. + + const bool is_padded = packed_bytes == unpacked_bytes; + + // Unless padded, pre-apply relative relocations to account for the + // hole, and pre-adjust all relocation offsets accordingly. + typename ELF::Shdr* section_header = ELF::getshdr(relocations_section_); + + if (!is_padded) { + LOG(INFO) << "Expansion : " << unpacked_bytes - packed_bytes << " bytes"; + } + + // Rewrite the current dynamic relocations section with unpacked version of + // relocations. + const void* section_data = nullptr; + std::vector unpacked_rel_relocations; + if (relocations_type_ == RELA) { + section_data = &unpacked_relocations[0]; + } else if (relocations_type_ == REL) { + ConvertRelaVectorToRelVector(unpacked_relocations, &unpacked_rel_relocations); + section_data = &unpacked_rel_relocations[0]; + } else { + NOTREACHED(); + } + + ResizeSection(elf_, relocations_section_, unpacked_bytes, + relocations_type_ == REL ? SHT_REL : SHT_RELA, relocations_type_); + RewriteSectionData(relocations_section_, section_data, unpacked_bytes); + + // Rewrite .dynamic to remove two tags describing packed android relocations. + data = GetSectionData(dynamic_section_); + const typename ELF::Dyn* dynamic_base = reinterpret_cast(data->d_buf); + std::vector dynamics( + dynamic_base, + dynamic_base + data->d_size / sizeof(dynamics[0])); + { + typename ELF::Dyn dyn; + dyn.d_tag = relocations_type_ == REL ? DT_REL : DT_RELA; + dyn.d_un.d_ptr = section_header->sh_addr; + ReplaceDynamicEntry(relocations_type_ == REL ? DT_ANDROID_REL : DT_ANDROID_RELA, + dyn, &dynamics); + } + + { + typename ELF::Dyn dyn; + dyn.d_tag = relocations_type_ == REL ? DT_RELSZ : DT_RELASZ; + dyn.d_un.d_val = section_header->sh_size; + ReplaceDynamicEntry(relocations_type_ == REL ? DT_ANDROID_RELSZ : DT_ANDROID_RELASZ, + dyn, &dynamics); + } + + const void* dynamics_data = &dynamics[0]; + const size_t dynamics_bytes = dynamics.size() * sizeof(dynamics[0]); + RewriteSectionData(dynamic_section_, dynamics_data, dynamics_bytes); + + Flush(); + return true; +} + +// Flush rewritten shared object file data. +template +void ElfFile::Flush() { + // Flag all ELF data held in memory as needing to be written back to the + // file, and tell libelf that we have controlled the file layout. + elf_flagelf(elf_, ELF_C_SET, ELF_F_DIRTY); + elf_flagelf(elf_, ELF_C_SET, ELF_F_LAYOUT); + + // Write ELF data back to disk. + const off_t file_bytes = elf_update(elf_, ELF_C_WRITE); + if (file_bytes == -1) { + LOG(ERROR) << "elf_update failed: " << elf_errmsg(elf_errno()); + } + + CHECK(file_bytes > 0); + VLOG(1) << "elf_update returned: " << file_bytes; + + // Clean up libelf, and truncate the output file to the number of bytes + // written by elf_update(). + elf_end(elf_); + elf_ = NULL; + const int truncate = ftruncate(fd_, file_bytes); + CHECK(truncate == 0); +} + +template +void ElfFile::ConvertRelArrayToRelaVector(const typename ELF::Rel* rel_array, + size_t rel_array_size, + std::vector* rela_vector) { + for (size_t i = 0; ipush_back(rela); + } +} + +template +void ElfFile::ConvertRelaVectorToRelVector(const std::vector& rela_vector, + std::vector* rel_vector) { + for (auto rela : rela_vector) { + typename ELF::Rel rel; + rel.r_offset = rela.r_offset; + rel.r_info = rela.r_info; + CHECK(rela.r_addend == 0); + rel_vector->push_back(rel); + } +} + +template class ElfFile; +template class ElfFile; + +} // namespace relocation_packer diff --git a/third_party/android_platform/bionic/tools/relocation_packer/src/elf_file.h b/third_party/android_platform/bionic/tools/relocation_packer/src/elf_file.h new file mode 100644 index 0000000000000..d6acc76b7ec86 --- /dev/null +++ b/third_party/android_platform/bionic/tools/relocation_packer/src/elf_file.h @@ -0,0 +1,121 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// ELF shared object file updates handler. +// +// Provides functions to pack relocations in the .rel.dyn or .rela.dyn +// sections, and unpack to return the file to its pre-packed state. +// +// SetPadding() causes PackRelocations() to pad .rel.dyn or .rela.dyn with +// NONE-type entries rather than cutting a hole out of the shared object +// file. This keeps all load addresses and offsets constant, and enables +// easier debugging and testing. +// +// A packed shared object file is shorter than its non-packed original. +// Unpacking a packed file restores the file to its non-packed state. + +#ifndef TOOLS_RELOCATION_PACKER_SRC_ELF_FILE_H_ +#define TOOLS_RELOCATION_PACKER_SRC_ELF_FILE_H_ + +#include +#include + +#include "elf.h" +#include "libelf.h" +#include "packer.h" + +namespace relocation_packer { + +// An ElfFile reads shared objects, and shuttles relative relocations +// between .rel.dyn or .rela.dyn and .android.rel.dyn or .android.rela.dyn +// sections. +template +class ElfFile { + public: + explicit ElfFile(int fd) + : fd_(fd), is_padding_relocations_(false), elf_(NULL), + relocations_section_(NULL), dynamic_section_(NULL), + relocations_type_(NONE), has_android_relocations_(false) {} + ~ElfFile() {} + + // Set padding mode. When padding, PackRelocations() will not shrink + // the .rel.dyn or .rela.dyn section, but instead replace relative with + // NONE-type entries. + // |flag| is true to pad .rel.dyn or .rela.dyn, false to shrink it. + inline void SetPadding(bool flag) { is_padding_relocations_ = flag; } + + // Transfer relative relocations from .rel.dyn or .rela.dyn to a packed + // representation in .android.rel.dyn or .android.rela.dyn. Returns true + // on success. + bool PackRelocations(); + + // Transfer relative relocations from a packed representation in + // .android.rel.dyn or .android.rela.dyn to .rel.dyn or .rela.dyn. Returns + // true on success. + bool UnpackRelocations(); + + private: + enum relocations_type_t { + NONE = 0, REL, RELA + }; + + // Load a new ElfFile from a filedescriptor. If flushing, the file must + // be open for read/write. Returns true on successful ELF file load. + // |fd| is an open file descriptor for the shared object. + bool Load(); + + // Templated packer, helper for PackRelocations(). Rel type is one of + // ELF::Rel or ELF::Rela. + bool PackTypedRelocations(std::vector* relocations); + + // Templated unpacker, helper for UnpackRelocations(). Rel type is one of + // ELF::Rel or ELF::Rela. + bool UnpackTypedRelocations(const std::vector& packed); + + // Write ELF file changes. + void Flush(); + + void AdjustRelativeRelocationTargets(typename ELF::Off hole_start, + ssize_t hole_size, + std::vector* relocations); + + static void ResizeSection(Elf* elf, Elf_Scn* section, size_t new_size, + typename ELF::Word new_sh_type, relocations_type_t relocations_type); + + static void AdjustDynamicSectionForHole(Elf_Scn* dynamic_section, + typename ELF::Off hole_start, + ssize_t hole_size, + relocations_type_t relocations_type); + + static void ConvertRelArrayToRelaVector(const typename ELF::Rel* rel_array, size_t rel_array_size, + std::vector* rela_vector); + + static void ConvertRelaVectorToRelVector(const std::vector& rela_vector, + std::vector* rel_vector); + + + // File descriptor opened on the shared object. + int fd_; + + // If set, pad rather than shrink .rel.dyn or .rela.dyn. Primarily for + // debugging, allows packing to be checked without affecting load addresses. + bool is_padding_relocations_; + + // Libelf handle, assigned by Load(). + Elf* elf_; + + // Sections that we manipulate, assigned by Load(). + Elf_Scn* relocations_section_; + Elf_Scn* dynamic_section_; + + // Relocation type found, assigned by Load(). + relocations_type_t relocations_type_; + + // Elf-file has android relocations section + bool has_android_relocations_; +}; + +} // namespace relocation_packer + +#endif // TOOLS_RELOCATION_PACKER_SRC_ELF_FILE_H_ diff --git a/third_party/android_platform/bionic/tools/relocation_packer/src/elf_file_unittest.cc b/third_party/android_platform/bionic/tools/relocation_packer/src/elf_file_unittest.cc new file mode 100644 index 0000000000000..d5c8918902f01 --- /dev/null +++ b/third_party/android_platform/bionic/tools/relocation_packer/src/elf_file_unittest.cc @@ -0,0 +1,218 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "elf_file.h" + +#include +#include +#include +#include +#include +#include "debug.h" +#include "elf_traits.h" +#include "gtest/gtest.h" + +namespace { + +void GetDataFilePath(const char* name, std::string* path) { + std::string data_dir; + + const char* bindir = getenv("bindir"); + if (bindir) { + data_dir = std::string(bindir); + } else { + char path[PATH_MAX]; + memset(path, 0, sizeof(path)); + ASSERT_NE(-1, readlink("/proc/self/exe", path, sizeof(path) - 1)); + + data_dir = std::string(path); + size_t pos = data_dir.rfind('/'); + ASSERT_NE(std::string::npos, pos); + + data_dir.erase(pos); + } + + *path = data_dir + "/" + name; +} + +void OpenRelocsTestFile(const char* name, FILE** stream) { + std::string path; + GetDataFilePath(name, &path); + + FILE* testfile = fopen(path.c_str(), "rb"); + ASSERT_FALSE(testfile == NULL) << "Error opening '" << path << "'"; + + FILE* temporary = tmpfile(); + ASSERT_FALSE(temporary == NULL); + + static const size_t buffer_size = 4096; + unsigned char buffer[buffer_size]; + + size_t bytes; + do { + bytes = fread(buffer, 1, sizeof(buffer), testfile); + ASSERT_EQ(bytes, fwrite(buffer, 1, bytes, temporary)); + } while (bytes > 0); + + ASSERT_EQ(0, fclose(testfile)); + ASSERT_EQ(0, fseek(temporary, 0, SEEK_SET)); + ASSERT_EQ(0, lseek(fileno(temporary), 0, SEEK_SET)); + + *stream = temporary; +} + +void OpenRelocsTestFiles(const std::string& arch, FILE** relocs_so, FILE** packed_relocs_so) { + const std::string base = std::string("elf_file_unittest_relocs_") + arch; + const std::string relocs = base + ".so"; + const std::string packed_relocs = base + "_packed.so"; + + OpenRelocsTestFile(relocs.c_str(), relocs_so); + OpenRelocsTestFile(packed_relocs.c_str(), packed_relocs_so); +} + +void CloseRelocsTestFile(FILE* temporary) { + fclose(temporary); +} + +void CloseRelocsTestFiles(FILE* relocs_so, FILE* packed_relocs_so) { + CloseRelocsTestFile(relocs_so); + CloseRelocsTestFile(packed_relocs_so); +} + +void CheckFileContentsEqual(FILE* first, FILE* second) { + ASSERT_EQ(0, fseek(first, 0, SEEK_SET)); + ASSERT_EQ(0, fseek(second, 0, SEEK_SET)); + + static const size_t buffer_size = 4096; + unsigned char first_buffer[buffer_size]; + unsigned char second_buffer[buffer_size]; + + do { + size_t first_read = fread(first_buffer, 1, sizeof(first_buffer), first); + size_t second_read = fread(second_buffer, 1, sizeof(second_buffer), second); + + EXPECT_EQ(first_read, second_read); + EXPECT_EQ(0, memcmp(first_buffer, second_buffer, first_read)); + } while (!feof(first) && !feof(second)); + + EXPECT_TRUE(feof(first) && feof(second)); +} + +template +static void ProcessUnpack(FILE* relocs_so, FILE* packed_relocs_so) { + relocation_packer::ElfFile elf_file(fileno(packed_relocs_so)); + + // Ensure packing already packed elf-file does not fail the build. + EXPECT_TRUE(elf_file.PackRelocations()); + + // Unpack golden relocations, and check files are now identical. + EXPECT_TRUE(elf_file.UnpackRelocations()); + CheckFileContentsEqual(packed_relocs_so, relocs_so); + + CloseRelocsTestFiles(relocs_so, packed_relocs_so); +} + +static void RunUnpackRelocationsTestFor(const std::string& arch) { + ASSERT_NE(static_cast(EV_NONE), elf_version(EV_CURRENT)); + + FILE* relocs_so = NULL; + FILE* packed_relocs_so = NULL; + OpenRelocsTestFiles(arch, &relocs_so, &packed_relocs_so); + + if (relocs_so != NULL && packed_relocs_so != NULL) { + // lets detect elf class + ASSERT_EQ(0, fseek(relocs_so, EI_CLASS, SEEK_SET)) + << "Invalid file length: " << strerror(errno); + uint8_t elf_class = 0; + ASSERT_EQ(1U, fread(&elf_class, 1, 1, relocs_so)); + ASSERT_EQ(0, fseek(relocs_so, 0, SEEK_SET)); + if (elf_class == ELFCLASS32) { + ProcessUnpack(relocs_so, packed_relocs_so); + } else { + ProcessUnpack(relocs_so, packed_relocs_so); + } + } +} + +template +static void ProcessPack(FILE* relocs_so, FILE* packed_relocs_so) { + relocation_packer::ElfFile elf_file(fileno(relocs_so)); + + // Ensure unpacking fails (not packed). + EXPECT_FALSE(elf_file.UnpackRelocations()); + + // Pack relocations, and check files are now identical. + EXPECT_TRUE(elf_file.PackRelocations()); + CheckFileContentsEqual(relocs_so, packed_relocs_so); + + CloseRelocsTestFiles(relocs_so, packed_relocs_so); +} + +static void RunPackRelocationsTestFor(const std::string& arch) { + ASSERT_NE(static_cast(EV_NONE), elf_version(EV_CURRENT)); + + FILE* relocs_so = NULL; + FILE* packed_relocs_so = NULL; + OpenRelocsTestFiles(arch, &relocs_so, &packed_relocs_so); + + if (relocs_so != NULL && packed_relocs_so != NULL) { + // lets detect elf class + ASSERT_EQ(0, fseek(packed_relocs_so, EI_CLASS, SEEK_SET)) + << "Invalid file length: " << strerror(errno); + uint8_t elf_class = 0; + ASSERT_EQ(1U, fread(&elf_class, 1, 1, packed_relocs_so)); + fseek(packed_relocs_so, 0, SEEK_SET); + if (elf_class == ELFCLASS32) { + ProcessPack(relocs_so, packed_relocs_so); + } else { + ProcessPack(relocs_so, packed_relocs_so); + } + } +} + +} // namespace + +namespace relocation_packer { + +TEST(ElfFile, PackRelocationsArm32) { + RunPackRelocationsTestFor("arm32"); +} + +TEST(ElfFile, PackRelocationsArm64) { + RunPackRelocationsTestFor("arm64"); +} + +TEST(ElfFile, PackRelocationsMips32) { + RunPackRelocationsTestFor("mips32"); +} + +TEST(ElfFile, PackRelocationsIa32) { + RunPackRelocationsTestFor("ia32"); +} + +TEST(ElfFile, PackRelocationsX64) { + RunPackRelocationsTestFor("x64"); +} + +TEST(ElfFile, UnpackRelocationsArm32) { + RunUnpackRelocationsTestFor("arm32"); +} + +TEST(ElfFile, UnpackRelocationsArm64) { + RunUnpackRelocationsTestFor("arm64"); +} + +TEST(ElfFile, UnpackRelocationsMips32) { + RunUnpackRelocationsTestFor("mips32"); +} + +TEST(ElfFile, UnpackRelocationsIa32) { + RunUnpackRelocationsTestFor("ia32"); +} + +TEST(ElfFile, UnpackRelocationsX64) { + RunUnpackRelocationsTestFor("x64"); +} + +} // namespace relocation_packer diff --git a/third_party/android_platform/bionic/tools/relocation_packer/src/elf_traits.h b/third_party/android_platform/bionic/tools/relocation_packer/src/elf_traits.h new file mode 100644 index 0000000000000..1c938faaa4874 --- /dev/null +++ b/third_party/android_platform/bionic/tools/relocation_packer/src/elf_traits.h @@ -0,0 +1,68 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Target-specific ELF type traits. + +#ifndef TOOLS_RELOCATION_PACKER_SRC_ELF_TRAITS_H_ +#define TOOLS_RELOCATION_PACKER_SRC_ELF_TRAITS_H_ + +#include "elf.h" +#include "libelf.h" + +#if !defined(DT_MIPS_RLD_MAP2) +#define DT_MIPS_RLD_MAP2 0x70000035 +#endif + +// ELF is a traits structure used to provide convenient aliases for +// 32/64 bit Elf types and functions, depending on the target file. + +struct ELF32_traits { + typedef Elf32_Addr Addr; + typedef Elf32_Dyn Dyn; + typedef Elf32_Ehdr Ehdr; + typedef Elf32_Off Off; + typedef Elf32_Phdr Phdr; + typedef Elf32_Rel Rel; + typedef Elf32_Rela Rela; + typedef Elf32_Shdr Shdr; + typedef Elf32_Sword Sword; + typedef Elf32_Sxword Sxword; + typedef Elf32_Sym Sym; + typedef Elf32_Word Word; + typedef Elf32_Xword Xword; + typedef Elf32_Half Half; + + static inline Ehdr* getehdr(Elf* elf) { return elf32_getehdr(elf); } + static inline Phdr* getphdr(Elf* elf) { return elf32_getphdr(elf); } + static inline Shdr* getshdr(Elf_Scn* scn) { return elf32_getshdr(scn); } + static inline Word elf_r_type(Word info) { return ELF32_R_TYPE(info); } + static inline int elf_st_type(uint8_t info) { return ELF32_ST_TYPE(info); } + static inline Word elf_r_sym(Word info) { return ELF32_R_SYM(info); } +}; + +struct ELF64_traits { + typedef Elf64_Addr Addr; + typedef Elf64_Dyn Dyn; + typedef Elf64_Ehdr Ehdr; + typedef Elf64_Off Off; + typedef Elf64_Phdr Phdr; + typedef Elf64_Rel Rel; + typedef Elf64_Rela Rela; + typedef Elf64_Shdr Shdr; + typedef Elf64_Sword Sword; + typedef Elf64_Sxword Sxword; + typedef Elf64_Sym Sym; + typedef Elf64_Word Word; + typedef Elf64_Xword Xword; + typedef Elf64_Half Half; + + static inline Ehdr* getehdr(Elf* elf) { return elf64_getehdr(elf); } + static inline Phdr* getphdr(Elf* elf) { return elf64_getphdr(elf); } + static inline Shdr* getshdr(Elf_Scn* scn) { return elf64_getshdr(scn); } + static inline Xword elf_r_type(Xword info) { return ELF64_R_TYPE(info); } + static inline int elf_st_type(uint8_t info) { return ELF64_ST_TYPE(info); } + static inline Word elf_r_sym(Xword info) { return ELF64_R_SYM(info); } +}; + +#endif // TOOLS_RELOCATION_PACKER_SRC_ELF_TRAITS_H_ diff --git a/third_party/android_platform/bionic/tools/relocation_packer/src/main.cc b/third_party/android_platform/bionic/tools/relocation_packer/src/main.cc new file mode 100644 index 0000000000000..8e9de6d96f567 --- /dev/null +++ b/third_party/android_platform/bionic/tools/relocation_packer/src/main.cc @@ -0,0 +1,150 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Tool to pack and unpack relative relocations in a shared library. +// +// Invoke with -v to trace actions taken when packing or unpacking. +// Invoke with -p to pad removed relocations with R_*_NONE. Suppresses +// shrinking of .rel.dyn. +// See PrintUsage() below for full usage details. +// +// NOTE: Breaks with libelf 0.152, which is buggy. libelf 0.158 works. + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "debug.h" +#include "elf_file.h" +#include "elf_traits.h" +#include "libelf.h" + +#include "nativehelper/ScopedFd.h" + +static void PrintUsage(const char* argv0) { + std::string temporary = argv0; + const size_t last_slash = temporary.find_last_of("/"); + if (last_slash != temporary.npos) { + temporary.erase(0, last_slash + 1); + } + const char* basename = temporary.c_str(); + + printf( + "Usage: %s [-u] [-v] [-p] file\n\n" + "Pack or unpack relative relocations in a shared library.\n\n" + " -u, --unpack unpack previously packed relative relocations\n" + " -v, --verbose trace object file modifications (for debugging)\n" + " -p, --pad do not shrink relocations, but pad (for debugging)\n\n", + basename); + + printf( + "Debug sections are not handled, so packing should not be used on\n" + "shared libraries compiled for debugging or otherwise unstripped.\n"); +} + +int main(int argc, char* argv[]) { + bool is_unpacking = false; + bool is_verbose = false; + bool is_padding = false; + + static const option options[] = { + {"unpack", 0, 0, 'u'}, {"verbose", 0, 0, 'v'}, {"pad", 0, 0, 'p'}, + {"help", 0, 0, 'h'}, {NULL, 0, 0, 0} + }; + bool has_options = true; + while (has_options) { + int c = getopt_long(argc, argv, "uvph", options, NULL); + switch (c) { + case 'u': + is_unpacking = true; + break; + case 'v': + is_verbose = true; + break; + case 'p': + is_padding = true; + break; + case 'h': + PrintUsage(argv[0]); + return 0; + case '?': + LOG(INFO) << "Try '" << argv[0] << " --help' for more information."; + return 1; + case -1: + has_options = false; + break; + default: + NOTREACHED(); + return 1; + } + } + if (optind != argc - 1) { + LOG(INFO) << "Try '" << argv[0] << " --help' for more information."; + return 1; + } + + if (elf_version(EV_CURRENT) == EV_NONE) { + LOG(WARNING) << "Elf Library is out of date!"; + } + + const char* file = argv[argc - 1]; + ScopedFd fd(open(file, O_RDWR)); + if (fd.get() == -1) { + LOG(ERROR) << file << ": " << strerror(errno); + return 1; + } + + if (is_verbose) + relocation_packer::Logger::SetVerbose(1); + + // We need to detect elf class in order to create + // correct implementation + uint8_t e_ident[EI_NIDENT]; + if (TEMP_FAILURE_RETRY(read(fd.get(), e_ident, EI_NIDENT) != EI_NIDENT)) { + LOG(ERROR) << file << ": failed to read elf header:" << strerror(errno); + return 1; + } + + if (TEMP_FAILURE_RETRY(lseek(fd.get(), 0, SEEK_SET)) != 0) { + LOG(ERROR) << file << ": lseek to 0 failed:" << strerror(errno); + return 1; + } + + bool status = false; + + if (e_ident[EI_CLASS] == ELFCLASS32) { + relocation_packer::ElfFile elf_file(fd.get()); + elf_file.SetPadding(is_padding); + + if (is_unpacking) { + status = elf_file.UnpackRelocations(); + } else { + status = elf_file.PackRelocations(); + } + } else if (e_ident[EI_CLASS] == ELFCLASS64) { + relocation_packer::ElfFile elf_file(fd.get()); + elf_file.SetPadding(is_padding); + + if (is_unpacking) { + status = elf_file.UnpackRelocations(); + } else { + status = elf_file.PackRelocations(); + } + } else { + LOG(ERROR) << file << ": unknown ELFCLASS: " << e_ident[EI_CLASS]; + return 1; + } + + if (!status) { + LOG(ERROR) << file << ": failed to pack/unpack file"; + return 1; + } + + return 0; +} diff --git a/third_party/android_platform/bionic/tools/relocation_packer/src/nativehelper/ScopedFd.h b/third_party/android_platform/bionic/tools/relocation_packer/src/nativehelper/ScopedFd.h new file mode 100644 index 0000000000000..5a22652cf0887 --- /dev/null +++ b/third_party/android_platform/bionic/tools/relocation_packer/src/nativehelper/ScopedFd.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SCOPED_FD_H_included +#define SCOPED_FD_H_included + +#include + +// Local definition of DISALLOW_COPY_AND_ASSIGN, avoids depending on base. +#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ + TypeName(const TypeName&); \ + void operator=(const TypeName&) + +// A smart pointer that closes the given fd on going out of scope. +// Use this when the fd is incidental to the purpose of your function, +// but needs to be cleaned up on exit. +class ScopedFd { +public: + explicit ScopedFd(int fd) : fd_(fd) { + } + + ~ScopedFd() { + reset(); + } + + int get() const { + return fd_; + } + + int release() __attribute__((warn_unused_result)) { + int localFd = fd_; + fd_ = -1; + return localFd; + } + + void reset(int new_fd = -1) { + if (fd_ != -1) { + TEMP_FAILURE_RETRY(close(fd_)); + } + fd_ = new_fd; + } + +private: + int fd_; + + DISALLOW_COPY_AND_ASSIGN(ScopedFd); +}; + +#endif // SCOPED_FD_H_included diff --git a/third_party/android_platform/bionic/tools/relocation_packer/src/packer.cc b/third_party/android_platform/bionic/tools/relocation_packer/src/packer.cc new file mode 100644 index 0000000000000..433611faa9a8a --- /dev/null +++ b/third_party/android_platform/bionic/tools/relocation_packer/src/packer.cc @@ -0,0 +1,67 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "packer.h" + +#include + +#include "debug.h" +#include "delta_encoder.h" +#include "elf_traits.h" +#include "sleb128.h" + +namespace relocation_packer { + +// Pack relocations into a group encoded packed representation. +template +void RelocationPacker::PackRelocations(const std::vector& relocations, + std::vector* packed) { + // Run-length encode. + std::vector packed_words; + RelocationDeltaCodec codec; + codec.Encode(relocations, &packed_words); + + // If insufficient data do nothing. + if (packed_words.empty()) + return; + + Sleb128Encoder sleb128_encoder; + + std::vector sleb128_packed; + + sleb128_encoder.EnqueueAll(packed_words); + sleb128_encoder.GetEncoding(&sleb128_packed); + + packed->push_back('A'); + packed->push_back('P'); + packed->push_back('S'); + packed->push_back('2'); + packed->insert(packed->end(), sleb128_packed.begin(), sleb128_packed.end()); +} + +// Unpack relative relocations from a run-length encoded packed +// representation. +template +void RelocationPacker::UnpackRelocations( + const std::vector& packed, + std::vector* relocations) { + + std::vector packed_words; + CHECK(packed.size() > 4 && + packed[0] == 'A' && + packed[1] == 'P' && + packed[2] == 'S' && + packed[3] == '2'); + + Sleb128Decoder decoder(packed, 4); + decoder.DequeueAll(&packed_words); + + RelocationDeltaCodec codec; + codec.Decode(packed_words, relocations); +} + +template class RelocationPacker; +template class RelocationPacker; + +} // namespace relocation_packer diff --git a/third_party/android_platform/bionic/tools/relocation_packer/src/packer.h b/third_party/android_platform/bionic/tools/relocation_packer/src/packer.h new file mode 100644 index 0000000000000..63f50e2496a6b --- /dev/null +++ b/third_party/android_platform/bionic/tools/relocation_packer/src/packer.h @@ -0,0 +1,37 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Pack relative relocations into a more compact form. + +#ifndef TOOLS_RELOCATION_PACKER_SRC_PACKER_H_ +#define TOOLS_RELOCATION_PACKER_SRC_PACKER_H_ + +#include +#include + +#include "elf.h" + +namespace relocation_packer { + +// A RelocationPacker packs vectors of relocations into more +// compact forms, and unpacks them to reproduce the pre-packed data. +template +class RelocationPacker { + public: + // Pack relocations into a more compact form. + // |relocations| is a vector of relocation structs. + // |packed| is the vector of packed bytes into which relocations are packed. + static void PackRelocations(const std::vector& relocations, + std::vector* packed); + + // Unpack relocations from their more compact form. + // |packed| is the vector of packed relocations. + // |relocations| is a vector of unpacked relocation structs. + static void UnpackRelocations(const std::vector& packed, + std::vector* relocations); +}; + +} // namespace relocation_packer + +#endif // TOOLS_RELOCATION_PACKER_SRC_PACKER_H_ diff --git a/third_party/android_platform/bionic/tools/relocation_packer/src/packer_unittest.cc b/third_party/android_platform/bionic/tools/relocation_packer/src/packer_unittest.cc new file mode 100644 index 0000000000000..424b92cd067c1 --- /dev/null +++ b/third_party/android_platform/bionic/tools/relocation_packer/src/packer_unittest.cc @@ -0,0 +1,300 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "packer.h" + +#include +#include "elf.h" +#include "elf_traits.h" +#include "gtest/gtest.h" + + +template +static void AddRelocation(typename ELF::Addr addr, + typename ELF::Xword info, + typename ELF::Sxword addend, + std::vector* relocations) { + typename ELF::Rela relocation; + relocation.r_offset = addr; + relocation.r_info = info; + relocation.r_addend = addend; + + relocations->push_back(relocation); +} + +template +static bool CheckRelocation(typename ELF::Addr addr, + typename ELF::Xword info, + typename ELF::Sxword addend, + const typename ELF::Rela& relocation) { + return relocation.r_offset == addr && + relocation.r_info == info && + relocation.r_addend == addend; +} + +namespace relocation_packer { + +template +static void DoPackNoAddend() { + std::vector relocations; + std::vector packed; + bool is_32 = sizeof(typename ELF::Addr) == 4; + // Initial relocation. + AddRelocation(0xd1ce0000, 0x11, 0, &relocations); + // Two more relocations, 4 byte deltas. + AddRelocation(0xd1ce0004, 0x11, 0, &relocations); + AddRelocation(0xd1ce0008, 0x11, 0, &relocations); + // Three more relocations, 8 byte deltas. + AddRelocation(0xd1ce0010, 0x11, 0, &relocations); + AddRelocation(0xd1ce0018, 0x11, 0, &relocations); + AddRelocation(0xd1ce0020, 0x11, 0, &relocations); + + RelocationPacker packer; + + packed.clear(); + packer.PackRelocations(relocations, &packed); + + ASSERT_EQ(18U, packed.size()); + // Identifier. + size_t ndx = 0; + EXPECT_EQ('A', packed[ndx++]); + EXPECT_EQ('P', packed[ndx++]); + EXPECT_EQ('S', packed[ndx++]); + EXPECT_EQ('2', packed[ndx++]); + // relocation count + EXPECT_EQ(6, packed[ndx++]); + // base relocation = 0xd1cdfffc -> fc, ff, b7, 8e, 7d/0d (32/64bit) + EXPECT_EQ(0xfc, packed[ndx++]); + EXPECT_EQ(0xff, packed[ndx++]); + EXPECT_EQ(0xb7, packed[ndx++]); + EXPECT_EQ(0x8e, packed[ndx++]); + EXPECT_EQ(is_32 ? 0x7d : 0x0d, packed[ndx++]); + // first group + EXPECT_EQ(3, packed[ndx++]); // size + EXPECT_EQ(3, packed[ndx++]); // flags + EXPECT_EQ(4, packed[ndx++]); // r_offset_delta + EXPECT_EQ(0x11, packed[ndx++]); // r_info + // second group + EXPECT_EQ(3, packed[ndx++]); // size + EXPECT_EQ(3, packed[ndx++]); // flags + EXPECT_EQ(8, packed[ndx++]); // r_offset_delta + EXPECT_EQ(0x11, packed[ndx++]); // r_info + + EXPECT_EQ(ndx, packed.size()); +} + +TEST(Packer, PackNoAddend32) { + DoPackNoAddend(); +} + +TEST(Packer, PackNoAddend64) { + DoPackNoAddend(); +} + +template +static void DoUnpackNoAddend() { + std::vector relocations; + std::vector packed; + bool is_32 = sizeof(typename ELF::Addr) == 4; + packed.push_back('A'); + packed.push_back('P'); + packed.push_back('S'); + packed.push_back('2'); + // relocation count + packed.push_back(6); + // base relocation = 0xd1cdfffc -> fc, ff, b7, 8e, 7d/0d (32/64bit) + packed.push_back(0xfc); + packed.push_back(0xff); + packed.push_back(0xb7); + packed.push_back(0x8e); + packed.push_back(is_32 ? 0x7d : 0x0d); + // first group + packed.push_back(3); // size + packed.push_back(3); // flags + packed.push_back(4); // r_offset_delta + packed.push_back(0x11); // r_info + // second group + packed.push_back(3); // size + packed.push_back(3); // flags + packed.push_back(8); // r_offset_delta + packed.push_back(0x11); // r_info + + RelocationPacker packer; + packer.UnpackRelocations(packed, &relocations); + + size_t ndx = 0; + EXPECT_EQ(6U, relocations.size()); + EXPECT_TRUE(CheckRelocation(0xd1ce0000, 0x11, 0, relocations[ndx++])); + EXPECT_TRUE(CheckRelocation(0xd1ce0004, 0x11, 0, relocations[ndx++])); + EXPECT_TRUE(CheckRelocation(0xd1ce0008, 0x11, 0, relocations[ndx++])); + + EXPECT_TRUE(CheckRelocation(0xd1ce0010, 0x11, 0, relocations[ndx++])); + EXPECT_TRUE(CheckRelocation(0xd1ce0018, 0x11, 0, relocations[ndx++])); + EXPECT_TRUE(CheckRelocation(0xd1ce0020, 0x11, 0, relocations[ndx++])); + + EXPECT_EQ(ndx, relocations.size()); +} + +TEST(Packer, UnpackNoAddend32) { + DoUnpackNoAddend(); +} + +TEST(Packer, UnpackNoAddend64) { + DoUnpackNoAddend(); +} + +template +static void DoPackWithAddend() { + std::vector relocations; + + // Initial relocation. + AddRelocation(0xd1ce0000, 0x01, 10024, &relocations); + // Two more relocations, 4 byte offset deltas, 12 byte addend deltas. + AddRelocation(0xd1ce0004, 0x01, 10012, &relocations); + AddRelocation(0xd1ce0008, 0x01, 10024, &relocations); + // Three more relocations, 8 byte deltas, -24 byte addend deltas. + AddRelocation(0xd1ce0010, 0x01, 10000, &relocations); + AddRelocation(0xd1ce0018, 0x01, 9976, &relocations); + AddRelocation(0xd1ce0020, 0x01, 9952, &relocations); + + std::vector packed; + + RelocationPacker packer; + + packed.clear(); + packer.PackRelocations(relocations, &packed); + + EXPECT_EQ(26U, packed.size()); + size_t ndx = 0; + // Identifier. + EXPECT_EQ('A', packed[ndx++]); + EXPECT_EQ('P', packed[ndx++]); + EXPECT_EQ('S', packed[ndx++]); + EXPECT_EQ('2', packed[ndx++]); + // Relocation count + EXPECT_EQ(6U, packed[ndx++]); + // base relocation = 0xd1cdfffc -> fc, ff, b7, 8e, 0d/7d (depending on ELF::Addr) + EXPECT_EQ(0xfc, packed[ndx++]); + EXPECT_EQ(0xff, packed[ndx++]); + EXPECT_EQ(0xb7, packed[ndx++]); + EXPECT_EQ(0x8e, packed[ndx++]); + if (sizeof(typename ELF::Addr) == 8) { + // positive for uint64_t + EXPECT_EQ(0x0d, packed[ndx++]); + } else { + // negative for uint32_t + EXPECT_EQ(0x7d, packed[ndx++]); + } + // group 1 + EXPECT_EQ(0x03, packed[ndx++]); // size + EXPECT_EQ(0x0b, packed[ndx++]); // flags + EXPECT_EQ(0x04, packed[ndx++]); // r_offset_delta + EXPECT_EQ(0x01, packed[ndx++]); // r_info + // group 1 - addend 1: 10024 = 0xa8, 0xce, 0x80 + EXPECT_EQ(0xa8, packed[ndx++]); + EXPECT_EQ(0xce, packed[ndx++]); + EXPECT_EQ(0x00, packed[ndx++]); + // group 1 - addend 2: -12 = 0x74 + EXPECT_EQ(0x74, packed[ndx++]); + // group 1 - addend 3: +12 = 0x0c + EXPECT_EQ(0x0c, packed[ndx++]); + + // group 2 + EXPECT_EQ(0x03, packed[ndx++]); // size + EXPECT_EQ(0x0b, packed[ndx++]); // flags + EXPECT_EQ(0x08, packed[ndx++]); // r_offset_delta + EXPECT_EQ(0x01, packed[ndx++]); // r_info + + // group 2 - addend 1: -24 = 0x68 + EXPECT_EQ(0x68, packed[ndx++]); + // group 2 - addend 2: -24 = 0x68 + EXPECT_EQ(0x68, packed[ndx++]); + // group 2 - addend 3: -24 = 0x68 + EXPECT_EQ(0x68, packed[ndx++]); + + EXPECT_EQ(ndx, packed.size()); +} + +TEST(Packer, PackWithAddend) { + DoPackWithAddend(); + DoPackWithAddend(); +} + +template +static void DoUnpackWithAddend() { + std::vector packed; + // Identifier. + packed.push_back('A'); + packed.push_back('P'); + packed.push_back('S'); + packed.push_back('2'); + // Relocation count + packed.push_back(6U); + // base relocation = 0xd1cdfffc -> fc, ff, b7, 8e, 0d + packed.push_back(0xfc); + packed.push_back(0xff); + packed.push_back(0xb7); + packed.push_back(0x8e); + if (sizeof(typename ELF::Addr) == 8) { + // positive for uint64_t + packed.push_back(0x0d); + } else { + // negative for uint32_t + packed.push_back(0x7d); + } + // group 1 + packed.push_back(0x03); // size + packed.push_back(0x0b); // flags + packed.push_back(0x04); // r_offset_delta + packed.push_back(0x01); // r_info + // group 1 - addend 1: 10024 = 0xa8, 0xce, 0x80 + packed.push_back(0xa8); + packed.push_back(0xce); + packed.push_back(0x00); + // group 1 - addend 2: -12 = 0x74 + packed.push_back(0x74); + // group 1 - addend 3: +12 = 0x0c + packed.push_back(0x0c); + + // group 2 + packed.push_back(0x03); // size + packed.push_back(0x0b); // flags + packed.push_back(0x08); // r_offset_delta + packed.push_back(0x01); // r_info + + // group 2 - addend 1: -24 = 0x68 + packed.push_back(0x68); + // group 2 - addend 2: -24 = 0x68 + packed.push_back(0x68); + // group 2 - addend 3: -24 = 0x68 + packed.push_back(0x68); + + std::vector relocations; + + RelocationPacker packer; + + relocations.clear(); + packer.UnpackRelocations(packed, &relocations); + + EXPECT_EQ(6U, relocations.size()); + size_t ndx = 0; + // Initial relocation. + EXPECT_TRUE(CheckRelocation(0xd1ce0000, 0x01, 10024, relocations[ndx++])); + // Two more relocations, 4 byte offset deltas, 12 byte addend deltas. + EXPECT_TRUE(CheckRelocation(0xd1ce0004, 0x01, 10012, relocations[ndx++])); + EXPECT_TRUE(CheckRelocation(0xd1ce0008, 0x01, 10024, relocations[ndx++])); + // Three more relocations, 8 byte offset deltas, -24 byte addend deltas. + EXPECT_TRUE(CheckRelocation(0xd1ce0010, 0x01, 10000, relocations[ndx++])); + EXPECT_TRUE(CheckRelocation(0xd1ce0018, 0x01, 9976, relocations[ndx++])); + EXPECT_TRUE(CheckRelocation(0xd1ce0020, 0x01, 9952, relocations[ndx++])); + + EXPECT_EQ(ndx, relocations.size()); +} + +TEST(Packer, UnpackWithAddend) { + DoUnpackWithAddend(); + DoUnpackWithAddend(); +} + +} // namespace relocation_packer diff --git a/third_party/android_platform/bionic/tools/relocation_packer/src/run_all_unittests.cc b/third_party/android_platform/bionic/tools/relocation_packer/src/run_all_unittests.cc new file mode 100644 index 0000000000000..4122be18cea7d --- /dev/null +++ b/third_party/android_platform/bionic/tools/relocation_packer/src/run_all_unittests.cc @@ -0,0 +1,10 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "testing/gtest/include/gtest/gtest.h" + +int main(int argc, char** argv) { + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/third_party/android_platform/bionic/tools/relocation_packer/src/sleb128.cc b/third_party/android_platform/bionic/tools/relocation_packer/src/sleb128.cc new file mode 100644 index 0000000000000..12c21e3645627 --- /dev/null +++ b/third_party/android_platform/bionic/tools/relocation_packer/src/sleb128.cc @@ -0,0 +1,131 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "sleb128.h" + +#include +#include +#include + +#include "elf_traits.h" + +namespace { + +template +class uint_traits {}; + +template <> +class uint_traits { + public: + typedef int64_t int_t; +}; + +template <> +class uint_traits { + public: + typedef int32_t int_t; +}; + +} + +namespace relocation_packer { + +// Empty constructor and destructor to silence chromium-style. +template +Sleb128Encoder::Sleb128Encoder() { } + +template +Sleb128Encoder::~Sleb128Encoder() { } + +// Add a single value to the encoding. Values are encoded with variable +// length. The least significant 7 bits of each byte hold 7 bits of data, +// and the most significant bit is set on each byte except the last. The +// value is sign extended up to a multiple of 7 bits (ensuring that the +// most significant bit is zero for a positive number and one for a +// negative number). +template +void Sleb128Encoder::Enqueue(uint_t value) { + typedef typename uint_traits::int_t int_t; + static const size_t size = CHAR_BIT * sizeof(value); + + bool more = true; + const bool negative = static_cast(value) < 0; + + while (more) { + uint8_t byte = value & 127; + value >>= 7; + + // Sign extend if encoding a -ve value. + if (negative) + value |= -(static_cast(1) << (size - 7)); + + // The sign bit of byte is second high order bit. + const bool sign_bit = byte & 64; + if ((value == 0 && !sign_bit) || (value == static_cast(-1) && sign_bit)) + more = false; + else + byte |= 128; + encoding_.push_back(byte); + } +} + +// Add a vector of values to the encoding. +template +void Sleb128Encoder::EnqueueAll(const std::vector& values) { + for (size_t i = 0; i < values.size(); ++i) { + Enqueue(values[i]); + } +} + +// Create a new decoder for the given encoded stream. +template +Sleb128Decoder::Sleb128Decoder(const std::vector& encoding, size_t start_with) { + encoding_ = encoding; + cursor_ = start_with; +} + +// Empty destructor to silence chromium-style. +template +Sleb128Decoder::~Sleb128Decoder() { } + +// Decode and retrieve a single value from the encoding. Consume bytes +// until one without its most significant bit is found, and re-form the +// value from the 7 bit fields of the bytes consumed. +template +uint_t Sleb128Decoder::Dequeue() { + uint_t value = 0; + static const size_t size = CHAR_BIT * sizeof(value); + + size_t shift = 0; + uint8_t byte; + + // Loop until we reach a byte with its high order bit clear. + do { + byte = encoding_[cursor_++]; + value |= (static_cast(byte & 127) << shift); + shift += 7; + } while (byte & 128); + + // The sign bit is second high order bit of the final byte decoded. + // Sign extend if value is -ve and we did not shift all of it. + if (shift < size && (byte & 64)) + value |= -(static_cast(1) << shift); + + return static_cast(value); +} + +// Decode and retrieve all remaining values from the encoding. +template +void Sleb128Decoder::DequeueAll(std::vector* values) { + while (cursor_ < encoding_.size()) { + values->push_back(Dequeue()); + } +} + +template class Sleb128Encoder; +template class Sleb128Encoder; +template class Sleb128Decoder; +template class Sleb128Decoder; + +} // namespace relocation_packer diff --git a/third_party/android_platform/bionic/tools/relocation_packer/src/sleb128.h b/third_party/android_platform/bionic/tools/relocation_packer/src/sleb128.h new file mode 100644 index 0000000000000..3a63f66799569 --- /dev/null +++ b/third_party/android_platform/bionic/tools/relocation_packer/src/sleb128.h @@ -0,0 +1,76 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// SLEB128 encoder and decoder for packed relative relocations. +// +// Packed relocations consist of a large number of relatively small +// integer values. Encoding these as LEB128 saves space. +// +// For more on LEB128 see http://en.wikipedia.org/wiki/LEB128. + +#ifndef TOOLS_RELOCATION_PACKER_SRC_SLEB128_H_ +#define TOOLS_RELOCATION_PACKER_SRC_SLEB128_H_ + +#include +#include +#include + +#include "elf_traits.h" + +namespace relocation_packer { + +// Encode packed words as a signed LEB128 byte stream. +template +class Sleb128Encoder { + public: + // Explicit (but empty) constructor and destructor, for chromium-style. + Sleb128Encoder(); + ~Sleb128Encoder(); + + // Add a value to the encoding stream. + // |value| is the signed int to add. + void Enqueue(int_t value); + + // Add a vector of values to the encoding stream. + // |values| is the vector of signed ints to add. + void EnqueueAll(const std::vector& values); + + // Retrieve the encoded representation of the values. + // |encoding| is the returned vector of encoded data. + void GetEncoding(std::vector* encoding) { *encoding = encoding_; } + + private: + // Growable vector holding the encoded LEB128 stream. + std::vector encoding_; +}; + +// Decode a LEB128 byte stream to produce packed words. +template +class Sleb128Decoder { + public: + // Create a new decoder for the given encoded stream. + // |encoding| is the vector of encoded data. + explicit Sleb128Decoder(const std::vector& encoding, size_t start_with); + + // Explicit (but empty) destructor, for chromium-style. + ~Sleb128Decoder(); + + // Retrieve the next value from the encoded stream. + int_t Dequeue(); + + // Retrieve all remaining values from the encoded stream. + // |values| is the vector of decoded data. + void DequeueAll(std::vector* values); + + private: + // Encoded LEB128 stream. + std::vector encoding_; + + // Cursor indicating the current stream retrieval point. + size_t cursor_; +}; + +} // namespace relocation_packer + +#endif // TOOLS_RELOCATION_PACKER_SRC_SLEB128_H_ diff --git a/third_party/android_platform/bionic/tools/relocation_packer/src/sleb128_unittest.cc b/third_party/android_platform/bionic/tools/relocation_packer/src/sleb128_unittest.cc new file mode 100644 index 0000000000000..49a553c2fb196 --- /dev/null +++ b/third_party/android_platform/bionic/tools/relocation_packer/src/sleb128_unittest.cc @@ -0,0 +1,166 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "sleb128.h" + +#include +#include "elf_traits.h" +#include "gtest/gtest.h" + +namespace relocation_packer { + +TEST(Sleb128, Encoder64) { + std::vector values; + values.push_back(624485U); + values.push_back(0U); + values.push_back(1U); + values.push_back(63U); + values.push_back(64U); + values.push_back(static_cast(-1)); + values.push_back(static_cast(-624485)); + + Sleb128Encoder encoder; + encoder.EnqueueAll(values); + + encoder.Enqueue(2147483647U); + encoder.Enqueue(static_cast(-2147483648)); + encoder.Enqueue(9223372036854775807ULL); + encoder.Enqueue(static_cast(-9223372036854775807LL - 1)); + + std::vector encoding; + encoder.GetEncoding(&encoding); + + EXPECT_EQ(42u, encoding.size()); + // 624485 + EXPECT_EQ(0xe5, encoding[0]); + EXPECT_EQ(0x8e, encoding[1]); + EXPECT_EQ(0x26, encoding[2]); + // 0 + EXPECT_EQ(0x00, encoding[3]); + // 1 + EXPECT_EQ(0x01, encoding[4]); + // 63 + EXPECT_EQ(0x3f, encoding[5]); + // 64 + EXPECT_EQ(0xc0, encoding[6]); + EXPECT_EQ(0x00, encoding[7]); + // -1 + EXPECT_EQ(0x7f, encoding[8]); + // -624485 + EXPECT_EQ(0x9b, encoding[9]); + EXPECT_EQ(0xf1, encoding[10]); + EXPECT_EQ(0x59, encoding[11]); + // 2147483647 + EXPECT_EQ(0xff, encoding[12]); + EXPECT_EQ(0xff, encoding[13]); + EXPECT_EQ(0xff, encoding[14]); + EXPECT_EQ(0xff, encoding[15]); + EXPECT_EQ(0x07, encoding[16]); + // -2147483648 + EXPECT_EQ(0x80, encoding[17]); + EXPECT_EQ(0x80, encoding[18]); + EXPECT_EQ(0x80, encoding[19]); + EXPECT_EQ(0x80, encoding[20]); + EXPECT_EQ(0x78, encoding[21]); + // 9223372036854775807 + EXPECT_EQ(0xff, encoding[22]); + EXPECT_EQ(0xff, encoding[23]); + EXPECT_EQ(0xff, encoding[24]); + EXPECT_EQ(0xff, encoding[25]); + EXPECT_EQ(0xff, encoding[26]); + EXPECT_EQ(0xff, encoding[27]); + EXPECT_EQ(0xff, encoding[28]); + EXPECT_EQ(0xff, encoding[29]); + EXPECT_EQ(0xff, encoding[30]); + EXPECT_EQ(0x00, encoding[31]); + // -9223372036854775808 + EXPECT_EQ(0x80, encoding[32]); + EXPECT_EQ(0x80, encoding[33]); + EXPECT_EQ(0x80, encoding[34]); + EXPECT_EQ(0x80, encoding[35]); + EXPECT_EQ(0x80, encoding[36]); + EXPECT_EQ(0x80, encoding[37]); + EXPECT_EQ(0x80, encoding[38]); + EXPECT_EQ(0x80, encoding[39]); + EXPECT_EQ(0x80, encoding[40]); + EXPECT_EQ(0x7f, encoding[41]); +} + +TEST(Sleb128, Decoder) { + std::vector encoding; + // 624485 + encoding.push_back(0xe5); + encoding.push_back(0x8e); + encoding.push_back(0x26); + // 0 + encoding.push_back(0x00); + // 1 + encoding.push_back(0x01); + // 63 + encoding.push_back(0x3f); + // 64 + encoding.push_back(0xc0); + encoding.push_back(0x00); + // -1 + encoding.push_back(0x7f); + // -624485 + encoding.push_back(0x9b); + encoding.push_back(0xf1); + encoding.push_back(0x59); + // 2147483647 + encoding.push_back(0xff); + encoding.push_back(0xff); + encoding.push_back(0xff); + encoding.push_back(0xff); + encoding.push_back(0x07); + // -2147483648 + encoding.push_back(0x80); + encoding.push_back(0x80); + encoding.push_back(0x80); + encoding.push_back(0x80); + encoding.push_back(0x78); + // 9223372036854775807 + encoding.push_back(0xff); + encoding.push_back(0xff); + encoding.push_back(0xff); + encoding.push_back(0xff); + encoding.push_back(0xff); + encoding.push_back(0xff); + encoding.push_back(0xff); + encoding.push_back(0xff); + encoding.push_back(0xff); + encoding.push_back(0x00); + // -9223372036854775808 + encoding.push_back(0x80); + encoding.push_back(0x80); + encoding.push_back(0x80); + encoding.push_back(0x80); + encoding.push_back(0x80); + encoding.push_back(0x80); + encoding.push_back(0x80); + encoding.push_back(0x80); + encoding.push_back(0x80); + encoding.push_back(0x7f); + + Sleb128Decoder decoder(encoding, 0); + + EXPECT_EQ(624485U, decoder.Dequeue()); + + std::vector dequeued; + decoder.DequeueAll(&dequeued); + + EXPECT_EQ(10U, dequeued.size()); + EXPECT_EQ(0U, dequeued[0]); + EXPECT_EQ(1U, dequeued[1]); + EXPECT_EQ(63U, dequeued[2]); + EXPECT_EQ(64U, dequeued[3]); + EXPECT_EQ(static_cast(-1), dequeued[4]); + EXPECT_EQ(static_cast(-624485), dequeued[5]); + EXPECT_EQ(2147483647U, dequeued[6]); + EXPECT_EQ(static_cast(-2147483648), dequeued[7]); + EXPECT_EQ(9223372036854775807ULL, dequeued[8]); + EXPECT_EQ(static_cast(-9223372036854775807LL - 1), dequeued[9]); +} + +} // namespace relocation_packer diff --git a/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs.cc b/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs.cc new file mode 100644 index 0000000000000..5e1fa747e853f --- /dev/null +++ b/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs.cc @@ -0,0 +1,1014 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Test data for packing/unpacking. When compiled, creates a run of +// relative relocations. +// +// See generate_elf_file_unittest_relocs.sh for instructions on how to build +// unit test data from this source file. + +const int i = 0; + +// Generator: +// python -c 'for i in xrange(0,1000):print"const void* pointer_%d = &i;"%i' +const void* pointer_0 = &i; +const void* pointer_1 = &i; +const void* pointer_2 = &i; +const void* pointer_3 = &i; +const void* pointer_4 = &i; +const void* pointer_5 = &i; +const void* pointer_6 = &i; +const void* pointer_7 = &i; +const void* pointer_8 = &i; +const void* pointer_9 = &i; +const void* pointer_10 = &i; +const void* pointer_11 = &i; +const void* pointer_12 = &i; +const void* pointer_13 = &i; +const void* pointer_14 = &i; +const void* pointer_15 = &i; +const void* pointer_16 = &i; +const void* pointer_17 = &i; +const void* pointer_18 = &i; +const void* pointer_19 = &i; +const void* pointer_20 = &i; +const void* pointer_21 = &i; +const void* pointer_22 = &i; +const void* pointer_23 = &i; +const void* pointer_24 = &i; +const void* pointer_25 = &i; +const void* pointer_26 = &i; +const void* pointer_27 = &i; +const void* pointer_28 = &i; +const void* pointer_29 = &i; +const void* pointer_30 = &i; +const void* pointer_31 = &i; +const void* pointer_32 = &i; +const void* pointer_33 = &i; +const void* pointer_34 = &i; +const void* pointer_35 = &i; +const void* pointer_36 = &i; +const void* pointer_37 = &i; +const void* pointer_38 = &i; +const void* pointer_39 = &i; +const void* pointer_40 = &i; +const void* pointer_41 = &i; +const void* pointer_42 = &i; +const void* pointer_43 = &i; +const void* pointer_44 = &i; +const void* pointer_45 = &i; +const void* pointer_46 = &i; +const void* pointer_47 = &i; +const void* pointer_48 = &i; +const void* pointer_49 = &i; +const void* pointer_50 = &i; +const void* pointer_51 = &i; +const void* pointer_52 = &i; +const void* pointer_53 = &i; +const void* pointer_54 = &i; +const void* pointer_55 = &i; +const void* pointer_56 = &i; +const void* pointer_57 = &i; +const void* pointer_58 = &i; +const void* pointer_59 = &i; +const void* pointer_60 = &i; +const void* pointer_61 = &i; +const void* pointer_62 = &i; +const void* pointer_63 = &i; +const void* pointer_64 = &i; +const void* pointer_65 = &i; +const void* pointer_66 = &i; +const void* pointer_67 = &i; +const void* pointer_68 = &i; +const void* pointer_69 = &i; +const void* pointer_70 = &i; +const void* pointer_71 = &i; +const void* pointer_72 = &i; +const void* pointer_73 = &i; +const void* pointer_74 = &i; +const void* pointer_75 = &i; +const void* pointer_76 = &i; +const void* pointer_77 = &i; +const void* pointer_78 = &i; +const void* pointer_79 = &i; +const void* pointer_80 = &i; +const void* pointer_81 = &i; +const void* pointer_82 = &i; +const void* pointer_83 = &i; +const void* pointer_84 = &i; +const void* pointer_85 = &i; +const void* pointer_86 = &i; +const void* pointer_87 = &i; +const void* pointer_88 = &i; +const void* pointer_89 = &i; +const void* pointer_90 = &i; +const void* pointer_91 = &i; +const void* pointer_92 = &i; +const void* pointer_93 = &i; +const void* pointer_94 = &i; +const void* pointer_95 = &i; +const void* pointer_96 = &i; +const void* pointer_97 = &i; +const void* pointer_98 = &i; +const void* pointer_99 = &i; +const void* pointer_100 = &i; +const void* pointer_101 = &i; +const void* pointer_102 = &i; +const void* pointer_103 = &i; +const void* pointer_104 = &i; +const void* pointer_105 = &i; +const void* pointer_106 = &i; +const void* pointer_107 = &i; +const void* pointer_108 = &i; +const void* pointer_109 = &i; +const void* pointer_110 = &i; +const void* pointer_111 = &i; +const void* pointer_112 = &i; +const void* pointer_113 = &i; +const void* pointer_114 = &i; +const void* pointer_115 = &i; +const void* pointer_116 = &i; +const void* pointer_117 = &i; +const void* pointer_118 = &i; +const void* pointer_119 = &i; +const void* pointer_120 = &i; +const void* pointer_121 = &i; +const void* pointer_122 = &i; +const void* pointer_123 = &i; +const void* pointer_124 = &i; +const void* pointer_125 = &i; +const void* pointer_126 = &i; +const void* pointer_127 = &i; +const void* pointer_128 = &i; +const void* pointer_129 = &i; +const void* pointer_130 = &i; +const void* pointer_131 = &i; +const void* pointer_132 = &i; +const void* pointer_133 = &i; +const void* pointer_134 = &i; +const void* pointer_135 = &i; +const void* pointer_136 = &i; +const void* pointer_137 = &i; +const void* pointer_138 = &i; +const void* pointer_139 = &i; +const void* pointer_140 = &i; +const void* pointer_141 = &i; +const void* pointer_142 = &i; +const void* pointer_143 = &i; +const void* pointer_144 = &i; +const void* pointer_145 = &i; +const void* pointer_146 = &i; +const void* pointer_147 = &i; +const void* pointer_148 = &i; +const void* pointer_149 = &i; +const void* pointer_150 = &i; +const void* pointer_151 = &i; +const void* pointer_152 = &i; +const void* pointer_153 = &i; +const void* pointer_154 = &i; +const void* pointer_155 = &i; +const void* pointer_156 = &i; +const void* pointer_157 = &i; +const void* pointer_158 = &i; +const void* pointer_159 = &i; +const void* pointer_160 = &i; +const void* pointer_161 = &i; +const void* pointer_162 = &i; +const void* pointer_163 = &i; +const void* pointer_164 = &i; +const void* pointer_165 = &i; +const void* pointer_166 = &i; +const void* pointer_167 = &i; +const void* pointer_168 = &i; +const void* pointer_169 = &i; +const void* pointer_170 = &i; +const void* pointer_171 = &i; +const void* pointer_172 = &i; +const void* pointer_173 = &i; +const void* pointer_174 = &i; +const void* pointer_175 = &i; +const void* pointer_176 = &i; +const void* pointer_177 = &i; +const void* pointer_178 = &i; +const void* pointer_179 = &i; +const void* pointer_180 = &i; +const void* pointer_181 = &i; +const void* pointer_182 = &i; +const void* pointer_183 = &i; +const void* pointer_184 = &i; +const void* pointer_185 = &i; +const void* pointer_186 = &i; +const void* pointer_187 = &i; +const void* pointer_188 = &i; +const void* pointer_189 = &i; +const void* pointer_190 = &i; +const void* pointer_191 = &i; +const void* pointer_192 = &i; +const void* pointer_193 = &i; +const void* pointer_194 = &i; +const void* pointer_195 = &i; +const void* pointer_196 = &i; +const void* pointer_197 = &i; +const void* pointer_198 = &i; +const void* pointer_199 = &i; +const void* pointer_200 = &i; +const void* pointer_201 = &i; +const void* pointer_202 = &i; +const void* pointer_203 = &i; +const void* pointer_204 = &i; +const void* pointer_205 = &i; +const void* pointer_206 = &i; +const void* pointer_207 = &i; +const void* pointer_208 = &i; +const void* pointer_209 = &i; +const void* pointer_210 = &i; +const void* pointer_211 = &i; +const void* pointer_212 = &i; +const void* pointer_213 = &i; +const void* pointer_214 = &i; +const void* pointer_215 = &i; +const void* pointer_216 = &i; +const void* pointer_217 = &i; +const void* pointer_218 = &i; +const void* pointer_219 = &i; +const void* pointer_220 = &i; +const void* pointer_221 = &i; +const void* pointer_222 = &i; +const void* pointer_223 = &i; +const void* pointer_224 = &i; +const void* pointer_225 = &i; +const void* pointer_226 = &i; +const void* pointer_227 = &i; +const void* pointer_228 = &i; +const void* pointer_229 = &i; +const void* pointer_230 = &i; +const void* pointer_231 = &i; +const void* pointer_232 = &i; +const void* pointer_233 = &i; +const void* pointer_234 = &i; +const void* pointer_235 = &i; +const void* pointer_236 = &i; +const void* pointer_237 = &i; +const void* pointer_238 = &i; +const void* pointer_239 = &i; +const void* pointer_240 = &i; +const void* pointer_241 = &i; +const void* pointer_242 = &i; +const void* pointer_243 = &i; +const void* pointer_244 = &i; +const void* pointer_245 = &i; +const void* pointer_246 = &i; +const void* pointer_247 = &i; +const void* pointer_248 = &i; +const void* pointer_249 = &i; +const void* pointer_250 = &i; +const void* pointer_251 = &i; +const void* pointer_252 = &i; +const void* pointer_253 = &i; +const void* pointer_254 = &i; +const void* pointer_255 = &i; +const void* pointer_256 = &i; +const void* pointer_257 = &i; +const void* pointer_258 = &i; +const void* pointer_259 = &i; +const void* pointer_260 = &i; +const void* pointer_261 = &i; +const void* pointer_262 = &i; +const void* pointer_263 = &i; +const void* pointer_264 = &i; +const void* pointer_265 = &i; +const void* pointer_266 = &i; +const void* pointer_267 = &i; +const void* pointer_268 = &i; +const void* pointer_269 = &i; +const void* pointer_270 = &i; +const void* pointer_271 = &i; +const void* pointer_272 = &i; +const void* pointer_273 = &i; +const void* pointer_274 = &i; +const void* pointer_275 = &i; +const void* pointer_276 = &i; +const void* pointer_277 = &i; +const void* pointer_278 = &i; +const void* pointer_279 = &i; +const void* pointer_280 = &i; +const void* pointer_281 = &i; +const void* pointer_282 = &i; +const void* pointer_283 = &i; +const void* pointer_284 = &i; +const void* pointer_285 = &i; +const void* pointer_286 = &i; +const void* pointer_287 = &i; +const void* pointer_288 = &i; +const void* pointer_289 = &i; +const void* pointer_290 = &i; +const void* pointer_291 = &i; +const void* pointer_292 = &i; +const void* pointer_293 = &i; +const void* pointer_294 = &i; +const void* pointer_295 = &i; +const void* pointer_296 = &i; +const void* pointer_297 = &i; +const void* pointer_298 = &i; +const void* pointer_299 = &i; +const void* pointer_300 = &i; +const void* pointer_301 = &i; +const void* pointer_302 = &i; +const void* pointer_303 = &i; +const void* pointer_304 = &i; +const void* pointer_305 = &i; +const void* pointer_306 = &i; +const void* pointer_307 = &i; +const void* pointer_308 = &i; +const void* pointer_309 = &i; +const void* pointer_310 = &i; +const void* pointer_311 = &i; +const void* pointer_312 = &i; +const void* pointer_313 = &i; +const void* pointer_314 = &i; +const void* pointer_315 = &i; +const void* pointer_316 = &i; +const void* pointer_317 = &i; +const void* pointer_318 = &i; +const void* pointer_319 = &i; +const void* pointer_320 = &i; +const void* pointer_321 = &i; +const void* pointer_322 = &i; +const void* pointer_323 = &i; +const void* pointer_324 = &i; +const void* pointer_325 = &i; +const void* pointer_326 = &i; +const void* pointer_327 = &i; +const void* pointer_328 = &i; +const void* pointer_329 = &i; +const void* pointer_330 = &i; +const void* pointer_331 = &i; +const void* pointer_332 = &i; +const void* pointer_333 = &i; +const void* pointer_334 = &i; +const void* pointer_335 = &i; +const void* pointer_336 = &i; +const void* pointer_337 = &i; +const void* pointer_338 = &i; +const void* pointer_339 = &i; +const void* pointer_340 = &i; +const void* pointer_341 = &i; +const void* pointer_342 = &i; +const void* pointer_343 = &i; +const void* pointer_344 = &i; +const void* pointer_345 = &i; +const void* pointer_346 = &i; +const void* pointer_347 = &i; +const void* pointer_348 = &i; +const void* pointer_349 = &i; +const void* pointer_350 = &i; +const void* pointer_351 = &i; +const void* pointer_352 = &i; +const void* pointer_353 = &i; +const void* pointer_354 = &i; +const void* pointer_355 = &i; +const void* pointer_356 = &i; +const void* pointer_357 = &i; +const void* pointer_358 = &i; +const void* pointer_359 = &i; +const void* pointer_360 = &i; +const void* pointer_361 = &i; +const void* pointer_362 = &i; +const void* pointer_363 = &i; +const void* pointer_364 = &i; +const void* pointer_365 = &i; +const void* pointer_366 = &i; +const void* pointer_367 = &i; +const void* pointer_368 = &i; +const void* pointer_369 = &i; +const void* pointer_370 = &i; +const void* pointer_371 = &i; +const void* pointer_372 = &i; +const void* pointer_373 = &i; +const void* pointer_374 = &i; +const void* pointer_375 = &i; +const void* pointer_376 = &i; +const void* pointer_377 = &i; +const void* pointer_378 = &i; +const void* pointer_379 = &i; +const void* pointer_380 = &i; +const void* pointer_381 = &i; +const void* pointer_382 = &i; +const void* pointer_383 = &i; +const void* pointer_384 = &i; +const void* pointer_385 = &i; +const void* pointer_386 = &i; +const void* pointer_387 = &i; +const void* pointer_388 = &i; +const void* pointer_389 = &i; +const void* pointer_390 = &i; +const void* pointer_391 = &i; +const void* pointer_392 = &i; +const void* pointer_393 = &i; +const void* pointer_394 = &i; +const void* pointer_395 = &i; +const void* pointer_396 = &i; +const void* pointer_397 = &i; +const void* pointer_398 = &i; +const void* pointer_399 = &i; +const void* pointer_400 = &i; +const void* pointer_401 = &i; +const void* pointer_402 = &i; +const void* pointer_403 = &i; +const void* pointer_404 = &i; +const void* pointer_405 = &i; +const void* pointer_406 = &i; +const void* pointer_407 = &i; +const void* pointer_408 = &i; +const void* pointer_409 = &i; +const void* pointer_410 = &i; +const void* pointer_411 = &i; +const void* pointer_412 = &i; +const void* pointer_413 = &i; +const void* pointer_414 = &i; +const void* pointer_415 = &i; +const void* pointer_416 = &i; +const void* pointer_417 = &i; +const void* pointer_418 = &i; +const void* pointer_419 = &i; +const void* pointer_420 = &i; +const void* pointer_421 = &i; +const void* pointer_422 = &i; +const void* pointer_423 = &i; +const void* pointer_424 = &i; +const void* pointer_425 = &i; +const void* pointer_426 = &i; +const void* pointer_427 = &i; +const void* pointer_428 = &i; +const void* pointer_429 = &i; +const void* pointer_430 = &i; +const void* pointer_431 = &i; +const void* pointer_432 = &i; +const void* pointer_433 = &i; +const void* pointer_434 = &i; +const void* pointer_435 = &i; +const void* pointer_436 = &i; +const void* pointer_437 = &i; +const void* pointer_438 = &i; +const void* pointer_439 = &i; +const void* pointer_440 = &i; +const void* pointer_441 = &i; +const void* pointer_442 = &i; +const void* pointer_443 = &i; +const void* pointer_444 = &i; +const void* pointer_445 = &i; +const void* pointer_446 = &i; +const void* pointer_447 = &i; +const void* pointer_448 = &i; +const void* pointer_449 = &i; +const void* pointer_450 = &i; +const void* pointer_451 = &i; +const void* pointer_452 = &i; +const void* pointer_453 = &i; +const void* pointer_454 = &i; +const void* pointer_455 = &i; +const void* pointer_456 = &i; +const void* pointer_457 = &i; +const void* pointer_458 = &i; +const void* pointer_459 = &i; +const void* pointer_460 = &i; +const void* pointer_461 = &i; +const void* pointer_462 = &i; +const void* pointer_463 = &i; +const void* pointer_464 = &i; +const void* pointer_465 = &i; +const void* pointer_466 = &i; +const void* pointer_467 = &i; +const void* pointer_468 = &i; +const void* pointer_469 = &i; +const void* pointer_470 = &i; +const void* pointer_471 = &i; +const void* pointer_472 = &i; +const void* pointer_473 = &i; +const void* pointer_474 = &i; +const void* pointer_475 = &i; +const void* pointer_476 = &i; +const void* pointer_477 = &i; +const void* pointer_478 = &i; +const void* pointer_479 = &i; +const void* pointer_480 = &i; +const void* pointer_481 = &i; +const void* pointer_482 = &i; +const void* pointer_483 = &i; +const void* pointer_484 = &i; +const void* pointer_485 = &i; +const void* pointer_486 = &i; +const void* pointer_487 = &i; +const void* pointer_488 = &i; +const void* pointer_489 = &i; +const void* pointer_490 = &i; +const void* pointer_491 = &i; +const void* pointer_492 = &i; +const void* pointer_493 = &i; +const void* pointer_494 = &i; +const void* pointer_495 = &i; +const void* pointer_496 = &i; +const void* pointer_497 = &i; +const void* pointer_498 = &i; +const void* pointer_499 = &i; +const void* pointer_500 = &i; +const void* pointer_501 = &i; +const void* pointer_502 = &i; +const void* pointer_503 = &i; +const void* pointer_504 = &i; +const void* pointer_505 = &i; +const void* pointer_506 = &i; +const void* pointer_507 = &i; +const void* pointer_508 = &i; +const void* pointer_509 = &i; +const void* pointer_510 = &i; +const void* pointer_511 = &i; +const void* pointer_512 = &i; +const void* pointer_513 = &i; +const void* pointer_514 = &i; +const void* pointer_515 = &i; +const void* pointer_516 = &i; +const void* pointer_517 = &i; +const void* pointer_518 = &i; +const void* pointer_519 = &i; +const void* pointer_520 = &i; +const void* pointer_521 = &i; +const void* pointer_522 = &i; +const void* pointer_523 = &i; +const void* pointer_524 = &i; +const void* pointer_525 = &i; +const void* pointer_526 = &i; +const void* pointer_527 = &i; +const void* pointer_528 = &i; +const void* pointer_529 = &i; +const void* pointer_530 = &i; +const void* pointer_531 = &i; +const void* pointer_532 = &i; +const void* pointer_533 = &i; +const void* pointer_534 = &i; +const void* pointer_535 = &i; +const void* pointer_536 = &i; +const void* pointer_537 = &i; +const void* pointer_538 = &i; +const void* pointer_539 = &i; +const void* pointer_540 = &i; +const void* pointer_541 = &i; +const void* pointer_542 = &i; +const void* pointer_543 = &i; +const void* pointer_544 = &i; +const void* pointer_545 = &i; +const void* pointer_546 = &i; +const void* pointer_547 = &i; +const void* pointer_548 = &i; +const void* pointer_549 = &i; +const void* pointer_550 = &i; +const void* pointer_551 = &i; +const void* pointer_552 = &i; +const void* pointer_553 = &i; +const void* pointer_554 = &i; +const void* pointer_555 = &i; +const void* pointer_556 = &i; +const void* pointer_557 = &i; +const void* pointer_558 = &i; +const void* pointer_559 = &i; +const void* pointer_560 = &i; +const void* pointer_561 = &i; +const void* pointer_562 = &i; +const void* pointer_563 = &i; +const void* pointer_564 = &i; +const void* pointer_565 = &i; +const void* pointer_566 = &i; +const void* pointer_567 = &i; +const void* pointer_568 = &i; +const void* pointer_569 = &i; +const void* pointer_570 = &i; +const void* pointer_571 = &i; +const void* pointer_572 = &i; +const void* pointer_573 = &i; +const void* pointer_574 = &i; +const void* pointer_575 = &i; +const void* pointer_576 = &i; +const void* pointer_577 = &i; +const void* pointer_578 = &i; +const void* pointer_579 = &i; +const void* pointer_580 = &i; +const void* pointer_581 = &i; +const void* pointer_582 = &i; +const void* pointer_583 = &i; +const void* pointer_584 = &i; +const void* pointer_585 = &i; +const void* pointer_586 = &i; +const void* pointer_587 = &i; +const void* pointer_588 = &i; +const void* pointer_589 = &i; +const void* pointer_590 = &i; +const void* pointer_591 = &i; +const void* pointer_592 = &i; +const void* pointer_593 = &i; +const void* pointer_594 = &i; +const void* pointer_595 = &i; +const void* pointer_596 = &i; +const void* pointer_597 = &i; +const void* pointer_598 = &i; +const void* pointer_599 = &i; +const void* pointer_600 = &i; +const void* pointer_601 = &i; +const void* pointer_602 = &i; +const void* pointer_603 = &i; +const void* pointer_604 = &i; +const void* pointer_605 = &i; +const void* pointer_606 = &i; +const void* pointer_607 = &i; +const void* pointer_608 = &i; +const void* pointer_609 = &i; +const void* pointer_610 = &i; +const void* pointer_611 = &i; +const void* pointer_612 = &i; +const void* pointer_613 = &i; +const void* pointer_614 = &i; +const void* pointer_615 = &i; +const void* pointer_616 = &i; +const void* pointer_617 = &i; +const void* pointer_618 = &i; +const void* pointer_619 = &i; +const void* pointer_620 = &i; +const void* pointer_621 = &i; +const void* pointer_622 = &i; +const void* pointer_623 = &i; +const void* pointer_624 = &i; +const void* pointer_625 = &i; +const void* pointer_626 = &i; +const void* pointer_627 = &i; +const void* pointer_628 = &i; +const void* pointer_629 = &i; +const void* pointer_630 = &i; +const void* pointer_631 = &i; +const void* pointer_632 = &i; +const void* pointer_633 = &i; +const void* pointer_634 = &i; +const void* pointer_635 = &i; +const void* pointer_636 = &i; +const void* pointer_637 = &i; +const void* pointer_638 = &i; +const void* pointer_639 = &i; +const void* pointer_640 = &i; +const void* pointer_641 = &i; +const void* pointer_642 = &i; +const void* pointer_643 = &i; +const void* pointer_644 = &i; +const void* pointer_645 = &i; +const void* pointer_646 = &i; +const void* pointer_647 = &i; +const void* pointer_648 = &i; +const void* pointer_649 = &i; +const void* pointer_650 = &i; +const void* pointer_651 = &i; +const void* pointer_652 = &i; +const void* pointer_653 = &i; +const void* pointer_654 = &i; +const void* pointer_655 = &i; +const void* pointer_656 = &i; +const void* pointer_657 = &i; +const void* pointer_658 = &i; +const void* pointer_659 = &i; +const void* pointer_660 = &i; +const void* pointer_661 = &i; +const void* pointer_662 = &i; +const void* pointer_663 = &i; +const void* pointer_664 = &i; +const void* pointer_665 = &i; +const void* pointer_666 = &i; +const void* pointer_667 = &i; +const void* pointer_668 = &i; +const void* pointer_669 = &i; +const void* pointer_670 = &i; +const void* pointer_671 = &i; +const void* pointer_672 = &i; +const void* pointer_673 = &i; +const void* pointer_674 = &i; +const void* pointer_675 = &i; +const void* pointer_676 = &i; +const void* pointer_677 = &i; +const void* pointer_678 = &i; +const void* pointer_679 = &i; +const void* pointer_680 = &i; +const void* pointer_681 = &i; +const void* pointer_682 = &i; +const void* pointer_683 = &i; +const void* pointer_684 = &i; +const void* pointer_685 = &i; +const void* pointer_686 = &i; +const void* pointer_687 = &i; +const void* pointer_688 = &i; +const void* pointer_689 = &i; +const void* pointer_690 = &i; +const void* pointer_691 = &i; +const void* pointer_692 = &i; +const void* pointer_693 = &i; +const void* pointer_694 = &i; +const void* pointer_695 = &i; +const void* pointer_696 = &i; +const void* pointer_697 = &i; +const void* pointer_698 = &i; +const void* pointer_699 = &i; +const void* pointer_700 = &i; +const void* pointer_701 = &i; +const void* pointer_702 = &i; +const void* pointer_703 = &i; +const void* pointer_704 = &i; +const void* pointer_705 = &i; +const void* pointer_706 = &i; +const void* pointer_707 = &i; +const void* pointer_708 = &i; +const void* pointer_709 = &i; +const void* pointer_710 = &i; +const void* pointer_711 = &i; +const void* pointer_712 = &i; +const void* pointer_713 = &i; +const void* pointer_714 = &i; +const void* pointer_715 = &i; +const void* pointer_716 = &i; +const void* pointer_717 = &i; +const void* pointer_718 = &i; +const void* pointer_719 = &i; +const void* pointer_720 = &i; +const void* pointer_721 = &i; +const void* pointer_722 = &i; +const void* pointer_723 = &i; +const void* pointer_724 = &i; +const void* pointer_725 = &i; +const void* pointer_726 = &i; +const void* pointer_727 = &i; +const void* pointer_728 = &i; +const void* pointer_729 = &i; +const void* pointer_730 = &i; +const void* pointer_731 = &i; +const void* pointer_732 = &i; +const void* pointer_733 = &i; +const void* pointer_734 = &i; +const void* pointer_735 = &i; +const void* pointer_736 = &i; +const void* pointer_737 = &i; +const void* pointer_738 = &i; +const void* pointer_739 = &i; +const void* pointer_740 = &i; +const void* pointer_741 = &i; +const void* pointer_742 = &i; +const void* pointer_743 = &i; +const void* pointer_744 = &i; +const void* pointer_745 = &i; +const void* pointer_746 = &i; +const void* pointer_747 = &i; +const void* pointer_748 = &i; +const void* pointer_749 = &i; +const void* pointer_750 = &i; +const void* pointer_751 = &i; +const void* pointer_752 = &i; +const void* pointer_753 = &i; +const void* pointer_754 = &i; +const void* pointer_755 = &i; +const void* pointer_756 = &i; +const void* pointer_757 = &i; +const void* pointer_758 = &i; +const void* pointer_759 = &i; +const void* pointer_760 = &i; +const void* pointer_761 = &i; +const void* pointer_762 = &i; +const void* pointer_763 = &i; +const void* pointer_764 = &i; +const void* pointer_765 = &i; +const void* pointer_766 = &i; +const void* pointer_767 = &i; +const void* pointer_768 = &i; +const void* pointer_769 = &i; +const void* pointer_770 = &i; +const void* pointer_771 = &i; +const void* pointer_772 = &i; +const void* pointer_773 = &i; +const void* pointer_774 = &i; +const void* pointer_775 = &i; +const void* pointer_776 = &i; +const void* pointer_777 = &i; +const void* pointer_778 = &i; +const void* pointer_779 = &i; +const void* pointer_780 = &i; +const void* pointer_781 = &i; +const void* pointer_782 = &i; +const void* pointer_783 = &i; +const void* pointer_784 = &i; +const void* pointer_785 = &i; +const void* pointer_786 = &i; +const void* pointer_787 = &i; +const void* pointer_788 = &i; +const void* pointer_789 = &i; +const void* pointer_790 = &i; +const void* pointer_791 = &i; +const void* pointer_792 = &i; +const void* pointer_793 = &i; +const void* pointer_794 = &i; +const void* pointer_795 = &i; +const void* pointer_796 = &i; +const void* pointer_797 = &i; +const void* pointer_798 = &i; +const void* pointer_799 = &i; +const void* pointer_800 = &i; +const void* pointer_801 = &i; +const void* pointer_802 = &i; +const void* pointer_803 = &i; +const void* pointer_804 = &i; +const void* pointer_805 = &i; +const void* pointer_806 = &i; +const void* pointer_807 = &i; +const void* pointer_808 = &i; +const void* pointer_809 = &i; +const void* pointer_810 = &i; +const void* pointer_811 = &i; +const void* pointer_812 = &i; +const void* pointer_813 = &i; +const void* pointer_814 = &i; +const void* pointer_815 = &i; +const void* pointer_816 = &i; +const void* pointer_817 = &i; +const void* pointer_818 = &i; +const void* pointer_819 = &i; +const void* pointer_820 = &i; +const void* pointer_821 = &i; +const void* pointer_822 = &i; +const void* pointer_823 = &i; +const void* pointer_824 = &i; +const void* pointer_825 = &i; +const void* pointer_826 = &i; +const void* pointer_827 = &i; +const void* pointer_828 = &i; +const void* pointer_829 = &i; +const void* pointer_830 = &i; +const void* pointer_831 = &i; +const void* pointer_832 = &i; +const void* pointer_833 = &i; +const void* pointer_834 = &i; +const void* pointer_835 = &i; +const void* pointer_836 = &i; +const void* pointer_837 = &i; +const void* pointer_838 = &i; +const void* pointer_839 = &i; +const void* pointer_840 = &i; +const void* pointer_841 = &i; +const void* pointer_842 = &i; +const void* pointer_843 = &i; +const void* pointer_844 = &i; +const void* pointer_845 = &i; +const void* pointer_846 = &i; +const void* pointer_847 = &i; +const void* pointer_848 = &i; +const void* pointer_849 = &i; +const void* pointer_850 = &i; +const void* pointer_851 = &i; +const void* pointer_852 = &i; +const void* pointer_853 = &i; +const void* pointer_854 = &i; +const void* pointer_855 = &i; +const void* pointer_856 = &i; +const void* pointer_857 = &i; +const void* pointer_858 = &i; +const void* pointer_859 = &i; +const void* pointer_860 = &i; +const void* pointer_861 = &i; +const void* pointer_862 = &i; +const void* pointer_863 = &i; +const void* pointer_864 = &i; +const void* pointer_865 = &i; +const void* pointer_866 = &i; +const void* pointer_867 = &i; +const void* pointer_868 = &i; +const void* pointer_869 = &i; +const void* pointer_870 = &i; +const void* pointer_871 = &i; +const void* pointer_872 = &i; +const void* pointer_873 = &i; +const void* pointer_874 = &i; +const void* pointer_875 = &i; +const void* pointer_876 = &i; +const void* pointer_877 = &i; +const void* pointer_878 = &i; +const void* pointer_879 = &i; +const void* pointer_880 = &i; +const void* pointer_881 = &i; +const void* pointer_882 = &i; +const void* pointer_883 = &i; +const void* pointer_884 = &i; +const void* pointer_885 = &i; +const void* pointer_886 = &i; +const void* pointer_887 = &i; +const void* pointer_888 = &i; +const void* pointer_889 = &i; +const void* pointer_890 = &i; +const void* pointer_891 = &i; +const void* pointer_892 = &i; +const void* pointer_893 = &i; +const void* pointer_894 = &i; +const void* pointer_895 = &i; +const void* pointer_896 = &i; +const void* pointer_897 = &i; +const void* pointer_898 = &i; +const void* pointer_899 = &i; +const void* pointer_900 = &i; +const void* pointer_901 = &i; +const void* pointer_902 = &i; +const void* pointer_903 = &i; +const void* pointer_904 = &i; +const void* pointer_905 = &i; +const void* pointer_906 = &i; +const void* pointer_907 = &i; +const void* pointer_908 = &i; +const void* pointer_909 = &i; +const void* pointer_910 = &i; +const void* pointer_911 = &i; +const void* pointer_912 = &i; +const void* pointer_913 = &i; +const void* pointer_914 = &i; +const void* pointer_915 = &i; +const void* pointer_916 = &i; +const void* pointer_917 = &i; +const void* pointer_918 = &i; +const void* pointer_919 = &i; +const void* pointer_920 = &i; +const void* pointer_921 = &i; +const void* pointer_922 = &i; +const void* pointer_923 = &i; +const void* pointer_924 = &i; +const void* pointer_925 = &i; +const void* pointer_926 = &i; +const void* pointer_927 = &i; +const void* pointer_928 = &i; +const void* pointer_929 = &i; +const void* pointer_930 = &i; +const void* pointer_931 = &i; +const void* pointer_932 = &i; +const void* pointer_933 = &i; +const void* pointer_934 = &i; +const void* pointer_935 = &i; +const void* pointer_936 = &i; +const void* pointer_937 = &i; +const void* pointer_938 = &i; +const void* pointer_939 = &i; +const void* pointer_940 = &i; +const void* pointer_941 = &i; +const void* pointer_942 = &i; +const void* pointer_943 = &i; +const void* pointer_944 = &i; +const void* pointer_945 = &i; +const void* pointer_946 = &i; +const void* pointer_947 = &i; +const void* pointer_948 = &i; +const void* pointer_949 = &i; +const void* pointer_950 = &i; +const void* pointer_951 = &i; +const void* pointer_952 = &i; +const void* pointer_953 = &i; +const void* pointer_954 = &i; +const void* pointer_955 = &i; +const void* pointer_956 = &i; +const void* pointer_957 = &i; +const void* pointer_958 = &i; +const void* pointer_959 = &i; +const void* pointer_960 = &i; +const void* pointer_961 = &i; +const void* pointer_962 = &i; +const void* pointer_963 = &i; +const void* pointer_964 = &i; +const void* pointer_965 = &i; +const void* pointer_966 = &i; +const void* pointer_967 = &i; +const void* pointer_968 = &i; +const void* pointer_969 = &i; +const void* pointer_970 = &i; +const void* pointer_971 = &i; +const void* pointer_972 = &i; +const void* pointer_973 = &i; +const void* pointer_974 = &i; +const void* pointer_975 = &i; +const void* pointer_976 = &i; +const void* pointer_977 = &i; +const void* pointer_978 = &i; +const void* pointer_979 = &i; +const void* pointer_980 = &i; +const void* pointer_981 = &i; +const void* pointer_982 = &i; +const void* pointer_983 = &i; +const void* pointer_984 = &i; +const void* pointer_985 = &i; +const void* pointer_986 = &i; +const void* pointer_987 = &i; +const void* pointer_988 = &i; +const void* pointer_989 = &i; +const void* pointer_990 = &i; +const void* pointer_991 = &i; +const void* pointer_992 = &i; +const void* pointer_993 = &i; +const void* pointer_994 = &i; +const void* pointer_995 = &i; +const void* pointer_996 = &i; +const void* pointer_997 = &i; +const void* pointer_998 = &i; +const void* pointer_999 = &i; diff --git a/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm32.so b/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm32.so new file mode 100755 index 0000000000000..5e339ae4b52a6 Binary files /dev/null and b/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm32.so differ diff --git a/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm32_packed.so b/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm32_packed.so new file mode 100755 index 0000000000000..253dd97c17741 Binary files /dev/null and b/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm32_packed.so differ diff --git a/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm64.so b/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm64.so new file mode 100755 index 0000000000000..d3d0194da68bc Binary files /dev/null and b/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm64.so differ diff --git a/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm64_packed.so b/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm64_packed.so new file mode 100755 index 0000000000000..269b97554d0c8 Binary files /dev/null and b/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm64_packed.so differ diff --git a/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_ia32.so b/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_ia32.so new file mode 100755 index 0000000000000..42db62c24d4db Binary files /dev/null and b/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_ia32.so differ diff --git a/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_ia32_packed.so b/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_ia32_packed.so new file mode 100755 index 0000000000000..27817cc381e30 Binary files /dev/null and b/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_ia32_packed.so differ diff --git a/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_mips32.so b/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_mips32.so new file mode 100755 index 0000000000000..6da324bb78f6c Binary files /dev/null and b/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_mips32.so differ diff --git a/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_mips32_packed.so b/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_mips32_packed.so new file mode 100755 index 0000000000000..b11ca4883014e Binary files /dev/null and b/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_mips32_packed.so differ diff --git a/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_x64.so b/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_x64.so new file mode 100755 index 0000000000000..6cb689ec534a7 Binary files /dev/null and b/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_x64.so differ diff --git a/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_x64_packed.so b/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_x64_packed.so new file mode 100755 index 0000000000000..60b9ad17921b9 Binary files /dev/null and b/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_x64_packed.so differ diff --git a/third_party/android_platform/development/scripts/stack b/third_party/android_platform/development/scripts/stack index e55f688ed4ed4..c5a56c61e031f 100755 --- a/third_party/android_platform/development/scripts/stack +++ b/third_party/android_platform/development/scripts/stack @@ -18,6 +18,7 @@ import getopt import glob +import logging import os import sys @@ -54,9 +55,12 @@ def PrintUsage(): print " argument information. Also, the 'stack data' section will be" print " printed." print - print " --arch=arm|arm64|x86_64|x86|mips" + print " --arch=arm|arm64|x64|x86|mips" print " the target architecture" print + print " --verbose" + print " enable extra logging, particularly for debugging failed symbolization" + print print " FILE should contain a stack trace in it somewhere" print " the tool will find that and re-print it with" print " source files and line numbers. If you don't" @@ -108,15 +112,16 @@ def UnzipSymbols(symbolfile, symdir=None): return (symdir, symdir) -def main(): +def main(argv): try: - options, arguments = getopt.getopt(sys.argv[1:], "", + options, arguments = getopt.getopt(argv, "", ["more-info", "less-info", "chrome-symbols-dir=", "symbols-dir=", "symbols-zip=", "arch=", + "verbose", "help"]) except getopt.GetoptError, unused_error: PrintUsage() @@ -138,6 +143,8 @@ def main(): more_info = True elif option == "--less-info": more_info = False + elif option == "--verbose": + logging.basicConfig(level=logging.DEBUG) if len(arguments) > 1: PrintUsage() @@ -167,6 +174,6 @@ def main(): os.system(cmd) if __name__ == "__main__": - main() + sys.exit(main(sys.argv[1:])) # vi: ts=2 sw=2 diff --git a/third_party/android_platform/development/scripts/stack_core.py b/third_party/android_platform/development/scripts/stack_core.py index a11fbb4cf97f4..281917f60cbc3 100755 --- a/third_party/android_platform/development/scripts/stack_core.py +++ b/third_party/android_platform/development/scripts/stack_core.py @@ -16,6 +16,7 @@ """stack symbolizes native crash dumps.""" +import logging import re import symbol @@ -74,7 +75,7 @@ def ConvertTrace(lines, more_info): dalvik_native_thread_line = re.compile("(\".*\" sysTid=[0-9]+ nice=[0-9]+.*)") width = "{8}" - if symbol.ARCH == "arm64" or symbol.ARCH == "x86_64": + if symbol.ARCH == "arm64" or symbol.ARCH == "x86_64" or symbol.ARCH == "x64": width = "{16}" # Matches LOG(FATAL) lines, like the following example: @@ -192,6 +193,7 @@ def ConvertTrace(lines, more_info): if match: frame, code_addr, area, symbol_present, symbol_name = match.group( 'frame', 'address', 'lib', 'symbol_present', 'symbol_name') + logging.debug('Found trace line: %s' % line.strip()) if frame <= last_frame and (trace_lines or value_lines): PrintOutput(trace_lines, value_lines, more_info) @@ -203,9 +205,11 @@ def ConvertTrace(lines, more_info): if area == UNKNOWN or area == HEAP or area == STACK: trace_lines.append((code_addr, "", area)) else: + logging.debug('Identified lib: %s' % area) # If a calls b which further calls c and c is inlined to b, we want to # display "a -> b -> c" in the stack trace instead of just "a -> c" info = symbol.SymbolInformation(area, code_addr, more_info) + logging.debug('symbol information: %s' % info) nest_count = len(info) - 1 for (source_symbol, source_location, object_symbol_with_offset) in info: if not source_symbol: diff --git a/third_party/android_platform/development/scripts/symbol.py b/third_party/android_platform/development/scripts/symbol.py index 5069d9e0f3506..4cde7d965afa2 100755 --- a/third_party/android_platform/development/scripts/symbol.py +++ b/third_party/android_platform/development/scripts/symbol.py @@ -21,8 +21,10 @@ import glob import itertools +import logging import os import re +import struct import subprocess import zipfile @@ -36,6 +38,19 @@ TOOLCHAIN_INFO = None +# See: +# http://bugs.python.org/issue14315 +# https://hg.python.org/cpython/rev/6dd5e9556a60#l2.8 +def PatchZipFile(): + oldDecodeExtra = zipfile.ZipInfo._decodeExtra + def decodeExtra(self): + try: + oldDecodeExtra(self) + except struct.error: + pass + zipfile.ZipInfo._decodeExtra = decodeExtra +PatchZipFile() + def Uname(): """'uname' for constructing prebuilt/<...> and out/host/<...> paths.""" uname = os.uname()[0] @@ -64,7 +79,7 @@ def ToolPath(tool, toolchain_info=None): toolchain_source = "x86-4.9" toolchain_prefix = "i686-linux-android" ndk = "ndk" - elif ARCH == "x86_64": + elif ARCH == "x86_64" or ARCH == "x64": toolchain_source = "x86_64-4.9" toolchain_prefix = "x86_64-linux-android" ndk = "ndk" @@ -110,7 +125,7 @@ def FindToolchain(): known_toolchains = [ ("x86-" + gcc_version, "x86", "i686-linux-android") ] - elif ARCH =="x86_64": + elif ARCH =="x86_64" or ARCH =="x64": known_toolchains = [ ("x86_64-" + gcc_version, "x86_64", "x86_64-linux-android") ] @@ -121,6 +136,7 @@ def FindToolchain(): else: known_toolchains = [] + logging.debug('FindToolcahin: known_toolchains=%s' % known_toolchains) # Look for addr2line to check for valid toolchain path. for (label, platform, target) in known_toolchains: toolchain_info = (label, platform, target); @@ -206,10 +222,10 @@ def GetCandidates(dirs, filepart, candidate_fun): candidates = PathListJoin([out_dir], buildtype_list) + [CHROME_SYMBOLS_DIR] candidates = PathListJoin(candidates, dirs) candidates = PathListJoin(candidates, [filepart]) + logging.debug('GetCandidates: prefiltered candidates = %s' % candidates) candidates = list( itertools.chain.from_iterable(map(candidate_fun, candidates))) candidates = sorted(candidates, key=os.path.getmtime, reverse=True) - # candidates = ['/usr/local/google/home/qsr/programmes/mojo/src/out/android_Debug/libmojo_shell.so'] return candidates def GetCandidateApks(): @@ -238,7 +254,13 @@ def GetCrazyLib(apk_filename): if match: return match.group(1) -def GetMatchingApks(device_apk_name): +def GetApkFromLibrary(device_library_path): + match = re.match(r'.*/([^/]*)-[0-9]+(\/[^/]*)?\.apk$', device_library_path) + if not match: + return None + return match.group(1) + +def GetMatchingApks(package_name): """Find any APKs which match the package indicated by the device_apk_name. Args: @@ -247,10 +269,6 @@ def GetMatchingApks(device_apk_name): Returns: A list of APK filenames which could contain the desired library. """ - match = re.match('(.*)-[0-9]+[.]apk$', device_apk_name) - if not match: - return None - package_name = match.group(1) return filter( lambda candidate_apk: ApkMatchPackageName(GetAapt(), candidate_apk, package_name), @@ -266,6 +284,7 @@ def MapDeviceApkToLibrary(device_apk_name): Name of the library which corresponds to that APK. """ matching_apks = GetMatchingApks(device_apk_name) + logging.debug('MapDeviceApkToLibrary: matching_apks=%s' % matching_apks) for matching_apk in matching_apks: crazy_lib = GetCrazyLib(matching_apk) if crazy_lib: @@ -281,18 +300,10 @@ def GetCandidateLibraries(library_name): A list of matching library filenames for library_name. """ return GetCandidates( - ['', 'lib', 'lib.target'], library_name, + ['lib', 'lib.target', '.'], library_name, lambda filename: filter(os.path.exists, [filename])) def TranslateLibPath(lib): - # SymbolInformation(lib, addr) receives lib as the path from symbols - # root to the symbols file. This needs to be translated to point to the - # correct .so path. If the user doesn't explicitly specify which directory to - # use, then use the most recently updated one in one of the known directories. - # If the .so is not found somewhere in CHROME_SYMBOLS_DIR, leave it - # untranslated in case it is an Android symbol in SYMBOLS_DIR. - library_name = os.path.basename(lib) - # The filename in the stack trace maybe an APK name rather than a library # name. This happens when the library was loaded directly from inside the # APK. If this is the case we try to figure out the library name by looking @@ -300,16 +311,30 @@ def TranslateLibPath(lib): # The name of the APK file on the device is of the form # -.apk. The APK file on the host may have any name # so we look at the APK badging to see if the package name matches. - if re.search('-[0-9]+[.]apk$', library_name): - mapping = MapDeviceApkToLibrary(library_name) + apk = GetApkFromLibrary(lib) + if apk is not None: + logging.debug('TranslateLibPath: apk=%s' % apk) + mapping = MapDeviceApkToLibrary(apk) if mapping: - library_name = mapping + lib = mapping + + # SymbolInformation(lib, addr) receives lib as the path from symbols + # root to the symbols file. This needs to be translated to point to the + # correct .so path. If the user doesn't explicitly specify which directory to + # use, then use the most recently updated one in one of the known directories. + # If the .so is not found somewhere in CHROME_SYMBOLS_DIR, leave it + # untranslated in case it is an Android symbol in SYMBOLS_DIR. + library_name = os.path.basename(lib) + + logging.debug('TranslateLibPath: lib=%s library_name=%s' % (lib, library_name)) candidate_libraries = GetCandidateLibraries(library_name) + logging.debug('TranslateLibPath: candidate_libraries=%s' % candidate_libraries) if not candidate_libraries: return lib library_path = os.path.relpath(candidate_libraries[0], SYMBOLS_DIR) + logging.debug('TranslateLibPath: library_path=%s' % library_path) return '/' + library_path def SymbolInformation(lib, addr, get_detailed_info): @@ -427,6 +452,9 @@ def CallAddr2LineForSet(lib, unique_addrs): symbols = SYMBOLS_DIR + lib + if not os.path.splitext(symbols)[1] in ['', '.so', '.apk']: + return None + if not os.path.isfile(symbols): return None diff --git a/third_party/android_platform/relocation_packer.gyp b/third_party/android_platform/relocation_packer.gyp new file mode 100644 index 0000000000000..cb09841fc2f7e --- /dev/null +++ b/third_party/android_platform/relocation_packer.gyp @@ -0,0 +1,87 @@ +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'variables': { + # These files lists are shared with the GN build. + 'relocation_packer_sources': [ + 'bionic/tools/relocation_packer/src/debug.cc', + 'bionic/tools/relocation_packer/src/delta_encoder.cc', + 'bionic/tools/relocation_packer/src/elf_file.cc', + 'bionic/tools/relocation_packer/src/packer.cc', + 'bionic/tools/relocation_packer/src/sleb128.cc', + ], + 'relocation_packer_main_source': [ + 'bionic/tools/relocation_packer/src/main.cc', + ], + 'relocation_packer_test_sources': [ + 'bionic/tools/relocation_packer/src/debug_unittest.cc', + 'bionic/tools/relocation_packer/src/delta_encoder_unittest.cc', + 'bionic/tools/relocation_packer/src/elf_file_unittest.cc', + 'bionic/tools/relocation_packer/src/packer_unittest.cc', + 'bionic/tools/relocation_packer/src/sleb128_unittest.cc', + 'bionic/tools/relocation_packer/src/run_all_unittests.cc', + ], + }, + 'targets': [ + { + # GN: //third_party/android_platform:android_lib_relocation_packer + 'target_name': 'android_lib_relocation_packer', + 'toolsets': ['host'], + 'type': 'static_library', + 'dependencies': [ + '../../third_party/elfutils/elfutils.gyp:libelf', + ], + 'sources': [ + '<@(relocation_packer_sources)' + ], + }, + { + # GN: //third_party/android_platform:android_relocation_packer + 'target_name': 'android_relocation_packer', + 'toolsets': ['host'], + 'type': 'executable', + 'dependencies': [ + '../../third_party/elfutils/elfutils.gyp:libelf', + 'android_lib_relocation_packer', + ], + 'sources': [ + '<@(relocation_packer_main_source)' + ], + }, + { + # TODO(GN) + 'target_name': 'android_relocation_packer_unittests', + 'toolsets': ['host'], + 'type': 'executable', + 'dependencies': [ + '../../testing/gtest.gyp:gtest', + 'android_lib_relocation_packer', + ], + 'include_dirs': [ + '../..', + ], + 'sources': [ + '<@(relocation_packer_test_sources)' + ], + 'copies': [ + { + 'destination': '<(PRODUCT_DIR)', + 'files': [ + 'bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm32.so', + 'bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm32_packed.so', + 'bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm64.so', + 'bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm64_packed.so', + 'bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_ia32.so', + 'bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_ia32_packed.so', + 'bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_x64.so', + 'bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_x64_packed.so', + 'bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_mips32.so', + 'bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_mips32_packed.so', + ], + }, + ], + }, + ], +} diff --git a/third_party/android_platform/webview/frameworks_1597296.jar b/third_party/android_platform/webview/frameworks_1597296.jar deleted file mode 100644 index 1e8ff87f5fbb4..0000000000000 Binary files a/third_party/android_platform/webview/frameworks_1597296.jar and /dev/null differ diff --git a/third_party/android_platform/webview/frameworks_1597296_manifest.xml b/third_party/android_platform/webview/frameworks_1597296_manifest.xml deleted file mode 100644 index 1fff68750c860..0000000000000 --- a/third_party/android_platform/webview/frameworks_1597296_manifest.xml +++ /dev/null @@ -1,507 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/third_party/android_platform/webview/frameworks_5.1.0_r1.jar b/third_party/android_platform/webview/frameworks_5.1.0_r1.jar new file mode 100644 index 0000000000000..4732888319a18 Binary files /dev/null and b/third_party/android_platform/webview/frameworks_5.1.0_r1.jar differ diff --git a/third_party/boringssl/BUILD.gn b/third_party/boringssl/BUILD.gn index e14775476d5a1..a8fe16edb9056 100644 --- a/third_party/boringssl/BUILD.gn +++ b/third_party/boringssl/BUILD.gn @@ -25,7 +25,7 @@ gypi_values = # Windows' assembly is built with Yasm. The other platforms use the platform # assembler. -if (is_win) { +if (is_win && !is_msan) { import("//third_party/yasm/yasm_assemble.gni") yasm_assemble("boringssl_asm") { if (current_cpu == "x64") { @@ -37,7 +37,8 @@ if (is_win) { } component("boringssl") { - sources = gypi_values.boringssl_lib_sources + sources = gypi_values.boringssl_crypto_sources + sources += gypi_values.boringssl_ssl_sources public_configs = [ ":openssl_config" ] @@ -70,8 +71,10 @@ component("boringssl") { "src/crypto", ] - if (current_cpu == "x64") { - if (is_mac) { + if (is_msan) { + defines += [ "OPENSSL_NO_ASM" ] + } else if (current_cpu == "x64") { + if (is_mac || is_ios) { sources += gypi_values.boringssl_mac_x86_64_sources } else if (is_linux || is_android) { sources += gypi_values.boringssl_linux_x86_64_sources @@ -81,7 +84,7 @@ component("boringssl") { defines += [ "OPENSSL_NO_ASM" ] } } else if (current_cpu == "x86") { - if (is_mac) { + if (is_mac || is_ios) { sources += gypi_values.boringssl_mac_x86_sources } else if (is_linux || is_android) { sources += gypi_values.boringssl_linux_x86_sources @@ -90,9 +93,9 @@ component("boringssl") { } else { defines += [ "OPENSSL_NO_ASM" ] } - } else if (current_cpu == "arm") { + } else if (current_cpu == "arm" && (is_linux || is_android)) { sources += gypi_values.boringssl_linux_arm_sources - } else if (current_cpu == "arm64") { + } else if (current_cpu == "arm64" && (is_linux || is_android)) { sources += gypi_values.boringssl_linux_aarch64_sources } else { defines += [ "OPENSSL_NO_ASM" ] diff --git a/third_party/boringssl/DEPS b/third_party/boringssl/DEPS new file mode 100644 index 0000000000000..dda2d7c7fc6f8 --- /dev/null +++ b/third_party/boringssl/DEPS @@ -0,0 +1,6 @@ +specific_include_rules = { + "boringssl_unittest\.cc": [ + "+base", + "+testing", + ], +} diff --git a/third_party/boringssl/OWNERS b/third_party/boringssl/OWNERS index 4d06bf0a7cf80..42d0d3b58b3b6 100644 --- a/third_party/boringssl/OWNERS +++ b/third_party/boringssl/OWNERS @@ -1,4 +1,3 @@ agl@chromium.org -rsleevi@chromium.org -wtc@chromium.org davidben@chromium.org +rsleevi@chromium.org diff --git a/third_party/boringssl/README.chromium b/third_party/boringssl/README.chromium index c4c63c444fd93..8c89faa63339b 100644 --- a/third_party/boringssl/README.chromium +++ b/third_party/boringssl/README.chromium @@ -9,3 +9,10 @@ Security Critical: yes Description: This is BoringSSL, a fork of OpenSSL. See https://www.imperialviolet.org/2014/06/20/boringssl.html + +Note: when rolling DEPS forward, remember to run + + cd third_party/boringssl + python src/util/generate_build_files.py chromium + +from a system with both Perl and Go installed. diff --git a/third_party/boringssl/boringssl.gyp b/third_party/boringssl/boringssl.gyp index 845a920589a2a..5118fc7cc28fb 100644 --- a/third_party/boringssl/boringssl.gyp +++ b/third_party/boringssl/boringssl.gyp @@ -11,7 +11,8 @@ 'boringssl.gypi', ], 'sources': [ - '<@(boringssl_lib_sources)', + '<@(boringssl_crypto_sources)', + '<@(boringssl_ssl_sources)', ], 'defines': [ 'BORINGSSL_IMPLEMENTATION', @@ -26,15 +27,27 @@ 'BORINGSSL_SHARED_LIBRARY', ], }], - ['target_arch == "arm"', { - 'sources': [ '<@(boringssl_linux_arm_sources)' ], + ['target_arch == "arm" and msan == 0', { + 'conditions': [ + ['OS == "linux" or OS == "android"', { + 'sources': [ '<@(boringssl_linux_arm_sources)' ], + }, { + 'defines': [ 'OPENSSL_NO_ASM' ], + }], + ], }], - ['target_arch == "arm64"', { - 'sources': [ '<@(boringssl_linux_aarch64_sources)' ], + ['target_arch == "arm64" and msan == 0', { + 'conditions': [ + ['OS == "linux" or OS == "android"', { + 'sources': [ '<@(boringssl_linux_aarch64_sources)' ], + }, { + 'defines': [ 'OPENSSL_NO_ASM' ], + }], + ], }], - ['target_arch == "ia32"', { + ['target_arch == "ia32" and msan == 0', { 'conditions': [ - ['OS == "mac"', { + ['OS == "mac" or OS == "ios"', { 'sources': [ '<@(boringssl_mac_x86_sources)' ], }], ['OS == "linux" or OS == "android"', { @@ -51,14 +64,14 @@ '../yasm/yasm_compile.gypi', ], }], - ['OS != "mac" and OS != "linux" and OS != "win" and OS != "android"', { + ['OS != "mac" and OS != "ios" and OS != "linux" and OS != "win" and OS != "android"', { 'defines': [ 'OPENSSL_NO_ASM' ], }], ] }], - ['target_arch == "x64"', { + ['target_arch == "x64" and msan == 0', { 'conditions': [ - ['OS == "mac"', { + ['OS == "mac" or OS == "ios"', { 'sources': [ '<@(boringssl_mac_x86_64_sources)' ], }], ['OS == "linux" or OS == "android"', { @@ -75,12 +88,12 @@ '../yasm/yasm_compile.gypi', ], }], - ['OS != "mac" and OS != "linux" and OS != "win" and OS != "android"', { + ['OS != "mac" and OS != "ios" and OS != "linux" and OS != "win" and OS != "android"', { 'defines': [ 'OPENSSL_NO_ASM' ], }], ] }], - ['target_arch != "arm" and target_arch != "ia32" and target_arch != "x64" and target_arch != "arm64"', { + ['msan == 1 or (target_arch != "arm" and target_arch != "ia32" and target_arch != "x64" and target_arch != "arm64")', { 'defines': [ 'OPENSSL_NO_ASM' ], }], ], diff --git a/third_party/boringssl/boringssl.gypi b/third_party/boringssl/boringssl.gypi index d2fc5d4b03477..b8a2a1293a2df 100644 --- a/third_party/boringssl/boringssl.gypi +++ b/third_party/boringssl/boringssl.gypi @@ -2,11 +2,40 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -# This file is created by update_gypi_and_asm.py. Do not edit manually. +# This file is created by generate_build_files.py. Do not edit manually. { 'variables': { - 'boringssl_lib_sources': [ + 'boringssl_ssl_sources': [ + 'src/ssl/d1_both.c', + 'src/ssl/d1_clnt.c', + 'src/ssl/d1_lib.c', + 'src/ssl/d1_meth.c', + 'src/ssl/d1_pkt.c', + 'src/ssl/d1_srtp.c', + 'src/ssl/d1_srvr.c', + 'src/ssl/pqueue/pqueue.c', + 'src/ssl/s3_both.c', + 'src/ssl/s3_clnt.c', + 'src/ssl/s3_enc.c', + 'src/ssl/s3_lib.c', + 'src/ssl/s3_meth.c', + 'src/ssl/s3_pkt.c', + 'src/ssl/s3_srvr.c', + 'src/ssl/ssl_aead_ctx.c', + 'src/ssl/ssl_algs.c', + 'src/ssl/ssl_asn1.c', + 'src/ssl/ssl_cert.c', + 'src/ssl/ssl_cipher.c', + 'src/ssl/ssl_lib.c', + 'src/ssl/ssl_rsa.c', + 'src/ssl/ssl_sess.c', + 'src/ssl/ssl_stat.c', + 'src/ssl/ssl_txt.c', + 'src/ssl/t1_enc.c', + 'src/ssl/t1_lib.c', + ], + 'boringssl_crypto_sources': [ 'err_data.c', 'src/crypto/aes/aes.c', 'src/crypto/aes/mode_wrappers.c', @@ -62,6 +91,7 @@ 'src/crypto/bn/add.c', 'src/crypto/bn/asm/x86_64-gcc.c', 'src/crypto/bn/bn.c', + 'src/crypto/bn/bn_asn1.c', 'src/crypto/bn/cmp.c', 'src/crypto/bn/convert.c', 'src/crypto/bn/ctx.c', @@ -95,6 +125,7 @@ 'src/crypto/cipher/e_ssl3.c', 'src/crypto/cipher/e_tls.c', 'src/crypto/cipher/tls_cbc.c', + 'src/crypto/cmac/cmac.c', 'src/crypto/conf/conf.c', 'src/crypto/cpu-arm.c', 'src/crypto/cpu-intel.c', @@ -117,29 +148,28 @@ 'src/crypto/ec/ec_key.c', 'src/crypto/ec/ec_montgomery.c', 'src/crypto/ec/oct.c', + 'src/crypto/ec/p256-64.c', 'src/crypto/ec/simple.c', + 'src/crypto/ec/util-64.c', 'src/crypto/ec/wnaf.c', 'src/crypto/ecdh/ecdh.c', 'src/crypto/ecdsa/ecdsa.c', 'src/crypto/ecdsa/ecdsa_asn1.c', 'src/crypto/engine/engine.c', 'src/crypto/err/err.c', - 'src/crypto/err/err_impl.c', 'src/crypto/evp/algorithm.c', - 'src/crypto/evp/asn1.c', 'src/crypto/evp/digestsign.c', 'src/crypto/evp/evp.c', + 'src/crypto/evp/evp_asn1.c', 'src/crypto/evp/evp_ctx.c', + 'src/crypto/evp/p_dsa_asn1.c', 'src/crypto/evp/p_ec.c', 'src/crypto/evp/p_ec_asn1.c', - 'src/crypto/evp/p_hmac.c', - 'src/crypto/evp/p_hmac_asn1.c', 'src/crypto/evp/p_rsa.c', 'src/crypto/evp/p_rsa_asn1.c', 'src/crypto/evp/pbkdf.c', 'src/crypto/evp/sign.c', 'src/crypto/ex_data.c', - 'src/crypto/ex_data_impl.c', 'src/crypto/hkdf/hkdf.c', 'src/crypto/hmac/hmac.c', 'src/crypto/lhash/lhash.c', @@ -168,10 +198,13 @@ 'src/crypto/poly1305/poly1305.c', 'src/crypto/poly1305/poly1305_arm.c', 'src/crypto/poly1305/poly1305_vec.c', + 'src/crypto/rand/hwrand.c', 'src/crypto/rand/rand.c', 'src/crypto/rand/urandom.c', 'src/crypto/rand/windows.c', 'src/crypto/rc4/rc4.c', + 'src/crypto/refcount_c11.c', + 'src/crypto/refcount_lock.c', 'src/crypto/rsa/blinding.c', 'src/crypto/rsa/padding.c', 'src/crypto/rsa/rsa.c', @@ -182,6 +215,9 @@ 'src/crypto/sha/sha512.c', 'src/crypto/stack/stack.c', 'src/crypto/thread.c', + 'src/crypto/thread_none.c', + 'src/crypto/thread_pthread.c', + 'src/crypto/thread_win.c', 'src/crypto/time_support.c', 'src/crypto/x509/a_digest.c', 'src/crypto/x509/a_sign.c', @@ -193,6 +229,7 @@ 'src/crypto/x509/i2d_pr.c', 'src/crypto/x509/pkcs7.c', 'src/crypto/x509/t_crl.c', + 'src/crypto/x509/t_req.c', 'src/crypto/x509/t_x509.c', 'src/crypto/x509/t_x509a.c', 'src/crypto/x509/x509.c', @@ -263,48 +300,21 @@ 'src/crypto/x509v3/v3_skey.c', 'src/crypto/x509v3/v3_sxnet.c', 'src/crypto/x509v3/v3_utl.c', - 'src/ssl/d1_both.c', - 'src/ssl/d1_clnt.c', - 'src/ssl/d1_lib.c', - 'src/ssl/d1_meth.c', - 'src/ssl/d1_pkt.c', - 'src/ssl/d1_srtp.c', - 'src/ssl/d1_srvr.c', - 'src/ssl/pqueue/pqueue.c', - 'src/ssl/s3_both.c', - 'src/ssl/s3_clnt.c', - 'src/ssl/s3_enc.c', - 'src/ssl/s3_lib.c', - 'src/ssl/s3_meth.c', - 'src/ssl/s3_pkt.c', - 'src/ssl/s3_srvr.c', - 'src/ssl/ssl_algs.c', - 'src/ssl/ssl_asn1.c', - 'src/ssl/ssl_cert.c', - 'src/ssl/ssl_ciph.c', - 'src/ssl/ssl_lib.c', - 'src/ssl/ssl_rsa.c', - 'src/ssl/ssl_sess.c', - 'src/ssl/ssl_stat.c', - 'src/ssl/ssl_txt.c', - 'src/ssl/t1_enc.c', - 'src/ssl/t1_lib.c', - 'src/ssl/t1_reneg.c', ], 'boringssl_linux_aarch64_sources': [ - 'linux-aarch64/crypto/aes/aesv8-armx.S', - 'linux-aarch64/crypto/modes/ghashv8-armx.S', + 'linux-aarch64/crypto/aes/aesv8-armx64.S', + 'linux-aarch64/crypto/modes/ghashv8-armx64.S', 'linux-aarch64/crypto/sha/sha1-armv8.S', 'linux-aarch64/crypto/sha/sha256-armv8.S', 'linux-aarch64/crypto/sha/sha512-armv8.S', ], 'boringssl_linux_arm_sources': [ 'linux-arm/crypto/aes/aes-armv4.S', - 'linux-arm/crypto/aes/aesv8-armx.S', + 'linux-arm/crypto/aes/aesv8-armx32.S', 'linux-arm/crypto/aes/bsaes-armv7.S', 'linux-arm/crypto/bn/armv4-mont.S', 'linux-arm/crypto/modes/ghash-armv4.S', - 'linux-arm/crypto/modes/ghashv8-armx.S', + 'linux-arm/crypto/modes/ghashv8-armx32.S', 'linux-arm/crypto/sha/sha1-armv4-large.S', 'linux-arm/crypto/sha/sha256-armv4.S', 'linux-arm/crypto/sha/sha512-armv4.S', @@ -340,6 +350,7 @@ 'linux-x86_64/crypto/md5/md5-x86_64.S', 'linux-x86_64/crypto/modes/aesni-gcm-x86_64.S', 'linux-x86_64/crypto/modes/ghash-x86_64.S', + 'linux-x86_64/crypto/rand/rdrand-x86_64.S', 'linux-x86_64/crypto/rc4/rc4-md5-x86_64.S', 'linux-x86_64/crypto/rc4/rc4-x86_64.S', 'linux-x86_64/crypto/sha/sha1-x86_64.S', @@ -374,6 +385,7 @@ 'mac-x86_64/crypto/md5/md5-x86_64.S', 'mac-x86_64/crypto/modes/aesni-gcm-x86_64.S', 'mac-x86_64/crypto/modes/ghash-x86_64.S', + 'mac-x86_64/crypto/rand/rdrand-x86_64.S', 'mac-x86_64/crypto/rc4/rc4-md5-x86_64.S', 'mac-x86_64/crypto/rc4/rc4-x86_64.S', 'mac-x86_64/crypto/sha/sha1-x86_64.S', @@ -408,6 +420,7 @@ 'win-x86_64/crypto/md5/md5-x86_64.asm', 'win-x86_64/crypto/modes/aesni-gcm-x86_64.asm', 'win-x86_64/crypto/modes/ghash-x86_64.asm', + 'win-x86_64/crypto/rand/rdrand-x86_64.asm', 'win-x86_64/crypto/rc4/rc4-md5-x86_64.asm', 'win-x86_64/crypto/rc4/rc4-x86_64.asm', 'win-x86_64/crypto/sha/sha1-x86_64.asm', diff --git a/third_party/boringssl/boringssl_nacl.gyp b/third_party/boringssl/boringssl_nacl.gyp index 6ab4b9d79aecd..e560c29e9c375 100644 --- a/third_party/boringssl/boringssl_nacl.gyp +++ b/third_party/boringssl/boringssl_nacl.gyp @@ -16,7 +16,6 @@ 'build_pnacl_newlib': 1, }, 'dependencies': [ - '<(DEPTH)/native_client/tools.gyp:prep_toolchain', '<(DEPTH)/native_client_sdk/native_client_sdk_untrusted.gyp:nacl_io_untrusted', ], 'includes': [ @@ -24,7 +23,8 @@ 'boringssl.gypi' ], 'sources': [ - '<@(boringssl_lib_sources)', + '<@(boringssl_crypto_sources)', + '<@(boringssl_ssl_sources)', ], 'defines': [ 'OPENSSL_NO_ASM', diff --git a/third_party/boringssl/boringssl_tests.gypi b/third_party/boringssl/boringssl_tests.gypi index 0373742cbe96b..675b9132494fe 100644 --- a/third_party/boringssl/boringssl_tests.gypi +++ b/third_party/boringssl/boringssl_tests.gypi @@ -2,10 +2,24 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -# This file is created by update_gypi_and_asm.py. Do not edit manually. +# This file is created by generate_build_files.py. Do not edit manually. { 'targets': [ + { + 'target_name': 'boringssl_aes_test', + 'type': 'executable', + 'dependencies': [ + 'boringssl.gyp:boringssl', + ], + 'sources': [ + 'src/crypto/aes/aes_test.cc', + '<@(boringssl_test_support_sources)', + ], + # TODO(davidben): Fix size_t truncations in BoringSSL. + # https://crbug.com/429039 + 'msvs_disabled_warnings': [ 4267, ], + }, { 'target_name': 'boringssl_base64_test', 'type': 'executable', @@ -13,7 +27,8 @@ 'boringssl.gyp:boringssl', ], 'sources': [ - 'src/crypto/base64/base64_test.c', + 'src/crypto/base64/base64_test.cc', + '<@(boringssl_test_support_sources)', ], # TODO(davidben): Fix size_t truncations in BoringSSL. # https://crbug.com/429039 @@ -26,7 +41,8 @@ 'boringssl.gyp:boringssl', ], 'sources': [ - 'src/crypto/bio/bio_test.c', + 'src/crypto/bio/bio_test.cc', + '<@(boringssl_test_support_sources)', ], # TODO(davidben): Fix size_t truncations in BoringSSL. # https://crbug.com/429039 @@ -39,7 +55,8 @@ 'boringssl.gyp:boringssl', ], 'sources': [ - 'src/crypto/bn/bn_test.c', + 'src/crypto/bn/bn_test.cc', + '<@(boringssl_test_support_sources)', ], # TODO(davidben): Fix size_t truncations in BoringSSL. # https://crbug.com/429039 @@ -52,7 +69,8 @@ 'boringssl.gyp:boringssl', ], 'sources': [ - 'src/crypto/bytestring/bytestring_test.c', + 'src/crypto/bytestring/bytestring_test.cc', + '<@(boringssl_test_support_sources)', ], # TODO(davidben): Fix size_t truncations in BoringSSL. # https://crbug.com/429039 @@ -65,7 +83,8 @@ 'boringssl.gyp:boringssl', ], 'sources': [ - 'src/crypto/cipher/aead_test.c', + 'src/crypto/cipher/aead_test.cc', + '<@(boringssl_test_support_sources)', ], # TODO(davidben): Fix size_t truncations in BoringSSL. # https://crbug.com/429039 @@ -78,7 +97,22 @@ 'boringssl.gyp:boringssl', ], 'sources': [ - 'src/crypto/cipher/cipher_test.c', + 'src/crypto/cipher/cipher_test.cc', + '<@(boringssl_test_support_sources)', + ], + # TODO(davidben): Fix size_t truncations in BoringSSL. + # https://crbug.com/429039 + 'msvs_disabled_warnings': [ 4267, ], + }, + { + 'target_name': 'boringssl_cmac_test', + 'type': 'executable', + 'dependencies': [ + 'boringssl.gyp:boringssl', + ], + 'sources': [ + 'src/crypto/cmac/cmac_test.cc', + '<@(boringssl_test_support_sources)', ], # TODO(davidben): Fix size_t truncations in BoringSSL. # https://crbug.com/429039 @@ -92,6 +126,7 @@ ], 'sources': [ 'src/crypto/constant_time_test.c', + '<@(boringssl_test_support_sources)', ], # TODO(davidben): Fix size_t truncations in BoringSSL. # https://crbug.com/429039 @@ -104,7 +139,8 @@ 'boringssl.gyp:boringssl', ], 'sources': [ - 'src/crypto/dh/dh_test.c', + 'src/crypto/dh/dh_test.cc', + '<@(boringssl_test_support_sources)', ], # TODO(davidben): Fix size_t truncations in BoringSSL. # https://crbug.com/429039 @@ -117,7 +153,8 @@ 'boringssl.gyp:boringssl', ], 'sources': [ - 'src/crypto/digest/digest_test.c', + 'src/crypto/digest/digest_test.cc', + '<@(boringssl_test_support_sources)', ], # TODO(davidben): Fix size_t truncations in BoringSSL. # https://crbug.com/429039 @@ -131,6 +168,7 @@ ], 'sources': [ 'src/crypto/dsa/dsa_test.c', + '<@(boringssl_test_support_sources)', ], # TODO(davidben): Fix size_t truncations in BoringSSL. # https://crbug.com/429039 @@ -143,7 +181,8 @@ 'boringssl.gyp:boringssl', ], 'sources': [ - 'src/crypto/ec/ec_test.c', + 'src/crypto/ec/ec_test.cc', + '<@(boringssl_test_support_sources)', ], # TODO(davidben): Fix size_t truncations in BoringSSL. # https://crbug.com/429039 @@ -157,6 +196,7 @@ ], 'sources': [ 'src/crypto/ec/example_mul.c', + '<@(boringssl_test_support_sources)', ], # TODO(davidben): Fix size_t truncations in BoringSSL. # https://crbug.com/429039 @@ -169,7 +209,8 @@ 'boringssl.gyp:boringssl', ], 'sources': [ - 'src/crypto/ecdsa/ecdsa_test.c', + 'src/crypto/ecdsa/ecdsa_test.cc', + '<@(boringssl_test_support_sources)', ], # TODO(davidben): Fix size_t truncations in BoringSSL. # https://crbug.com/429039 @@ -182,7 +223,22 @@ 'boringssl.gyp:boringssl', ], 'sources': [ - 'src/crypto/err/err_test.c', + 'src/crypto/err/err_test.cc', + '<@(boringssl_test_support_sources)', + ], + # TODO(davidben): Fix size_t truncations in BoringSSL. + # https://crbug.com/429039 + 'msvs_disabled_warnings': [ 4267, ], + }, + { + 'target_name': 'boringssl_evp_extra_test', + 'type': 'executable', + 'dependencies': [ + 'boringssl.gyp:boringssl', + ], + 'sources': [ + 'src/crypto/evp/evp_extra_test.cc', + '<@(boringssl_test_support_sources)', ], # TODO(davidben): Fix size_t truncations in BoringSSL. # https://crbug.com/429039 @@ -195,7 +251,8 @@ 'boringssl.gyp:boringssl', ], 'sources': [ - 'src/crypto/evp/evp_test.c', + 'src/crypto/evp/evp_test.cc', + '<@(boringssl_test_support_sources)', ], # TODO(davidben): Fix size_t truncations in BoringSSL. # https://crbug.com/429039 @@ -208,7 +265,8 @@ 'boringssl.gyp:boringssl', ], 'sources': [ - 'src/crypto/evp/pbkdf_test.c', + 'src/crypto/evp/pbkdf_test.cc', + '<@(boringssl_test_support_sources)', ], # TODO(davidben): Fix size_t truncations in BoringSSL. # https://crbug.com/429039 @@ -222,6 +280,7 @@ ], 'sources': [ 'src/crypto/hkdf/hkdf_test.c', + '<@(boringssl_test_support_sources)', ], # TODO(davidben): Fix size_t truncations in BoringSSL. # https://crbug.com/429039 @@ -234,7 +293,8 @@ 'boringssl.gyp:boringssl', ], 'sources': [ - 'src/crypto/hmac/hmac_test.c', + 'src/crypto/hmac/hmac_test.cc', + '<@(boringssl_test_support_sources)', ], # TODO(davidben): Fix size_t truncations in BoringSSL. # https://crbug.com/429039 @@ -248,6 +308,7 @@ ], 'sources': [ 'src/crypto/lhash/lhash_test.c', + '<@(boringssl_test_support_sources)', ], # TODO(davidben): Fix size_t truncations in BoringSSL. # https://crbug.com/429039 @@ -261,6 +322,7 @@ ], 'sources': [ 'src/crypto/modes/gcm_test.c', + '<@(boringssl_test_support_sources)', ], # TODO(davidben): Fix size_t truncations in BoringSSL. # https://crbug.com/429039 @@ -273,7 +335,36 @@ 'boringssl.gyp:boringssl', ], 'sources': [ - 'src/crypto/pkcs8/pkcs12_test.c', + 'src/crypto/pkcs8/pkcs12_test.cc', + '<@(boringssl_test_support_sources)', + ], + # TODO(davidben): Fix size_t truncations in BoringSSL. + # https://crbug.com/429039 + 'msvs_disabled_warnings': [ 4267, ], + }, + { + 'target_name': 'boringssl_poly1305_test', + 'type': 'executable', + 'dependencies': [ + 'boringssl.gyp:boringssl', + ], + 'sources': [ + 'src/crypto/poly1305/poly1305_test.cc', + '<@(boringssl_test_support_sources)', + ], + # TODO(davidben): Fix size_t truncations in BoringSSL. + # https://crbug.com/429039 + 'msvs_disabled_warnings': [ 4267, ], + }, + { + 'target_name': 'boringssl_refcount_test', + 'type': 'executable', + 'dependencies': [ + 'boringssl.gyp:boringssl', + ], + 'sources': [ + 'src/crypto/refcount_test.c', + '<@(boringssl_test_support_sources)', ], # TODO(davidben): Fix size_t truncations in BoringSSL. # https://crbug.com/429039 @@ -286,7 +377,22 @@ 'boringssl.gyp:boringssl', ], 'sources': [ - 'src/crypto/rsa/rsa_test.c', + 'src/crypto/rsa/rsa_test.cc', + '<@(boringssl_test_support_sources)', + ], + # TODO(davidben): Fix size_t truncations in BoringSSL. + # https://crbug.com/429039 + 'msvs_disabled_warnings': [ 4267, ], + }, + { + 'target_name': 'boringssl_thread_test', + 'type': 'executable', + 'dependencies': [ + 'boringssl.gyp:boringssl', + ], + 'sources': [ + 'src/crypto/thread_test.c', + '<@(boringssl_test_support_sources)', ], # TODO(davidben): Fix size_t truncations in BoringSSL. # https://crbug.com/429039 @@ -300,6 +406,35 @@ ], 'sources': [ 'src/crypto/x509/pkcs7_test.c', + '<@(boringssl_test_support_sources)', + ], + # TODO(davidben): Fix size_t truncations in BoringSSL. + # https://crbug.com/429039 + 'msvs_disabled_warnings': [ 4267, ], + }, + { + 'target_name': 'boringssl_tab_test', + 'type': 'executable', + 'dependencies': [ + 'boringssl.gyp:boringssl', + ], + 'sources': [ + 'src/crypto/x509v3/tab_test.c', + '<@(boringssl_test_support_sources)', + ], + # TODO(davidben): Fix size_t truncations in BoringSSL. + # https://crbug.com/429039 + 'msvs_disabled_warnings': [ 4267, ], + }, + { + 'target_name': 'boringssl_v3name_test', + 'type': 'executable', + 'dependencies': [ + 'boringssl.gyp:boringssl', + ], + 'sources': [ + 'src/crypto/x509v3/v3name_test.c', + '<@(boringssl_test_support_sources)', ], # TODO(davidben): Fix size_t truncations in BoringSSL. # https://crbug.com/429039 @@ -313,6 +448,7 @@ ], 'sources': [ 'src/ssl/pqueue/pqueue_test.c', + '<@(boringssl_test_support_sources)', ], # TODO(davidben): Fix size_t truncations in BoringSSL. # https://crbug.com/429039 @@ -325,7 +461,8 @@ 'boringssl.gyp:boringssl', ], 'sources': [ - 'src/ssl/ssl_test.c', + 'src/ssl/ssl_test.cc', + '<@(boringssl_test_support_sources)', ], # TODO(davidben): Fix size_t truncations in BoringSSL. # https://crbug.com/429039 @@ -333,13 +470,19 @@ }, ], 'variables': { + 'boringssl_test_support_sources': [ + 'src/crypto/test/file_test.cc', + 'src/crypto/test/malloc.cc', + ], 'boringssl_test_targets': [ 'boringssl_aead_test', + 'boringssl_aes_test', 'boringssl_base64_test', 'boringssl_bio_test', 'boringssl_bn_test', 'boringssl_bytestring_test', 'boringssl_cipher_test', + 'boringssl_cmac_test', 'boringssl_constant_time_test', 'boringssl_dh_test', 'boringssl_digest_test', @@ -347,6 +490,7 @@ 'boringssl_ec_test', 'boringssl_ecdsa_test', 'boringssl_err_test', + 'boringssl_evp_extra_test', 'boringssl_evp_test', 'boringssl_example_mul', 'boringssl_gcm_test', @@ -356,9 +500,14 @@ 'boringssl_pbkdf_test', 'boringssl_pkcs12_test', 'boringssl_pkcs7_test', + 'boringssl_poly1305_test', 'boringssl_pqueue_test', + 'boringssl_refcount_test', 'boringssl_rsa_test', 'boringssl_ssl_test', + 'boringssl_tab_test', + 'boringssl_thread_test', + 'boringssl_v3name_test', ], } } diff --git a/third_party/boringssl/boringssl_unittest.cc b/third_party/boringssl/boringssl_unittest.cc index d568e33e9755b..75b9db80bfcb6 100644 --- a/third_party/boringssl/boringssl_unittest.cc +++ b/third_party/boringssl/boringssl_unittest.cc @@ -32,7 +32,7 @@ void TestProcess(const std::string& name, std::string output; EXPECT_TRUE(base::GetAppOutput(cmd, &output)); // Account for Windows line endings. - ReplaceSubstringsAfterOffset(&output, 0, "\r\n", "\n"); + base::ReplaceSubstringsAfterOffset(&output, 0, "\r\n", "\n"); const bool ok = output.size() >= 5 && memcmp("PASS\n", &output[output.size() - 5], 5) == 0 && @@ -141,6 +141,10 @@ TEST(BoringSSL, AEADs) { } } +TEST(BoringSSL, AES) { + TestSimple("aes_test"); +} + TEST(BoringSSL, Base64) { TestSimple("base64_test"); } @@ -157,10 +161,6 @@ TEST(BoringSSL, ByteString) { TestSimple("bytestring_test"); } -TEST(BoringSSL, ConstantTime) { - TestSimple("constant_time_test"); -} - TEST(BoringSSL, Cipher) { base::FilePath data_file; ASSERT_TRUE(CryptoCipherTestPath(&data_file)); @@ -172,6 +172,14 @@ TEST(BoringSSL, Cipher) { TestProcess("cipher_test", args); } +TEST(BoringSSL, CMAC) { + TestSimple("cmac_test"); +} + +TEST(BoringSSL, ConstantTime) { + TestSimple("constant_time_test"); +} + TEST(BoringSSL, DH) { TestSimple("dh_test"); } @@ -196,20 +204,67 @@ TEST(BoringSSL, ERR) { TestSimple("err_test"); } +TEST(BoringSSL, EVP) { + base::FilePath data_file; + ASSERT_TRUE(BoringSSLPath(&data_file)); + data_file = data_file.Append(FILE_PATH_LITERAL("crypto")); + data_file = data_file.Append(FILE_PATH_LITERAL("evp")); + data_file = data_file.Append(FILE_PATH_LITERAL("evp_tests.txt")); + + std::vector args; + args.push_back(data_file.value()); + + TestProcess("evp_test", args); +} + +TEST(BoringSSL, EVPExtra) { + TestSimple("evp_extra_test"); +} + +TEST(BoringSSL, ExampleMul) { + TestSimple("example_mul"); +} + TEST(BoringSSL, GCM) { TestSimple("gcm_test"); } +TEST(BoringSSL, HKDF) { + TestSimple("hkdf_test"); +} + TEST(BoringSSL, HMAC) { - TestSimple("hmac_test"); + base::FilePath data_file; + ASSERT_TRUE(BoringSSLPath(&data_file)); + data_file = data_file.Append(FILE_PATH_LITERAL("crypto")); + data_file = data_file.Append(FILE_PATH_LITERAL("hmac")); + data_file = data_file.Append(FILE_PATH_LITERAL("hmac_tests.txt")); + + std::vector args; + args.push_back(data_file.value()); + + TestProcess("hmac_test", args); } TEST(BoringSSL, LH) { TestSimple("lhash_test"); } -TEST(BoringSSL, RSA) { - TestSimple("rsa_test"); +TEST(BoringSSL, PBKDF) { + TestSimple("pbkdf_test"); +} + +TEST(BoringSSL, Poly1305) { + base::FilePath data_file; + ASSERT_TRUE(BoringSSLPath(&data_file)); + data_file = data_file.Append(FILE_PATH_LITERAL("crypto")); + data_file = data_file.Append(FILE_PATH_LITERAL("poly1305")); + data_file = data_file.Append(FILE_PATH_LITERAL("poly1305_test.txt")); + + std::vector args; + args.push_back(data_file.value()); + + TestProcess("poly1305_test", args); } TEST(BoringSSL, PKCS7) { @@ -220,26 +275,30 @@ TEST(BoringSSL, PKCS12) { TestSimple("pkcs12_test"); } -TEST(BoringSSL, ExampleMul) { - TestSimple("example_mul"); +TEST(BoringSSL, PQueue) { + TestSimple("pqueue_test"); } -TEST(BoringSSL, EVP) { - TestSimple("evp_test"); +TEST(BoringSSL, RefcountTest) { + TestSimple("refcount_test"); +} + +TEST(BoringSSL, RSA) { + TestSimple("rsa_test"); } TEST(BoringSSL, SSL) { TestSimple("ssl_test"); } -TEST(BoringSSL, PQueue) { - TestSimple("pqueue_test"); +TEST(BoringSSL, TabTest) { + TestSimple("tab_test"); } -TEST(BoringSSL, HKDF) { - TestSimple("hkdf_test"); +TEST(BoringSSL, Thread) { + TestSimple("thread_test"); } -TEST(BoringSSL, PBKDF) { - TestSimple("pbkdf_test"); +TEST(BoringSSL, V3NameTest) { + TestSimple("v3name_test"); } diff --git a/third_party/boringssl/err_data.c b/third_party/boringssl/err_data.c index fe8e3d469cd13..ddb7eb49f01cd 100644 --- a/third_party/boringssl/err_data.c +++ b/third_party/boringssl/err_data.c @@ -54,219 +54,246 @@ OPENSSL_COMPILE_ASSERT(ERR_LIB_HKDF == 32, library_values_changed_32); OPENSSL_COMPILE_ASSERT(ERR_NUM_LIBS == 33, library_values_changed_num); const uint32_t kOpenSSLFunctionValues[] = { - 0xc320540, - 0xc32854b, - 0xc330556, - 0xc338563, - 0xc34056d, - 0xc348577, - 0xc35057e, - 0xc35858a, - 0xc360591, - 0xc3685a7, - 0xc3705bc, - 0xc3785cd, - 0xc3805dd, - 0xc3885f7, - 0xc39060c, - 0xc39861b, - 0xc3a0634, - 0xc3a8648, - 0xc3b0654, - 0xc3b865b, - 0xc3c0663, - 0xc3c8671, - 0xc3d0679, - 0xc3d8681, - 0xc3e068c, - 0x103217ce, - 0x103297e5, - 0x103317fe, - 0x10339814, - 0x10341824, - 0x10349837, - 0x10351845, - 0x10359854, - 0x10361874, - 0x10369893, - 0x103718b0, - 0x103798cd, - 0x103818e2, - 0x10389904, - 0x10391923, - 0x10399942, - 0x103a1959, - 0x103a9970, - 0x103b1979, - 0x103b9984, - 0x103c199e, - 0x103c99a6, - 0x103d19ae, - 0x103d99b5, - 0x103e19c8, - 0x103e99da, - 0x103f19ed, - 0x103f99f6, - 0x14320a25, - 0x14328a33, - 0x14330a3f, - 0x14338a4c, - 0x18321065, - 0x1832907d, - 0x1833109f, - 0x183390b1, - 0x183410e3, - 0x183490fc, - 0x1835110d, - 0x18359123, - 0x18361133, - 0x18369148, - 0x18371161, - 0x18379172, - 0x18381188, - 0x18389199, - 0x183911ab, - 0x183991c0, - 0x183a11d2, - 0x183a91e2, - 0x183b11f7, - 0x183b9204, - 0x183c1216, - 0x183c9224, - 0x183d1237, - 0x183d9247, - 0x183e125c, - 0x183e926d, - 0x183f1280, - 0x183f928f, - 0x1840129f, - 0x184092ac, - 0x184112bb, - 0x184192cc, - 0x184212df, - 0x184292f1, - 0x18431303, - 0x18439314, - 0x18441325, - 0x18449336, - 0x18451347, - 0x18459354, - 0x18461362, - 0x18469375, - 0x18471389, - 0x18479396, - 0x184813a5, - 0x184893b4, - 0x184913c5, - 0x184993e1, - 0x184a13ef, - 0x184a9400, - 0x184b1411, - 0x184b941f, - 0x184c142f, - 0x184c9455, - 0x184d1464, - 0x184d9474, - 0x184e1484, - 0x184e9493, - 0x184f13d2, - 0x184f90c2, - 0x1c320699, - 0x1c3286a5, - 0x1c3306b0, - 0x1c3386bc, - 0x203214a7, - 0x203294b2, - 0x203314ba, - 0x203394c6, - 0x243214d2, - 0x243294e0, - 0x243314f2, - 0x24339501, - 0x24341514, - 0x24349527, - 0x2435153e, - 0x24359556, - 0x24361564, - 0x2436957c, - 0x24371585, - 0x24379597, - 0x243815ab, - 0x243895b8, - 0x243915ce, - 0x243995e6, - 0x243a15fe, - 0x243a9608, - 0x243b161d, - 0x243b962b, - 0x243c1643, - 0x243c965a, - 0x243d1665, - 0x243d9673, - 0x28320a85, - 0x28328a94, - 0x28330a9f, - 0x28338aa4, - 0x28340aaf, - 0x2c3228da, - 0x2c32a8e6, - 0x2c3328f9, - 0x2c33a90a, - 0x2c342923, - 0x2c34a94b, - 0x2c352962, - 0x2c35a97f, - 0x2c36299c, - 0x2c36a9b9, - 0x2c3729d2, - 0x2c37a9eb, - 0x2c382a01, - 0x2c38aa0f, - 0x2c392a21, - 0x2c39aa3e, - 0x2c3a2a5b, - 0x2c3aaa69, - 0x2c3b2a87, - 0x2c3baaa5, - 0x2c3c2ac0, - 0x2c3caad4, - 0x2c3d2ae6, - 0x2c3daaf6, - 0x2c3e2b04, - 0x2c3eab14, - 0x2c3f2b24, - 0x2c3fab3f, - 0x2c402b50, - 0x2c40ab6b, - 0x2c412b7f, - 0x2c41ab92, - 0x2c422bb1, - 0x2c42abc5, - 0x2c432bd8, - 0x2c43abe7, - 0x2c442bf6, - 0x2c44ac0d, - 0x2c452c28, - 0x2c45ac40, - 0x2c462c54, - 0x2c46ac67, - 0x2c472c78, - 0x2c47ac89, - 0x2c482c9a, - 0x2c48acab, - 0x2c492cba, - 0x2c49acc7, - 0x2c4a2cd4, - 0x2c4aace1, - 0x2c4b2cea, - 0x2c4bacfe, - 0x2c4c2d0d, - 0x2c4cad1b, - 0x2c4d2d3d, - 0x2c4dad4e, - 0x2c4e2d5f, - 0x2c4ead2a, - 0x2c4f293c, + 0xc32054b, + 0xc328556, + 0xc330561, + 0xc338578, + 0xc340582, + 0xc34859c, + 0xc3505a3, + 0xc3585af, + 0xc3605b6, + 0xc3685cc, + 0xc3705eb, + 0xc3785fc, + 0xc38060c, + 0xc388626, + 0xc39063b, + 0xc39864a, + 0xc3a0663, + 0xc3a8677, + 0xc3b0683, + 0xc3b868a, + 0xc3c0692, + 0xc3c86aa, + 0xc3d06b2, + 0xc3d86ba, + 0xc3e06c5, + 0xc3e85e1, + 0xc3f06a0, + 0xc3f856e, + 0xc40058c, + 0x103219ca, + 0x103299e1, + 0x103319fa, + 0x10339a10, + 0x10341a20, + 0x10349a48, + 0x10351a85, + 0x10359a94, + 0x10361ab4, + 0x10369ad3, + 0x10371af0, + 0x10379b0d, + 0x10381b22, + 0x10389b44, + 0x10391b63, + 0x10399b82, + 0x103a1c2a, + 0x103a9c41, + 0x103b1c4a, + 0x103b9c55, + 0x103c1c6f, + 0x103c9c77, + 0x103d1ca2, + 0x103d9a33, + 0x103e1ccb, + 0x103e9cf8, + 0x103f1d0b, + 0x103f9d14, + 0x10401ca9, + 0x10409a6e, + 0x10411baf, + 0x10419bf8, + 0x10421c12, + 0x10429c91, + 0x10431cbb, + 0x10439a56, + 0x10441b99, + 0x10449bc4, + 0x10451bdf, + 0x10459c7f, + 0x10461cdd, + 0x14320a68, + 0x14328a76, + 0x14330a82, + 0x14338a8f, + 0x183612b1, + 0x183712df, + 0x183792f0, + 0x18381306, + 0x18391329, + 0x1839933e, + 0x183a1350, + 0x183c1394, + 0x183c93a2, + 0x183d13b5, + 0x183d93c5, + 0x183e93eb, + 0x183f13fe, + 0x183f940d, + 0x18409437, + 0x184114a3, + 0x184194b4, + 0x184214c7, + 0x184294d9, + 0x184314eb, + 0x184394fc, + 0x1844150d, + 0x1844951e, + 0x1845152f, + 0x1845953c, + 0x1846155e, + 0x18469571, + 0x18471585, + 0x18479592, + 0x184815a1, + 0x184895b0, + 0x184915c1, + 0x184995dd, + 0x184a15eb, + 0x184a95fc, + 0x184b160d, + 0x184b961b, + 0x184c162b, + 0x184c9651, + 0x184d1660, + 0x184d9670, + 0x184e1680, + 0x184e968f, + 0x184f15ce, + 0x184f9240, + 0x185011e3, + 0x185091fb, + 0x1851121d, + 0x1851922f, + 0x18521261, + 0x1852927a, + 0x1853128b, + 0x185392a1, + 0x185412c6, + 0x18549317, + 0x18551360, + 0x18559375, + 0x18561382, + 0x185693da, + 0x1857141d, + 0x1857942a, + 0x18581446, + 0x18589457, + 0x18591467, + 0x18599477, + 0x185a1486, + 0x185a9495, + 0x185b154a, + 0x1c3206d2, + 0x1c3286de, + 0x1c3306e9, + 0x1c3386f5, + 0x203216a3, + 0x203296ae, + 0x203316b6, + 0x203396c2, + 0x243216ce, + 0x243296dc, + 0x243316ee, + 0x243396fd, + 0x24341710, + 0x24349723, + 0x2435173a, + 0x24359752, + 0x24361760, + 0x24369778, + 0x24371781, + 0x24379793, + 0x243817a7, + 0x243897b4, + 0x243917ca, + 0x243997e2, + 0x243a17fa, + 0x243a9804, + 0x243b1819, + 0x243b9827, + 0x243c183f, + 0x243c9856, + 0x243d1861, + 0x243d986f, + 0x28320ac8, + 0x28328ad7, + 0x28330ae2, + 0x28338ae7, + 0x28340af2, + 0x2c322da2, + 0x2c32adae, + 0x2c332dc1, + 0x2c33add2, + 0x2c342deb, + 0x2c34ae13, + 0x2c352e2a, + 0x2c35ae47, + 0x2c362e64, + 0x2c36ae81, + 0x2c372e9a, + 0x2c37aeb3, + 0x2c382ec9, + 0x2c38aed7, + 0x2c392ee9, + 0x2c39af06, + 0x2c3a2f23, + 0x2c3aaf31, + 0x2c3b2f4f, + 0x2c3baf6d, + 0x2c3c2f88, + 0x2c3caf9c, + 0x2c3d2fae, + 0x2c3dafbe, + 0x2c3e2fcc, + 0x2c3eafdc, + 0x2c3f2fec, + 0x2c3fb02b, + 0x2c40303c, + 0x2c40b057, + 0x2c41306b, + 0x2c41b07e, + 0x2c42309d, + 0x2c42b0b1, + 0x2c4330c4, + 0x2c43b0d3, + 0x2c4430e2, + 0x2c44b0f9, + 0x2c453114, + 0x2c45b12c, + 0x2c463140, + 0x2c46b153, + 0x2c473164, + 0x2c47b175, + 0x2c483186, + 0x2c48b197, + 0x2c4931a6, + 0x2c49b1b3, + 0x2c4a31c0, + 0x2c4ab1cd, + 0x2c4b31d6, + 0x2c4bb1ea, + 0x2c4c31f9, + 0x2c4cb207, + 0x2c4d3229, + 0x2c4db23a, + 0x2c4e324b, + 0x2c4eb216, + 0x2c4f2e04, + 0x2c4fb007, + 0x2c503019, 0x30320000, 0x30328018, 0x3033002c, @@ -331,376 +358,411 @@ const uint32_t kOpenSSLFunctionValues[] = { 0x30508404, 0x30510413, 0x3051841c, - 0x343209b7, - 0x343289c7, - 0x343309d2, - 0x343389df, - 0x383209e8, - 0x383289fb, - 0x38330a05, - 0x38338a17, - 0x3c320ab6, - 0x3c328ac4, - 0x3c330adb, - 0x3c338aef, - 0x3c340b0a, - 0x3c348b1b, - 0x3c350b27, - 0x3c358b3b, - 0x3c360b4d, - 0x3c368b76, - 0x3c370b83, - 0x3c378b90, - 0x3c380b9e, - 0x3c388bab, - 0x3c390bb8, - 0x3c398bdc, - 0x3c3a0bec, - 0x3c3a8c04, - 0x3c3b0c19, - 0x3c3b8c2e, - 0x3c3c0c3b, - 0x3c3c8c4e, - 0x3c3d0c61, - 0x3c3d8c85, - 0x3c3e0cad, - 0x3c3e8cc6, - 0x3c3f0cdc, - 0x3c3f8ce9, - 0x3c400cfc, - 0x3c408d0d, - 0x3c410d1e, - 0x3c418d37, - 0x3c420d50, - 0x3c428d66, - 0x3c430d83, - 0x3c438d99, - 0x3c440db5, - 0x3c448ddc, - 0x3c450dfa, - 0x3c458e14, - 0x3c460e2c, - 0x3c468e44, - 0x3c470e6f, - 0x3c478e9a, - 0x3c480ebb, - 0x3c488ee4, - 0x3c490eff, - 0x3c498f1a, - 0x3c4a0f27, - 0x3c4a8f3e, - 0x3c4b0f55, - 0x3c4b8f7e, - 0x3c4c0f8e, - 0x3c4c8f9a, - 0x3c4d0fb2, - 0x3c4d8fc5, - 0x3c4e0fd6, - 0x3c4e8fe7, - 0x3c4f0ff7, - 0x40321a01, - 0x40329a1b, - 0x40331a27, - 0x40339a3f, - 0x40341a5d, - 0x40349a7c, - 0x40351a93, - 0x40359aaf, - 0x40361acb, - 0x40369ae5, - 0x40371b04, - 0x40379b23, - 0x40381b3b, - 0x40389b58, - 0x40391b7b, - 0x40399b98, - 0x403a1bb6, - 0x403a9bc6, - 0x403b1bdb, - 0x403b9bf7, - 0x403c1c11, - 0x403c9c1c, - 0x403d1c3f, - 0x403d9c63, - 0x403e1c79, - 0x403e9c83, - 0x403f1c8f, - 0x403f9ca0, - 0x40401cb8, - 0x40409cc0, - 0x40411cc9, - 0x40419cd2, - 0x40421ce2, - 0x40429cf6, - 0x40431d01, - 0x40439d0d, - 0x40441d28, - 0x40449d34, - 0x40451d41, - 0x40459d54, - 0x40461d6c, - 0x40469d84, - 0x40471d9a, - 0x40479db5, - 0x40481dd0, - 0x40489de4, - 0x40491dfd, - 0x40499e16, - 0x404a1e30, - 0x404a9e3a, - 0x404b1e4a, - 0x404b9e6b, - 0x404c1e86, - 0x404c9e94, - 0x404d1ea1, - 0x404d9eb5, - 0x404e1ecd, - 0x404e9edb, - 0x404f1f05, - 0x404f9f1c, - 0x40501f2e, - 0x40509f5f, - 0x40511f90, - 0x40519fa5, - 0x40521fb6, - 0x40529fd6, - 0x40531ff1, - 0x4053a001, - 0x4054200d, - 0x4054a020, - 0x40552036, - 0x4055a054, - 0x40562061, - 0x4056a06b, - 0x40572079, - 0x4057a094, - 0x405820af, - 0x4058a0ce, - 0x405920e3, - 0x4059a0f8, - 0x405a2115, - 0x405aa129, - 0x405b2145, - 0x405ba15b, - 0x405c2178, - 0x405ca18a, - 0x405d21a1, - 0x405da1b2, - 0x405e21ce, - 0x405ea1e2, - 0x405f21f2, - 0x405fa20e, - 0x40602223, - 0x4060a239, - 0x40612256, - 0x4061a26f, - 0x40622282, - 0x4062a28b, - 0x4063229b, - 0x4063a2a7, - 0x406422bd, - 0x4064a2db, - 0x406522f0, - 0x4065a30d, - 0x40662324, - 0x4066a342, - 0x4067235f, - 0x4067a376, - 0x40682394, - 0x4068a3ab, - 0x406923c3, - 0x4069a3d4, - 0x406a23e7, - 0x406aa3fa, - 0x406b240e, - 0x406ba432, - 0x406c244d, - 0x406ca46e, - 0x406d2492, - 0x406da4ad, - 0x406e24ce, - 0x406ea4e3, - 0x406f24fc, - 0x406fa509, - 0x40702517, - 0x4070a524, - 0x40712541, - 0x4071a561, - 0x4072257c, - 0x4072a595, - 0x407325ac, - 0x4073a5c6, - 0x407425ea, - 0x4074a600, - 0x40752614, - 0x4075a629, - 0x40762643, - 0x4076a655, - 0x4077266a, - 0x4077a690, - 0x407826ad, - 0x4078a6d0, - 0x407926f6, - 0x4079a713, - 0x407a2736, - 0x407aa752, - 0x407b276e, - 0x407ba780, - 0x407c278d, - 0x407ca79a, - 0x407d27b7, - 0x407da7ce, - 0x407e27ea, - 0x407ea800, - 0x407f2818, - 0x407fa82b, - 0x40802840, - 0x4080a859, - 0x40812877, - 0x4081a897, - 0x408228a0, - 0x4082a8bc, - 0x408328c5, - 0x40839eea, - 0x40841f79, - 0x40849f49, + 0x343209f0, + 0x34328a00, + 0x34330a0b, + 0x34338a18, + 0x38320a21, + 0x38328a39, + 0x38330a4c, + 0x38338a56, + 0x3c320b05, + 0x3c328b13, + 0x3c330b2a, + 0x3c338b3e, + 0x3c340b70, + 0x3c348b81, + 0x3c350b8d, + 0x3c358bba, + 0x3c360bcc, + 0x3c368bf5, + 0x3c370c02, + 0x3c378c0f, + 0x3c380c1d, + 0x3c388c2a, + 0x3c390c37, + 0x3c398c5b, + 0x3c3a0c6b, + 0x3c3a8c83, + 0x3c3b0c98, + 0x3c3b8cad, + 0x3c3c0cba, + 0x3c3c8ccd, + 0x3c3d0ce0, + 0x3c3d8d04, + 0x3c3e0d2c, + 0x3c3e8d45, + 0x3c3f0d5b, + 0x3c3f8d68, + 0x3c400d7b, + 0x3c408d8c, + 0x3c410d9d, + 0x3c418db6, + 0x3c420dcf, + 0x3c428de5, + 0x3c430e02, + 0x3c438e18, + 0x3c440e9c, + 0x3c448ec3, + 0x3c450ee1, + 0x3c458efb, + 0x3c460f13, + 0x3c468f2b, + 0x3c470f56, + 0x3c478f81, + 0x3c480fa2, + 0x3c488fcb, + 0x3c490fe6, + 0x3c49900f, + 0x3c4a101c, + 0x3c4a9033, + 0x3c4b104a, + 0x3c4b9073, + 0x3c4c1083, + 0x3c4c908f, + 0x3c4d10a7, + 0x3c4d90ba, + 0x3c4e10cb, + 0x3c4e90dc, + 0x3c4f1102, + 0x3c4f8af9, + 0x3c500e34, + 0x3c508e54, + 0x3c510e81, + 0x3c519001, + 0x3c5210ec, + 0x3c528ba1, + 0x3c530b59, + 0x40321d54, + 0x40329d8d, + 0x40331db5, + 0x40339dcd, + 0x40341deb, + 0x40349e51, + 0x40351e68, + 0x40359e84, + 0x40361ea0, + 0x40369eba, + 0x40371ed9, + 0x40379ef8, + 0x40381f10, + 0x40389f2d, + 0x40391f50, + 0x40399f6d, + 0x403a1fa2, + 0x403a9ffc, + 0x403b2011, + 0x403ba02d, + 0x403c2047, + 0x403ca052, + 0x403d2075, + 0x403da099, + 0x403e20af, + 0x403ea0b9, + 0x403f20c5, + 0x403fa0d6, + 0x404020ee, + 0x4040a0f6, + 0x404120ff, + 0x4041a108, + 0x40422130, + 0x4042a144, + 0x4043214f, + 0x4043a15b, + 0x404421af, + 0x4044a1bb, + 0x404521c8, + 0x4045a1db, + 0x404621f3, + 0x4046a20b, + 0x40472221, + 0x4047a23c, + 0x40482257, + 0x4048a26b, + 0x40492284, + 0x4049a29d, + 0x404a22b7, + 0x404aa2c1, + 0x404b1fc4, + 0x404b9fe3, + 0x404c22d1, + 0x404ca2df, + 0x404d22ec, + 0x404da300, + 0x404e2318, + 0x404ea326, + 0x404f2350, + 0x404fa367, + 0x40502379, + 0x4050a3aa, + 0x405123db, + 0x4051a3f0, + 0x40522413, + 0x4052a433, + 0x405324b6, + 0x4053a4c6, + 0x4054a4d2, + 0x405524e8, + 0x4055a528, + 0x40562535, + 0x4056a53f, + 0x4057254d, + 0x4057a568, + 0x40582583, + 0x4058a5a2, + 0x405925b7, + 0x4059a5cc, + 0x405a25e9, + 0x405aa5fd, + 0x405b2619, + 0x405ba62f, + 0x405c264c, + 0x405ca65e, + 0x405d2675, + 0x405da686, + 0x405e26a2, + 0x405ea6b6, + 0x405f26c6, + 0x405fa6e2, + 0x406026f7, + 0x4060a70d, + 0x4061272a, + 0x4061a743, + 0x4062276d, + 0x4062a776, + 0x40632786, + 0x4063a7bf, + 0x406427d5, + 0x4064a7f3, + 0x40652808, + 0x4065a825, + 0x4066283c, + 0x4066a85a, + 0x40672877, + 0x4067a88e, + 0x406828ac, + 0x4068a8c3, + 0x406928db, + 0x4069a8ec, + 0x406a28ff, + 0x406aa912, + 0x406b2926, + 0x406ba94a, + 0x406c2965, + 0x406ca986, + 0x406d29aa, + 0x406da9c5, + 0x406e29e6, + 0x406ea9fb, + 0x406f2a14, + 0x406faa21, + 0x40702a2f, + 0x4070aa3c, + 0x40712a59, + 0x4071aa79, + 0x40722a94, + 0x4072aaad, + 0x40732ac4, + 0x4073aade, + 0x40742b02, + 0x4074ab18, + 0x40752b2c, + 0x4075ab41, + 0x40762b5b, + 0x4076ab6d, + 0x40772b82, + 0x4077aba8, + 0x40782bc5, + 0x4078abe8, + 0x40792c0e, + 0x4079ac2b, + 0x407a2c4e, + 0x407aac6a, + 0x407b2c86, + 0x407bac98, + 0x407c2ca5, + 0x407e2cb2, + 0x407eacc8, + 0x407f2ce0, + 0x407facf3, + 0x40802d08, + 0x4080ad21, + 0x40812d3f, + 0x4081ad5f, + 0x40822d68, + 0x4082ad84, + 0x40832d8d, + 0x4083a335, + 0x408423c4, + 0x4084a394, + 0x408527ae, + 0x4085a792, + 0x40861e29, + 0x40869e3c, + 0x4087218f, + 0x4087a19e, + 0x40881d99, + 0x4088a118, + 0x40892176, + 0x4089a756, + 0x408a1d1f, + 0x408a9d30, + 0x408b1d42, + 0x408ba401, + 0x408c1f8b, + 0x408c9fb2, + 0x408d2506, + 0x408d9d6e, + 0x408e1e0a, + 0x408ea448, + 0x408f2461, + 0x408fa47a, + 0x40902498, 0x4432042a, 0x4432843c, 0x44330445, 0x4433844d, 0x4434045a, - 0x4434846a, - 0x44350485, - 0x443584a5, - 0x443604c1, - 0x443684e2, - 0x443704e9, - 0x443784f7, - 0x44380501, - 0x4438850d, - 0x44390517, - 0x44398522, - 0x443a052c, - 0x443a8536, - 0x4c32167b, - 0x4c32968a, - 0x4c331699, - 0x4c3396b2, - 0x4c3416cd, - 0x4c3496e9, - 0x4c3516fb, - 0x4c359709, - 0x4c36171e, - 0x4c36972f, - 0x4c37173d, - 0x4c37974b, - 0x4c38175d, - 0x4c38976d, - 0x4c391777, - 0x4c39978f, - 0x4c3a17a7, - 0x4c3a97ba, - 0x50322d70, - 0x5032ad85, - 0x50332d96, - 0x5033ada9, - 0x50342dba, - 0x5034adcd, - 0x50352ddc, - 0x5035adf1, - 0x50362e01, - 0x5036ae10, - 0x50372e21, - 0x5037ae31, - 0x50382e42, - 0x5038ae55, - 0x50392e67, - 0x5039ae7d, - 0x503a2e8f, - 0x503aaea0, - 0x503b2eb1, - 0x503baec2, - 0x503c2ecd, - 0x503caed9, - 0x503d2ee4, - 0x503daeef, - 0x503e2efc, - 0x503eaf11, - 0x503f2f1f, - 0x503faf33, - 0x50402f46, - 0x5040af57, - 0x50412f71, - 0x5041af80, - 0x50422f89, - 0x5042af98, - 0x50432faa, - 0x5043afb6, - 0x50442fbe, - 0x5044afd1, - 0x50452fe2, - 0x5045aff8, - 0x50463004, - 0x5046b018, - 0x50473026, - 0x5047b03a, - 0x50483054, - 0x5048b068, - 0x5049307e, - 0x5049b095, - 0x504a30a7, - 0x504ab0bb, - 0x504b30d0, - 0x504bb0e7, - 0x504c30fb, - 0x504cb104, - 0x504d310c, - 0x504db11b, - 0x504e312b, - 0x68321018, - 0x68329029, - 0x68331039, - 0x68339047, - 0x68341054, - 0x6c321007, - 0x74320a60, - 0x74328a72, - 0x783206c9, - 0x783286fc, - 0x7833070e, - 0x78338720, - 0x78340734, - 0x78348748, - 0x78350766, - 0x78358778, - 0x7836078c, - 0x783687fa, - 0x7837080c, - 0x7837881e, - 0x78380830, - 0x78388847, - 0x7839085e, - 0x78398875, - 0x783a0891, - 0x783a88ad, - 0x783b08c9, - 0x783b88df, - 0x783c08f5, - 0x783c890b, - 0x783d0928, - 0x783d8937, - 0x783e0946, - 0x783e8955, - 0x783f0971, - 0x783f897f, - 0x7840098d, - 0x7840899b, - 0x784109a8, - 0x784186db, - 0x784207a0, - 0x784287be, - 0x784307dc, - 0x803214a2, + 0x44348475, + 0x44350490, + 0x443584b0, + 0x443604cc, + 0x443684ed, + 0x443704f4, + 0x44378502, + 0x4438050c, + 0x44388518, + 0x44390522, + 0x4439852d, + 0x443a0537, + 0x443a8541, + 0x443b046a, + 0x4c321877, + 0x4c329886, + 0x4c331895, + 0x4c3398ae, + 0x4c3418c9, + 0x4c3498e5, + 0x4c3518f7, + 0x4c359905, + 0x4c36191a, + 0x4c36992b, + 0x4c371939, + 0x4c379947, + 0x4c381959, + 0x4c389969, + 0x4c391973, + 0x4c39998b, + 0x4c3a19a3, + 0x4c3a99b6, + 0x5032325c, + 0x5032b271, + 0x50333282, + 0x5033b295, + 0x503432a6, + 0x5034b2b9, + 0x503532c8, + 0x5035b2dd, + 0x503632ed, + 0x5036b2fc, + 0x5037330d, + 0x5037b31d, + 0x5038332e, + 0x5038b341, + 0x50393353, + 0x5039b369, + 0x503a337b, + 0x503ab38c, + 0x503b339d, + 0x503bb3ae, + 0x503c33b9, + 0x503cb3c5, + 0x503d33d0, + 0x503db3db, + 0x503e33e8, + 0x503eb3fd, + 0x503f340b, + 0x503fb41f, + 0x50403432, + 0x5040b443, + 0x5041345d, + 0x5041b46c, + 0x50423475, + 0x5042b484, + 0x50433496, + 0x5043b4a2, + 0x504434aa, + 0x5044b4bd, + 0x504534ce, + 0x5045b4e4, + 0x504634f0, + 0x5046b504, + 0x50473512, + 0x5047b526, + 0x50483540, + 0x5048b554, + 0x5049356a, + 0x5049b581, + 0x504a3593, + 0x504ab5a7, + 0x504b35bc, + 0x504bb5d3, + 0x504c35e7, + 0x504cb5f0, + 0x504d35f8, + 0x504db607, + 0x504e3617, + 0x6832116d, + 0x6832917e, + 0x6833118e, + 0x683391b7, + 0x683411c4, + 0x683491a9, + 0x68351123, + 0x68359138, + 0x6836114a, + 0x6836915a, + 0x6837119c, + 0x683811d5, + 0x6c321112, + 0x74320aa3, + 0x74328ab5, + 0x78320702, + 0x78328735, + 0x78330747, + 0x78338759, + 0x7834076d, + 0x78348781, + 0x7835079f, + 0x783587b1, + 0x783607c5, + 0x78368833, + 0x78370845, + 0x78378857, + 0x78380869, + 0x78388880, + 0x78390897, + 0x783988ae, + 0x783a08ca, + 0x783a88e6, + 0x783b0902, + 0x783b8918, + 0x783c092e, + 0x783c8944, + 0x783d0961, + 0x783d8970, + 0x783e097f, + 0x783e898e, + 0x783f09aa, + 0x783f89b8, + 0x784009c6, + 0x784089d4, + 0x784109e1, + 0x78418714, + 0x784207d9, + 0x784287f7, + 0x78430815, + 0x8032169e, }; const size_t kOpenSSLFunctionValuesLen = sizeof(kOpenSSLFunctionValues) / sizeof(kOpenSSLFunctionValues[0]); @@ -775,6 +837,7 @@ const char kOpenSSLFunctionStringData[] = "BIO_new\0" "BIO_new_file\0" "BIO_new_mem_buf\0" + "BIO_printf\0" "BIO_zero_copy_get_read_buf\0" "BIO_zero_copy_get_read_buf_done\0" "BIO_zero_copy_get_write_buf\0" @@ -791,13 +854,16 @@ const char kOpenSSLFunctionStringData[] = "BN_CTX_get\0" "BN_CTX_new\0" "BN_CTX_start\0" + "BN_bn2cbb\0" "BN_bn2dec\0" "BN_bn2hex\0" + "BN_cbs2unsigned\0" "BN_div\0" "BN_div_recp\0" "BN_exp\0" "BN_generate_dsa_nonce\0" "BN_generate_prime_ex\0" + "BN_lshift\0" "BN_mod_exp2_mont\0" "BN_mod_exp_mont\0" "BN_mod_exp_mont_consttime\0" @@ -809,6 +875,7 @@ const char kOpenSSLFunctionStringData[] = "BN_new\0" "BN_rand\0" "BN_rand_range\0" + "BN_rshift\0" "BN_sqrt\0" "BN_usub\0" "bn_wexpand\0" @@ -856,10 +923,10 @@ const char kOpenSSLFunctionStringData[] = "NCONF_load\0" "def_load_bio\0" "str_copy\0" + "CRYPTO_get_ex_new_index\0" "CRYPTO_set_ex_data\0" "get_class\0" "get_func_pointers\0" - "get_new_index\0" "DH_new_method\0" "compute_key\0" "generate_key\0" @@ -871,13 +938,16 @@ const char kOpenSSLFunctionStringData[] = "sign\0" "sign_setup\0" "verify\0" + "BN_to_felem\0" "EC_GROUP_copy\0" "EC_GROUP_get_curve_GFp\0" "EC_GROUP_get_degree\0" "EC_GROUP_new_by_curve_name\0" + "EC_GROUP_new_curve_GFp\0" "EC_KEY_check_key\0" "EC_KEY_copy\0" "EC_KEY_generate_key\0" + "EC_KEY_new_by_curve_name\0" "EC_KEY_new_method\0" "EC_KEY_set_public_key_affine_coordinates\0" "EC_POINT_add\0" @@ -907,6 +977,9 @@ const char kOpenSSLFunctionStringData[] = "ec_GFp_mont_field_set_to_one\0" "ec_GFp_mont_field_sqr\0" "ec_GFp_mont_group_set_curve\0" + "ec_GFp_nistp256_group_set_curve\0" + "ec_GFp_nistp256_point_get_affine_coordinates\0" + "ec_GFp_nistp256_points_mul\0" "ec_GFp_simple_group_check_discriminant\0" "ec_GFp_simple_group_set_curve\0" "ec_GFp_simple_make_affine\0" @@ -918,6 +991,7 @@ const char kOpenSSLFunctionStringData[] = "ec_GFp_simple_set_compressed_coordinates\0" "ec_asn1_group2pkparameters\0" "ec_asn1_pkparameters2group\0" + "ec_group_copy\0" "ec_group_new\0" "ec_group_new_curve_GFp\0" "ec_group_new_from_data\0" @@ -929,13 +1003,21 @@ const char kOpenSSLFunctionStringData[] = "i2d_ECParameters\0" "i2d_ECPrivateKey\0" "i2o_ECPublicKey\0" + "nistp256_pre_comp_new\0" "o2i_ECPublicKey\0" "ECDH_compute_key\0" + "ECDSA_SIG_from_bytes\0" + "ECDSA_SIG_marshal\0" + "ECDSA_SIG_parse\0" + "ECDSA_SIG_to_bytes\0" "ECDSA_do_sign_ex\0" "ECDSA_do_verify\0" "ECDSA_sign_ex\0" + "ECDSA_verify\0" + "d2i_ECDSA_SIG\0" "digest_to_bn\0" "ecdsa_sign_setup\0" + "i2d_ECDSA_SIG\0" "EVP_DigestSignAlgorithm\0" "EVP_DigestVerifyInitFromAlgorithm\0" "EVP_PKEY_CTX_ctrl\0" @@ -965,8 +1047,15 @@ const char kOpenSSLFunctionStringData[] = "d2i_AutoPrivateKey\0" "d2i_PrivateKey\0" "do_EC_KEY_print\0" + "do_dsa_print\0" "do_rsa_print\0" "do_sigver_init\0" + "dsa_param_decode\0" + "dsa_priv_decode\0" + "dsa_priv_encode\0" + "dsa_pub_decode\0" + "dsa_pub_encode\0" + "dsa_sig_print\0" "eckey_param2type\0" "eckey_param_decode\0" "eckey_priv_decode\0" @@ -977,6 +1066,7 @@ const char kOpenSSLFunctionStringData[] = "evp_pkey_ctx_new\0" "hmac_signctx\0" "i2d_PublicKey\0" + "old_dsa_priv_decode\0" "old_ec_priv_decode\0" "old_rsa_priv_decode\0" "pkey_ec_ctrl\0" @@ -1048,7 +1138,10 @@ const char kOpenSSLFunctionStringData[] = "BN_BLINDING_invert_ex\0" "BN_BLINDING_new\0" "BN_BLINDING_update\0" + "RSA_add_pkcs1_prefix\0" "RSA_check_key\0" + "RSA_marshal_private_key\0" + "RSA_marshal_public_key\0" "RSA_new_method\0" "RSA_padding_add_PKCS1_OAEP_mgf1\0" "RSA_padding_add_PKCS1_PSS_mgf1\0" @@ -1059,23 +1152,41 @@ const char kOpenSSLFunctionStringData[] = "RSA_padding_check_PKCS1_type_1\0" "RSA_padding_check_PKCS1_type_2\0" "RSA_padding_check_none\0" + "RSA_parse_private_key\0" + "RSA_parse_public_key\0" + "RSA_private_key_from_bytes\0" + "RSA_private_key_to_bytes\0" + "RSA_public_key_from_bytes\0" + "RSA_public_key_to_bytes\0" "RSA_recover_crt_params\0" "RSA_sign\0" "RSA_verify\0" "RSA_verify_PKCS1_PSS_mgf1\0" "decrypt\0" "encrypt\0" + "i2d_RSAPrivateKey\0" + "i2d_RSAPublicKey\0" "keygen\0" - "pkcs1_prefixed_msg\0" + "keygen_multiprime\0" + "marshal_integer\0" "private_transform\0" + "rsa_parse_additional_prime\0" "rsa_setup_blinding\0" "sign_raw\0" "verify_raw\0" + "SSL_AEAD_CTX_new\0" + "SSL_AEAD_CTX_open\0" + "SSL_AEAD_CTX_seal\0" "SSL_CTX_check_private_key\0" + "SSL_CTX_get_tlsext_ticket_keys\0" "SSL_CTX_new\0" + "SSL_CTX_set1_tls_channel_id\0" "SSL_CTX_set_cipher_list\0" "SSL_CTX_set_cipher_list_tls11\0" "SSL_CTX_set_session_id_context\0" + "SSL_CTX_set_tlsext_ticket_keys\0" + "SSL_CTX_set_tmp_dh\0" + "SSL_CTX_set_tmp_ecdh\0" "SSL_CTX_use_PrivateKey\0" "SSL_CTX_use_PrivateKey_ASN1\0" "SSL_CTX_use_PrivateKey_file\0" @@ -1087,7 +1198,11 @@ const char kOpenSSLFunctionStringData[] = "SSL_CTX_use_certificate_chain_file\0" "SSL_CTX_use_certificate_file\0" "SSL_CTX_use_psk_identity_hint\0" + "SSL_SESSION_from_bytes\0" "SSL_SESSION_new\0" + "SSL_SESSION_parse\0" + "SSL_SESSION_parse_octet_string\0" + "SSL_SESSION_parse_string\0" "SSL_SESSION_print_fp\0" "SSL_SESSION_set1_id_context\0" "SSL_SESSION_to_bytes_full\0" @@ -1103,10 +1218,14 @@ const char kOpenSSLFunctionStringData[] = "SSL_peek\0" "SSL_read\0" "SSL_renegotiate\0" + "SSL_set1_tls_channel_id\0" "SSL_set_cipher_list\0" "SSL_set_fd\0" "SSL_set_rfd\0" "SSL_set_session_id_context\0" + "SSL_set_tlsext_host_name\0" + "SSL_set_tmp_dh\0" + "SSL_set_tmp_ecdh\0" "SSL_set_wfd\0" "SSL_shutdown\0" "SSL_use_PrivateKey\0" @@ -1121,8 +1240,6 @@ const char kOpenSSLFunctionStringData[] = "SSL_use_psk_identity_hint\0" "SSL_write\0" "d2i_SSL_SESSION\0" - "d2i_SSL_SESSION_get_octet_string\0" - "d2i_SSL_SESSION_get_string\0" "do_ssl3_write\0" "dtls1_accept\0" "dtls1_buffer_record\0" @@ -1138,13 +1255,18 @@ const char kOpenSSLFunctionStringData[] = "dtls1_process_fragment\0" "dtls1_process_record\0" "dtls1_read_bytes\0" + "dtls1_seal_record\0" "dtls1_send_hello_verify_request\0" - "dtls1_write_app_data_bytes\0" + "dtls1_write_app_data\0" + "ext_ri_parse_clienthello\0" + "ext_ri_parse_serverhello\0" + "ext_sigalgs_parse_clienthello\0" + "ext_sigalgs_parse_serverhello\0" "i2d_SSL_SESSION\0" "ssl3_accept\0" - "ssl3_callback_ctrl\0" "ssl3_cert_verify_hash\0" "ssl3_check_cert_and_algorithm\0" + "ssl3_check_certificate_for_cipher\0" "ssl3_connect\0" "ssl3_ctrl\0" "ssl3_ctx_ctrl\0" @@ -1170,9 +1292,12 @@ const char kOpenSSLFunctionStringData[] = "ssl3_get_server_key_exchange\0" "ssl3_get_v2_client_hello\0" "ssl3_handshake_mac\0" + "ssl3_output_cert_chain\0" "ssl3_prf\0" "ssl3_read_bytes\0" "ssl3_read_n\0" + "ssl3_record_sequence_update\0" + "ssl3_seal_record\0" "ssl3_send_cert_verify\0" "ssl3_send_certificate_request\0" "ssl3_send_channel_id\0" @@ -1223,9 +1348,6 @@ const char kOpenSSLFunctionStringData[] = "ssl_sess_cert_new\0" "ssl_set_cert\0" "ssl_set_pkey\0" - "ssl_undefined_const_function\0" - "ssl_undefined_function\0" - "ssl_undefined_void_function\0" "ssl_verify_cert_chain\0" "tls12_check_peer_sigalg\0" "tls1_aead_ctx_init\0" @@ -1265,6 +1387,8 @@ const char kOpenSSLFunctionStringData[] = "X509_PUBKEY_get\0" "X509_PUBKEY_set\0" "X509_REQ_check_private_key\0" + "X509_REQ_print_ex\0" + "X509_REQ_print_fp\0" "X509_REQ_to_X509\0" "X509_STORE_CTX_get1_issuer\0" "X509_STORE_CTX_init\0" @@ -1357,168 +1481,177 @@ const char kOpenSSLFunctionStringData[] = const uint32_t kOpenSSLReasonValues[] = { 0xc3207ba, - 0xc3287c7, - 0xc3307d6, - 0xc3387e6, - 0xc3407f5, - 0xc34880e, - 0xc35081a, - 0xc358837, - 0xc360849, - 0xc368857, - 0xc370867, - 0xc378874, - 0xc380884, - 0xc38888f, - 0xc3908a5, - 0xc3988b4, - 0xc3a08c8, - 0x10321417, - 0x10329423, - 0x1033143c, - 0x1033944f, - 0x10340da9, - 0x10349462, - 0x10351477, - 0x1035948a, - 0x103614a3, - 0x103694b8, - 0x103714d6, - 0x103794e5, - 0x10381501, - 0x1038951c, - 0x1039152b, - 0x10399547, - 0x103a1562, - 0x103a9579, - 0x103b158a, - 0x103b959e, - 0x103c15bd, - 0x103c95cc, - 0x103d15e3, - 0x103d95f6, - 0x103e0b5f, - 0x103e9609, - 0x103f161c, - 0x103f9636, - 0x10401646, - 0x1040965a, - 0x10411670, - 0x10419688, - 0x1042169d, - 0x104296b1, - 0x104316c3, + 0xc3287d4, + 0xc3307e3, + 0xc3387f3, + 0xc340802, + 0xc34881b, + 0xc350827, + 0xc358844, + 0xc360856, + 0xc368864, + 0xc370874, + 0xc378881, + 0xc380891, + 0xc38889c, + 0xc3908b2, + 0xc3988c1, + 0xc3a08d5, + 0xc3a87c7, + 0xc3b00b0, + 0x10321478, + 0x10329484, + 0x1033149d, + 0x103394b0, + 0x10340de1, + 0x103494cf, + 0x103514e4, + 0x10359516, + 0x1036152f, + 0x10369544, + 0x10371562, + 0x10379571, + 0x1038158d, + 0x103895a8, + 0x103915b7, + 0x103995d3, + 0x103a15ee, + 0x103a9605, + 0x103b1616, + 0x103b962a, + 0x103c1649, + 0x103c9658, + 0x103d166f, + 0x103d9682, + 0x103e0b6c, + 0x103e96b3, + 0x103f16c6, + 0x103f96e0, + 0x104016f0, + 0x10409704, + 0x1041171a, + 0x10419732, + 0x10421747, + 0x1042975b, + 0x1043176d, 0x104385d0, - 0x104408b4, - 0x104496d8, - 0x104516ef, - 0x10459704, - 0x10461712, - 0x14320b42, - 0x14328b50, - 0x14330b5f, - 0x14338b71, + 0x104408c1, + 0x10449782, + 0x10451799, + 0x104597ae, + 0x104617bc, + 0x10469695, + 0x104714f7, + 0x104787c7, + 0x104800b0, + 0x104894c3, + 0x14320b4f, + 0x14328b5d, + 0x14330b6c, + 0x14338b7e, 0x18320083, - 0x18328dff, - 0x18330e15, - 0x18338094, - 0x18340e2d, - 0x18348e41, - 0x18350e56, - 0x18358e78, - 0x18360e90, - 0x18368ea5, - 0x18370eb8, - 0x18378ecc, - 0x18380ef0, - 0x18388efe, - 0x18390f14, - 0x18398f28, - 0x183a0f38, - 0x183a89cc, - 0x183b0f48, - 0x183b8f5d, - 0x183c0f74, - 0x183c8f88, - 0x183d0f9c, - 0x183d8fac, - 0x183e0b8e, - 0x183e8fb9, - 0x183f0fcb, - 0x183f8fd6, - 0x18400fe6, - 0x18408ff7, - 0x18411008, - 0x1841901a, - 0x18421043, - 0x1842905c, - 0x1843106b, - 0x1843907f, - 0x184410a0, - 0x184490b8, - 0x184510d4, - 0x184590ea, - 0x18461105, - 0x1846866b, - 0x18471120, - 0x1847913b, - 0x20321162, - 0x2432116e, - 0x243288fa, - 0x24331180, - 0x2433918d, - 0x2434119a, - 0x243491ac, - 0x243511bb, - 0x243591d8, - 0x243611e5, - 0x243691f3, - 0x24371201, - 0x2437920f, - 0x24381218, - 0x24389225, - 0x24391238, - 0x28320b82, - 0x28328b8e, - 0x28330b5f, - 0x28338ba1, - 0x2c3229d2, - 0x2c32a9e0, - 0x2c3329f2, - 0x2c33aa04, - 0x2c342a18, - 0x2c34aa2a, - 0x2c352a45, - 0x2c35aa57, - 0x2c362a6a, + 0x18328e47, + 0x18340e75, + 0x18348e89, + 0x18358ec0, + 0x18368eed, + 0x18370f00, + 0x18378f14, + 0x18380f38, + 0x18388f46, + 0x18390f5c, + 0x18398f70, + 0x183a0f80, + 0x183b0f90, + 0x183b8fa5, + 0x183c8fd0, + 0x183d0fe4, + 0x183d8ff4, + 0x183e0b9b, + 0x183e9001, + 0x183f1013, + 0x183f901e, + 0x1840102e, + 0x1840903f, + 0x18411050, + 0x18419062, + 0x1842108b, + 0x184290bd, + 0x184310cc, + 0x18451135, + 0x1845914b, + 0x18461166, + 0x18468ed8, + 0x184709d9, + 0x18478094, + 0x18480fbc, + 0x18489101, + 0x18490e5d, + 0x18498e9e, + 0x184a119c, + 0x184a9119, + 0x184b10e0, + 0x184b8e37, + 0x184c10a4, + 0x184c866b, + 0x184d1181, + 0x203211c3, + 0x243211cf, + 0x24328907, + 0x243311e1, + 0x243391ee, + 0x243411fb, + 0x2434920d, + 0x2435121c, + 0x24359239, + 0x24361246, + 0x24369254, + 0x24371262, + 0x24379270, + 0x24381279, + 0x24389286, + 0x24391299, + 0x28320b8f, + 0x28328b9b, + 0x28330b6c, + 0x28338bae, + 0x2c322b64, + 0x2c32ab72, + 0x2c332b84, + 0x2c33ab96, + 0x2c342baa, + 0x2c34abbc, + 0x2c352bd7, + 0x2c35abe9, + 0x2c362bfc, 0x2c3682f3, - 0x2c372a77, - 0x2c37aa89, - 0x2c382a9c, - 0x2c38aaaa, - 0x2c392aba, - 0x2c39aacc, - 0x2c3a2ae0, - 0x2c3aaaf1, - 0x2c3b12f8, - 0x2c3bab02, - 0x2c3c2b16, - 0x2c3cab2c, - 0x2c3d2b45, - 0x2c3dab73, - 0x2c3e2b81, - 0x2c3eab99, - 0x2c3f2bb1, - 0x2c3fabbe, - 0x2c402be1, - 0x2c40ac00, - 0x2c411162, - 0x2c41ac11, - 0x2c422c24, - 0x2c4290d4, - 0x2c432c35, + 0x2c372c09, + 0x2c37ac1b, + 0x2c382c2e, + 0x2c38ac3c, + 0x2c392c4c, + 0x2c39ac5e, + 0x2c3a2c72, + 0x2c3aac83, + 0x2c3b1359, + 0x2c3bac94, + 0x2c3c2ca8, + 0x2c3cacbe, + 0x2c3d2cd7, + 0x2c3dad05, + 0x2c3e2d13, + 0x2c3ead2b, + 0x2c3f2d43, + 0x2c3fad50, + 0x2c402d73, + 0x2c40ad92, + 0x2c4111c3, + 0x2c41ada3, + 0x2c422db6, + 0x2c429135, + 0x2c432dc7, 0x2c4386a2, - 0x2c442b62, + 0x2c442cf4, 0x30320000, 0x30328015, 0x3033001f, @@ -1607,240 +1740,251 @@ const uint32_t kOpenSSLReasonValues[] = { 0x305c8687, 0x305d0698, 0x305d86a2, - 0x34320abc, - 0x34328ad0, - 0x34330aed, - 0x34338b00, - 0x34340b0f, - 0x34348b2c, + 0x34320ac9, + 0x34328add, + 0x34330afa, + 0x34338b0d, + 0x34340b1c, + 0x34348b39, 0x3c320083, - 0x3c328bb7, - 0x3c330bd0, - 0x3c338beb, - 0x3c340c08, - 0x3c348c23, - 0x3c350c3e, - 0x3c358c53, - 0x3c360c6c, - 0x3c368c84, - 0x3c370c95, - 0x3c378ca3, - 0x3c380cb0, - 0x3c388cc4, - 0x3c390b8e, - 0x3c398cd8, - 0x3c3a0cec, - 0x3c3a8874, - 0x3c3b0cfc, - 0x3c3b8d17, - 0x3c3c0d29, - 0x3c3c8d3f, - 0x3c3d0d49, - 0x3c3d8d5d, - 0x3c3e0d6b, - 0x3c3e8d79, - 0x40321729, - 0x4032973f, - 0x4033176d, - 0x40339777, - 0x4034178e, - 0x403497ac, - 0x403517bc, - 0x403597ce, - 0x403617db, - 0x403697e7, - 0x403717fc, - 0x40379811, - 0x40381823, - 0x4038982e, - 0x40391840, - 0x40398da9, - 0x403a1850, - 0x403a9863, - 0x403b1884, - 0x403b9895, - 0x403c18a5, + 0x3c328bd8, + 0x3c330bf1, + 0x3c338c0c, + 0x3c340c29, + 0x3c348c44, + 0x3c350c5f, + 0x3c358c74, + 0x3c360c8d, + 0x3c368ca5, + 0x3c370cb6, + 0x3c378cc4, + 0x3c380cd1, + 0x3c388ce5, + 0x3c390b9b, + 0x3c398cf9, + 0x3c3a0d0d, + 0x3c3a8881, + 0x3c3b0d1d, + 0x3c3b8d38, + 0x3c3c0d4a, + 0x3c3c8d60, + 0x3c3d0d6a, + 0x3c3d8d7e, + 0x3c3e0d8c, + 0x3c3e8db1, + 0x3c3f0bc4, + 0x3c3f8d9a, + 0x403217d3, + 0x403297e9, + 0x40331817, + 0x40339821, + 0x40341838, + 0x40349856, + 0x40351866, + 0x40359878, + 0x40361885, + 0x40369891, + 0x403718a6, + 0x403798bb, + 0x403818cd, + 0x403898d8, + 0x403918ea, + 0x40398de1, + 0x403a18fa, + 0x403a990d, + 0x403b192e, + 0x403b993f, + 0x403c194f, 0x403c8064, - 0x403d18b1, - 0x403d98cd, - 0x403e18e3, - 0x403e98f2, - 0x403f1905, - 0x403f991f, - 0x4040192d, - 0x40409942, - 0x40411956, - 0x40419973, - 0x4042198c, - 0x404299a7, - 0x404319c0, - 0x404399d3, - 0x404419e7, - 0x404499ff, - 0x40451a0f, - 0x40459a1d, - 0x40461a3b, + 0x403d195b, + 0x403d9977, + 0x403e198d, + 0x403e999c, + 0x403f19af, + 0x403f99c9, + 0x404019d7, + 0x404099ec, + 0x40411a00, + 0x40419a1d, + 0x40421a36, + 0x40429a51, + 0x40431a6a, + 0x40439a7d, + 0x40441a91, + 0x40449aa9, + 0x40451ab9, + 0x40459ac7, + 0x40461ae5, 0x40468094, - 0x40471a50, - 0x40479a62, - 0x40481a86, - 0x40489aa6, - 0x40491aba, - 0x40499acf, - 0x404a1ae8, - 0x404a9b0b, - 0x404b1b25, - 0x404b9b43, - 0x404c1b5e, - 0x404c9b78, - 0x404d1b8f, - 0x404d9bb7, - 0x404e1bce, - 0x404e9bea, - 0x404f1c06, - 0x404f9c27, - 0x40501c49, - 0x40509c65, - 0x40511c79, - 0x40519c86, - 0x40521c9d, - 0x40529cad, - 0x40531cbd, - 0x40539cd1, - 0x40541cec, - 0x40549cfc, - 0x40551d13, - 0x40559d22, - 0x40561d3d, - 0x40569d55, - 0x40571d71, - 0x40579d8a, - 0x40581d9d, - 0x40589db2, - 0x40591dd5, - 0x40599de3, - 0x405a1df0, - 0x405a9e09, - 0x405b1e21, - 0x405b9e34, - 0x405c1e49, - 0x405c9e5b, - 0x405d1e70, - 0x405d9e80, - 0x405e1e99, - 0x405e9ead, - 0x405f1ebd, - 0x405f9ed5, - 0x40601ee6, - 0x40609ef9, - 0x40611f0a, - 0x40619f28, - 0x40621f39, - 0x40629f46, - 0x40631f5d, - 0x40639f7d, - 0x40641f94, - 0x40649fa1, - 0x40651faf, - 0x40659fd1, - 0x40661ff9, - 0x4066a00e, - 0x40672025, - 0x4067a036, - 0x40682047, - 0x4068a058, - 0x4069206d, - 0x4069a084, - 0x406a2095, - 0x406aa0ae, - 0x406b20c9, - 0x406ba0e0, - 0x406c20f8, - 0x406ca119, - 0x406d212c, - 0x406da14d, - 0x406e2168, - 0x406ea183, - 0x406f21a4, - 0x406fa1ca, - 0x407021ea, - 0x4070a206, - 0x40712393, - 0x4071a3b6, - 0x407223cc, - 0x4072a3eb, - 0x40732403, - 0x4073a423, - 0x4074264d, - 0x4074a672, - 0x4075268d, - 0x4075a6ac, - 0x407626db, - 0x4076a703, - 0x4077271c, - 0x4077a73b, - 0x40782760, - 0x4078a777, - 0x4079278a, - 0x4079a7a7, + 0x40471afa, + 0x40479b0c, + 0x40481b30, + 0x40489b50, + 0x40491b64, + 0x40499b79, + 0x404a1b92, + 0x404a9bcc, + 0x404b1be6, + 0x404b9c04, + 0x404c1c1f, + 0x404c9c39, + 0x404d1c50, + 0x404d9c78, + 0x404e1c8f, + 0x404e9cab, + 0x404f1cc7, + 0x404f9ce8, + 0x40501d0a, + 0x40509d26, + 0x40511d3a, + 0x40519d47, + 0x40521d5e, + 0x40529d6e, + 0x40531d7e, + 0x40539d92, + 0x40541dad, + 0x40549dbd, + 0x40551dd4, + 0x40559de3, + 0x40561dfe, + 0x40569e16, + 0x40571e32, + 0x40579e4b, + 0x40581e5e, + 0x40589e73, + 0x40591e96, + 0x40599ea4, + 0x405a1eb1, + 0x405a9eca, + 0x405b1ee2, + 0x405b9ef5, + 0x405c1f0a, + 0x405c9f1c, + 0x405d1f31, + 0x405d9f41, + 0x405e1f5a, + 0x405e9f6e, + 0x405f1f7e, + 0x405f9f96, + 0x40601fa7, + 0x40609fba, + 0x40611fcb, + 0x40619fe9, + 0x40621ffa, + 0x4062a007, + 0x4063201e, + 0x4063a05f, + 0x40642076, + 0x4064a083, + 0x40652091, + 0x4065a0b3, + 0x406620db, + 0x4066a0f0, + 0x40672107, + 0x4067a118, + 0x40682129, + 0x4068a13a, + 0x4069214f, + 0x4069a166, + 0x406a2177, + 0x406aa190, + 0x406b21ab, + 0x406ba1c2, + 0x406c222f, + 0x406ca250, + 0x406d2263, + 0x406da284, + 0x406e229f, + 0x406ea2e8, + 0x406f2309, + 0x406fa32f, + 0x4070234f, + 0x4070a36b, + 0x407124f8, + 0x4071a51b, + 0x40722531, + 0x4072a550, + 0x40732568, + 0x4073a588, + 0x407427b2, + 0x4074a7d7, + 0x407527f2, + 0x4075a811, + 0x40762840, + 0x4076a868, + 0x40772899, + 0x4077a8b8, + 0x407828f2, + 0x4078a909, + 0x4079291c, + 0x4079a939, 0x407a0782, - 0x407aa7b9, - 0x407b27cc, - 0x407ba7e5, - 0x407c27fd, - 0x407c905c, - 0x407d2811, - 0x407da82b, - 0x407e283c, - 0x407ea850, - 0x407f285e, - 0x407fa879, - 0x40801225, - 0x4080a89e, - 0x408128c0, - 0x4081a8db, - 0x408228f0, - 0x4082a908, - 0x40832920, - 0x4083a937, - 0x4084294d, - 0x4084a959, - 0x4085296c, - 0x4085a981, - 0x40862993, - 0x4086a9a8, - 0x408729b1, - 0x40879ba5, - 0x41f422be, - 0x41f92350, - 0x41fe2243, - 0x41fea474, - 0x41ff2565, - 0x420322d7, - 0x420822f9, - 0x4208a335, - 0x42092227, - 0x4209a36f, - 0x420a227e, - 0x420aa25e, - 0x420b229e, - 0x420ba317, - 0x420c2581, - 0x420ca441, - 0x420d245b, - 0x420da492, - 0x421224ac, - 0x42172548, - 0x4217a4ee, - 0x421c2510, - 0x421f24cb, - 0x42212598, - 0x4226252b, - 0x422b2631, - 0x422ba5fa, - 0x422c2619, - 0x422ca5d4, - 0x422d25b3, + 0x407aa94b, + 0x407b295e, + 0x407ba977, + 0x407c298f, + 0x407c90bd, + 0x407d29a3, + 0x407da9bd, + 0x407e29ce, + 0x407ea9e2, + 0x407f29f0, + 0x407faa0b, + 0x40801286, + 0x4080aa30, + 0x40812a52, + 0x4081aa6d, + 0x40822a82, + 0x4082aa9a, + 0x40832ab2, + 0x4083aac9, + 0x40842adf, + 0x4084aaeb, + 0x40852afe, + 0x4085ab13, + 0x40862b25, + 0x4086ab3a, + 0x40872b43, + 0x40879c66, + 0x40880083, + 0x4088a03e, + 0x40890a17, + 0x4089a1da, + 0x408a1bb5, + 0x408aa204, + 0x408b2881, + 0x408ba8dd, + 0x408c22ba, + 0x41f42423, + 0x41f924b5, + 0x41fe23a8, + 0x41fea5d9, + 0x41ff26ca, + 0x4203243c, + 0x4208245e, + 0x4208a49a, + 0x4209238c, + 0x4209a4d4, + 0x420a23e3, + 0x420aa3c3, + 0x420b2403, + 0x420ba47c, + 0x420c26e6, + 0x420ca5a6, + 0x420d25c0, + 0x420da5f7, + 0x42122611, + 0x421726ad, + 0x4217a653, + 0x421c2675, + 0x421f2630, + 0x422126fd, + 0x42262690, + 0x422b2796, + 0x422ba75f, + 0x422c277e, + 0x422ca739, + 0x422d2718, 0x443206ad, 0x443286bc, 0x443306c8, @@ -1858,130 +2002,131 @@ const uint32_t kOpenSSLReasonValues[] = { 0x44390782, 0x44398790, 0x443a07a3, - 0x4c32124f, - 0x4c32925f, - 0x4c331272, - 0x4c339292, + 0x4c3212b0, + 0x4c3292c0, + 0x4c3312d3, + 0x4c3392f3, 0x4c340094, 0x4c3480b0, - 0x4c35129e, - 0x4c3592ac, - 0x4c3612c8, - 0x4c3692db, - 0x4c3712ea, - 0x4c3792f8, - 0x4c38130d, - 0x4c389319, - 0x4c391339, - 0x4c399363, - 0x4c3a137c, - 0x4c3a9395, + 0x4c3512ff, + 0x4c35930d, + 0x4c361329, + 0x4c36933c, + 0x4c37134b, + 0x4c379359, + 0x4c38136e, + 0x4c38937a, + 0x4c39139a, + 0x4c3993c4, + 0x4c3a13dd, + 0x4c3a93f6, 0x4c3b05d0, - 0x4c3b93ae, - 0x4c3c13c0, - 0x4c3c93cf, - 0x4c3d105c, - 0x4c3d93e8, - 0x4c3e13f5, - 0x50322c47, - 0x5032ac56, - 0x50332c61, - 0x5033ac71, - 0x50342c8a, - 0x5034aca4, - 0x50352cb2, - 0x5035acc8, - 0x50362cda, - 0x5036acf0, - 0x50372d09, - 0x5037ad1c, - 0x50382d34, - 0x5038ad45, - 0x50392d5a, - 0x5039ad6e, - 0x503a2d8e, - 0x503aada4, - 0x503b2dbc, - 0x503badce, - 0x503c2dea, - 0x503cae01, - 0x503d2e1a, - 0x503dae30, - 0x503e2e3d, - 0x503eae53, - 0x503f2e65, + 0x4c3b940f, + 0x4c3c1421, + 0x4c3c9430, + 0x4c3d10bd, + 0x4c3d9449, + 0x4c3e1456, + 0x50322dd9, + 0x5032ade8, + 0x50332df3, + 0x5033ae03, + 0x50342e1c, + 0x5034ae36, + 0x50352e44, + 0x5035ae5a, + 0x50362e6c, + 0x5036ae82, + 0x50372e9b, + 0x5037aeae, + 0x50382ec6, + 0x5038aed7, + 0x50392eec, + 0x5039af00, + 0x503a2f20, + 0x503aaf36, + 0x503b2f4e, + 0x503baf60, + 0x503c2f7c, + 0x503caf93, + 0x503d2fac, + 0x503dafc2, + 0x503e2fcf, + 0x503eafe5, + 0x503f2ff7, 0x503f8348, - 0x50402e78, - 0x5040ae88, - 0x50412ea2, - 0x5041aeb1, - 0x50422ecb, - 0x5042aee8, - 0x50432ef8, - 0x5043af08, - 0x50442f17, + 0x5040300a, + 0x5040b01a, + 0x50413034, + 0x5041b043, + 0x5042305d, + 0x5042b07a, + 0x5043308a, + 0x5043b09a, + 0x504430a9, 0x50448414, - 0x50452f2b, - 0x5045af49, - 0x50462f5c, - 0x5046af72, - 0x50472f84, - 0x5047af99, - 0x50482fbf, - 0x5048afcd, - 0x50492fe0, - 0x5049aff5, - 0x504a300b, - 0x504ab01b, - 0x504b303b, - 0x504bb04e, - 0x504c3071, - 0x504cb09f, - 0x504d30b1, - 0x504db0ce, - 0x504e30e9, - 0x504eb105, - 0x504f3117, - 0x504fb12e, - 0x5050313d, + 0x504530bd, + 0x5045b0db, + 0x504630ee, + 0x5046b104, + 0x50473116, + 0x5047b12b, + 0x50483151, + 0x5048b15f, + 0x50493172, + 0x5049b187, + 0x504a319d, + 0x504ab1ad, + 0x504b31cd, + 0x504bb1e0, + 0x504c3203, + 0x504cb231, + 0x504d3243, + 0x504db260, + 0x504e327b, + 0x504eb297, + 0x504f32a9, + 0x504fb2c0, + 0x505032cf, 0x50508687, - 0x50513150, - 0x58320de7, - 0x68320da9, - 0x68328b8e, - 0x68330ba1, - 0x68338db7, - 0x68340dc7, - 0x6c320d85, - 0x6c328b71, - 0x6c330d90, - 0x74320980, - 0x783208e5, - 0x783288fa, - 0x78330906, + 0x505132e2, + 0x58320e1f, + 0x68320de1, + 0x68328b9b, + 0x68330bae, + 0x68338def, + 0x68340dff, + 0x683480b0, + 0x6c320dbd, + 0x6c328b7e, + 0x6c330dc8, + 0x7432098d, + 0x783208f2, + 0x78328907, + 0x78330913, 0x78338083, - 0x78340915, - 0x7834892a, - 0x78350949, - 0x7835896b, - 0x78360980, - 0x78368996, - 0x783709a6, - 0x783789b9, - 0x783809cc, - 0x783889de, - 0x783909eb, - 0x78398a0a, - 0x783a0a1f, - 0x783a8a2d, - 0x783b0a37, - 0x783b8a4b, - 0x783c0a62, - 0x783c8a77, - 0x783d0a8e, - 0x783d8aa3, - 0x783e09f9, - 0x80321151, + 0x78340922, + 0x78348937, + 0x78350956, + 0x78358978, + 0x7836098d, + 0x783689a3, + 0x783709b3, + 0x783789c6, + 0x783809d9, + 0x783889eb, + 0x783909f8, + 0x78398a17, + 0x783a0a2c, + 0x783a8a3a, + 0x783b0a44, + 0x783b8a58, + 0x783c0a6f, + 0x783c8a84, + 0x783d0a9b, + 0x783d8ab0, + 0x783e0a06, + 0x803211b2, }; const size_t kOpenSSLReasonValuesLen = sizeof(kOpenSSLReasonValues) / sizeof(kOpenSSLReasonValues[0]); @@ -2093,6 +2238,7 @@ const char kOpenSSLReasonStringData[] = "UNSUPPORTED_METHOD\0" "WRITE_TO_READ_ONLY_BIO\0" "ARG2_LT_ARG3\0" + "BAD_ENCODING\0" "BAD_RECIPROCAL\0" "BIGNUM_TOO_LONG\0" "BITS_TOO_SMALL\0" @@ -2146,6 +2292,7 @@ const char kOpenSSLReasonStringData[] = "BAD_Q_VALUE\0" "MISSING_PARAMETERS\0" "NEED_NEW_SETUP_VALUES\0" + "BIGNUM_OUT_OF_RANGE\0" "COORDINATES_OUT_OF_RANGE\0" "D2I_ECPKPARAMETERS_FAILURE\0" "EC_GROUP_NEW_BY_NAME_FAILURE\0" @@ -2168,6 +2315,7 @@ const char kOpenSSLReasonStringData[] = "UNDEFINED_GENERATOR\0" "UNKNOWN_GROUP\0" "UNKNOWN_ORDER\0" + "WRONG_CURVE_PARAMETERS\0" "WRONG_ORDER\0" "KDF_FAILED\0" "POINT_ARITHMETIC_FAILURE\0" @@ -2175,6 +2323,7 @@ const char kOpenSSLReasonStringData[] = "NOT_IMPLEMENTED\0" "RANDOM_NUMBER_GENERATION_FAILED\0" "OPERATION_NOT_SUPPORTED\0" + "BN_DECODE_ERROR\0" "COMMAND_NOT_SUPPORTED\0" "CONTEXT_NOT_INITIALISED\0" "DIFFERENT_KEY_TYPES\0" @@ -2204,6 +2353,7 @@ const char kOpenSSLReasonStringData[] = "NO_PARAMETERS_SET\0" "OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE\0" "OPERATON_NOT_INITIALIZED\0" + "PARAMETER_ENCODING_ERROR\0" "UNKNOWN_DIGEST\0" "UNKNOWN_MASK_DIGEST\0" "UNKNOWN_MESSAGE_DIGEST_ALGORITHM\0" @@ -2255,8 +2405,10 @@ const char kOpenSSLReasonStringData[] = "BAD_FIXED_HEADER_DECRYPT\0" "BAD_PAD_BYTE_COUNT\0" "BAD_RSA_PARAMETERS\0" + "BAD_VERSION\0" "BLOCK_TYPE_IS_NOT_01\0" "BN_NOT_INITIALIZED\0" + "CANNOT_RECOVER_MULTI_PRIME_KEY\0" "CRT_PARAMS_ALREADY_GIVEN\0" "CRT_VALUES_INCORRECT\0" "DATA_LEN_NOT_EQUAL_TO_MOD_LEN\0" @@ -2274,6 +2426,7 @@ const char kOpenSSLReasonStringData[] = "INVALID_MESSAGE_LENGTH\0" "KEY_SIZE_TOO_SMALL\0" "LAST_OCTET_INVALID\0" + "MUST_HAVE_AT_LEAST_TWO_PRIMES\0" "NO_PUBLIC_EXPONENT\0" "NULL_BEFORE_BLOCK_MISSING\0" "N_NOT_EQUAL_P_Q\0" @@ -2334,6 +2487,7 @@ const char kOpenSSLReasonStringData[] = "DTLS_MESSAGE_TOO_BIG\0" "ECC_CERT_NOT_FOR_SIGNING\0" "EMPTY_SRTP_PROTECTION_PROFILE_LIST\0" + "EMS_STATE_INCONSISTENT\0" "ENCRYPTED_LENGTH_TOO_LONG\0" "ERROR_IN_RECEIVED_CIPHER_LIST\0" "EVP_DIGESTSIGNFINAL_FAILED\0" @@ -2385,6 +2539,7 @@ const char kOpenSSLReasonStringData[] = "NULL_SSL_CTX\0" "NULL_SSL_METHOD_PASSED\0" "OLD_SESSION_CIPHER_NOT_RETURNED\0" + "OLD_SESSION_VERSION_NOT_RETURNED\0" "PACKET_LENGTH_TOO_LONG\0" "PARSE_TLSEXT\0" "PATH_TOO_LONG\0" @@ -2402,11 +2557,14 @@ const char kOpenSSLReasonStringData[] = "RENEGOTIATION_ENCODING_ERR\0" "RENEGOTIATION_MISMATCH\0" "REQUIRED_CIPHER_MISSING\0" + "RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION\0" + "RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION\0" "SCSV_RECEIVED_WHEN_RENEGOTIATING\0" "SERVERHELLO_TLSEXT\0" "SESSION_ID_CONTEXT_UNINITIALIZED\0" "SESSION_MAY_NOT_BE_CREATED\0" "SIGNATURE_ALGORITHMS_ERROR\0" + "SIGNATURE_ALGORITHMS_EXTENSION_SENT_BY_SERVER\0" "SRTP_COULD_NOT_ALLOCATE_PROFILES\0" "SRTP_PROTECTION_PROFILE_LIST_TOO_LONG\0" "SRTP_UNKNOWN_PROTECTION_PROFILE\0" @@ -2454,8 +2612,10 @@ const char kOpenSSLReasonStringData[] = "TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST\0" "TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG\0" "TOO_MANY_EMPTY_FRAGMENTS\0" + "TOO_MANY_WARNING_ALERTS\0" "UNABLE_TO_FIND_ECDH_PARAMETERS\0" "UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS\0" + "UNEXPECTED_EXTENSION\0" "UNEXPECTED_GROUP_CLOSE\0" "UNEXPECTED_MESSAGE\0" "UNEXPECTED_OPERATOR_IN_GROUP\0" diff --git a/third_party/boringssl/linux-aarch64/crypto/aes/aesv8-armx.S b/third_party/boringssl/linux-aarch64/crypto/aes/aesv8-armx64.S similarity index 66% rename from third_party/boringssl/linux-aarch64/crypto/aes/aesv8-armx.S rename to third_party/boringssl/linux-aarch64/crypto/aes/aesv8-armx64.S index 0a4b1ac4c4008..c414476cdf72f 100644 --- a/third_party/boringssl/linux-aarch64/crypto/aes/aesv8-armx.S +++ b/third_party/boringssl/linux-aarch64/crypto/aes/aesv8-armx64.S @@ -1,10 +1,13 @@ +#if defined(__aarch64__) #include "arm_arch.h" #if __ARM_MAX_ARCH__>=7 .text +#if !defined(__clang__) .arch armv8-a+crypto +#endif .align 5 -rcon: +.Lrcon: .long 0x01,0x01,0x01,0x01 .long 0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d // rotate-n-splat .long 0x1b,0x1b,0x1b,0x1b @@ -29,7 +32,7 @@ aes_v8_set_encrypt_key: tst w1,#0x3f b.ne .Lenc_key_abort - adr x3,rcon + adr x3,.Lrcon cmp w1,#192 eor v0.16b,v0.16b,v0.16b @@ -53,7 +56,7 @@ aes_v8_set_encrypt_key: ext v5.16b,v0.16b,v5.16b,#12 eor v3.16b,v3.16b,v5.16b ext v5.16b,v0.16b,v5.16b,#12 - eor v6.16b,v6.16b,v1.16b + eor v6.16b,v6.16b,v1.16b eor v3.16b,v3.16b,v5.16b shl v1.16b,v1.16b,#1 eor v3.16b,v3.16b,v6.16b @@ -70,7 +73,7 @@ aes_v8_set_encrypt_key: ext v5.16b,v0.16b,v5.16b,#12 eor v3.16b,v3.16b,v5.16b ext v5.16b,v0.16b,v5.16b,#12 - eor v6.16b,v6.16b,v1.16b + eor v6.16b,v6.16b,v1.16b eor v3.16b,v3.16b,v5.16b shl v1.16b,v1.16b,#1 eor v3.16b,v3.16b,v6.16b @@ -84,7 +87,7 @@ aes_v8_set_encrypt_key: ext v5.16b,v0.16b,v5.16b,#12 eor v3.16b,v3.16b,v5.16b ext v5.16b,v0.16b,v5.16b,#12 - eor v6.16b,v6.16b,v1.16b + eor v6.16b,v6.16b,v1.16b eor v3.16b,v3.16b,v5.16b eor v3.16b,v3.16b,v6.16b st1 {v3.4s},[x2] @@ -115,7 +118,7 @@ aes_v8_set_encrypt_key: dup v5.4s,v3.s[3] eor v5.16b,v5.16b,v4.16b - eor v6.16b,v6.16b,v1.16b + eor v6.16b,v6.16b,v1.16b ext v4.16b,v0.16b,v4.16b,#12 shl v1.16b,v1.16b,#1 eor v4.16b,v4.16b,v5.16b @@ -146,7 +149,7 @@ aes_v8_set_encrypt_key: ext v5.16b,v0.16b,v5.16b,#12 eor v3.16b,v3.16b,v5.16b ext v5.16b,v0.16b,v5.16b,#12 - eor v6.16b,v6.16b,v1.16b + eor v6.16b,v6.16b,v1.16b eor v3.16b,v3.16b,v5.16b shl v1.16b,v1.16b,#1 eor v3.16b,v3.16b,v6.16b @@ -227,17 +230,17 @@ aes_v8_encrypt: .Loop_enc: aese v2.16b,v0.16b - ld1 {v0.4s},[x2],#16 aesmc v2.16b,v2.16b + ld1 {v0.4s},[x2],#16 subs w3,w3,#2 aese v2.16b,v1.16b - ld1 {v1.4s},[x2],#16 aesmc v2.16b,v2.16b + ld1 {v1.4s},[x2],#16 b.gt .Loop_enc aese v2.16b,v0.16b - ld1 {v0.4s},[x2] aesmc v2.16b,v2.16b + ld1 {v0.4s},[x2] aese v2.16b,v1.16b eor v2.16b,v2.16b,v0.16b @@ -256,17 +259,17 @@ aes_v8_decrypt: .Loop_dec: aesd v2.16b,v0.16b - ld1 {v0.4s},[x2],#16 aesimc v2.16b,v2.16b + ld1 {v0.4s},[x2],#16 subs w3,w3,#2 aesd v2.16b,v1.16b - ld1 {v1.4s},[x2],#16 aesimc v2.16b,v2.16b + ld1 {v1.4s},[x2],#16 b.gt .Loop_dec aesd v2.16b,v0.16b - ld1 {v0.4s},[x2] aesimc v2.16b,v2.16b + ld1 {v0.4s},[x2] aesd v2.16b,v1.16b eor v2.16b,v2.16b,v0.16b @@ -290,13 +293,13 @@ aes_v8_cbc_encrypt: ld1 {v6.16b},[x4] ld1 {v0.16b},[x0],x8 - ld1 {v16.4s-v17.4s},[x3] // load key schedule... + ld1 {v16.4s,v17.4s},[x3] // load key schedule... sub w5,w5,#6 add x7,x3,x5,lsl#4 // pointer to last 7 round keys sub w5,w5,#2 - ld1 {v18.4s-v19.4s},[x7],#32 - ld1 {v20.4s-v21.4s},[x7],#32 - ld1 {v22.4s-v23.4s},[x7],#32 + ld1 {v18.4s,v19.4s},[x7],#32 + ld1 {v20.4s,v21.4s},[x7],#32 + ld1 {v22.4s,v23.4s},[x7],#32 ld1 {v7.4s},[x7] add x7,x3,#32 @@ -308,76 +311,99 @@ aes_v8_cbc_encrypt: eor v5.16b,v16.16b,v7.16b b.eq .Lcbc_enc128 + ld1 {v2.4s,v3.4s},[x7] + add x7,x3,#16 + add x6,x3,#16*4 + add x12,x3,#16*5 + aese v0.16b,v16.16b + aesmc v0.16b,v0.16b + add x14,x3,#16*6 + add x3,x3,#16*7 + b .Lenter_cbc_enc + +.align 4 .Loop_cbc_enc: aese v0.16b,v16.16b - ld1 {v16.4s},[x7],#16 aesmc v0.16b,v0.16b - subs w6,w6,#2 + st1 {v6.16b},[x1],#16 +.Lenter_cbc_enc: aese v0.16b,v17.16b - ld1 {v17.4s},[x7],#16 aesmc v0.16b,v0.16b - b.gt .Loop_cbc_enc + aese v0.16b,v2.16b + aesmc v0.16b,v0.16b + ld1 {v16.4s},[x6] + cmp w5,#4 + aese v0.16b,v3.16b + aesmc v0.16b,v0.16b + ld1 {v17.4s},[x12] + b.eq .Lcbc_enc192 aese v0.16b,v16.16b aesmc v0.16b,v0.16b - subs x2,x2,#16 + ld1 {v16.4s},[x14] aese v0.16b,v17.16b aesmc v0.16b,v0.16b - csel x8,xzr,x8,eq + ld1 {v17.4s},[x3] + nop + +.Lcbc_enc192: + aese v0.16b,v16.16b + aesmc v0.16b,v0.16b + subs x2,x2,#16 + aese v0.16b,v17.16b + aesmc v0.16b,v0.16b + csel x8,xzr,x8,eq aese v0.16b,v18.16b aesmc v0.16b,v0.16b - add x7,x3,#16 aese v0.16b,v19.16b aesmc v0.16b,v0.16b - ld1 {v16.16b},[x0],x8 + ld1 {v16.16b},[x0],x8 aese v0.16b,v20.16b aesmc v0.16b,v0.16b - eor v16.16b,v16.16b,v5.16b + eor v16.16b,v16.16b,v5.16b aese v0.16b,v21.16b aesmc v0.16b,v0.16b - ld1 {v17.4s},[x7],#16 // re-pre-load rndkey[1] + ld1 {v17.4s},[x7] // re-pre-load rndkey[1] aese v0.16b,v22.16b aesmc v0.16b,v0.16b aese v0.16b,v23.16b - - mov w6,w5 eor v6.16b,v0.16b,v7.16b - st1 {v6.16b},[x1],#16 b.hs .Loop_cbc_enc + st1 {v6.16b},[x1],#16 b .Lcbc_done .align 5 .Lcbc_enc128: - ld1 {v2.4s-v3.4s},[x7] + ld1 {v2.4s,v3.4s},[x7] aese v0.16b,v16.16b aesmc v0.16b,v0.16b b .Lenter_cbc_enc128 .Loop_cbc_enc128: aese v0.16b,v16.16b aesmc v0.16b,v0.16b - st1 {v6.16b},[x1],#16 + st1 {v6.16b},[x1],#16 .Lenter_cbc_enc128: aese v0.16b,v17.16b aesmc v0.16b,v0.16b - subs x2,x2,#16 + subs x2,x2,#16 aese v0.16b,v2.16b aesmc v0.16b,v0.16b - csel x8,xzr,x8,eq + csel x8,xzr,x8,eq aese v0.16b,v3.16b aesmc v0.16b,v0.16b aese v0.16b,v18.16b aesmc v0.16b,v0.16b aese v0.16b,v19.16b aesmc v0.16b,v0.16b - ld1 {v16.16b},[x0],x8 + ld1 {v16.16b},[x0],x8 aese v0.16b,v20.16b aesmc v0.16b,v0.16b aese v0.16b,v21.16b aesmc v0.16b,v0.16b aese v0.16b,v22.16b aesmc v0.16b,v0.16b - eor v16.16b,v16.16b,v5.16b + eor v16.16b,v16.16b,v5.16b aese v0.16b,v23.16b eor v6.16b,v0.16b,v7.16b b.hs .Loop_cbc_enc128 @@ -402,81 +428,80 @@ aes_v8_cbc_encrypt: .Loop3x_cbc_dec: aesd v0.16b,v16.16b - aesd v1.16b,v16.16b - aesd v18.16b,v16.16b - ld1 {v16.4s},[x7],#16 aesimc v0.16b,v0.16b + aesd v1.16b,v16.16b aesimc v1.16b,v1.16b + aesd v18.16b,v16.16b aesimc v18.16b,v18.16b + ld1 {v16.4s},[x7],#16 subs w6,w6,#2 aesd v0.16b,v17.16b - aesd v1.16b,v17.16b - aesd v18.16b,v17.16b - ld1 {v17.4s},[x7],#16 aesimc v0.16b,v0.16b + aesd v1.16b,v17.16b aesimc v1.16b,v1.16b + aesd v18.16b,v17.16b aesimc v18.16b,v18.16b + ld1 {v17.4s},[x7],#16 b.gt .Loop3x_cbc_dec aesd v0.16b,v16.16b - aesd v1.16b,v16.16b - aesd v18.16b,v16.16b - eor v4.16b,v6.16b,v7.16b aesimc v0.16b,v0.16b + aesd v1.16b,v16.16b aesimc v1.16b,v1.16b + aesd v18.16b,v16.16b aesimc v18.16b,v18.16b - eor v5.16b,v2.16b,v7.16b + eor v4.16b,v6.16b,v7.16b + subs x2,x2,#0x30 + eor v5.16b,v2.16b,v7.16b + csel x6,x2,x6,lo // x6, w6, is zero at this point aesd v0.16b,v17.16b - aesd v1.16b,v17.16b - aesd v18.16b,v17.16b - eor v17.16b,v3.16b,v7.16b - subs x2,x2,#0x30 aesimc v0.16b,v0.16b + aesd v1.16b,v17.16b aesimc v1.16b,v1.16b + aesd v18.16b,v17.16b aesimc v18.16b,v18.16b - orr v6.16b,v19.16b,v19.16b - csel x6,x2,x6,lo // x6, w6, is zero at this point - aesd v0.16b,v20.16b - aesd v1.16b,v20.16b - aesd v18.16b,v20.16b - add x0,x0,x6 // x0 is adjusted in such way that + eor v17.16b,v3.16b,v7.16b + add x0,x0,x6 // x0 is adjusted in such way that // at exit from the loop v1.16b-v18.16b // are loaded with last "words" + orr v6.16b,v19.16b,v19.16b + mov x7,x3 + aesd v0.16b,v20.16b aesimc v0.16b,v0.16b + aesd v1.16b,v20.16b aesimc v1.16b,v1.16b + aesd v18.16b,v20.16b aesimc v18.16b,v18.16b - mov x7,x3 + ld1 {v2.16b},[x0],#16 aesd v0.16b,v21.16b - aesd v1.16b,v21.16b - aesd v18.16b,v21.16b - ld1 {v2.16b},[x0],#16 aesimc v0.16b,v0.16b + aesd v1.16b,v21.16b aesimc v1.16b,v1.16b + aesd v18.16b,v21.16b aesimc v18.16b,v18.16b - ld1 {v3.16b},[x0],#16 + ld1 {v3.16b},[x0],#16 aesd v0.16b,v22.16b - aesd v1.16b,v22.16b - aesd v18.16b,v22.16b - ld1 {v19.16b},[x0],#16 aesimc v0.16b,v0.16b + aesd v1.16b,v22.16b aesimc v1.16b,v1.16b + aesd v18.16b,v22.16b aesimc v18.16b,v18.16b - ld1 {v16.4s},[x7],#16 // re-pre-load rndkey[0] + ld1 {v19.16b},[x0],#16 aesd v0.16b,v23.16b aesd v1.16b,v23.16b aesd v18.16b,v23.16b - - add w6,w5,#2 + ld1 {v16.4s},[x7],#16 // re-pre-load rndkey[0] + add w6,w5,#2 eor v4.16b,v4.16b,v0.16b eor v5.16b,v5.16b,v1.16b eor v18.16b,v18.16b,v17.16b - ld1 {v17.4s},[x7],#16 // re-pre-load rndkey[1] - orr v0.16b,v2.16b,v2.16b + ld1 {v17.4s},[x7],#16 // re-pre-load rndkey[1] st1 {v4.16b},[x1],#16 - orr v1.16b,v3.16b,v3.16b + orr v0.16b,v2.16b,v2.16b st1 {v5.16b},[x1],#16 + orr v1.16b,v3.16b,v3.16b st1 {v18.16b},[x1],#16 - orr v18.16b,v19.16b,v19.16b + orr v18.16b,v19.16b,v19.16b b.hs .Loop3x_cbc_dec cmn x2,#0x30 @@ -485,54 +510,54 @@ aes_v8_cbc_encrypt: .Lcbc_dec_tail: aesd v1.16b,v16.16b - aesd v18.16b,v16.16b - ld1 {v16.4s},[x7],#16 aesimc v1.16b,v1.16b + aesd v18.16b,v16.16b aesimc v18.16b,v18.16b + ld1 {v16.4s},[x7],#16 subs w6,w6,#2 aesd v1.16b,v17.16b - aesd v18.16b,v17.16b - ld1 {v17.4s},[x7],#16 aesimc v1.16b,v1.16b + aesd v18.16b,v17.16b aesimc v18.16b,v18.16b + ld1 {v17.4s},[x7],#16 b.gt .Lcbc_dec_tail aesd v1.16b,v16.16b - aesd v18.16b,v16.16b aesimc v1.16b,v1.16b + aesd v18.16b,v16.16b aesimc v18.16b,v18.16b aesd v1.16b,v17.16b - aesd v18.16b,v17.16b aesimc v1.16b,v1.16b + aesd v18.16b,v17.16b aesimc v18.16b,v18.16b aesd v1.16b,v20.16b - aesd v18.16b,v20.16b aesimc v1.16b,v1.16b + aesd v18.16b,v20.16b aesimc v18.16b,v18.16b - cmn x2,#0x20 + cmn x2,#0x20 aesd v1.16b,v21.16b - aesd v18.16b,v21.16b aesimc v1.16b,v1.16b + aesd v18.16b,v21.16b aesimc v18.16b,v18.16b - eor v5.16b,v6.16b,v7.16b + eor v5.16b,v6.16b,v7.16b aesd v1.16b,v22.16b - aesd v18.16b,v22.16b aesimc v1.16b,v1.16b + aesd v18.16b,v22.16b aesimc v18.16b,v18.16b - eor v17.16b,v3.16b,v7.16b + eor v17.16b,v3.16b,v7.16b aesd v1.16b,v23.16b aesd v18.16b,v23.16b b.eq .Lcbc_dec_one eor v5.16b,v5.16b,v1.16b eor v17.16b,v17.16b,v18.16b - orr v6.16b,v19.16b,v19.16b + orr v6.16b,v19.16b,v19.16b st1 {v5.16b},[x1],#16 st1 {v17.16b},[x1],#16 b .Lcbc_done .Lcbc_dec_one: eor v5.16b,v5.16b,v18.16b - orr v6.16b,v19.16b,v19.16b + orr v6.16b,v19.16b,v19.16b st1 {v5.16b},[x1],#16 .Lcbc_done: @@ -545,181 +570,182 @@ aes_v8_cbc_encrypt: .type aes_v8_ctr32_encrypt_blocks,%function .align 5 aes_v8_ctr32_encrypt_blocks: - stp x29,x30,[sp,#-16]! - add x29,sp,#0 - ldr w5,[x3,#240] - - ldr w8, [x4, #12] - ld1 {v0.4s},[x4] - - ld1 {v16.4s-v17.4s},[x3] // load key schedule... - sub w5,w5,#4 - mov x12,#16 - cmp x2,#2 - add x7,x3,x5,lsl#4 // pointer to last 5 round keys - sub w5,w5,#2 - ld1 {v20.4s-v21.4s},[x7],#32 - ld1 {v22.4s-v23.4s},[x7],#32 - ld1 {v7.4s},[x7] - add x7,x3,#32 - mov w6,w5 + stp x29,x30,[sp,#-16]! + add x29,sp,#0 + ldr w5,[x3,#240] + + ldr w8, [x4, #12] + ld1 {v0.4s},[x4] + + ld1 {v16.4s,v17.4s},[x3] // load key schedule... + sub w5,w5,#4 + mov x12,#16 + cmp x2,#2 + add x7,x3,x5,lsl#4 // pointer to last 5 round keys + sub w5,w5,#2 + ld1 {v20.4s,v21.4s},[x7],#32 + ld1 {v22.4s,v23.4s},[x7],#32 + ld1 {v7.4s},[x7] + add x7,x3,#32 + mov w6,w5 csel x12,xzr,x12,lo #ifndef __ARMEB__ - rev w8, w8 + rev w8, w8 #endif - orr v1.16b,v0.16b,v0.16b - add w10, w8, #1 - orr v18.16b,v0.16b,v0.16b - add w8, w8, #2 - orr v6.16b,v0.16b,v0.16b - rev w10, w10 - mov v1.s[3],w10 - b.ls .Lctr32_tail - rev w12, w8 - sub x2,x2,#3 // bias - mov v18.s[3],w12 - b .Loop3x_ctr32 + orr v1.16b,v0.16b,v0.16b + add w10, w8, #1 + orr v18.16b,v0.16b,v0.16b + add w8, w8, #2 + orr v6.16b,v0.16b,v0.16b + rev w10, w10 + mov v1.s[3],w10 + b.ls .Lctr32_tail + rev w12, w8 + sub x2,x2,#3 // bias + mov v18.s[3],w12 + b .Loop3x_ctr32 .align 4 .Loop3x_ctr32: - aese v0.16b,v16.16b - aese v1.16b,v16.16b - aese v18.16b,v16.16b - ld1 {v16.4s},[x7],#16 - aesmc v0.16b,v0.16b - aesmc v1.16b,v1.16b - aesmc v18.16b,v18.16b - subs w6,w6,#2 - aese v0.16b,v17.16b - aese v1.16b,v17.16b - aese v18.16b,v17.16b - ld1 {v17.4s},[x7],#16 - aesmc v0.16b,v0.16b - aesmc v1.16b,v1.16b - aesmc v18.16b,v18.16b - b.gt .Loop3x_ctr32 - - aese v0.16b,v16.16b - aese v1.16b,v16.16b - aese v18.16b,v16.16b - mov x7,x3 - aesmc v4.16b,v0.16b - ld1 {v2.16b},[x0],#16 - aesmc v5.16b,v1.16b - aesmc v18.16b,v18.16b - orr v0.16b,v6.16b,v6.16b - aese v4.16b,v17.16b - ld1 {v3.16b},[x0],#16 - aese v5.16b,v17.16b - aese v18.16b,v17.16b - orr v1.16b,v6.16b,v6.16b - aesmc v4.16b,v4.16b - ld1 {v19.16b},[x0],#16 - aesmc v5.16b,v5.16b - aesmc v17.16b,v18.16b - orr v18.16b,v6.16b,v6.16b - add w9,w8,#1 - aese v4.16b,v20.16b - aese v5.16b,v20.16b - aese v17.16b,v20.16b - eor v2.16b,v2.16b,v7.16b - add w10,w8,#2 - aesmc v4.16b,v4.16b - aesmc v5.16b,v5.16b - aesmc v17.16b,v17.16b - eor v3.16b,v3.16b,v7.16b - add w8,w8,#3 - aese v4.16b,v21.16b - aese v5.16b,v21.16b - aese v17.16b,v21.16b - eor v19.16b,v19.16b,v7.16b - rev w9,w9 - aesmc v4.16b,v4.16b - ld1 {v16.4s},[x7],#16 // re-pre-load rndkey[0] - aesmc v5.16b,v5.16b - aesmc v17.16b,v17.16b - mov v0.s[3], w9 - rev w10,w10 - aese v4.16b,v22.16b - aese v5.16b,v22.16b - aese v17.16b,v22.16b - mov v1.s[3], w10 - rev w12,w8 - aesmc v4.16b,v4.16b - aesmc v5.16b,v5.16b - aesmc v17.16b,v17.16b - mov v18.s[3], w12 - subs x2,x2,#3 - aese v4.16b,v23.16b - aese v5.16b,v23.16b - aese v17.16b,v23.16b - - mov w6,w5 - eor v2.16b,v2.16b,v4.16b - eor v3.16b,v3.16b,v5.16b - eor v19.16b,v19.16b,v17.16b - ld1 {v17.4s},[x7],#16 // re-pre-load rndkey[1] - st1 {v2.16b},[x1],#16 - st1 {v3.16b},[x1],#16 - st1 {v19.16b},[x1],#16 - b.hs .Loop3x_ctr32 - - adds x2,x2,#3 - b.eq .Lctr32_done - cmp x2,#1 - mov x12,#16 + aese v0.16b,v16.16b + aesmc v0.16b,v0.16b + aese v1.16b,v16.16b + aesmc v1.16b,v1.16b + aese v18.16b,v16.16b + aesmc v18.16b,v18.16b + ld1 {v16.4s},[x7],#16 + subs w6,w6,#2 + aese v0.16b,v17.16b + aesmc v0.16b,v0.16b + aese v1.16b,v17.16b + aesmc v1.16b,v1.16b + aese v18.16b,v17.16b + aesmc v18.16b,v18.16b + ld1 {v17.4s},[x7],#16 + b.gt .Loop3x_ctr32 + + aese v0.16b,v16.16b + aesmc v4.16b,v0.16b + aese v1.16b,v16.16b + aesmc v5.16b,v1.16b + ld1 {v2.16b},[x0],#16 + orr v0.16b,v6.16b,v6.16b + aese v18.16b,v16.16b + aesmc v18.16b,v18.16b + ld1 {v3.16b},[x0],#16 + orr v1.16b,v6.16b,v6.16b + aese v4.16b,v17.16b + aesmc v4.16b,v4.16b + aese v5.16b,v17.16b + aesmc v5.16b,v5.16b + ld1 {v19.16b},[x0],#16 + mov x7,x3 + aese v18.16b,v17.16b + aesmc v17.16b,v18.16b + orr v18.16b,v6.16b,v6.16b + add w9,w8,#1 + aese v4.16b,v20.16b + aesmc v4.16b,v4.16b + aese v5.16b,v20.16b + aesmc v5.16b,v5.16b + eor v2.16b,v2.16b,v7.16b + add w10,w8,#2 + aese v17.16b,v20.16b + aesmc v17.16b,v17.16b + eor v3.16b,v3.16b,v7.16b + add w8,w8,#3 + aese v4.16b,v21.16b + aesmc v4.16b,v4.16b + aese v5.16b,v21.16b + aesmc v5.16b,v5.16b + eor v19.16b,v19.16b,v7.16b + rev w9,w9 + aese v17.16b,v21.16b + aesmc v17.16b,v17.16b + mov v0.s[3], w9 + rev w10,w10 + aese v4.16b,v22.16b + aesmc v4.16b,v4.16b + aese v5.16b,v22.16b + aesmc v5.16b,v5.16b + mov v1.s[3], w10 + rev w12,w8 + aese v17.16b,v22.16b + aesmc v17.16b,v17.16b + mov v18.s[3], w12 + subs x2,x2,#3 + aese v4.16b,v23.16b + aese v5.16b,v23.16b + aese v17.16b,v23.16b + + eor v2.16b,v2.16b,v4.16b + ld1 {v16.4s},[x7],#16 // re-pre-load rndkey[0] + st1 {v2.16b},[x1],#16 + eor v3.16b,v3.16b,v5.16b + mov w6,w5 + st1 {v3.16b},[x1],#16 + eor v19.16b,v19.16b,v17.16b + ld1 {v17.4s},[x7],#16 // re-pre-load rndkey[1] + st1 {v19.16b},[x1],#16 + b.hs .Loop3x_ctr32 + + adds x2,x2,#3 + b.eq .Lctr32_done + cmp x2,#1 + mov x12,#16 csel x12,xzr,x12,eq .Lctr32_tail: - aese v0.16b,v16.16b - aese v1.16b,v16.16b - ld1 {v16.4s},[x7],#16 - aesmc v0.16b,v0.16b - aesmc v1.16b,v1.16b - subs w6,w6,#2 - aese v0.16b,v17.16b - aese v1.16b,v17.16b - ld1 {v17.4s},[x7],#16 - aesmc v0.16b,v0.16b - aesmc v1.16b,v1.16b - b.gt .Lctr32_tail - - aese v0.16b,v16.16b - aese v1.16b,v16.16b - aesmc v0.16b,v0.16b - aesmc v1.16b,v1.16b - aese v0.16b,v17.16b - aese v1.16b,v17.16b - aesmc v0.16b,v0.16b - aesmc v1.16b,v1.16b - ld1 {v2.16b},[x0],x12 - aese v0.16b,v20.16b - aese v1.16b,v20.16b - ld1 {v3.16b},[x0] - aesmc v0.16b,v0.16b - aesmc v1.16b,v1.16b - aese v0.16b,v21.16b - aese v1.16b,v21.16b - aesmc v0.16b,v0.16b - aesmc v1.16b,v1.16b - aese v0.16b,v22.16b - aese v1.16b,v22.16b - eor v2.16b,v2.16b,v7.16b - aesmc v0.16b,v0.16b - aesmc v1.16b,v1.16b - eor v3.16b,v3.16b,v7.16b - aese v0.16b,v23.16b - aese v1.16b,v23.16b - - cmp x2,#1 - eor v2.16b,v2.16b,v0.16b - eor v3.16b,v3.16b,v1.16b - st1 {v2.16b},[x1],#16 - b.eq .Lctr32_done - st1 {v3.16b},[x1] + aese v0.16b,v16.16b + aesmc v0.16b,v0.16b + aese v1.16b,v16.16b + aesmc v1.16b,v1.16b + ld1 {v16.4s},[x7],#16 + subs w6,w6,#2 + aese v0.16b,v17.16b + aesmc v0.16b,v0.16b + aese v1.16b,v17.16b + aesmc v1.16b,v1.16b + ld1 {v17.4s},[x7],#16 + b.gt .Lctr32_tail + + aese v0.16b,v16.16b + aesmc v0.16b,v0.16b + aese v1.16b,v16.16b + aesmc v1.16b,v1.16b + aese v0.16b,v17.16b + aesmc v0.16b,v0.16b + aese v1.16b,v17.16b + aesmc v1.16b,v1.16b + ld1 {v2.16b},[x0],x12 + aese v0.16b,v20.16b + aesmc v0.16b,v0.16b + aese v1.16b,v20.16b + aesmc v1.16b,v1.16b + ld1 {v3.16b},[x0] + aese v0.16b,v21.16b + aesmc v0.16b,v0.16b + aese v1.16b,v21.16b + aesmc v1.16b,v1.16b + eor v2.16b,v2.16b,v7.16b + aese v0.16b,v22.16b + aesmc v0.16b,v0.16b + aese v1.16b,v22.16b + aesmc v1.16b,v1.16b + eor v3.16b,v3.16b,v7.16b + aese v0.16b,v23.16b + aese v1.16b,v23.16b + + cmp x2,#1 + eor v2.16b,v2.16b,v0.16b + eor v3.16b,v3.16b,v1.16b + st1 {v2.16b},[x1],#16 + b.eq .Lctr32_done + st1 {v3.16b},[x1] .Lctr32_done: - ldr x29,[sp],#16 + ldr x29,[sp],#16 ret .size aes_v8_ctr32_encrypt_blocks,.-aes_v8_ctr32_encrypt_blocks #endif +#endif \ No newline at end of file diff --git a/third_party/boringssl/linux-aarch64/crypto/modes/ghashv8-armx.S b/third_party/boringssl/linux-aarch64/crypto/modes/ghashv8-armx.S deleted file mode 100644 index 1bfb26340a6e9..0000000000000 --- a/third_party/boringssl/linux-aarch64/crypto/modes/ghashv8-armx.S +++ /dev/null @@ -1,115 +0,0 @@ -#include "arm_arch.h" - -.text -.arch armv8-a+crypto -.global gcm_init_v8 -.type gcm_init_v8,%function -.align 4 -gcm_init_v8: - ld1 {v17.2d},[x1] //load H - movi v16.16b,#0xe1 - ext v3.16b,v17.16b,v17.16b,#8 - shl v16.2d,v16.2d,#57 - ushr v18.2d,v16.2d,#63 - ext v16.16b,v18.16b,v16.16b,#8 //t0=0xc2....01 - dup v17.4s,v17.s[1] - ushr v19.2d,v3.2d,#63 - sshr v17.4s,v17.4s,#31 //broadcast carry bit - and v19.16b,v19.16b,v16.16b - shl v3.2d,v3.2d,#1 - ext v19.16b,v19.16b,v19.16b,#8 - and v16.16b,v16.16b,v17.16b - orr v3.16b,v3.16b,v19.16b //H<<<=1 - eor v3.16b,v3.16b,v16.16b //twisted H - st1 {v3.2d},[x0] - - ret -.size gcm_init_v8,.-gcm_init_v8 - -.global gcm_gmult_v8 -.type gcm_gmult_v8,%function -.align 4 -gcm_gmult_v8: - ld1 {v17.2d},[x0] //load Xi - movi v19.16b,#0xe1 - ld1 {v20.2d},[x1] //load twisted H - shl v19.2d,v19.2d,#57 -#ifndef __ARMEB__ - rev64 v17.16b,v17.16b -#endif - ext v21.16b,v20.16b,v20.16b,#8 - mov x3,#0 - ext v3.16b,v17.16b,v17.16b,#8 - mov x12,#0 - eor v21.16b,v21.16b,v20.16b //Karatsuba pre-processing - mov x2,x0 - b .Lgmult_v8 -.size gcm_gmult_v8,.-gcm_gmult_v8 - -.global gcm_ghash_v8 -.type gcm_ghash_v8,%function -.align 4 -gcm_ghash_v8: - ld1 {v0.2d},[x0] //load [rotated] Xi - subs x3,x3,#16 - movi v19.16b,#0xe1 - mov x12,#16 - ld1 {v20.2d},[x1] //load twisted H - csel x12,xzr,x12,eq - ext v0.16b,v0.16b,v0.16b,#8 - shl v19.2d,v19.2d,#57 - ld1 {v17.2d},[x2],x12 //load [rotated] inp - ext v21.16b,v20.16b,v20.16b,#8 -#ifndef __ARMEB__ - rev64 v0.16b,v0.16b - rev64 v17.16b,v17.16b -#endif - eor v21.16b,v21.16b,v20.16b //Karatsuba pre-processing - ext v3.16b,v17.16b,v17.16b,#8 - b .Loop_v8 - -.align 4 -.Loop_v8: - ext v18.16b,v0.16b,v0.16b,#8 - eor v3.16b,v3.16b,v0.16b //inp^=Xi - eor v17.16b,v17.16b,v18.16b //v17.16b is rotated inp^Xi - -.Lgmult_v8: - pmull v0.1q,v20.1d,v3.1d //H.lo�Xi.lo - eor v17.16b,v17.16b,v3.16b //Karatsuba pre-processing - pmull2 v2.1q,v20.2d,v3.2d //H.hi�Xi.hi - subs x3,x3,#16 - pmull v1.1q,v21.1d,v17.1d //(H.lo+H.hi)�(Xi.lo+Xi.hi) - csel x12,xzr,x12,eq - - ext v17.16b,v0.16b,v2.16b,#8 //Karatsuba post-processing - eor v18.16b,v0.16b,v2.16b - eor v1.16b,v1.16b,v17.16b - ld1 {v17.2d},[x2],x12 //load [rotated] inp - eor v1.16b,v1.16b,v18.16b - pmull v18.1q,v0.1d,v19.1d //1st phase - - ins v2.d[0],v1.d[1] - ins v1.d[1],v0.d[0] -#ifndef __ARMEB__ - rev64 v17.16b,v17.16b -#endif - eor v0.16b,v1.16b,v18.16b - ext v3.16b,v17.16b,v17.16b,#8 - - ext v18.16b,v0.16b,v0.16b,#8 //2nd phase - pmull v0.1q,v0.1d,v19.1d - eor v18.16b,v18.16b,v2.16b - eor v0.16b,v0.16b,v18.16b - b.hs .Loop_v8 - -#ifndef __ARMEB__ - rev64 v0.16b,v0.16b -#endif - ext v0.16b,v0.16b,v0.16b,#8 - st1 {v0.2d},[x0] //write out Xi - - ret -.size gcm_ghash_v8,.-gcm_ghash_v8 -.asciz "GHASH for ARMv8, CRYPTOGAMS by " -.align 2 diff --git a/third_party/boringssl/linux-aarch64/crypto/modes/ghashv8-armx64.S b/third_party/boringssl/linux-aarch64/crypto/modes/ghashv8-armx64.S new file mode 100644 index 0000000000000..a0a9b6807a96b --- /dev/null +++ b/third_party/boringssl/linux-aarch64/crypto/modes/ghashv8-armx64.S @@ -0,0 +1,232 @@ +#if defined(__aarch64__) +#include "arm_arch.h" + +.text +#if !defined(__clang__) +.arch armv8-a+crypto +#endif +.globl gcm_init_v8 +.type gcm_init_v8,%function +.align 4 +gcm_init_v8: + ld1 {v17.2d},[x1] //load input H + movi v19.16b,#0xe1 + shl v19.2d,v19.2d,#57 //0xc2.0 + ext v3.16b,v17.16b,v17.16b,#8 + ushr v18.2d,v19.2d,#63 + dup v17.4s,v17.s[1] + ext v16.16b,v18.16b,v19.16b,#8 //t0=0xc2....01 + ushr v18.2d,v3.2d,#63 + sshr v17.4s,v17.4s,#31 //broadcast carry bit + and v18.16b,v18.16b,v16.16b + shl v3.2d,v3.2d,#1 + ext v18.16b,v18.16b,v18.16b,#8 + and v16.16b,v16.16b,v17.16b + orr v3.16b,v3.16b,v18.16b //H<<<=1 + eor v20.16b,v3.16b,v16.16b //twisted H + st1 {v20.2d},[x0],#16 //store Htable[0] + + //calculate H^2 + ext v16.16b,v20.16b,v20.16b,#8 //Karatsuba pre-processing + pmull v0.1q,v20.1d,v20.1d + eor v16.16b,v16.16b,v20.16b + pmull2 v2.1q,v20.2d,v20.2d + pmull v1.1q,v16.1d,v16.1d + + ext v17.16b,v0.16b,v2.16b,#8 //Karatsuba post-processing + eor v18.16b,v0.16b,v2.16b + eor v1.16b,v1.16b,v17.16b + eor v1.16b,v1.16b,v18.16b + pmull v18.1q,v0.1d,v19.1d //1st phase + + ins v2.d[0],v1.d[1] + ins v1.d[1],v0.d[0] + eor v0.16b,v1.16b,v18.16b + + ext v18.16b,v0.16b,v0.16b,#8 //2nd phase + pmull v0.1q,v0.1d,v19.1d + eor v18.16b,v18.16b,v2.16b + eor v22.16b,v0.16b,v18.16b + + ext v17.16b,v22.16b,v22.16b,#8 //Karatsuba pre-processing + eor v17.16b,v17.16b,v22.16b + ext v21.16b,v16.16b,v17.16b,#8 //pack Karatsuba pre-processed + st1 {v21.2d,v22.2d},[x0] //store Htable[1..2] + + ret +.size gcm_init_v8,.-gcm_init_v8 +.globl gcm_gmult_v8 +.type gcm_gmult_v8,%function +.align 4 +gcm_gmult_v8: + ld1 {v17.2d},[x0] //load Xi + movi v19.16b,#0xe1 + ld1 {v20.2d,v21.2d},[x1] //load twisted H, ... + shl v19.2d,v19.2d,#57 +#ifndef __ARMEB__ + rev64 v17.16b,v17.16b +#endif + ext v3.16b,v17.16b,v17.16b,#8 + + pmull v0.1q,v20.1d,v3.1d //H.lo�Xi.lo + eor v17.16b,v17.16b,v3.16b //Karatsuba pre-processing + pmull2 v2.1q,v20.2d,v3.2d //H.hi�Xi.hi + pmull v1.1q,v21.1d,v17.1d //(H.lo+H.hi)�(Xi.lo+Xi.hi) + + ext v17.16b,v0.16b,v2.16b,#8 //Karatsuba post-processing + eor v18.16b,v0.16b,v2.16b + eor v1.16b,v1.16b,v17.16b + eor v1.16b,v1.16b,v18.16b + pmull v18.1q,v0.1d,v19.1d //1st phase of reduction + + ins v2.d[0],v1.d[1] + ins v1.d[1],v0.d[0] + eor v0.16b,v1.16b,v18.16b + + ext v18.16b,v0.16b,v0.16b,#8 //2nd phase of reduction + pmull v0.1q,v0.1d,v19.1d + eor v18.16b,v18.16b,v2.16b + eor v0.16b,v0.16b,v18.16b + +#ifndef __ARMEB__ + rev64 v0.16b,v0.16b +#endif + ext v0.16b,v0.16b,v0.16b,#8 + st1 {v0.2d},[x0] //write out Xi + + ret +.size gcm_gmult_v8,.-gcm_gmult_v8 +.globl gcm_ghash_v8 +.type gcm_ghash_v8,%function +.align 4 +gcm_ghash_v8: + ld1 {v0.2d},[x0] //load [rotated] Xi + //"[rotated]" means that + //loaded value would have + //to be rotated in order to + //make it appear as in + //alorithm specification + subs x3,x3,#32 //see if x3 is 32 or larger + mov x12,#16 //x12 is used as post- + //increment for input pointer; + //as loop is modulo-scheduled + //x12 is zeroed just in time + //to preclude oversteping + //inp[len], which means that + //last block[s] are actually + //loaded twice, but last + //copy is not processed + ld1 {v20.2d,v21.2d},[x1],#32 //load twisted H, ..., H^2 + movi v19.16b,#0xe1 + ld1 {v22.2d},[x1] + csel x12,xzr,x12,eq //is it time to zero x12? + ext v0.16b,v0.16b,v0.16b,#8 //rotate Xi + ld1 {v16.2d},[x2],#16 //load [rotated] I[0] + shl v19.2d,v19.2d,#57 //compose 0xc2.0 constant +#ifndef __ARMEB__ + rev64 v16.16b,v16.16b + rev64 v0.16b,v0.16b +#endif + ext v3.16b,v16.16b,v16.16b,#8 //rotate I[0] + b.lo .Lodd_tail_v8 //x3 was less than 32 + ld1 {v17.2d},[x2],x12 //load [rotated] I[1] +#ifndef __ARMEB__ + rev64 v17.16b,v17.16b +#endif + ext v7.16b,v17.16b,v17.16b,#8 + eor v3.16b,v3.16b,v0.16b //I[i]^=Xi + pmull v4.1q,v20.1d,v7.1d //H�Ii+1 + eor v17.16b,v17.16b,v7.16b //Karatsuba pre-processing + pmull2 v6.1q,v20.2d,v7.2d + b .Loop_mod2x_v8 + +.align 4 +.Loop_mod2x_v8: + ext v18.16b,v3.16b,v3.16b,#8 + subs x3,x3,#32 //is there more data? + pmull v0.1q,v22.1d,v3.1d //H^2.lo�Xi.lo + csel x12,xzr,x12,lo //is it time to zero x12? + + pmull v5.1q,v21.1d,v17.1d + eor v18.16b,v18.16b,v3.16b //Karatsuba pre-processing + pmull2 v2.1q,v22.2d,v3.2d //H^2.hi�Xi.hi + eor v0.16b,v0.16b,v4.16b //accumulate + pmull2 v1.1q,v21.2d,v18.2d //(H^2.lo+H^2.hi)�(Xi.lo+Xi.hi) + ld1 {v16.2d},[x2],x12 //load [rotated] I[i+2] + + eor v2.16b,v2.16b,v6.16b + csel x12,xzr,x12,eq //is it time to zero x12? + eor v1.16b,v1.16b,v5.16b + + ext v17.16b,v0.16b,v2.16b,#8 //Karatsuba post-processing + eor v18.16b,v0.16b,v2.16b + eor v1.16b,v1.16b,v17.16b + ld1 {v17.2d},[x2],x12 //load [rotated] I[i+3] +#ifndef __ARMEB__ + rev64 v16.16b,v16.16b +#endif + eor v1.16b,v1.16b,v18.16b + pmull v18.1q,v0.1d,v19.1d //1st phase of reduction + +#ifndef __ARMEB__ + rev64 v17.16b,v17.16b +#endif + ins v2.d[0],v1.d[1] + ins v1.d[1],v0.d[0] + ext v7.16b,v17.16b,v17.16b,#8 + ext v3.16b,v16.16b,v16.16b,#8 + eor v0.16b,v1.16b,v18.16b + pmull v4.1q,v20.1d,v7.1d //H�Ii+1 + eor v3.16b,v3.16b,v2.16b //accumulate v3.16b early + + ext v18.16b,v0.16b,v0.16b,#8 //2nd phase of reduction + pmull v0.1q,v0.1d,v19.1d + eor v3.16b,v3.16b,v18.16b + eor v17.16b,v17.16b,v7.16b //Karatsuba pre-processing + eor v3.16b,v3.16b,v0.16b + pmull2 v6.1q,v20.2d,v7.2d + b.hs .Loop_mod2x_v8 //there was at least 32 more bytes + + eor v2.16b,v2.16b,v18.16b + ext v3.16b,v16.16b,v16.16b,#8 //re-construct v3.16b + adds x3,x3,#32 //re-construct x3 + eor v0.16b,v0.16b,v2.16b //re-construct v0.16b + b.eq .Ldone_v8 //is x3 zero? +.Lodd_tail_v8: + ext v18.16b,v0.16b,v0.16b,#8 + eor v3.16b,v3.16b,v0.16b //inp^=Xi + eor v17.16b,v16.16b,v18.16b //v17.16b is rotated inp^Xi + + pmull v0.1q,v20.1d,v3.1d //H.lo�Xi.lo + eor v17.16b,v17.16b,v3.16b //Karatsuba pre-processing + pmull2 v2.1q,v20.2d,v3.2d //H.hi�Xi.hi + pmull v1.1q,v21.1d,v17.1d //(H.lo+H.hi)�(Xi.lo+Xi.hi) + + ext v17.16b,v0.16b,v2.16b,#8 //Karatsuba post-processing + eor v18.16b,v0.16b,v2.16b + eor v1.16b,v1.16b,v17.16b + eor v1.16b,v1.16b,v18.16b + pmull v18.1q,v0.1d,v19.1d //1st phase of reduction + + ins v2.d[0],v1.d[1] + ins v1.d[1],v0.d[0] + eor v0.16b,v1.16b,v18.16b + + ext v18.16b,v0.16b,v0.16b,#8 //2nd phase of reduction + pmull v0.1q,v0.1d,v19.1d + eor v18.16b,v18.16b,v2.16b + eor v0.16b,v0.16b,v18.16b + +.Ldone_v8: +#ifndef __ARMEB__ + rev64 v0.16b,v0.16b +#endif + ext v0.16b,v0.16b,v0.16b,#8 + st1 {v0.2d},[x0] //write out Xi + + ret +.size gcm_ghash_v8,.-gcm_ghash_v8 +.byte 71,72,65,83,72,32,102,111,114,32,65,82,77,118,56,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0 +.align 2 +.align 2 +#endif \ No newline at end of file diff --git a/third_party/boringssl/linux-aarch64/crypto/sha/sha1-armv8.S b/third_party/boringssl/linux-aarch64/crypto/sha/sha1-armv8.S index f9d126252ef2c..487a497da27f6 100644 --- a/third_party/boringssl/linux-aarch64/crypto/sha/sha1-armv8.S +++ b/third_party/boringssl/linux-aarch64/crypto/sha/sha1-armv8.S @@ -1,7 +1,9 @@ +#if defined(__aarch64__) #include "arm_arch.h" .text + .globl sha1_block_data_order .type sha1_block_data_order,%function .align 6 @@ -213,826 +215,826 @@ sha1_block_data_order: add w20,w20,w17 // future e+=X[i] add w21,w21,w25 // e+=F(b,c,d) lsr x19,x17,#32 - eor w3,w3,w5 + eor w3,w3,w5 bic w25,w24,w22 and w26,w23,w22 ror w27,w21,#27 - eor w3,w3,w11 + eor w3,w3,w11 add w24,w24,w28 // future e+=K orr w25,w25,w26 add w20,w20,w27 // e+=rot(a,5) - eor w3,w3,w16 + eor w3,w3,w16 ror w22,w22,#2 add w24,w24,w19 // future e+=X[i] add w20,w20,w25 // e+=F(b,c,d) - ror w3,w3,#31 - eor w4,w4,w6 + ror w3,w3,#31 + eor w4,w4,w6 bic w25,w23,w21 and w26,w22,w21 ror w27,w20,#27 - eor w4,w4,w12 + eor w4,w4,w12 add w23,w23,w28 // future e+=K orr w25,w25,w26 add w24,w24,w27 // e+=rot(a,5) - eor w4,w4,w17 + eor w4,w4,w17 ror w21,w21,#2 add w23,w23,w3 // future e+=X[i] add w24,w24,w25 // e+=F(b,c,d) - ror w4,w4,#31 - eor w5,w5,w7 + ror w4,w4,#31 + eor w5,w5,w7 bic w25,w22,w20 and w26,w21,w20 ror w27,w24,#27 - eor w5,w5,w13 + eor w5,w5,w13 add w22,w22,w28 // future e+=K orr w25,w25,w26 add w23,w23,w27 // e+=rot(a,5) - eor w5,w5,w19 + eor w5,w5,w19 ror w20,w20,#2 add w22,w22,w4 // future e+=X[i] add w23,w23,w25 // e+=F(b,c,d) - ror w5,w5,#31 - eor w6,w6,w8 + ror w5,w5,#31 + eor w6,w6,w8 bic w25,w21,w24 and w26,w20,w24 ror w27,w23,#27 - eor w6,w6,w14 + eor w6,w6,w14 add w21,w21,w28 // future e+=K orr w25,w25,w26 add w22,w22,w27 // e+=rot(a,5) - eor w6,w6,w3 + eor w6,w6,w3 ror w24,w24,#2 add w21,w21,w5 // future e+=X[i] add w22,w22,w25 // e+=F(b,c,d) - ror w6,w6,#31 - eor w7,w7,w9 + ror w6,w6,#31 + eor w7,w7,w9 bic w25,w20,w23 and w26,w24,w23 ror w27,w22,#27 - eor w7,w7,w15 + eor w7,w7,w15 add w20,w20,w28 // future e+=K orr w25,w25,w26 add w21,w21,w27 // e+=rot(a,5) - eor w7,w7,w4 + eor w7,w7,w4 ror w23,w23,#2 add w20,w20,w6 // future e+=X[i] add w21,w21,w25 // e+=F(b,c,d) - ror w7,w7,#31 + ror w7,w7,#31 movz w28,#0xeba1 movk w28,#0x6ed9,lsl#16 - eor w8,w8,w10 + eor w8,w8,w10 bic w25,w24,w22 and w26,w23,w22 ror w27,w21,#27 - eor w8,w8,w16 + eor w8,w8,w16 add w24,w24,w28 // future e+=K orr w25,w25,w26 add w20,w20,w27 // e+=rot(a,5) - eor w8,w8,w5 + eor w8,w8,w5 ror w22,w22,#2 add w24,w24,w7 // future e+=X[i] add w20,w20,w25 // e+=F(b,c,d) - ror w8,w8,#31 - eor w9,w9,w11 + ror w8,w8,#31 + eor w9,w9,w11 eor w25,w23,w21 ror w27,w20,#27 add w23,w23,w28 // future e+=K - eor w9,w9,w17 + eor w9,w9,w17 eor w25,w25,w22 add w24,w24,w27 // e+=rot(a,5) ror w21,w21,#2 - eor w9,w9,w6 + eor w9,w9,w6 add w23,w23,w8 // future e+=X[i] add w24,w24,w25 // e+=F(b,c,d) - ror w9,w9,#31 - eor w10,w10,w12 + ror w9,w9,#31 + eor w10,w10,w12 eor w25,w22,w20 ror w27,w24,#27 add w22,w22,w28 // future e+=K - eor w10,w10,w19 + eor w10,w10,w19 eor w25,w25,w21 add w23,w23,w27 // e+=rot(a,5) ror w20,w20,#2 - eor w10,w10,w7 + eor w10,w10,w7 add w22,w22,w9 // future e+=X[i] add w23,w23,w25 // e+=F(b,c,d) - ror w10,w10,#31 - eor w11,w11,w13 + ror w10,w10,#31 + eor w11,w11,w13 eor w25,w21,w24 ror w27,w23,#27 add w21,w21,w28 // future e+=K - eor w11,w11,w3 + eor w11,w11,w3 eor w25,w25,w20 add w22,w22,w27 // e+=rot(a,5) ror w24,w24,#2 - eor w11,w11,w8 + eor w11,w11,w8 add w21,w21,w10 // future e+=X[i] add w22,w22,w25 // e+=F(b,c,d) - ror w11,w11,#31 - eor w12,w12,w14 + ror w11,w11,#31 + eor w12,w12,w14 eor w25,w20,w23 ror w27,w22,#27 add w20,w20,w28 // future e+=K - eor w12,w12,w4 + eor w12,w12,w4 eor w25,w25,w24 add w21,w21,w27 // e+=rot(a,5) ror w23,w23,#2 - eor w12,w12,w9 + eor w12,w12,w9 add w20,w20,w11 // future e+=X[i] add w21,w21,w25 // e+=F(b,c,d) - ror w12,w12,#31 - eor w13,w13,w15 + ror w12,w12,#31 + eor w13,w13,w15 eor w25,w24,w22 ror w27,w21,#27 add w24,w24,w28 // future e+=K - eor w13,w13,w5 + eor w13,w13,w5 eor w25,w25,w23 add w20,w20,w27 // e+=rot(a,5) ror w22,w22,#2 - eor w13,w13,w10 + eor w13,w13,w10 add w24,w24,w12 // future e+=X[i] add w20,w20,w25 // e+=F(b,c,d) - ror w13,w13,#31 - eor w14,w14,w16 + ror w13,w13,#31 + eor w14,w14,w16 eor w25,w23,w21 ror w27,w20,#27 add w23,w23,w28 // future e+=K - eor w14,w14,w6 + eor w14,w14,w6 eor w25,w25,w22 add w24,w24,w27 // e+=rot(a,5) ror w21,w21,#2 - eor w14,w14,w11 + eor w14,w14,w11 add w23,w23,w13 // future e+=X[i] add w24,w24,w25 // e+=F(b,c,d) - ror w14,w14,#31 - eor w15,w15,w17 + ror w14,w14,#31 + eor w15,w15,w17 eor w25,w22,w20 ror w27,w24,#27 add w22,w22,w28 // future e+=K - eor w15,w15,w7 + eor w15,w15,w7 eor w25,w25,w21 add w23,w23,w27 // e+=rot(a,5) ror w20,w20,#2 - eor w15,w15,w12 + eor w15,w15,w12 add w22,w22,w14 // future e+=X[i] add w23,w23,w25 // e+=F(b,c,d) - ror w15,w15,#31 - eor w16,w16,w19 + ror w15,w15,#31 + eor w16,w16,w19 eor w25,w21,w24 ror w27,w23,#27 add w21,w21,w28 // future e+=K - eor w16,w16,w8 + eor w16,w16,w8 eor w25,w25,w20 add w22,w22,w27 // e+=rot(a,5) ror w24,w24,#2 - eor w16,w16,w13 + eor w16,w16,w13 add w21,w21,w15 // future e+=X[i] add w22,w22,w25 // e+=F(b,c,d) - ror w16,w16,#31 - eor w17,w17,w3 + ror w16,w16,#31 + eor w17,w17,w3 eor w25,w20,w23 ror w27,w22,#27 add w20,w20,w28 // future e+=K - eor w17,w17,w9 + eor w17,w17,w9 eor w25,w25,w24 add w21,w21,w27 // e+=rot(a,5) ror w23,w23,#2 - eor w17,w17,w14 + eor w17,w17,w14 add w20,w20,w16 // future e+=X[i] add w21,w21,w25 // e+=F(b,c,d) - ror w17,w17,#31 - eor w19,w19,w4 + ror w17,w17,#31 + eor w19,w19,w4 eor w25,w24,w22 ror w27,w21,#27 add w24,w24,w28 // future e+=K - eor w19,w19,w10 + eor w19,w19,w10 eor w25,w25,w23 add w20,w20,w27 // e+=rot(a,5) ror w22,w22,#2 - eor w19,w19,w15 + eor w19,w19,w15 add w24,w24,w17 // future e+=X[i] add w20,w20,w25 // e+=F(b,c,d) - ror w19,w19,#31 - eor w3,w3,w5 + ror w19,w19,#31 + eor w3,w3,w5 eor w25,w23,w21 ror w27,w20,#27 add w23,w23,w28 // future e+=K - eor w3,w3,w11 + eor w3,w3,w11 eor w25,w25,w22 add w24,w24,w27 // e+=rot(a,5) ror w21,w21,#2 - eor w3,w3,w16 + eor w3,w3,w16 add w23,w23,w19 // future e+=X[i] add w24,w24,w25 // e+=F(b,c,d) - ror w3,w3,#31 - eor w4,w4,w6 + ror w3,w3,#31 + eor w4,w4,w6 eor w25,w22,w20 ror w27,w24,#27 add w22,w22,w28 // future e+=K - eor w4,w4,w12 + eor w4,w4,w12 eor w25,w25,w21 add w23,w23,w27 // e+=rot(a,5) ror w20,w20,#2 - eor w4,w4,w17 + eor w4,w4,w17 add w22,w22,w3 // future e+=X[i] add w23,w23,w25 // e+=F(b,c,d) - ror w4,w4,#31 - eor w5,w5,w7 + ror w4,w4,#31 + eor w5,w5,w7 eor w25,w21,w24 ror w27,w23,#27 add w21,w21,w28 // future e+=K - eor w5,w5,w13 + eor w5,w5,w13 eor w25,w25,w20 add w22,w22,w27 // e+=rot(a,5) ror w24,w24,#2 - eor w5,w5,w19 + eor w5,w5,w19 add w21,w21,w4 // future e+=X[i] add w22,w22,w25 // e+=F(b,c,d) - ror w5,w5,#31 - eor w6,w6,w8 + ror w5,w5,#31 + eor w6,w6,w8 eor w25,w20,w23 ror w27,w22,#27 add w20,w20,w28 // future e+=K - eor w6,w6,w14 + eor w6,w6,w14 eor w25,w25,w24 add w21,w21,w27 // e+=rot(a,5) ror w23,w23,#2 - eor w6,w6,w3 + eor w6,w6,w3 add w20,w20,w5 // future e+=X[i] add w21,w21,w25 // e+=F(b,c,d) - ror w6,w6,#31 - eor w7,w7,w9 + ror w6,w6,#31 + eor w7,w7,w9 eor w25,w24,w22 ror w27,w21,#27 add w24,w24,w28 // future e+=K - eor w7,w7,w15 + eor w7,w7,w15 eor w25,w25,w23 add w20,w20,w27 // e+=rot(a,5) ror w22,w22,#2 - eor w7,w7,w4 + eor w7,w7,w4 add w24,w24,w6 // future e+=X[i] add w20,w20,w25 // e+=F(b,c,d) - ror w7,w7,#31 - eor w8,w8,w10 + ror w7,w7,#31 + eor w8,w8,w10 eor w25,w23,w21 ror w27,w20,#27 add w23,w23,w28 // future e+=K - eor w8,w8,w16 + eor w8,w8,w16 eor w25,w25,w22 add w24,w24,w27 // e+=rot(a,5) ror w21,w21,#2 - eor w8,w8,w5 + eor w8,w8,w5 add w23,w23,w7 // future e+=X[i] add w24,w24,w25 // e+=F(b,c,d) - ror w8,w8,#31 - eor w9,w9,w11 + ror w8,w8,#31 + eor w9,w9,w11 eor w25,w22,w20 ror w27,w24,#27 add w22,w22,w28 // future e+=K - eor w9,w9,w17 + eor w9,w9,w17 eor w25,w25,w21 add w23,w23,w27 // e+=rot(a,5) ror w20,w20,#2 - eor w9,w9,w6 + eor w9,w9,w6 add w22,w22,w8 // future e+=X[i] add w23,w23,w25 // e+=F(b,c,d) - ror w9,w9,#31 - eor w10,w10,w12 + ror w9,w9,#31 + eor w10,w10,w12 eor w25,w21,w24 ror w27,w23,#27 add w21,w21,w28 // future e+=K - eor w10,w10,w19 + eor w10,w10,w19 eor w25,w25,w20 add w22,w22,w27 // e+=rot(a,5) ror w24,w24,#2 - eor w10,w10,w7 + eor w10,w10,w7 add w21,w21,w9 // future e+=X[i] add w22,w22,w25 // e+=F(b,c,d) - ror w10,w10,#31 - eor w11,w11,w13 + ror w10,w10,#31 + eor w11,w11,w13 eor w25,w20,w23 ror w27,w22,#27 add w20,w20,w28 // future e+=K - eor w11,w11,w3 + eor w11,w11,w3 eor w25,w25,w24 add w21,w21,w27 // e+=rot(a,5) ror w23,w23,#2 - eor w11,w11,w8 + eor w11,w11,w8 add w20,w20,w10 // future e+=X[i] add w21,w21,w25 // e+=F(b,c,d) - ror w11,w11,#31 + ror w11,w11,#31 movz w28,#0xbcdc movk w28,#0x8f1b,lsl#16 - eor w12,w12,w14 + eor w12,w12,w14 eor w25,w24,w22 ror w27,w21,#27 add w24,w24,w28 // future e+=K - eor w12,w12,w4 + eor w12,w12,w4 eor w25,w25,w23 add w20,w20,w27 // e+=rot(a,5) ror w22,w22,#2 - eor w12,w12,w9 + eor w12,w12,w9 add w24,w24,w11 // future e+=X[i] add w20,w20,w25 // e+=F(b,c,d) - ror w12,w12,#31 + ror w12,w12,#31 orr w25,w21,w22 and w26,w21,w22 - eor w13,w13,w15 + eor w13,w13,w15 ror w27,w20,#27 and w25,w25,w23 add w23,w23,w28 // future e+=K - eor w13,w13,w5 + eor w13,w13,w5 add w24,w24,w27 // e+=rot(a,5) orr w25,w25,w26 ror w21,w21,#2 - eor w13,w13,w10 + eor w13,w13,w10 add w23,w23,w12 // future e+=X[i] add w24,w24,w25 // e+=F(b,c,d) - ror w13,w13,#31 + ror w13,w13,#31 orr w25,w20,w21 and w26,w20,w21 - eor w14,w14,w16 + eor w14,w14,w16 ror w27,w24,#27 and w25,w25,w22 add w22,w22,w28 // future e+=K - eor w14,w14,w6 + eor w14,w14,w6 add w23,w23,w27 // e+=rot(a,5) orr w25,w25,w26 ror w20,w20,#2 - eor w14,w14,w11 + eor w14,w14,w11 add w22,w22,w13 // future e+=X[i] add w23,w23,w25 // e+=F(b,c,d) - ror w14,w14,#31 + ror w14,w14,#31 orr w25,w24,w20 and w26,w24,w20 - eor w15,w15,w17 + eor w15,w15,w17 ror w27,w23,#27 and w25,w25,w21 add w21,w21,w28 // future e+=K - eor w15,w15,w7 + eor w15,w15,w7 add w22,w22,w27 // e+=rot(a,5) orr w25,w25,w26 ror w24,w24,#2 - eor w15,w15,w12 + eor w15,w15,w12 add w21,w21,w14 // future e+=X[i] add w22,w22,w25 // e+=F(b,c,d) - ror w15,w15,#31 + ror w15,w15,#31 orr w25,w23,w24 and w26,w23,w24 - eor w16,w16,w19 + eor w16,w16,w19 ror w27,w22,#27 and w25,w25,w20 add w20,w20,w28 // future e+=K - eor w16,w16,w8 + eor w16,w16,w8 add w21,w21,w27 // e+=rot(a,5) orr w25,w25,w26 ror w23,w23,#2 - eor w16,w16,w13 + eor w16,w16,w13 add w20,w20,w15 // future e+=X[i] add w21,w21,w25 // e+=F(b,c,d) - ror w16,w16,#31 + ror w16,w16,#31 orr w25,w22,w23 and w26,w22,w23 - eor w17,w17,w3 + eor w17,w17,w3 ror w27,w21,#27 and w25,w25,w24 add w24,w24,w28 // future e+=K - eor w17,w17,w9 + eor w17,w17,w9 add w20,w20,w27 // e+=rot(a,5) orr w25,w25,w26 ror w22,w22,#2 - eor w17,w17,w14 + eor w17,w17,w14 add w24,w24,w16 // future e+=X[i] add w20,w20,w25 // e+=F(b,c,d) - ror w17,w17,#31 + ror w17,w17,#31 orr w25,w21,w22 and w26,w21,w22 - eor w19,w19,w4 + eor w19,w19,w4 ror w27,w20,#27 and w25,w25,w23 add w23,w23,w28 // future e+=K - eor w19,w19,w10 + eor w19,w19,w10 add w24,w24,w27 // e+=rot(a,5) orr w25,w25,w26 ror w21,w21,#2 - eor w19,w19,w15 + eor w19,w19,w15 add w23,w23,w17 // future e+=X[i] add w24,w24,w25 // e+=F(b,c,d) - ror w19,w19,#31 + ror w19,w19,#31 orr w25,w20,w21 and w26,w20,w21 - eor w3,w3,w5 + eor w3,w3,w5 ror w27,w24,#27 and w25,w25,w22 add w22,w22,w28 // future e+=K - eor w3,w3,w11 + eor w3,w3,w11 add w23,w23,w27 // e+=rot(a,5) orr w25,w25,w26 ror w20,w20,#2 - eor w3,w3,w16 + eor w3,w3,w16 add w22,w22,w19 // future e+=X[i] add w23,w23,w25 // e+=F(b,c,d) - ror w3,w3,#31 + ror w3,w3,#31 orr w25,w24,w20 and w26,w24,w20 - eor w4,w4,w6 + eor w4,w4,w6 ror w27,w23,#27 and w25,w25,w21 add w21,w21,w28 // future e+=K - eor w4,w4,w12 + eor w4,w4,w12 add w22,w22,w27 // e+=rot(a,5) orr w25,w25,w26 ror w24,w24,#2 - eor w4,w4,w17 + eor w4,w4,w17 add w21,w21,w3 // future e+=X[i] add w22,w22,w25 // e+=F(b,c,d) - ror w4,w4,#31 + ror w4,w4,#31 orr w25,w23,w24 and w26,w23,w24 - eor w5,w5,w7 + eor w5,w5,w7 ror w27,w22,#27 and w25,w25,w20 add w20,w20,w28 // future e+=K - eor w5,w5,w13 + eor w5,w5,w13 add w21,w21,w27 // e+=rot(a,5) orr w25,w25,w26 ror w23,w23,#2 - eor w5,w5,w19 + eor w5,w5,w19 add w20,w20,w4 // future e+=X[i] add w21,w21,w25 // e+=F(b,c,d) - ror w5,w5,#31 + ror w5,w5,#31 orr w25,w22,w23 and w26,w22,w23 - eor w6,w6,w8 + eor w6,w6,w8 ror w27,w21,#27 and w25,w25,w24 add w24,w24,w28 // future e+=K - eor w6,w6,w14 + eor w6,w6,w14 add w20,w20,w27 // e+=rot(a,5) orr w25,w25,w26 ror w22,w22,#2 - eor w6,w6,w3 + eor w6,w6,w3 add w24,w24,w5 // future e+=X[i] add w20,w20,w25 // e+=F(b,c,d) - ror w6,w6,#31 + ror w6,w6,#31 orr w25,w21,w22 and w26,w21,w22 - eor w7,w7,w9 + eor w7,w7,w9 ror w27,w20,#27 and w25,w25,w23 add w23,w23,w28 // future e+=K - eor w7,w7,w15 + eor w7,w7,w15 add w24,w24,w27 // e+=rot(a,5) orr w25,w25,w26 ror w21,w21,#2 - eor w7,w7,w4 + eor w7,w7,w4 add w23,w23,w6 // future e+=X[i] add w24,w24,w25 // e+=F(b,c,d) - ror w7,w7,#31 + ror w7,w7,#31 orr w25,w20,w21 and w26,w20,w21 - eor w8,w8,w10 + eor w8,w8,w10 ror w27,w24,#27 and w25,w25,w22 add w22,w22,w28 // future e+=K - eor w8,w8,w16 + eor w8,w8,w16 add w23,w23,w27 // e+=rot(a,5) orr w25,w25,w26 ror w20,w20,#2 - eor w8,w8,w5 + eor w8,w8,w5 add w22,w22,w7 // future e+=X[i] add w23,w23,w25 // e+=F(b,c,d) - ror w8,w8,#31 + ror w8,w8,#31 orr w25,w24,w20 and w26,w24,w20 - eor w9,w9,w11 + eor w9,w9,w11 ror w27,w23,#27 and w25,w25,w21 add w21,w21,w28 // future e+=K - eor w9,w9,w17 + eor w9,w9,w17 add w22,w22,w27 // e+=rot(a,5) orr w25,w25,w26 ror w24,w24,#2 - eor w9,w9,w6 + eor w9,w9,w6 add w21,w21,w8 // future e+=X[i] add w22,w22,w25 // e+=F(b,c,d) - ror w9,w9,#31 + ror w9,w9,#31 orr w25,w23,w24 and w26,w23,w24 - eor w10,w10,w12 + eor w10,w10,w12 ror w27,w22,#27 and w25,w25,w20 add w20,w20,w28 // future e+=K - eor w10,w10,w19 + eor w10,w10,w19 add w21,w21,w27 // e+=rot(a,5) orr w25,w25,w26 ror w23,w23,#2 - eor w10,w10,w7 + eor w10,w10,w7 add w20,w20,w9 // future e+=X[i] add w21,w21,w25 // e+=F(b,c,d) - ror w10,w10,#31 + ror w10,w10,#31 orr w25,w22,w23 and w26,w22,w23 - eor w11,w11,w13 + eor w11,w11,w13 ror w27,w21,#27 and w25,w25,w24 add w24,w24,w28 // future e+=K - eor w11,w11,w3 + eor w11,w11,w3 add w20,w20,w27 // e+=rot(a,5) orr w25,w25,w26 ror w22,w22,#2 - eor w11,w11,w8 + eor w11,w11,w8 add w24,w24,w10 // future e+=X[i] add w20,w20,w25 // e+=F(b,c,d) - ror w11,w11,#31 + ror w11,w11,#31 orr w25,w21,w22 and w26,w21,w22 - eor w12,w12,w14 + eor w12,w12,w14 ror w27,w20,#27 and w25,w25,w23 add w23,w23,w28 // future e+=K - eor w12,w12,w4 + eor w12,w12,w4 add w24,w24,w27 // e+=rot(a,5) orr w25,w25,w26 ror w21,w21,#2 - eor w12,w12,w9 + eor w12,w12,w9 add w23,w23,w11 // future e+=X[i] add w24,w24,w25 // e+=F(b,c,d) - ror w12,w12,#31 + ror w12,w12,#31 orr w25,w20,w21 and w26,w20,w21 - eor w13,w13,w15 + eor w13,w13,w15 ror w27,w24,#27 and w25,w25,w22 add w22,w22,w28 // future e+=K - eor w13,w13,w5 + eor w13,w13,w5 add w23,w23,w27 // e+=rot(a,5) orr w25,w25,w26 ror w20,w20,#2 - eor w13,w13,w10 + eor w13,w13,w10 add w22,w22,w12 // future e+=X[i] add w23,w23,w25 // e+=F(b,c,d) - ror w13,w13,#31 + ror w13,w13,#31 orr w25,w24,w20 and w26,w24,w20 - eor w14,w14,w16 + eor w14,w14,w16 ror w27,w23,#27 and w25,w25,w21 add w21,w21,w28 // future e+=K - eor w14,w14,w6 + eor w14,w14,w6 add w22,w22,w27 // e+=rot(a,5) orr w25,w25,w26 ror w24,w24,#2 - eor w14,w14,w11 + eor w14,w14,w11 add w21,w21,w13 // future e+=X[i] add w22,w22,w25 // e+=F(b,c,d) - ror w14,w14,#31 + ror w14,w14,#31 orr w25,w23,w24 and w26,w23,w24 - eor w15,w15,w17 + eor w15,w15,w17 ror w27,w22,#27 and w25,w25,w20 add w20,w20,w28 // future e+=K - eor w15,w15,w7 + eor w15,w15,w7 add w21,w21,w27 // e+=rot(a,5) orr w25,w25,w26 ror w23,w23,#2 - eor w15,w15,w12 + eor w15,w15,w12 add w20,w20,w14 // future e+=X[i] add w21,w21,w25 // e+=F(b,c,d) - ror w15,w15,#31 + ror w15,w15,#31 movz w28,#0xc1d6 movk w28,#0xca62,lsl#16 orr w25,w22,w23 and w26,w22,w23 - eor w16,w16,w19 + eor w16,w16,w19 ror w27,w21,#27 and w25,w25,w24 add w24,w24,w28 // future e+=K - eor w16,w16,w8 + eor w16,w16,w8 add w20,w20,w27 // e+=rot(a,5) orr w25,w25,w26 ror w22,w22,#2 - eor w16,w16,w13 + eor w16,w16,w13 add w24,w24,w15 // future e+=X[i] add w20,w20,w25 // e+=F(b,c,d) - ror w16,w16,#31 - eor w17,w17,w3 + ror w16,w16,#31 + eor w17,w17,w3 eor w25,w23,w21 ror w27,w20,#27 add w23,w23,w28 // future e+=K - eor w17,w17,w9 + eor w17,w17,w9 eor w25,w25,w22 add w24,w24,w27 // e+=rot(a,5) ror w21,w21,#2 - eor w17,w17,w14 + eor w17,w17,w14 add w23,w23,w16 // future e+=X[i] add w24,w24,w25 // e+=F(b,c,d) - ror w17,w17,#31 - eor w19,w19,w4 + ror w17,w17,#31 + eor w19,w19,w4 eor w25,w22,w20 ror w27,w24,#27 add w22,w22,w28 // future e+=K - eor w19,w19,w10 + eor w19,w19,w10 eor w25,w25,w21 add w23,w23,w27 // e+=rot(a,5) ror w20,w20,#2 - eor w19,w19,w15 + eor w19,w19,w15 add w22,w22,w17 // future e+=X[i] add w23,w23,w25 // e+=F(b,c,d) - ror w19,w19,#31 - eor w3,w3,w5 + ror w19,w19,#31 + eor w3,w3,w5 eor w25,w21,w24 ror w27,w23,#27 add w21,w21,w28 // future e+=K - eor w3,w3,w11 + eor w3,w3,w11 eor w25,w25,w20 add w22,w22,w27 // e+=rot(a,5) ror w24,w24,#2 - eor w3,w3,w16 + eor w3,w3,w16 add w21,w21,w19 // future e+=X[i] add w22,w22,w25 // e+=F(b,c,d) - ror w3,w3,#31 - eor w4,w4,w6 + ror w3,w3,#31 + eor w4,w4,w6 eor w25,w20,w23 ror w27,w22,#27 add w20,w20,w28 // future e+=K - eor w4,w4,w12 + eor w4,w4,w12 eor w25,w25,w24 add w21,w21,w27 // e+=rot(a,5) ror w23,w23,#2 - eor w4,w4,w17 + eor w4,w4,w17 add w20,w20,w3 // future e+=X[i] add w21,w21,w25 // e+=F(b,c,d) - ror w4,w4,#31 - eor w5,w5,w7 + ror w4,w4,#31 + eor w5,w5,w7 eor w25,w24,w22 ror w27,w21,#27 add w24,w24,w28 // future e+=K - eor w5,w5,w13 + eor w5,w5,w13 eor w25,w25,w23 add w20,w20,w27 // e+=rot(a,5) ror w22,w22,#2 - eor w5,w5,w19 + eor w5,w5,w19 add w24,w24,w4 // future e+=X[i] add w20,w20,w25 // e+=F(b,c,d) - ror w5,w5,#31 - eor w6,w6,w8 + ror w5,w5,#31 + eor w6,w6,w8 eor w25,w23,w21 ror w27,w20,#27 add w23,w23,w28 // future e+=K - eor w6,w6,w14 + eor w6,w6,w14 eor w25,w25,w22 add w24,w24,w27 // e+=rot(a,5) ror w21,w21,#2 - eor w6,w6,w3 + eor w6,w6,w3 add w23,w23,w5 // future e+=X[i] add w24,w24,w25 // e+=F(b,c,d) - ror w6,w6,#31 - eor w7,w7,w9 + ror w6,w6,#31 + eor w7,w7,w9 eor w25,w22,w20 ror w27,w24,#27 add w22,w22,w28 // future e+=K - eor w7,w7,w15 + eor w7,w7,w15 eor w25,w25,w21 add w23,w23,w27 // e+=rot(a,5) ror w20,w20,#2 - eor w7,w7,w4 + eor w7,w7,w4 add w22,w22,w6 // future e+=X[i] add w23,w23,w25 // e+=F(b,c,d) - ror w7,w7,#31 - eor w8,w8,w10 + ror w7,w7,#31 + eor w8,w8,w10 eor w25,w21,w24 ror w27,w23,#27 add w21,w21,w28 // future e+=K - eor w8,w8,w16 + eor w8,w8,w16 eor w25,w25,w20 add w22,w22,w27 // e+=rot(a,5) ror w24,w24,#2 - eor w8,w8,w5 + eor w8,w8,w5 add w21,w21,w7 // future e+=X[i] add w22,w22,w25 // e+=F(b,c,d) - ror w8,w8,#31 - eor w9,w9,w11 + ror w8,w8,#31 + eor w9,w9,w11 eor w25,w20,w23 ror w27,w22,#27 add w20,w20,w28 // future e+=K - eor w9,w9,w17 + eor w9,w9,w17 eor w25,w25,w24 add w21,w21,w27 // e+=rot(a,5) ror w23,w23,#2 - eor w9,w9,w6 + eor w9,w9,w6 add w20,w20,w8 // future e+=X[i] add w21,w21,w25 // e+=F(b,c,d) - ror w9,w9,#31 - eor w10,w10,w12 + ror w9,w9,#31 + eor w10,w10,w12 eor w25,w24,w22 ror w27,w21,#27 add w24,w24,w28 // future e+=K - eor w10,w10,w19 + eor w10,w10,w19 eor w25,w25,w23 add w20,w20,w27 // e+=rot(a,5) ror w22,w22,#2 - eor w10,w10,w7 + eor w10,w10,w7 add w24,w24,w9 // future e+=X[i] add w20,w20,w25 // e+=F(b,c,d) - ror w10,w10,#31 - eor w11,w11,w13 + ror w10,w10,#31 + eor w11,w11,w13 eor w25,w23,w21 ror w27,w20,#27 add w23,w23,w28 // future e+=K - eor w11,w11,w3 + eor w11,w11,w3 eor w25,w25,w22 add w24,w24,w27 // e+=rot(a,5) ror w21,w21,#2 - eor w11,w11,w8 + eor w11,w11,w8 add w23,w23,w10 // future e+=X[i] add w24,w24,w25 // e+=F(b,c,d) - ror w11,w11,#31 - eor w12,w12,w14 + ror w11,w11,#31 + eor w12,w12,w14 eor w25,w22,w20 ror w27,w24,#27 add w22,w22,w28 // future e+=K - eor w12,w12,w4 + eor w12,w12,w4 eor w25,w25,w21 add w23,w23,w27 // e+=rot(a,5) ror w20,w20,#2 - eor w12,w12,w9 + eor w12,w12,w9 add w22,w22,w11 // future e+=X[i] add w23,w23,w25 // e+=F(b,c,d) - ror w12,w12,#31 - eor w13,w13,w15 + ror w12,w12,#31 + eor w13,w13,w15 eor w25,w21,w24 ror w27,w23,#27 add w21,w21,w28 // future e+=K - eor w13,w13,w5 + eor w13,w13,w5 eor w25,w25,w20 add w22,w22,w27 // e+=rot(a,5) ror w24,w24,#2 - eor w13,w13,w10 + eor w13,w13,w10 add w21,w21,w12 // future e+=X[i] add w22,w22,w25 // e+=F(b,c,d) - ror w13,w13,#31 - eor w14,w14,w16 + ror w13,w13,#31 + eor w14,w14,w16 eor w25,w20,w23 ror w27,w22,#27 add w20,w20,w28 // future e+=K - eor w14,w14,w6 + eor w14,w14,w6 eor w25,w25,w24 add w21,w21,w27 // e+=rot(a,5) ror w23,w23,#2 - eor w14,w14,w11 + eor w14,w14,w11 add w20,w20,w13 // future e+=X[i] add w21,w21,w25 // e+=F(b,c,d) - ror w14,w14,#31 - eor w15,w15,w17 + ror w14,w14,#31 + eor w15,w15,w17 eor w25,w24,w22 ror w27,w21,#27 add w24,w24,w28 // future e+=K - eor w15,w15,w7 + eor w15,w15,w7 eor w25,w25,w23 add w20,w20,w27 // e+=rot(a,5) ror w22,w22,#2 - eor w15,w15,w12 + eor w15,w15,w12 add w24,w24,w14 // future e+=X[i] add w20,w20,w25 // e+=F(b,c,d) - ror w15,w15,#31 - eor w16,w16,w19 + ror w15,w15,#31 + eor w16,w16,w19 eor w25,w23,w21 ror w27,w20,#27 add w23,w23,w28 // future e+=K - eor w16,w16,w8 + eor w16,w16,w8 eor w25,w25,w22 add w24,w24,w27 // e+=rot(a,5) ror w21,w21,#2 - eor w16,w16,w13 + eor w16,w16,w13 add w23,w23,w15 // future e+=X[i] add w24,w24,w25 // e+=F(b,c,d) - ror w16,w16,#31 - eor w17,w17,w3 + ror w16,w16,#31 + eor w17,w17,w3 eor w25,w22,w20 ror w27,w24,#27 add w22,w22,w28 // future e+=K - eor w17,w17,w9 + eor w17,w17,w9 eor w25,w25,w21 add w23,w23,w27 // e+=rot(a,5) ror w20,w20,#2 - eor w17,w17,w14 + eor w17,w17,w14 add w22,w22,w16 // future e+=X[i] add w23,w23,w25 // e+=F(b,c,d) - ror w17,w17,#31 - eor w19,w19,w4 + ror w17,w17,#31 + eor w19,w19,w4 eor w25,w21,w24 ror w27,w23,#27 add w21,w21,w28 // future e+=K - eor w19,w19,w10 + eor w19,w19,w10 eor w25,w25,w20 add w22,w22,w27 // e+=rot(a,5) ror w24,w24,#2 - eor w19,w19,w15 + eor w19,w19,w15 add w21,w21,w17 // future e+=X[i] add w22,w22,w25 // e+=F(b,c,d) - ror w19,w19,#31 + ror w19,w19,#31 ldp w4,w5,[x0] eor w25,w20,w23 ror w27,w22,#27 @@ -1080,10 +1082,10 @@ sha1_block_armv8: ld1 {v0.4s},[x0],#16 ld1 {v1.s}[0],[x0] sub x0,x0,#16 - ld1 {v16.4s-v19.4s},[x4] + ld1 {v16.4s,v17.4s,v18.4s,v19.4s},[x4] .Loop_hw: - ld1 {v4.16b-v7.16b},[x1],#64 + ld1 {v4.16b,v5.16b,v6.16b,v7.16b},[x1],#64 sub x2,x2,#1 rev32 v4.16b,v4.16b rev32 v5.16b,v5.16b @@ -1094,98 +1096,98 @@ sha1_block_armv8: add v21.4s,v16.4s,v5.4s rev32 v7.16b,v7.16b - .inst 0x5e280803 //sha1h v3.16b,v0.16b - .inst 0x5e140020 //sha1c v0.16b,v1.16b,v20.4s // 0 +.inst 0x5e280803 //sha1h v3.16b,v0.16b +.inst 0x5e140020 //sha1c v0.16b,v1.16b,v20.4s // 0 add v20.4s,v16.4s,v6.4s - .inst 0x5e0630a4 //sha1su0 v4.16b,v5.16b,v6.16b - .inst 0x5e280802 //sha1h v2.16b,v0.16b // 1 - .inst 0x5e150060 //sha1c v0.16b,v3.16b,v21.4s +.inst 0x5e0630a4 //sha1su0 v4.16b,v5.16b,v6.16b +.inst 0x5e280802 //sha1h v2.16b,v0.16b // 1 +.inst 0x5e150060 //sha1c v0.16b,v3.16b,v21.4s add v21.4s,v16.4s,v7.4s - .inst 0x5e2818e4 //sha1su1 v4.16b,v7.16b - .inst 0x5e0730c5 //sha1su0 v5.16b,v6.16b,v7.16b - .inst 0x5e280803 //sha1h v3.16b,v0.16b // 2 - .inst 0x5e140040 //sha1c v0.16b,v2.16b,v20.4s +.inst 0x5e2818e4 //sha1su1 v4.16b,v7.16b +.inst 0x5e0730c5 //sha1su0 v5.16b,v6.16b,v7.16b +.inst 0x5e280803 //sha1h v3.16b,v0.16b // 2 +.inst 0x5e140040 //sha1c v0.16b,v2.16b,v20.4s add v20.4s,v16.4s,v4.4s - .inst 0x5e281885 //sha1su1 v5.16b,v4.16b - .inst 0x5e0430e6 //sha1su0 v6.16b,v7.16b,v4.16b - .inst 0x5e280802 //sha1h v2.16b,v0.16b // 3 - .inst 0x5e150060 //sha1c v0.16b,v3.16b,v21.4s +.inst 0x5e281885 //sha1su1 v5.16b,v4.16b +.inst 0x5e0430e6 //sha1su0 v6.16b,v7.16b,v4.16b +.inst 0x5e280802 //sha1h v2.16b,v0.16b // 3 +.inst 0x5e150060 //sha1c v0.16b,v3.16b,v21.4s add v21.4s,v17.4s,v5.4s - .inst 0x5e2818a6 //sha1su1 v6.16b,v5.16b - .inst 0x5e053087 //sha1su0 v7.16b,v4.16b,v5.16b - .inst 0x5e280803 //sha1h v3.16b,v0.16b // 4 - .inst 0x5e140040 //sha1c v0.16b,v2.16b,v20.4s +.inst 0x5e2818a6 //sha1su1 v6.16b,v5.16b +.inst 0x5e053087 //sha1su0 v7.16b,v4.16b,v5.16b +.inst 0x5e280803 //sha1h v3.16b,v0.16b // 4 +.inst 0x5e140040 //sha1c v0.16b,v2.16b,v20.4s add v20.4s,v17.4s,v6.4s - .inst 0x5e2818c7 //sha1su1 v7.16b,v6.16b - .inst 0x5e0630a4 //sha1su0 v4.16b,v5.16b,v6.16b - .inst 0x5e280802 //sha1h v2.16b,v0.16b // 5 - .inst 0x5e151060 //sha1p v0.16b,v3.16b,v21.4s +.inst 0x5e2818c7 //sha1su1 v7.16b,v6.16b +.inst 0x5e0630a4 //sha1su0 v4.16b,v5.16b,v6.16b +.inst 0x5e280802 //sha1h v2.16b,v0.16b // 5 +.inst 0x5e151060 //sha1p v0.16b,v3.16b,v21.4s add v21.4s,v17.4s,v7.4s - .inst 0x5e2818e4 //sha1su1 v4.16b,v7.16b - .inst 0x5e0730c5 //sha1su0 v5.16b,v6.16b,v7.16b - .inst 0x5e280803 //sha1h v3.16b,v0.16b // 6 - .inst 0x5e141040 //sha1p v0.16b,v2.16b,v20.4s +.inst 0x5e2818e4 //sha1su1 v4.16b,v7.16b +.inst 0x5e0730c5 //sha1su0 v5.16b,v6.16b,v7.16b +.inst 0x5e280803 //sha1h v3.16b,v0.16b // 6 +.inst 0x5e141040 //sha1p v0.16b,v2.16b,v20.4s add v20.4s,v17.4s,v4.4s - .inst 0x5e281885 //sha1su1 v5.16b,v4.16b - .inst 0x5e0430e6 //sha1su0 v6.16b,v7.16b,v4.16b - .inst 0x5e280802 //sha1h v2.16b,v0.16b // 7 - .inst 0x5e151060 //sha1p v0.16b,v3.16b,v21.4s +.inst 0x5e281885 //sha1su1 v5.16b,v4.16b +.inst 0x5e0430e6 //sha1su0 v6.16b,v7.16b,v4.16b +.inst 0x5e280802 //sha1h v2.16b,v0.16b // 7 +.inst 0x5e151060 //sha1p v0.16b,v3.16b,v21.4s add v21.4s,v17.4s,v5.4s - .inst 0x5e2818a6 //sha1su1 v6.16b,v5.16b - .inst 0x5e053087 //sha1su0 v7.16b,v4.16b,v5.16b - .inst 0x5e280803 //sha1h v3.16b,v0.16b // 8 - .inst 0x5e141040 //sha1p v0.16b,v2.16b,v20.4s +.inst 0x5e2818a6 //sha1su1 v6.16b,v5.16b +.inst 0x5e053087 //sha1su0 v7.16b,v4.16b,v5.16b +.inst 0x5e280803 //sha1h v3.16b,v0.16b // 8 +.inst 0x5e141040 //sha1p v0.16b,v2.16b,v20.4s add v20.4s,v18.4s,v6.4s - .inst 0x5e2818c7 //sha1su1 v7.16b,v6.16b - .inst 0x5e0630a4 //sha1su0 v4.16b,v5.16b,v6.16b - .inst 0x5e280802 //sha1h v2.16b,v0.16b // 9 - .inst 0x5e151060 //sha1p v0.16b,v3.16b,v21.4s +.inst 0x5e2818c7 //sha1su1 v7.16b,v6.16b +.inst 0x5e0630a4 //sha1su0 v4.16b,v5.16b,v6.16b +.inst 0x5e280802 //sha1h v2.16b,v0.16b // 9 +.inst 0x5e151060 //sha1p v0.16b,v3.16b,v21.4s add v21.4s,v18.4s,v7.4s - .inst 0x5e2818e4 //sha1su1 v4.16b,v7.16b - .inst 0x5e0730c5 //sha1su0 v5.16b,v6.16b,v7.16b - .inst 0x5e280803 //sha1h v3.16b,v0.16b // 10 - .inst 0x5e142040 //sha1m v0.16b,v2.16b,v20.4s +.inst 0x5e2818e4 //sha1su1 v4.16b,v7.16b +.inst 0x5e0730c5 //sha1su0 v5.16b,v6.16b,v7.16b +.inst 0x5e280803 //sha1h v3.16b,v0.16b // 10 +.inst 0x5e142040 //sha1m v0.16b,v2.16b,v20.4s add v20.4s,v18.4s,v4.4s - .inst 0x5e281885 //sha1su1 v5.16b,v4.16b - .inst 0x5e0430e6 //sha1su0 v6.16b,v7.16b,v4.16b - .inst 0x5e280802 //sha1h v2.16b,v0.16b // 11 - .inst 0x5e152060 //sha1m v0.16b,v3.16b,v21.4s +.inst 0x5e281885 //sha1su1 v5.16b,v4.16b +.inst 0x5e0430e6 //sha1su0 v6.16b,v7.16b,v4.16b +.inst 0x5e280802 //sha1h v2.16b,v0.16b // 11 +.inst 0x5e152060 //sha1m v0.16b,v3.16b,v21.4s add v21.4s,v18.4s,v5.4s - .inst 0x5e2818a6 //sha1su1 v6.16b,v5.16b - .inst 0x5e053087 //sha1su0 v7.16b,v4.16b,v5.16b - .inst 0x5e280803 //sha1h v3.16b,v0.16b // 12 - .inst 0x5e142040 //sha1m v0.16b,v2.16b,v20.4s +.inst 0x5e2818a6 //sha1su1 v6.16b,v5.16b +.inst 0x5e053087 //sha1su0 v7.16b,v4.16b,v5.16b +.inst 0x5e280803 //sha1h v3.16b,v0.16b // 12 +.inst 0x5e142040 //sha1m v0.16b,v2.16b,v20.4s add v20.4s,v18.4s,v6.4s - .inst 0x5e2818c7 //sha1su1 v7.16b,v6.16b - .inst 0x5e0630a4 //sha1su0 v4.16b,v5.16b,v6.16b - .inst 0x5e280802 //sha1h v2.16b,v0.16b // 13 - .inst 0x5e152060 //sha1m v0.16b,v3.16b,v21.4s +.inst 0x5e2818c7 //sha1su1 v7.16b,v6.16b +.inst 0x5e0630a4 //sha1su0 v4.16b,v5.16b,v6.16b +.inst 0x5e280802 //sha1h v2.16b,v0.16b // 13 +.inst 0x5e152060 //sha1m v0.16b,v3.16b,v21.4s add v21.4s,v19.4s,v7.4s - .inst 0x5e2818e4 //sha1su1 v4.16b,v7.16b - .inst 0x5e0730c5 //sha1su0 v5.16b,v6.16b,v7.16b - .inst 0x5e280803 //sha1h v3.16b,v0.16b // 14 - .inst 0x5e142040 //sha1m v0.16b,v2.16b,v20.4s +.inst 0x5e2818e4 //sha1su1 v4.16b,v7.16b +.inst 0x5e0730c5 //sha1su0 v5.16b,v6.16b,v7.16b +.inst 0x5e280803 //sha1h v3.16b,v0.16b // 14 +.inst 0x5e142040 //sha1m v0.16b,v2.16b,v20.4s add v20.4s,v19.4s,v4.4s - .inst 0x5e281885 //sha1su1 v5.16b,v4.16b - .inst 0x5e0430e6 //sha1su0 v6.16b,v7.16b,v4.16b - .inst 0x5e280802 //sha1h v2.16b,v0.16b // 15 - .inst 0x5e151060 //sha1p v0.16b,v3.16b,v21.4s +.inst 0x5e281885 //sha1su1 v5.16b,v4.16b +.inst 0x5e0430e6 //sha1su0 v6.16b,v7.16b,v4.16b +.inst 0x5e280802 //sha1h v2.16b,v0.16b // 15 +.inst 0x5e151060 //sha1p v0.16b,v3.16b,v21.4s add v21.4s,v19.4s,v5.4s - .inst 0x5e2818a6 //sha1su1 v6.16b,v5.16b - .inst 0x5e053087 //sha1su0 v7.16b,v4.16b,v5.16b - .inst 0x5e280803 //sha1h v3.16b,v0.16b // 16 - .inst 0x5e141040 //sha1p v0.16b,v2.16b,v20.4s +.inst 0x5e2818a6 //sha1su1 v6.16b,v5.16b +.inst 0x5e053087 //sha1su0 v7.16b,v4.16b,v5.16b +.inst 0x5e280803 //sha1h v3.16b,v0.16b // 16 +.inst 0x5e141040 //sha1p v0.16b,v2.16b,v20.4s add v20.4s,v19.4s,v6.4s - .inst 0x5e2818c7 //sha1su1 v7.16b,v6.16b - .inst 0x5e280802 //sha1h v2.16b,v0.16b // 17 - .inst 0x5e151060 //sha1p v0.16b,v3.16b,v21.4s +.inst 0x5e2818c7 //sha1su1 v7.16b,v6.16b +.inst 0x5e280802 //sha1h v2.16b,v0.16b // 17 +.inst 0x5e151060 //sha1p v0.16b,v3.16b,v21.4s add v21.4s,v19.4s,v7.4s - .inst 0x5e280803 //sha1h v3.16b,v0.16b // 18 - .inst 0x5e141040 //sha1p v0.16b,v2.16b,v20.4s +.inst 0x5e280803 //sha1h v3.16b,v0.16b // 18 +.inst 0x5e141040 //sha1p v0.16b,v2.16b,v20.4s - .inst 0x5e280802 //sha1h v2.16b,v0.16b // 19 - .inst 0x5e151060 //sha1p v0.16b,v3.16b,v21.4s +.inst 0x5e280802 //sha1h v2.16b,v0.16b // 19 +.inst 0x5e151060 //sha1p v0.16b,v3.16b,v21.4s add v1.4s,v1.4s,v2.4s add v0.4s,v0.4s,v22.4s @@ -1206,6 +1208,8 @@ sha1_block_armv8: .long 0xca62c1d6,0xca62c1d6,0xca62c1d6,0xca62c1d6 //K_60_79 .LOPENSSL_armcap_P: .quad OPENSSL_armcap_P-. -.asciz "SHA1 block transform for ARMv8, CRYPTOGAMS by " +.byte 83,72,65,49,32,98,108,111,99,107,32,116,114,97,110,115,102,111,114,109,32,102,111,114,32,65,82,77,118,56,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0 +.align 2 .align 2 .comm OPENSSL_armcap_P,4,4 +#endif \ No newline at end of file diff --git a/third_party/boringssl/linux-aarch64/crypto/sha/sha256-armv8.S b/third_party/boringssl/linux-aarch64/crypto/sha/sha256-armv8.S index bd43b1fe76dd3..4834553dc1186 100644 --- a/third_party/boringssl/linux-aarch64/crypto/sha/sha256-armv8.S +++ b/third_party/boringssl/linux-aarch64/crypto/sha/sha256-armv8.S @@ -1,7 +1,9 @@ +#if defined(__aarch64__) #include "arm_arch.h" .text + .globl sha256_block_data_order .type sha256_block_data_order,%function .align 6 @@ -27,7 +29,7 @@ sha256_block_data_order: ldp w24,w25,[x0,#4*4] add x2,x1,x2,lsl#6 // end of input ldp w26,w27,[x0,#6*4] - adr x30,K256 + adr x30,.LK256 stp x0,x2,[x29,#96] .Loop: @@ -975,167 +977,169 @@ sha256_block_data_order: .size sha256_block_data_order,.-sha256_block_data_order .align 6 -.type K256,%object -K256: - .long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5 - .long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5 - .long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3 - .long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174 - .long 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc - .long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da - .long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7 - .long 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967 - .long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13 - .long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85 - .long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3 - .long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070 - .long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5 - .long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3 - .long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208 - .long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 - .long 0 //terminator -.size K256,.-K256 +.type .LK256,%object +.LK256: +.long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5 +.long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5 +.long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3 +.long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174 +.long 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc +.long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da +.long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7 +.long 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967 +.long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13 +.long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85 +.long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3 +.long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070 +.long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5 +.long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3 +.long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208 +.long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 +.long 0 //terminator +.size .LK256,.-.LK256 .align 3 .LOPENSSL_armcap_P: - .quad OPENSSL_armcap_P-. -.asciz "SHA256 block transform for ARMv8, CRYPTOGAMS by " +.quad OPENSSL_armcap_P-. +.byte 83,72,65,50,53,54,32,98,108,111,99,107,32,116,114,97,110,115,102,111,114,109,32,102,111,114,32,65,82,77,118,56,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0 +.align 2 .align 2 .type sha256_block_armv8,%function .align 6 sha256_block_armv8: .Lv8_entry: - stp x29,x30,[sp,#-16]! - add x29,sp,#0 + stp x29,x30,[sp,#-16]! + add x29,sp,#0 - ld1 {v0.4s,v1.4s},[x0] - adr x3,K256 + ld1 {v0.4s,v1.4s},[x0] + adr x3,.LK256 .Loop_hw: - ld1 {v4.16b-v7.16b},[x1],#64 - sub x2,x2,#1 - ld1 {v16.4s},[x3],#16 - rev32 v4.16b,v4.16b - rev32 v5.16b,v5.16b - rev32 v6.16b,v6.16b - rev32 v7.16b,v7.16b - orr v18.16b,v0.16b,v0.16b // offload - orr v19.16b,v1.16b,v1.16b - ld1 {v17.4s},[x3],#16 - add v16.4s,v16.4s,v4.4s - .inst 0x5e2828a4 //sha256su0 v4.16b,v5.16b - orr v2.16b,v0.16b,v0.16b - .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s - .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s - .inst 0x5e0760c4 //sha256su1 v4.16b,v6.16b,v7.16b - ld1 {v16.4s},[x3],#16 - add v17.4s,v17.4s,v5.4s - .inst 0x5e2828c5 //sha256su0 v5.16b,v6.16b - orr v2.16b,v0.16b,v0.16b - .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s - .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s - .inst 0x5e0460e5 //sha256su1 v5.16b,v7.16b,v4.16b - ld1 {v17.4s},[x3],#16 - add v16.4s,v16.4s,v6.4s - .inst 0x5e2828e6 //sha256su0 v6.16b,v7.16b - orr v2.16b,v0.16b,v0.16b - .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s - .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s - .inst 0x5e056086 //sha256su1 v6.16b,v4.16b,v5.16b - ld1 {v16.4s},[x3],#16 - add v17.4s,v17.4s,v7.4s - .inst 0x5e282887 //sha256su0 v7.16b,v4.16b - orr v2.16b,v0.16b,v0.16b - .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s - .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s - .inst 0x5e0660a7 //sha256su1 v7.16b,v5.16b,v6.16b - ld1 {v17.4s},[x3],#16 - add v16.4s,v16.4s,v4.4s - .inst 0x5e2828a4 //sha256su0 v4.16b,v5.16b - orr v2.16b,v0.16b,v0.16b - .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s - .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s - .inst 0x5e0760c4 //sha256su1 v4.16b,v6.16b,v7.16b - ld1 {v16.4s},[x3],#16 - add v17.4s,v17.4s,v5.4s - .inst 0x5e2828c5 //sha256su0 v5.16b,v6.16b - orr v2.16b,v0.16b,v0.16b - .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s - .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s - .inst 0x5e0460e5 //sha256su1 v5.16b,v7.16b,v4.16b - ld1 {v17.4s},[x3],#16 - add v16.4s,v16.4s,v6.4s - .inst 0x5e2828e6 //sha256su0 v6.16b,v7.16b - orr v2.16b,v0.16b,v0.16b - .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s - .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s - .inst 0x5e056086 //sha256su1 v6.16b,v4.16b,v5.16b - ld1 {v16.4s},[x3],#16 - add v17.4s,v17.4s,v7.4s - .inst 0x5e282887 //sha256su0 v7.16b,v4.16b - orr v2.16b,v0.16b,v0.16b - .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s - .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s - .inst 0x5e0660a7 //sha256su1 v7.16b,v5.16b,v6.16b - ld1 {v17.4s},[x3],#16 - add v16.4s,v16.4s,v4.4s - .inst 0x5e2828a4 //sha256su0 v4.16b,v5.16b - orr v2.16b,v0.16b,v0.16b - .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s - .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s - .inst 0x5e0760c4 //sha256su1 v4.16b,v6.16b,v7.16b - ld1 {v16.4s},[x3],#16 - add v17.4s,v17.4s,v5.4s - .inst 0x5e2828c5 //sha256su0 v5.16b,v6.16b - orr v2.16b,v0.16b,v0.16b - .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s - .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s - .inst 0x5e0460e5 //sha256su1 v5.16b,v7.16b,v4.16b - ld1 {v17.4s},[x3],#16 - add v16.4s,v16.4s,v6.4s - .inst 0x5e2828e6 //sha256su0 v6.16b,v7.16b - orr v2.16b,v0.16b,v0.16b - .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s - .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s - .inst 0x5e056086 //sha256su1 v6.16b,v4.16b,v5.16b - ld1 {v16.4s},[x3],#16 - add v17.4s,v17.4s,v7.4s - .inst 0x5e282887 //sha256su0 v7.16b,v4.16b - orr v2.16b,v0.16b,v0.16b - .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s - .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s - .inst 0x5e0660a7 //sha256su1 v7.16b,v5.16b,v6.16b - ld1 {v17.4s},[x3],#16 - add v16.4s,v16.4s,v4.4s - orr v2.16b,v0.16b,v0.16b - .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s - .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s + ld1 {v4.16b,v5.16b,v6.16b,v7.16b},[x1],#64 + sub x2,x2,#1 + ld1 {v16.4s},[x3],#16 + rev32 v4.16b,v4.16b + rev32 v5.16b,v5.16b + rev32 v6.16b,v6.16b + rev32 v7.16b,v7.16b + orr v18.16b,v0.16b,v0.16b // offload + orr v19.16b,v1.16b,v1.16b + ld1 {v17.4s},[x3],#16 + add v16.4s,v16.4s,v4.4s +.inst 0x5e2828a4 //sha256su0 v4.16b,v5.16b + orr v2.16b,v0.16b,v0.16b +.inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s +.inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s +.inst 0x5e0760c4 //sha256su1 v4.16b,v6.16b,v7.16b + ld1 {v16.4s},[x3],#16 + add v17.4s,v17.4s,v5.4s +.inst 0x5e2828c5 //sha256su0 v5.16b,v6.16b + orr v2.16b,v0.16b,v0.16b +.inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s +.inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s +.inst 0x5e0460e5 //sha256su1 v5.16b,v7.16b,v4.16b + ld1 {v17.4s},[x3],#16 + add v16.4s,v16.4s,v6.4s +.inst 0x5e2828e6 //sha256su0 v6.16b,v7.16b + orr v2.16b,v0.16b,v0.16b +.inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s +.inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s +.inst 0x5e056086 //sha256su1 v6.16b,v4.16b,v5.16b + ld1 {v16.4s},[x3],#16 + add v17.4s,v17.4s,v7.4s +.inst 0x5e282887 //sha256su0 v7.16b,v4.16b + orr v2.16b,v0.16b,v0.16b +.inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s +.inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s +.inst 0x5e0660a7 //sha256su1 v7.16b,v5.16b,v6.16b + ld1 {v17.4s},[x3],#16 + add v16.4s,v16.4s,v4.4s +.inst 0x5e2828a4 //sha256su0 v4.16b,v5.16b + orr v2.16b,v0.16b,v0.16b +.inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s +.inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s +.inst 0x5e0760c4 //sha256su1 v4.16b,v6.16b,v7.16b + ld1 {v16.4s},[x3],#16 + add v17.4s,v17.4s,v5.4s +.inst 0x5e2828c5 //sha256su0 v5.16b,v6.16b + orr v2.16b,v0.16b,v0.16b +.inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s +.inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s +.inst 0x5e0460e5 //sha256su1 v5.16b,v7.16b,v4.16b + ld1 {v17.4s},[x3],#16 + add v16.4s,v16.4s,v6.4s +.inst 0x5e2828e6 //sha256su0 v6.16b,v7.16b + orr v2.16b,v0.16b,v0.16b +.inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s +.inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s +.inst 0x5e056086 //sha256su1 v6.16b,v4.16b,v5.16b + ld1 {v16.4s},[x3],#16 + add v17.4s,v17.4s,v7.4s +.inst 0x5e282887 //sha256su0 v7.16b,v4.16b + orr v2.16b,v0.16b,v0.16b +.inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s +.inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s +.inst 0x5e0660a7 //sha256su1 v7.16b,v5.16b,v6.16b + ld1 {v17.4s},[x3],#16 + add v16.4s,v16.4s,v4.4s +.inst 0x5e2828a4 //sha256su0 v4.16b,v5.16b + orr v2.16b,v0.16b,v0.16b +.inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s +.inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s +.inst 0x5e0760c4 //sha256su1 v4.16b,v6.16b,v7.16b + ld1 {v16.4s},[x3],#16 + add v17.4s,v17.4s,v5.4s +.inst 0x5e2828c5 //sha256su0 v5.16b,v6.16b + orr v2.16b,v0.16b,v0.16b +.inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s +.inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s +.inst 0x5e0460e5 //sha256su1 v5.16b,v7.16b,v4.16b + ld1 {v17.4s},[x3],#16 + add v16.4s,v16.4s,v6.4s +.inst 0x5e2828e6 //sha256su0 v6.16b,v7.16b + orr v2.16b,v0.16b,v0.16b +.inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s +.inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s +.inst 0x5e056086 //sha256su1 v6.16b,v4.16b,v5.16b + ld1 {v16.4s},[x3],#16 + add v17.4s,v17.4s,v7.4s +.inst 0x5e282887 //sha256su0 v7.16b,v4.16b + orr v2.16b,v0.16b,v0.16b +.inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s +.inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s +.inst 0x5e0660a7 //sha256su1 v7.16b,v5.16b,v6.16b + ld1 {v17.4s},[x3],#16 + add v16.4s,v16.4s,v4.4s + orr v2.16b,v0.16b,v0.16b +.inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s +.inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s - ld1 {v16.4s},[x3],#16 - add v17.4s,v17.4s,v5.4s - orr v2.16b,v0.16b,v0.16b - .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s - .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s + ld1 {v16.4s},[x3],#16 + add v17.4s,v17.4s,v5.4s + orr v2.16b,v0.16b,v0.16b +.inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s +.inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s - ld1 {v17.4s},[x3] - add v16.4s,v16.4s,v6.4s - sub x3,x3,#64*4-16 // rewind - orr v2.16b,v0.16b,v0.16b - .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s - .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s + ld1 {v17.4s},[x3] + add v16.4s,v16.4s,v6.4s + sub x3,x3,#64*4-16 // rewind + orr v2.16b,v0.16b,v0.16b +.inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s +.inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s - add v17.4s,v17.4s,v7.4s - orr v2.16b,v0.16b,v0.16b - .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s - .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s + add v17.4s,v17.4s,v7.4s + orr v2.16b,v0.16b,v0.16b +.inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s +.inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s - add v0.4s,v0.4s,v18.4s - add v1.4s,v1.4s,v19.4s + add v0.4s,v0.4s,v18.4s + add v1.4s,v1.4s,v19.4s - cbnz x2,.Loop_hw + cbnz x2,.Loop_hw - st1 {v0.4s,v1.4s},[x0] + st1 {v0.4s,v1.4s},[x0] - ldr x29,[sp],#16 + ldr x29,[sp],#16 ret .size sha256_block_armv8,.-sha256_block_armv8 .comm OPENSSL_armcap_P,4,4 +#endif \ No newline at end of file diff --git a/third_party/boringssl/linux-aarch64/crypto/sha/sha512-armv8.S b/third_party/boringssl/linux-aarch64/crypto/sha/sha512-armv8.S index 6b0d1940c6bef..654c473f2763a 100644 --- a/third_party/boringssl/linux-aarch64/crypto/sha/sha512-armv8.S +++ b/third_party/boringssl/linux-aarch64/crypto/sha/sha512-armv8.S @@ -1,7 +1,9 @@ +#if defined(__aarch64__) #include "arm_arch.h" .text + .globl sha512_block_data_order .type sha512_block_data_order,%function .align 6 @@ -21,7 +23,7 @@ sha512_block_data_order: ldp x24,x25,[x0,#4*8] add x2,x1,x2,lsl#7 // end of input ldp x26,x27,[x0,#6*8] - adr x30,K512 + adr x30,.LK512 stp x0,x2,[x29,#96] .Loop: @@ -969,53 +971,55 @@ sha512_block_data_order: .size sha512_block_data_order,.-sha512_block_data_order .align 6 -.type K512,%object -K512: - .quad 0x428a2f98d728ae22,0x7137449123ef65cd - .quad 0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc - .quad 0x3956c25bf348b538,0x59f111f1b605d019 - .quad 0x923f82a4af194f9b,0xab1c5ed5da6d8118 - .quad 0xd807aa98a3030242,0x12835b0145706fbe - .quad 0x243185be4ee4b28c,0x550c7dc3d5ffb4e2 - .quad 0x72be5d74f27b896f,0x80deb1fe3b1696b1 - .quad 0x9bdc06a725c71235,0xc19bf174cf692694 - .quad 0xe49b69c19ef14ad2,0xefbe4786384f25e3 - .quad 0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65 - .quad 0x2de92c6f592b0275,0x4a7484aa6ea6e483 - .quad 0x5cb0a9dcbd41fbd4,0x76f988da831153b5 - .quad 0x983e5152ee66dfab,0xa831c66d2db43210 - .quad 0xb00327c898fb213f,0xbf597fc7beef0ee4 - .quad 0xc6e00bf33da88fc2,0xd5a79147930aa725 - .quad 0x06ca6351e003826f,0x142929670a0e6e70 - .quad 0x27b70a8546d22ffc,0x2e1b21385c26c926 - .quad 0x4d2c6dfc5ac42aed,0x53380d139d95b3df - .quad 0x650a73548baf63de,0x766a0abb3c77b2a8 - .quad 0x81c2c92e47edaee6,0x92722c851482353b - .quad 0xa2bfe8a14cf10364,0xa81a664bbc423001 - .quad 0xc24b8b70d0f89791,0xc76c51a30654be30 - .quad 0xd192e819d6ef5218,0xd69906245565a910 - .quad 0xf40e35855771202a,0x106aa07032bbd1b8 - .quad 0x19a4c116b8d2d0c8,0x1e376c085141ab53 - .quad 0x2748774cdf8eeb99,0x34b0bcb5e19b48a8 - .quad 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb - .quad 0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3 - .quad 0x748f82ee5defb2fc,0x78a5636f43172f60 - .quad 0x84c87814a1f0ab72,0x8cc702081a6439ec - .quad 0x90befffa23631e28,0xa4506cebde82bde9 - .quad 0xbef9a3f7b2c67915,0xc67178f2e372532b - .quad 0xca273eceea26619c,0xd186b8c721c0c207 - .quad 0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178 - .quad 0x06f067aa72176fba,0x0a637dc5a2c898a6 - .quad 0x113f9804bef90dae,0x1b710b35131c471b - .quad 0x28db77f523047d84,0x32caab7b40c72493 - .quad 0x3c9ebe0a15c9bebc,0x431d67c49c100d4c - .quad 0x4cc5d4becb3e42b6,0x597f299cfc657e2a - .quad 0x5fcb6fab3ad6faec,0x6c44198c4a475817 - .quad 0 // terminator -.size K512,.-K512 +.type .LK512,%object +.LK512: +.quad 0x428a2f98d728ae22,0x7137449123ef65cd +.quad 0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc +.quad 0x3956c25bf348b538,0x59f111f1b605d019 +.quad 0x923f82a4af194f9b,0xab1c5ed5da6d8118 +.quad 0xd807aa98a3030242,0x12835b0145706fbe +.quad 0x243185be4ee4b28c,0x550c7dc3d5ffb4e2 +.quad 0x72be5d74f27b896f,0x80deb1fe3b1696b1 +.quad 0x9bdc06a725c71235,0xc19bf174cf692694 +.quad 0xe49b69c19ef14ad2,0xefbe4786384f25e3 +.quad 0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65 +.quad 0x2de92c6f592b0275,0x4a7484aa6ea6e483 +.quad 0x5cb0a9dcbd41fbd4,0x76f988da831153b5 +.quad 0x983e5152ee66dfab,0xa831c66d2db43210 +.quad 0xb00327c898fb213f,0xbf597fc7beef0ee4 +.quad 0xc6e00bf33da88fc2,0xd5a79147930aa725 +.quad 0x06ca6351e003826f,0x142929670a0e6e70 +.quad 0x27b70a8546d22ffc,0x2e1b21385c26c926 +.quad 0x4d2c6dfc5ac42aed,0x53380d139d95b3df +.quad 0x650a73548baf63de,0x766a0abb3c77b2a8 +.quad 0x81c2c92e47edaee6,0x92722c851482353b +.quad 0xa2bfe8a14cf10364,0xa81a664bbc423001 +.quad 0xc24b8b70d0f89791,0xc76c51a30654be30 +.quad 0xd192e819d6ef5218,0xd69906245565a910 +.quad 0xf40e35855771202a,0x106aa07032bbd1b8 +.quad 0x19a4c116b8d2d0c8,0x1e376c085141ab53 +.quad 0x2748774cdf8eeb99,0x34b0bcb5e19b48a8 +.quad 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb +.quad 0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3 +.quad 0x748f82ee5defb2fc,0x78a5636f43172f60 +.quad 0x84c87814a1f0ab72,0x8cc702081a6439ec +.quad 0x90befffa23631e28,0xa4506cebde82bde9 +.quad 0xbef9a3f7b2c67915,0xc67178f2e372532b +.quad 0xca273eceea26619c,0xd186b8c721c0c207 +.quad 0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178 +.quad 0x06f067aa72176fba,0x0a637dc5a2c898a6 +.quad 0x113f9804bef90dae,0x1b710b35131c471b +.quad 0x28db77f523047d84,0x32caab7b40c72493 +.quad 0x3c9ebe0a15c9bebc,0x431d67c49c100d4c +.quad 0x4cc5d4becb3e42b6,0x597f299cfc657e2a +.quad 0x5fcb6fab3ad6faec,0x6c44198c4a475817 +.quad 0 // terminator +.size .LK512,.-.LK512 .align 3 .LOPENSSL_armcap_P: - .quad OPENSSL_armcap_P-. -.asciz "SHA512 block transform for ARMv8, CRYPTOGAMS by " +.quad OPENSSL_armcap_P-. +.byte 83,72,65,53,49,50,32,98,108,111,99,107,32,116,114,97,110,115,102,111,114,109,32,102,111,114,32,65,82,77,118,56,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0 +.align 2 .align 2 .comm OPENSSL_armcap_P,4,4 +#endif \ No newline at end of file diff --git a/third_party/boringssl/linux-arm/crypto/aes/aes-armv4.S b/third_party/boringssl/linux-arm/crypto/aes/aes-armv4.S index 0b7d1938d1d30..cb94841e0283e 100644 --- a/third_party/boringssl/linux-arm/crypto/aes/aes-armv4.S +++ b/third_party/boringssl/linux-arm/crypto/aes/aes-armv4.S @@ -1,3 +1,4 @@ +#if defined(__arm__) @ ==================================================================== @ Written by Andy Polyakov for the OpenSSL @@ -43,7 +44,7 @@ .code 32 #else .syntax unified -# ifdef __thumb2__ +# if defined(__thumb2__) && !defined(__APPLE__) .thumb # else .code 32 @@ -158,9 +159,9 @@ AES_Te: @ void asm_AES_encrypt(const unsigned char *in, unsigned char *out, @ const AES_KEY *key) { -.global asm_AES_encrypt -.hidden asm_AES_encrypt -.type asm_AES_encrypt,%function +.globl asm_AES_encrypt +.hidden asm_AES_encrypt +.type asm_AES_encrypt,%function .align 5 asm_AES_encrypt: #if __ARM_ARCH__<7 @@ -168,10 +169,14 @@ asm_AES_encrypt: #else adr r3,asm_AES_encrypt #endif - stmdb sp!,{r1,r4-r12,lr} + stmdb sp!,{r1,r4-r12,lr} +#ifdef __APPLE__ + adr r10,AES_Te +#else + sub r10,r3,#asm_AES_encrypt-AES_Te @ Te +#endif mov r12,r0 @ inp mov r11,r2 - sub r10,r3,#asm_AES_encrypt-AES_Te @ Te #if __ARM_ARCH__<7 ldrb r0,[r12,#3] @ load input data in endian-neutral ldrb r4,[r12,#2] @ manner... @@ -258,20 +263,20 @@ asm_AES_encrypt: strb r3,[r12,#15] #endif #if __ARM_ARCH__>=5 - ldmia sp!,{r4-r12,pc} + ldmia sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,pc} #else - ldmia sp!,{r4-r12,lr} + ldmia sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,lr} tst lr,#1 moveq pc,lr @ be binary compatible with V4, yet - .word 0xe12fff1e @ interoperable with Thumb ISA:-) +.word 0xe12fff1e @ interoperable with Thumb ISA:-) #endif .size asm_AES_encrypt,.-asm_AES_encrypt -.type _armv4_AES_encrypt,%function +.type _armv4_AES_encrypt,%function .align 2 _armv4_AES_encrypt: str lr,[sp,#-4]! @ push lr - ldmia r11!,{r4-r7} + ldmia r11!,{r4,r5,r6,r7} eor r0,r0,r4 ldr r12,[r11,#240-16] eor r1,r1,r5 @@ -404,9 +409,9 @@ _armv4_AES_encrypt: ldr pc,[sp],#4 @ pop and return .size _armv4_AES_encrypt,.-_armv4_AES_encrypt -.global asm_AES_set_encrypt_key -.hidden asm_AES_set_encrypt_key -.type asm_AES_set_encrypt_key,%function +.globl asm_AES_set_encrypt_key +.hidden asm_AES_set_encrypt_key +.type asm_AES_set_encrypt_key,%function .align 5 asm_AES_set_encrypt_key: _armv4_AES_set_encrypt_key: @@ -439,13 +444,17 @@ _armv4_AES_set_encrypt_key: movne r0,#-1 bne .Labrt -.Lok: stmdb sp!,{r4-r12,lr} - sub r10,r3,#_armv4_AES_set_encrypt_key-AES_Te-1024 @ Te4 - +.Lok: stmdb sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,lr} mov r12,r0 @ inp mov lr,r1 @ bits mov r11,r2 @ key +#ifdef __APPLE__ + adr r10,AES_Te+1024 @ Te4 +#else + sub r10,r3,#_armv4_AES_set_encrypt_key-AES_Te-1024 @ Te4 +#endif + #if __ARM_ARCH__<7 ldrb r0,[r12,#3] @ load input data in endian-neutral ldrb r4,[r12,#2] @ manner... @@ -696,20 +705,20 @@ _armv4_AES_set_encrypt_key: .align 2 .Ldone: mov r0,#0 - ldmia sp!,{r4-r12,lr} + ldmia sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,lr} .Labrt: -#if defined(__thumb2__) && __ARM_ARCH__>=7 - .short 0x4770 @ .word 0xe12fff1e in Thumb2 encoding +#if __ARM_ARCH__>=5 + bx lr @ .word 0xe12fff1e #else tst lr,#1 moveq pc,lr @ be binary compatible with V4, yet - .word 0xe12fff1e @ interoperable with Thumb ISA:-) +.word 0xe12fff1e @ interoperable with Thumb ISA:-) #endif .size asm_AES_set_encrypt_key,.-asm_AES_set_encrypt_key -.global asm_AES_set_decrypt_key -.hidden asm_AES_set_decrypt_key -.type asm_AES_set_decrypt_key,%function +.globl asm_AES_set_decrypt_key +.hidden asm_AES_set_decrypt_key +.type asm_AES_set_decrypt_key,%function .align 5 asm_AES_set_decrypt_key: str lr,[sp,#-4]! @ push lr @@ -724,13 +733,13 @@ asm_AES_set_decrypt_key: .size asm_AES_set_decrypt_key,.-asm_AES_set_decrypt_key @ void AES_set_enc2dec_key(const AES_KEY *inp,AES_KEY *out) -.global AES_set_enc2dec_key +.globl AES_set_enc2dec_key .hidden AES_set_enc2dec_key .type AES_set_enc2dec_key,%function .align 5 AES_set_enc2dec_key: _armv4_AES_set_enc2dec_key: - stmdb sp!,{r4-r12,lr} + stmdb sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,lr} ldr r12,[r0,#240] mov r7,r0 @ input @@ -812,12 +821,12 @@ _armv4_AES_set_enc2dec_key: mov r0,#0 #if __ARM_ARCH__>=5 - ldmia sp!,{r4-r12,pc} + ldmia sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,pc} #else - ldmia sp!,{r4-r12,lr} + ldmia sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,lr} tst lr,#1 moveq pc,lr @ be binary compatible with V4, yet - .word 0xe12fff1e @ interoperable with Thumb ISA:-) +.word 0xe12fff1e @ interoperable with Thumb ISA:-) #endif .size AES_set_enc2dec_key,.-AES_set_enc2dec_key @@ -925,9 +934,9 @@ AES_Td: @ void asm_AES_decrypt(const unsigned char *in, unsigned char *out, @ const AES_KEY *key) { -.global asm_AES_decrypt -.hidden asm_AES_decrypt -.type asm_AES_decrypt,%function +.globl asm_AES_decrypt +.hidden asm_AES_decrypt +.type asm_AES_decrypt,%function .align 5 asm_AES_decrypt: #if __ARM_ARCH__<7 @@ -935,10 +944,14 @@ asm_AES_decrypt: #else adr r3,asm_AES_decrypt #endif - stmdb sp!,{r1,r4-r12,lr} + stmdb sp!,{r1,r4-r12,lr} +#ifdef __APPLE__ + adr r10,AES_Td +#else + sub r10,r3,#asm_AES_decrypt-AES_Td @ Td +#endif mov r12,r0 @ inp mov r11,r2 - sub r10,r3,#asm_AES_decrypt-AES_Td @ Td #if __ARM_ARCH__<7 ldrb r0,[r12,#3] @ load input data in endian-neutral ldrb r4,[r12,#2] @ manner... @@ -1025,20 +1038,20 @@ asm_AES_decrypt: strb r3,[r12,#15] #endif #if __ARM_ARCH__>=5 - ldmia sp!,{r4-r12,pc} + ldmia sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,pc} #else - ldmia sp!,{r4-r12,lr} + ldmia sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,lr} tst lr,#1 moveq pc,lr @ be binary compatible with V4, yet - .word 0xe12fff1e @ interoperable with Thumb ISA:-) +.word 0xe12fff1e @ interoperable with Thumb ISA:-) #endif .size asm_AES_decrypt,.-asm_AES_decrypt -.type _armv4_AES_decrypt,%function +.type _armv4_AES_decrypt,%function .align 2 _armv4_AES_decrypt: str lr,[sp,#-4]! @ push lr - ldmia r11!,{r4-r7} + ldmia r11!,{r4,r5,r6,r7} eor r0,r0,r4 ldr r12,[r11,#240-16] eor r1,r1,r5 @@ -1179,7 +1192,9 @@ _armv4_AES_decrypt: sub r10,r10,#1024 ldr pc,[sp],#4 @ pop and return .size _armv4_AES_decrypt,.-_armv4_AES_decrypt -.asciz "AES for ARMv4, CRYPTOGAMS by " +.byte 65,69,83,32,102,111,114,32,65,82,77,118,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0 +.align 2 .align 2 #endif +#endif \ No newline at end of file diff --git a/third_party/boringssl/linux-arm/crypto/aes/aesv8-armx.S b/third_party/boringssl/linux-arm/crypto/aes/aesv8-armx.S deleted file mode 100644 index fede6edd18b31..0000000000000 --- a/third_party/boringssl/linux-arm/crypto/aes/aesv8-armx.S +++ /dev/null @@ -1,732 +0,0 @@ -#include "arm_arch.h" - -#if __ARM_MAX_ARCH__>=7 -.text -.arch armv7-a -.fpu neon -.code 32 -.align 5 -rcon: -.long 0x01,0x01,0x01,0x01 -.long 0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d @ rotate-n-splat -.long 0x1b,0x1b,0x1b,0x1b - -.globl aes_v8_set_encrypt_key -.type aes_v8_set_encrypt_key,%function -.align 5 -aes_v8_set_encrypt_key: -.Lenc_key: - mov r3,#-1 - cmp r0,#0 - beq .Lenc_key_abort - cmp r2,#0 - beq .Lenc_key_abort - mov r3,#-2 - cmp r1,#128 - blt .Lenc_key_abort - cmp r1,#256 - bgt .Lenc_key_abort - tst r1,#0x3f - bne .Lenc_key_abort - - adr r3,rcon - cmp r1,#192 - - veor q0,q0,q0 - vld1.8 {q3},[r0]! - mov r1,#8 @ reuse r1 - vld1.32 {q1,q2},[r3]! - - blt .Loop128 - beq .L192 - b .L256 - -.align 4 -.Loop128: - vtbl.8 d20,{q3},d4 - vtbl.8 d21,{q3},d5 - vext.8 q9,q0,q3,#12 - vst1.32 {q3},[r2]! - .byte 0x00,0x43,0xf0,0xf3 @ aese q10,q0 - subs r1,r1,#1 - - veor q3,q3,q9 - vext.8 q9,q0,q9,#12 - veor q3,q3,q9 - vext.8 q9,q0,q9,#12 - veor q10,q10,q1 - veor q3,q3,q9 - vshl.u8 q1,q1,#1 - veor q3,q3,q10 - bne .Loop128 - - vld1.32 {q1},[r3] - - vtbl.8 d20,{q3},d4 - vtbl.8 d21,{q3},d5 - vext.8 q9,q0,q3,#12 - vst1.32 {q3},[r2]! - .byte 0x00,0x43,0xf0,0xf3 @ aese q10,q0 - - veor q3,q3,q9 - vext.8 q9,q0,q9,#12 - veor q3,q3,q9 - vext.8 q9,q0,q9,#12 - veor q10,q10,q1 - veor q3,q3,q9 - vshl.u8 q1,q1,#1 - veor q3,q3,q10 - - vtbl.8 d20,{q3},d4 - vtbl.8 d21,{q3},d5 - vext.8 q9,q0,q3,#12 - vst1.32 {q3},[r2]! - .byte 0x00,0x43,0xf0,0xf3 @ aese q10,q0 - - veor q3,q3,q9 - vext.8 q9,q0,q9,#12 - veor q3,q3,q9 - vext.8 q9,q0,q9,#12 - veor q10,q10,q1 - veor q3,q3,q9 - veor q3,q3,q10 - vst1.32 {q3},[r2] - add r2,r2,#0x50 - - mov r12,#10 - b .Ldone - -.align 4 -.L192: - vld1.8 {d16},[r0]! - vmov.i8 q10,#8 @ borrow q10 - vst1.32 {q3},[r2]! - vsub.i8 q2,q2,q10 @ adjust the mask - -.Loop192: - vtbl.8 d20,{q8},d4 - vtbl.8 d21,{q8},d5 - vext.8 q9,q0,q3,#12 - vst1.32 {d16},[r2]! - .byte 0x00,0x43,0xf0,0xf3 @ aese q10,q0 - subs r1,r1,#1 - - veor q3,q3,q9 - vext.8 q9,q0,q9,#12 - veor q3,q3,q9 - vext.8 q9,q0,q9,#12 - veor q3,q3,q9 - - vdup.32 q9,d7[1] - veor q9,q9,q8 - veor q10,q10,q1 - vext.8 q8,q0,q8,#12 - vshl.u8 q1,q1,#1 - veor q8,q8,q9 - veor q3,q3,q10 - veor q8,q8,q10 - vst1.32 {q3},[r2]! - bne .Loop192 - - mov r12,#12 - add r2,r2,#0x20 - b .Ldone - -.align 4 -.L256: - vld1.8 {q8},[r0] - mov r1,#7 - mov r12,#14 - vst1.32 {q3},[r2]! - -.Loop256: - vtbl.8 d20,{q8},d4 - vtbl.8 d21,{q8},d5 - vext.8 q9,q0,q3,#12 - vst1.32 {q8},[r2]! - .byte 0x00,0x43,0xf0,0xf3 @ aese q10,q0 - subs r1,r1,#1 - - veor q3,q3,q9 - vext.8 q9,q0,q9,#12 - veor q3,q3,q9 - vext.8 q9,q0,q9,#12 - veor q10,q10,q1 - veor q3,q3,q9 - vshl.u8 q1,q1,#1 - veor q3,q3,q10 - vst1.32 {q3},[r2]! - beq .Ldone - - vdup.32 q10,d7[1] - vext.8 q9,q0,q8,#12 - .byte 0x00,0x43,0xf0,0xf3 @ aese q10,q0 - - veor q8,q8,q9 - vext.8 q9,q0,q9,#12 - veor q8,q8,q9 - vext.8 q9,q0,q9,#12 - veor q8,q8,q9 - - veor q8,q8,q10 - b .Loop256 - -.Ldone: - str r12,[r2] - mov r3,#0 - -.Lenc_key_abort: - mov r0,r3 @ return value - - bx lr -.size aes_v8_set_encrypt_key,.-aes_v8_set_encrypt_key - -.globl aes_v8_set_decrypt_key -.type aes_v8_set_decrypt_key,%function -.align 5 -aes_v8_set_decrypt_key: - stmdb sp!,{r4,lr} - bl .Lenc_key - - cmp r0,#0 - bne .Ldec_key_abort - - sub r2,r2,#240 @ restore original r2 - mov r4,#-16 - add r0,r2,r12,lsl#4 @ end of key schedule - - vld1.32 {q0},[r2] - vld1.32 {q1},[r0] - vst1.32 {q0},[r0],r4 - vst1.32 {q1},[r2]! - -.Loop_imc: - vld1.32 {q0},[r2] - vld1.32 {q1},[r0] - .byte 0xc0,0x03,0xb0,0xf3 @ aesimc q0,q0 - .byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1 - vst1.32 {q0},[r0],r4 - vst1.32 {q1},[r2]! - cmp r0,r2 - bhi .Loop_imc - - vld1.32 {q0},[r2] - .byte 0xc0,0x03,0xb0,0xf3 @ aesimc q0,q0 - vst1.32 {q0},[r0] - - eor r0,r0,r0 @ return value -.Ldec_key_abort: - ldmia sp!,{r4,pc} -.size aes_v8_set_decrypt_key,.-aes_v8_set_decrypt_key -.globl aes_v8_encrypt -.type aes_v8_encrypt,%function -.align 5 -aes_v8_encrypt: - ldr r3,[r2,#240] - vld1.32 {q0},[r2]! - vld1.8 {q2},[r0] - sub r3,r3,#2 - vld1.32 {q1},[r2]! - -.Loop_enc: - .byte 0x00,0x43,0xb0,0xf3 @ aese q2,q0 - vld1.32 {q0},[r2]! - .byte 0x84,0x43,0xb0,0xf3 @ aesmc q2,q2 - subs r3,r3,#2 - .byte 0x02,0x43,0xb0,0xf3 @ aese q2,q1 - vld1.32 {q1},[r2]! - .byte 0x84,0x43,0xb0,0xf3 @ aesmc q2,q2 - bgt .Loop_enc - - .byte 0x00,0x43,0xb0,0xf3 @ aese q2,q0 - vld1.32 {q0},[r2] - .byte 0x84,0x43,0xb0,0xf3 @ aesmc q2,q2 - .byte 0x02,0x43,0xb0,0xf3 @ aese q2,q1 - veor q2,q2,q0 - - vst1.8 {q2},[r1] - bx lr -.size aes_v8_encrypt,.-aes_v8_encrypt -.globl aes_v8_decrypt -.type aes_v8_decrypt,%function -.align 5 -aes_v8_decrypt: - ldr r3,[r2,#240] - vld1.32 {q0},[r2]! - vld1.8 {q2},[r0] - sub r3,r3,#2 - vld1.32 {q1},[r2]! - -.Loop_dec: - .byte 0x40,0x43,0xb0,0xf3 @ aesd q2,q0 - vld1.32 {q0},[r2]! - .byte 0xc4,0x43,0xb0,0xf3 @ aesimc q2,q2 - subs r3,r3,#2 - .byte 0x42,0x43,0xb0,0xf3 @ aesd q2,q1 - vld1.32 {q1},[r2]! - .byte 0xc4,0x43,0xb0,0xf3 @ aesimc q2,q2 - bgt .Loop_dec - - .byte 0x40,0x43,0xb0,0xf3 @ aesd q2,q0 - vld1.32 {q0},[r2] - .byte 0xc4,0x43,0xb0,0xf3 @ aesimc q2,q2 - .byte 0x42,0x43,0xb0,0xf3 @ aesd q2,q1 - veor q2,q2,q0 - - vst1.8 {q2},[r1] - bx lr -.size aes_v8_decrypt,.-aes_v8_decrypt -.globl aes_v8_cbc_encrypt -.type aes_v8_cbc_encrypt,%function -.align 5 -aes_v8_cbc_encrypt: - mov ip,sp - stmdb sp!,{r4-r8,lr} - vstmdb sp!,{d8-d15} @ ABI specification says so - ldmia ip,{r4-r5} @ load remaining args - subs r2,r2,#16 - mov r8,#16 - blo .Lcbc_abort - moveq r8,#0 - - cmp r5,#0 @ en- or decrypting? - ldr r5,[r3,#240] - and r2,r2,#-16 - vld1.8 {q6},[r4] - vld1.8 {q0},[r0],r8 - - vld1.32 {q8-q9},[r3] @ load key schedule... - sub r5,r5,#6 - add r7,r3,r5,lsl#4 @ pointer to last 7 round keys - sub r5,r5,#2 - vld1.32 {q10-q11},[r7]! - vld1.32 {q12-q13},[r7]! - vld1.32 {q14-q15},[r7]! - vld1.32 {q7},[r7] - - add r7,r3,#32 - mov r6,r5 - beq .Lcbc_dec - - cmp r5,#2 - veor q0,q0,q6 - veor q5,q8,q7 - beq .Lcbc_enc128 - -.Loop_cbc_enc: - .byte 0x20,0x03,0xb0,0xf3 @ aese q0,q8 - vld1.32 {q8},[r7]! - .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 - subs r6,r6,#2 - .byte 0x22,0x03,0xb0,0xf3 @ aese q0,q9 - vld1.32 {q9},[r7]! - .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 - bgt .Loop_cbc_enc - - .byte 0x20,0x03,0xb0,0xf3 @ aese q0,q8 - .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 - subs r2,r2,#16 - .byte 0x22,0x03,0xb0,0xf3 @ aese q0,q9 - .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 - moveq r8,#0 - .byte 0x24,0x03,0xb0,0xf3 @ aese q0,q10 - .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 - add r7,r3,#16 - .byte 0x26,0x03,0xb0,0xf3 @ aese q0,q11 - .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 - vld1.8 {q8},[r0],r8 - .byte 0x28,0x03,0xb0,0xf3 @ aese q0,q12 - .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 - veor q8,q8,q5 - .byte 0x2a,0x03,0xb0,0xf3 @ aese q0,q13 - .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 - vld1.32 {q9},[r7]! @ re-pre-load rndkey[1] - .byte 0x2c,0x03,0xb0,0xf3 @ aese q0,q14 - .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 - .byte 0x2e,0x03,0xb0,0xf3 @ aese q0,q15 - - mov r6,r5 - veor q6,q0,q7 - vst1.8 {q6},[r1]! - bhs .Loop_cbc_enc - - b .Lcbc_done - -.align 5 -.Lcbc_enc128: - vld1.32 {q2-q3},[r7] - .byte 0x20,0x03,0xb0,0xf3 @ aese q0,q8 - .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 - b .Lenter_cbc_enc128 -.Loop_cbc_enc128: - .byte 0x20,0x03,0xb0,0xf3 @ aese q0,q8 - .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 - vst1.8 {q6},[r1]! -.Lenter_cbc_enc128: - .byte 0x22,0x03,0xb0,0xf3 @ aese q0,q9 - .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 - subs r2,r2,#16 - .byte 0x04,0x03,0xb0,0xf3 @ aese q0,q2 - .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 - moveq r8,#0 - .byte 0x06,0x03,0xb0,0xf3 @ aese q0,q3 - .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 - .byte 0x24,0x03,0xb0,0xf3 @ aese q0,q10 - .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 - .byte 0x26,0x03,0xb0,0xf3 @ aese q0,q11 - .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 - vld1.8 {q8},[r0],r8 - .byte 0x28,0x03,0xb0,0xf3 @ aese q0,q12 - .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 - .byte 0x2a,0x03,0xb0,0xf3 @ aese q0,q13 - .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 - .byte 0x2c,0x03,0xb0,0xf3 @ aese q0,q14 - .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 - veor q8,q8,q5 - .byte 0x2e,0x03,0xb0,0xf3 @ aese q0,q15 - veor q6,q0,q7 - bhs .Loop_cbc_enc128 - - vst1.8 {q6},[r1]! - b .Lcbc_done -.align 5 -.Lcbc_dec: - vld1.8 {q10},[r0]! - subs r2,r2,#32 @ bias - add r6,r5,#2 - vorr q3,q0,q0 - vorr q1,q0,q0 - vorr q11,q10,q10 - blo .Lcbc_dec_tail - - vorr q1,q10,q10 - vld1.8 {q10},[r0]! - vorr q2,q0,q0 - vorr q3,q1,q1 - vorr q11,q10,q10 - -.Loop3x_cbc_dec: - .byte 0x60,0x03,0xb0,0xf3 @ aesd q0,q8 - .byte 0x60,0x23,0xb0,0xf3 @ aesd q1,q8 - .byte 0x60,0x43,0xf0,0xf3 @ aesd q10,q8 - vld1.32 {q8},[r7]! - .byte 0xc0,0x03,0xb0,0xf3 @ aesimc q0,q0 - .byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1 - .byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10 - subs r6,r6,#2 - .byte 0x62,0x03,0xb0,0xf3 @ aesd q0,q9 - .byte 0x62,0x23,0xb0,0xf3 @ aesd q1,q9 - .byte 0x62,0x43,0xf0,0xf3 @ aesd q10,q9 - vld1.32 {q9},[r7]! - .byte 0xc0,0x03,0xb0,0xf3 @ aesimc q0,q0 - .byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1 - .byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10 - bgt .Loop3x_cbc_dec - - .byte 0x60,0x03,0xb0,0xf3 @ aesd q0,q8 - .byte 0x60,0x23,0xb0,0xf3 @ aesd q1,q8 - .byte 0x60,0x43,0xf0,0xf3 @ aesd q10,q8 - veor q4,q6,q7 - .byte 0xc0,0x03,0xb0,0xf3 @ aesimc q0,q0 - .byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1 - .byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10 - veor q5,q2,q7 - .byte 0x62,0x03,0xb0,0xf3 @ aesd q0,q9 - .byte 0x62,0x23,0xb0,0xf3 @ aesd q1,q9 - .byte 0x62,0x43,0xf0,0xf3 @ aesd q10,q9 - veor q9,q3,q7 - subs r2,r2,#0x30 - .byte 0xc0,0x03,0xb0,0xf3 @ aesimc q0,q0 - .byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1 - .byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10 - vorr q6,q11,q11 - movlo r6,r2 @ r6, r6, is zero at this point - .byte 0x68,0x03,0xb0,0xf3 @ aesd q0,q12 - .byte 0x68,0x23,0xb0,0xf3 @ aesd q1,q12 - .byte 0x68,0x43,0xf0,0xf3 @ aesd q10,q12 - add r0,r0,r6 @ r0 is adjusted in such way that - @ at exit from the loop q1-q10 - @ are loaded with last "words" - .byte 0xc0,0x03,0xb0,0xf3 @ aesimc q0,q0 - .byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1 - .byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10 - mov r7,r3 - .byte 0x6a,0x03,0xb0,0xf3 @ aesd q0,q13 - .byte 0x6a,0x23,0xb0,0xf3 @ aesd q1,q13 - .byte 0x6a,0x43,0xf0,0xf3 @ aesd q10,q13 - vld1.8 {q2},[r0]! - .byte 0xc0,0x03,0xb0,0xf3 @ aesimc q0,q0 - .byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1 - .byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10 - vld1.8 {q3},[r0]! - .byte 0x6c,0x03,0xb0,0xf3 @ aesd q0,q14 - .byte 0x6c,0x23,0xb0,0xf3 @ aesd q1,q14 - .byte 0x6c,0x43,0xf0,0xf3 @ aesd q10,q14 - vld1.8 {q11},[r0]! - .byte 0xc0,0x03,0xb0,0xf3 @ aesimc q0,q0 - .byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1 - .byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10 - vld1.32 {q8},[r7]! @ re-pre-load rndkey[0] - .byte 0x6e,0x03,0xb0,0xf3 @ aesd q0,q15 - .byte 0x6e,0x23,0xb0,0xf3 @ aesd q1,q15 - .byte 0x6e,0x43,0xf0,0xf3 @ aesd q10,q15 - - add r6,r5,#2 - veor q4,q4,q0 - veor q5,q5,q1 - veor q10,q10,q9 - vld1.32 {q9},[r7]! @ re-pre-load rndkey[1] - vorr q0,q2,q2 - vst1.8 {q4},[r1]! - vorr q1,q3,q3 - vst1.8 {q5},[r1]! - vst1.8 {q10},[r1]! - vorr q10,q11,q11 - bhs .Loop3x_cbc_dec - - cmn r2,#0x30 - beq .Lcbc_done - nop - -.Lcbc_dec_tail: - .byte 0x60,0x23,0xb0,0xf3 @ aesd q1,q8 - .byte 0x60,0x43,0xf0,0xf3 @ aesd q10,q8 - vld1.32 {q8},[r7]! - .byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1 - .byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10 - subs r6,r6,#2 - .byte 0x62,0x23,0xb0,0xf3 @ aesd q1,q9 - .byte 0x62,0x43,0xf0,0xf3 @ aesd q10,q9 - vld1.32 {q9},[r7]! - .byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1 - .byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10 - bgt .Lcbc_dec_tail - - .byte 0x60,0x23,0xb0,0xf3 @ aesd q1,q8 - .byte 0x60,0x43,0xf0,0xf3 @ aesd q10,q8 - .byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1 - .byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10 - .byte 0x62,0x23,0xb0,0xf3 @ aesd q1,q9 - .byte 0x62,0x43,0xf0,0xf3 @ aesd q10,q9 - .byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1 - .byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10 - .byte 0x68,0x23,0xb0,0xf3 @ aesd q1,q12 - .byte 0x68,0x43,0xf0,0xf3 @ aesd q10,q12 - .byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1 - .byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10 - cmn r2,#0x20 - .byte 0x6a,0x23,0xb0,0xf3 @ aesd q1,q13 - .byte 0x6a,0x43,0xf0,0xf3 @ aesd q10,q13 - .byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1 - .byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10 - veor q5,q6,q7 - .byte 0x6c,0x23,0xb0,0xf3 @ aesd q1,q14 - .byte 0x6c,0x43,0xf0,0xf3 @ aesd q10,q14 - .byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1 - .byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10 - veor q9,q3,q7 - .byte 0x6e,0x23,0xb0,0xf3 @ aesd q1,q15 - .byte 0x6e,0x43,0xf0,0xf3 @ aesd q10,q15 - beq .Lcbc_dec_one - veor q5,q5,q1 - veor q9,q9,q10 - vorr q6,q11,q11 - vst1.8 {q5},[r1]! - vst1.8 {q9},[r1]! - b .Lcbc_done - -.Lcbc_dec_one: - veor q5,q5,q10 - vorr q6,q11,q11 - vst1.8 {q5},[r1]! - -.Lcbc_done: - vst1.8 {q6},[r4] -.Lcbc_abort: - vldmia sp!,{d8-d15} - ldmia sp!,{r4-r8,pc} -.size aes_v8_cbc_encrypt,.-aes_v8_cbc_encrypt -.globl aes_v8_ctr32_encrypt_blocks -.type aes_v8_ctr32_encrypt_blocks,%function -.align 5 -aes_v8_ctr32_encrypt_blocks: - mov ip,sp - stmdb sp!,{r4-r10,lr} - vstmdb sp!,{d8-d15} @ ABI specification says so - ldr r4, [ip] @ load remaining arg - ldr r5,[r3,#240] - - ldr r8, [r4, #12] - vld1.32 {q0},[r4] - - vld1.32 {q8-q9},[r3] @ load key schedule... - sub r5,r5,#4 - mov r12,#16 - cmp r2,#2 - add r7,r3,r5,lsl#4 @ pointer to last 5 round keys - sub r5,r5,#2 - vld1.32 {q12-q13},[r7]! - vld1.32 {q14-q15},[r7]! - vld1.32 {q7},[r7] - add r7,r3,#32 - mov r6,r5 - movlo r12,#0 -#ifndef __ARMEB__ - rev r8, r8 -#endif - vorr q1,q0,q0 - add r10, r8, #1 - vorr q10,q0,q0 - add r8, r8, #2 - vorr q6,q0,q0 - rev r10, r10 - vmov.32 d3[1],r10 - bls .Lctr32_tail - rev r12, r8 - sub r2,r2,#3 @ bias - vmov.32 d21[1],r12 - b .Loop3x_ctr32 - -.align 4 -.Loop3x_ctr32: - .byte 0x20,0x03,0xb0,0xf3 @ aese q0,q8 - .byte 0x20,0x23,0xb0,0xf3 @ aese q1,q8 - .byte 0x20,0x43,0xf0,0xf3 @ aese q10,q8 - vld1.32 {q8},[r7]! - .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 - .byte 0x82,0x23,0xb0,0xf3 @ aesmc q1,q1 - .byte 0xa4,0x43,0xf0,0xf3 @ aesmc q10,q10 - subs r6,r6,#2 - .byte 0x22,0x03,0xb0,0xf3 @ aese q0,q9 - .byte 0x22,0x23,0xb0,0xf3 @ aese q1,q9 - .byte 0x22,0x43,0xf0,0xf3 @ aese q10,q9 - vld1.32 {q9},[r7]! - .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 - .byte 0x82,0x23,0xb0,0xf3 @ aesmc q1,q1 - .byte 0xa4,0x43,0xf0,0xf3 @ aesmc q10,q10 - bgt .Loop3x_ctr32 - - .byte 0x20,0x03,0xb0,0xf3 @ aese q0,q8 - .byte 0x20,0x23,0xb0,0xf3 @ aese q1,q8 - .byte 0x20,0x43,0xf0,0xf3 @ aese q10,q8 - mov r7,r3 - .byte 0x80,0x83,0xb0,0xf3 @ aesmc q4,q0 - vld1.8 {q2},[r0]! - .byte 0x82,0xa3,0xb0,0xf3 @ aesmc q5,q1 - .byte 0xa4,0x43,0xf0,0xf3 @ aesmc q10,q10 - vorr q0,q6,q6 - .byte 0x22,0x83,0xb0,0xf3 @ aese q4,q9 - vld1.8 {q3},[r0]! - .byte 0x22,0xa3,0xb0,0xf3 @ aese q5,q9 - .byte 0x22,0x43,0xf0,0xf3 @ aese q10,q9 - vorr q1,q6,q6 - .byte 0x88,0x83,0xb0,0xf3 @ aesmc q4,q4 - vld1.8 {q11},[r0]! - .byte 0x8a,0xa3,0xb0,0xf3 @ aesmc q5,q5 - .byte 0xa4,0x23,0xf0,0xf3 @ aesmc q9,q10 - vorr q10,q6,q6 - add r9,r8,#1 - .byte 0x28,0x83,0xb0,0xf3 @ aese q4,q12 - .byte 0x28,0xa3,0xb0,0xf3 @ aese q5,q12 - .byte 0x28,0x23,0xf0,0xf3 @ aese q9,q12 - veor q2,q2,q7 - add r10,r8,#2 - .byte 0x88,0x83,0xb0,0xf3 @ aesmc q4,q4 - .byte 0x8a,0xa3,0xb0,0xf3 @ aesmc q5,q5 - .byte 0xa2,0x23,0xf0,0xf3 @ aesmc q9,q9 - veor q3,q3,q7 - add r8,r8,#3 - .byte 0x2a,0x83,0xb0,0xf3 @ aese q4,q13 - .byte 0x2a,0xa3,0xb0,0xf3 @ aese q5,q13 - .byte 0x2a,0x23,0xf0,0xf3 @ aese q9,q13 - veor q11,q11,q7 - rev r9,r9 - .byte 0x88,0x83,0xb0,0xf3 @ aesmc q4,q4 - vld1.32 {q8},[r7]! @ re-pre-load rndkey[0] - .byte 0x8a,0xa3,0xb0,0xf3 @ aesmc q5,q5 - .byte 0xa2,0x23,0xf0,0xf3 @ aesmc q9,q9 - vmov.32 d1[1], r9 - rev r10,r10 - .byte 0x2c,0x83,0xb0,0xf3 @ aese q4,q14 - .byte 0x2c,0xa3,0xb0,0xf3 @ aese q5,q14 - .byte 0x2c,0x23,0xf0,0xf3 @ aese q9,q14 - vmov.32 d3[1], r10 - rev r12,r8 - .byte 0x88,0x83,0xb0,0xf3 @ aesmc q4,q4 - .byte 0x8a,0xa3,0xb0,0xf3 @ aesmc q5,q5 - .byte 0xa2,0x23,0xf0,0xf3 @ aesmc q9,q9 - vmov.32 d21[1], r12 - subs r2,r2,#3 - .byte 0x2e,0x83,0xb0,0xf3 @ aese q4,q15 - .byte 0x2e,0xa3,0xb0,0xf3 @ aese q5,q15 - .byte 0x2e,0x23,0xf0,0xf3 @ aese q9,q15 - - mov r6,r5 - veor q2,q2,q4 - veor q3,q3,q5 - veor q11,q11,q9 - vld1.32 {q9},[r7]! @ re-pre-load rndkey[1] - vst1.8 {q2},[r1]! - vst1.8 {q3},[r1]! - vst1.8 {q11},[r1]! - bhs .Loop3x_ctr32 - - adds r2,r2,#3 - beq .Lctr32_done - cmp r2,#1 - mov r12,#16 - moveq r12,#0 - -.Lctr32_tail: - .byte 0x20,0x03,0xb0,0xf3 @ aese q0,q8 - .byte 0x20,0x23,0xb0,0xf3 @ aese q1,q8 - vld1.32 {q8},[r7]! - .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 - .byte 0x82,0x23,0xb0,0xf3 @ aesmc q1,q1 - subs r6,r6,#2 - .byte 0x22,0x03,0xb0,0xf3 @ aese q0,q9 - .byte 0x22,0x23,0xb0,0xf3 @ aese q1,q9 - vld1.32 {q9},[r7]! - .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 - .byte 0x82,0x23,0xb0,0xf3 @ aesmc q1,q1 - bgt .Lctr32_tail - - .byte 0x20,0x03,0xb0,0xf3 @ aese q0,q8 - .byte 0x20,0x23,0xb0,0xf3 @ aese q1,q8 - .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 - .byte 0x82,0x23,0xb0,0xf3 @ aesmc q1,q1 - .byte 0x22,0x03,0xb0,0xf3 @ aese q0,q9 - .byte 0x22,0x23,0xb0,0xf3 @ aese q1,q9 - .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 - .byte 0x82,0x23,0xb0,0xf3 @ aesmc q1,q1 - vld1.8 {q2},[r0],r12 - .byte 0x28,0x03,0xb0,0xf3 @ aese q0,q12 - .byte 0x28,0x23,0xb0,0xf3 @ aese q1,q12 - vld1.8 {q3},[r0] - .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 - .byte 0x82,0x23,0xb0,0xf3 @ aesmc q1,q1 - .byte 0x2a,0x03,0xb0,0xf3 @ aese q0,q13 - .byte 0x2a,0x23,0xb0,0xf3 @ aese q1,q13 - .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 - .byte 0x82,0x23,0xb0,0xf3 @ aesmc q1,q1 - .byte 0x2c,0x03,0xb0,0xf3 @ aese q0,q14 - .byte 0x2c,0x23,0xb0,0xf3 @ aese q1,q14 - veor q2,q2,q7 - .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 - .byte 0x82,0x23,0xb0,0xf3 @ aesmc q1,q1 - veor q3,q3,q7 - .byte 0x2e,0x03,0xb0,0xf3 @ aese q0,q15 - .byte 0x2e,0x23,0xb0,0xf3 @ aese q1,q15 - - cmp r2,#1 - veor q2,q2,q0 - veor q3,q3,q1 - vst1.8 {q2},[r1]! - beq .Lctr32_done - vst1.8 {q3},[r1] - -.Lctr32_done: - vldmia sp!,{d8-d15} - ldmia sp!,{r4-r10,pc} -.size aes_v8_ctr32_encrypt_blocks,.-aes_v8_ctr32_encrypt_blocks -#endif diff --git a/third_party/boringssl/linux-arm/crypto/aes/aesv8-armx32.S b/third_party/boringssl/linux-arm/crypto/aes/aesv8-armx32.S new file mode 100644 index 0000000000000..6f0ee7d81da9e --- /dev/null +++ b/third_party/boringssl/linux-arm/crypto/aes/aesv8-armx32.S @@ -0,0 +1,756 @@ +#if defined(__arm__) +#include "arm_arch.h" + +#if __ARM_MAX_ARCH__>=7 +.text +.arch armv7-a +.fpu neon +.code 32 +.align 5 +.Lrcon: +.long 0x01,0x01,0x01,0x01 +.long 0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d @ rotate-n-splat +.long 0x1b,0x1b,0x1b,0x1b + +.globl aes_v8_set_encrypt_key +.type aes_v8_set_encrypt_key,%function +.align 5 +aes_v8_set_encrypt_key: +.Lenc_key: + mov r3,#-1 + cmp r0,#0 + beq .Lenc_key_abort + cmp r2,#0 + beq .Lenc_key_abort + mov r3,#-2 + cmp r1,#128 + blt .Lenc_key_abort + cmp r1,#256 + bgt .Lenc_key_abort + tst r1,#0x3f + bne .Lenc_key_abort + + adr r3,.Lrcon + cmp r1,#192 + + veor q0,q0,q0 + vld1.8 {q3},[r0]! + mov r1,#8 @ reuse r1 + vld1.32 {q1,q2},[r3]! + + blt .Loop128 + beq .L192 + b .L256 + +.align 4 +.Loop128: + vtbl.8 d20,{q3},d4 + vtbl.8 d21,{q3},d5 + vext.8 q9,q0,q3,#12 + vst1.32 {q3},[r2]! +.byte 0x00,0x43,0xf0,0xf3 @ aese q10,q0 + subs r1,r1,#1 + + veor q3,q3,q9 + vext.8 q9,q0,q9,#12 + veor q3,q3,q9 + vext.8 q9,q0,q9,#12 + veor q10,q10,q1 + veor q3,q3,q9 + vshl.u8 q1,q1,#1 + veor q3,q3,q10 + bne .Loop128 + + vld1.32 {q1},[r3] + + vtbl.8 d20,{q3},d4 + vtbl.8 d21,{q3},d5 + vext.8 q9,q0,q3,#12 + vst1.32 {q3},[r2]! +.byte 0x00,0x43,0xf0,0xf3 @ aese q10,q0 + + veor q3,q3,q9 + vext.8 q9,q0,q9,#12 + veor q3,q3,q9 + vext.8 q9,q0,q9,#12 + veor q10,q10,q1 + veor q3,q3,q9 + vshl.u8 q1,q1,#1 + veor q3,q3,q10 + + vtbl.8 d20,{q3},d4 + vtbl.8 d21,{q3},d5 + vext.8 q9,q0,q3,#12 + vst1.32 {q3},[r2]! +.byte 0x00,0x43,0xf0,0xf3 @ aese q10,q0 + + veor q3,q3,q9 + vext.8 q9,q0,q9,#12 + veor q3,q3,q9 + vext.8 q9,q0,q9,#12 + veor q10,q10,q1 + veor q3,q3,q9 + veor q3,q3,q10 + vst1.32 {q3},[r2] + add r2,r2,#0x50 + + mov r12,#10 + b .Ldone + +.align 4 +.L192: + vld1.8 {d16},[r0]! + vmov.i8 q10,#8 @ borrow q10 + vst1.32 {q3},[r2]! + vsub.i8 q2,q2,q10 @ adjust the mask + +.Loop192: + vtbl.8 d20,{q8},d4 + vtbl.8 d21,{q8},d5 + vext.8 q9,q0,q3,#12 + vst1.32 {d16},[r2]! +.byte 0x00,0x43,0xf0,0xf3 @ aese q10,q0 + subs r1,r1,#1 + + veor q3,q3,q9 + vext.8 q9,q0,q9,#12 + veor q3,q3,q9 + vext.8 q9,q0,q9,#12 + veor q3,q3,q9 + + vdup.32 q9,d7[1] + veor q9,q9,q8 + veor q10,q10,q1 + vext.8 q8,q0,q8,#12 + vshl.u8 q1,q1,#1 + veor q8,q8,q9 + veor q3,q3,q10 + veor q8,q8,q10 + vst1.32 {q3},[r2]! + bne .Loop192 + + mov r12,#12 + add r2,r2,#0x20 + b .Ldone + +.align 4 +.L256: + vld1.8 {q8},[r0] + mov r1,#7 + mov r12,#14 + vst1.32 {q3},[r2]! + +.Loop256: + vtbl.8 d20,{q8},d4 + vtbl.8 d21,{q8},d5 + vext.8 q9,q0,q3,#12 + vst1.32 {q8},[r2]! +.byte 0x00,0x43,0xf0,0xf3 @ aese q10,q0 + subs r1,r1,#1 + + veor q3,q3,q9 + vext.8 q9,q0,q9,#12 + veor q3,q3,q9 + vext.8 q9,q0,q9,#12 + veor q10,q10,q1 + veor q3,q3,q9 + vshl.u8 q1,q1,#1 + veor q3,q3,q10 + vst1.32 {q3},[r2]! + beq .Ldone + + vdup.32 q10,d7[1] + vext.8 q9,q0,q8,#12 +.byte 0x00,0x43,0xf0,0xf3 @ aese q10,q0 + + veor q8,q8,q9 + vext.8 q9,q0,q9,#12 + veor q8,q8,q9 + vext.8 q9,q0,q9,#12 + veor q8,q8,q9 + + veor q8,q8,q10 + b .Loop256 + +.Ldone: + str r12,[r2] + mov r3,#0 + +.Lenc_key_abort: + mov r0,r3 @ return value + + bx lr +.size aes_v8_set_encrypt_key,.-aes_v8_set_encrypt_key + +.globl aes_v8_set_decrypt_key +.type aes_v8_set_decrypt_key,%function +.align 5 +aes_v8_set_decrypt_key: + stmdb sp!,{r4,lr} + bl .Lenc_key + + cmp r0,#0 + bne .Ldec_key_abort + + sub r2,r2,#240 @ restore original r2 + mov r4,#-16 + add r0,r2,r12,lsl#4 @ end of key schedule + + vld1.32 {q0},[r2] + vld1.32 {q1},[r0] + vst1.32 {q0},[r0],r4 + vst1.32 {q1},[r2]! + +.Loop_imc: + vld1.32 {q0},[r2] + vld1.32 {q1},[r0] +.byte 0xc0,0x03,0xb0,0xf3 @ aesimc q0,q0 +.byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1 + vst1.32 {q0},[r0],r4 + vst1.32 {q1},[r2]! + cmp r0,r2 + bhi .Loop_imc + + vld1.32 {q0},[r2] +.byte 0xc0,0x03,0xb0,0xf3 @ aesimc q0,q0 + vst1.32 {q0},[r0] + + eor r0,r0,r0 @ return value +.Ldec_key_abort: + ldmia sp!,{r4,pc} +.size aes_v8_set_decrypt_key,.-aes_v8_set_decrypt_key +.globl aes_v8_encrypt +.type aes_v8_encrypt,%function +.align 5 +aes_v8_encrypt: + ldr r3,[r2,#240] + vld1.32 {q0},[r2]! + vld1.8 {q2},[r0] + sub r3,r3,#2 + vld1.32 {q1},[r2]! + +.Loop_enc: +.byte 0x00,0x43,0xb0,0xf3 @ aese q2,q0 +.byte 0x84,0x43,0xb0,0xf3 @ aesmc q2,q2 + vld1.32 {q0},[r2]! + subs r3,r3,#2 +.byte 0x02,0x43,0xb0,0xf3 @ aese q2,q1 +.byte 0x84,0x43,0xb0,0xf3 @ aesmc q2,q2 + vld1.32 {q1},[r2]! + bgt .Loop_enc + +.byte 0x00,0x43,0xb0,0xf3 @ aese q2,q0 +.byte 0x84,0x43,0xb0,0xf3 @ aesmc q2,q2 + vld1.32 {q0},[r2] +.byte 0x02,0x43,0xb0,0xf3 @ aese q2,q1 + veor q2,q2,q0 + + vst1.8 {q2},[r1] + bx lr +.size aes_v8_encrypt,.-aes_v8_encrypt +.globl aes_v8_decrypt +.type aes_v8_decrypt,%function +.align 5 +aes_v8_decrypt: + ldr r3,[r2,#240] + vld1.32 {q0},[r2]! + vld1.8 {q2},[r0] + sub r3,r3,#2 + vld1.32 {q1},[r2]! + +.Loop_dec: +.byte 0x40,0x43,0xb0,0xf3 @ aesd q2,q0 +.byte 0xc4,0x43,0xb0,0xf3 @ aesimc q2,q2 + vld1.32 {q0},[r2]! + subs r3,r3,#2 +.byte 0x42,0x43,0xb0,0xf3 @ aesd q2,q1 +.byte 0xc4,0x43,0xb0,0xf3 @ aesimc q2,q2 + vld1.32 {q1},[r2]! + bgt .Loop_dec + +.byte 0x40,0x43,0xb0,0xf3 @ aesd q2,q0 +.byte 0xc4,0x43,0xb0,0xf3 @ aesimc q2,q2 + vld1.32 {q0},[r2] +.byte 0x42,0x43,0xb0,0xf3 @ aesd q2,q1 + veor q2,q2,q0 + + vst1.8 {q2},[r1] + bx lr +.size aes_v8_decrypt,.-aes_v8_decrypt +.globl aes_v8_cbc_encrypt +.type aes_v8_cbc_encrypt,%function +.align 5 +aes_v8_cbc_encrypt: + mov ip,sp + stmdb sp!,{r4,r5,r6,r7,r8,lr} + vstmdb sp!,{d8,d9,d10,d11,d12,d13,d14,d15} @ ABI specification says so + ldmia ip,{r4,r5} @ load remaining args + subs r2,r2,#16 + mov r8,#16 + blo .Lcbc_abort + moveq r8,#0 + + cmp r5,#0 @ en- or decrypting? + ldr r5,[r3,#240] + and r2,r2,#-16 + vld1.8 {q6},[r4] + vld1.8 {q0},[r0],r8 + + vld1.32 {q8,q9},[r3] @ load key schedule... + sub r5,r5,#6 + add r7,r3,r5,lsl#4 @ pointer to last 7 round keys + sub r5,r5,#2 + vld1.32 {q10,q11},[r7]! + vld1.32 {q12,q13},[r7]! + vld1.32 {q14,q15},[r7]! + vld1.32 {q7},[r7] + + add r7,r3,#32 + mov r6,r5 + beq .Lcbc_dec + + cmp r5,#2 + veor q0,q0,q6 + veor q5,q8,q7 + beq .Lcbc_enc128 + + vld1.32 {q2,q3},[r7] + add r7,r3,#16 + add r6,r3,#16*4 + add r12,r3,#16*5 +.byte 0x20,0x03,0xb0,0xf3 @ aese q0,q8 +.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 + add r14,r3,#16*6 + add r3,r3,#16*7 + b .Lenter_cbc_enc + +.align 4 +.Loop_cbc_enc: +.byte 0x20,0x03,0xb0,0xf3 @ aese q0,q8 +.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 + vst1.8 {q6},[r1]! +.Lenter_cbc_enc: +.byte 0x22,0x03,0xb0,0xf3 @ aese q0,q9 +.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 +.byte 0x04,0x03,0xb0,0xf3 @ aese q0,q2 +.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 + vld1.32 {q8},[r6] + cmp r5,#4 +.byte 0x06,0x03,0xb0,0xf3 @ aese q0,q3 +.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 + vld1.32 {q9},[r12] + beq .Lcbc_enc192 + +.byte 0x20,0x03,0xb0,0xf3 @ aese q0,q8 +.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 + vld1.32 {q8},[r14] +.byte 0x22,0x03,0xb0,0xf3 @ aese q0,q9 +.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 + vld1.32 {q9},[r3] + nop + +.Lcbc_enc192: +.byte 0x20,0x03,0xb0,0xf3 @ aese q0,q8 +.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 + subs r2,r2,#16 +.byte 0x22,0x03,0xb0,0xf3 @ aese q0,q9 +.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 + moveq r8,#0 +.byte 0x24,0x03,0xb0,0xf3 @ aese q0,q10 +.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 +.byte 0x26,0x03,0xb0,0xf3 @ aese q0,q11 +.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 + vld1.8 {q8},[r0],r8 +.byte 0x28,0x03,0xb0,0xf3 @ aese q0,q12 +.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 + veor q8,q8,q5 +.byte 0x2a,0x03,0xb0,0xf3 @ aese q0,q13 +.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 + vld1.32 {q9},[r7] @ re-pre-load rndkey[1] +.byte 0x2c,0x03,0xb0,0xf3 @ aese q0,q14 +.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 +.byte 0x2e,0x03,0xb0,0xf3 @ aese q0,q15 + veor q6,q0,q7 + bhs .Loop_cbc_enc + + vst1.8 {q6},[r1]! + b .Lcbc_done + +.align 5 +.Lcbc_enc128: + vld1.32 {q2,q3},[r7] +.byte 0x20,0x03,0xb0,0xf3 @ aese q0,q8 +.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 + b .Lenter_cbc_enc128 +.Loop_cbc_enc128: +.byte 0x20,0x03,0xb0,0xf3 @ aese q0,q8 +.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 + vst1.8 {q6},[r1]! +.Lenter_cbc_enc128: +.byte 0x22,0x03,0xb0,0xf3 @ aese q0,q9 +.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 + subs r2,r2,#16 +.byte 0x04,0x03,0xb0,0xf3 @ aese q0,q2 +.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 + moveq r8,#0 +.byte 0x06,0x03,0xb0,0xf3 @ aese q0,q3 +.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 +.byte 0x24,0x03,0xb0,0xf3 @ aese q0,q10 +.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 +.byte 0x26,0x03,0xb0,0xf3 @ aese q0,q11 +.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 + vld1.8 {q8},[r0],r8 +.byte 0x28,0x03,0xb0,0xf3 @ aese q0,q12 +.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 +.byte 0x2a,0x03,0xb0,0xf3 @ aese q0,q13 +.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 +.byte 0x2c,0x03,0xb0,0xf3 @ aese q0,q14 +.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 + veor q8,q8,q5 +.byte 0x2e,0x03,0xb0,0xf3 @ aese q0,q15 + veor q6,q0,q7 + bhs .Loop_cbc_enc128 + + vst1.8 {q6},[r1]! + b .Lcbc_done +.align 5 +.Lcbc_dec: + vld1.8 {q10},[r0]! + subs r2,r2,#32 @ bias + add r6,r5,#2 + vorr q3,q0,q0 + vorr q1,q0,q0 + vorr q11,q10,q10 + blo .Lcbc_dec_tail + + vorr q1,q10,q10 + vld1.8 {q10},[r0]! + vorr q2,q0,q0 + vorr q3,q1,q1 + vorr q11,q10,q10 + +.Loop3x_cbc_dec: +.byte 0x60,0x03,0xb0,0xf3 @ aesd q0,q8 +.byte 0xc0,0x03,0xb0,0xf3 @ aesimc q0,q0 +.byte 0x60,0x23,0xb0,0xf3 @ aesd q1,q8 +.byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1 +.byte 0x60,0x43,0xf0,0xf3 @ aesd q10,q8 +.byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10 + vld1.32 {q8},[r7]! + subs r6,r6,#2 +.byte 0x62,0x03,0xb0,0xf3 @ aesd q0,q9 +.byte 0xc0,0x03,0xb0,0xf3 @ aesimc q0,q0 +.byte 0x62,0x23,0xb0,0xf3 @ aesd q1,q9 +.byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1 +.byte 0x62,0x43,0xf0,0xf3 @ aesd q10,q9 +.byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10 + vld1.32 {q9},[r7]! + bgt .Loop3x_cbc_dec + +.byte 0x60,0x03,0xb0,0xf3 @ aesd q0,q8 +.byte 0xc0,0x03,0xb0,0xf3 @ aesimc q0,q0 +.byte 0x60,0x23,0xb0,0xf3 @ aesd q1,q8 +.byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1 +.byte 0x60,0x43,0xf0,0xf3 @ aesd q10,q8 +.byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10 + veor q4,q6,q7 + subs r2,r2,#0x30 + veor q5,q2,q7 + movlo r6,r2 @ r6, r6, is zero at this point +.byte 0x62,0x03,0xb0,0xf3 @ aesd q0,q9 +.byte 0xc0,0x03,0xb0,0xf3 @ aesimc q0,q0 +.byte 0x62,0x23,0xb0,0xf3 @ aesd q1,q9 +.byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1 +.byte 0x62,0x43,0xf0,0xf3 @ aesd q10,q9 +.byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10 + veor q9,q3,q7 + add r0,r0,r6 @ r0 is adjusted in such way that + @ at exit from the loop q1-q10 + @ are loaded with last "words" + vorr q6,q11,q11 + mov r7,r3 +.byte 0x68,0x03,0xb0,0xf3 @ aesd q0,q12 +.byte 0xc0,0x03,0xb0,0xf3 @ aesimc q0,q0 +.byte 0x68,0x23,0xb0,0xf3 @ aesd q1,q12 +.byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1 +.byte 0x68,0x43,0xf0,0xf3 @ aesd q10,q12 +.byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10 + vld1.8 {q2},[r0]! +.byte 0x6a,0x03,0xb0,0xf3 @ aesd q0,q13 +.byte 0xc0,0x03,0xb0,0xf3 @ aesimc q0,q0 +.byte 0x6a,0x23,0xb0,0xf3 @ aesd q1,q13 +.byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1 +.byte 0x6a,0x43,0xf0,0xf3 @ aesd q10,q13 +.byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10 + vld1.8 {q3},[r0]! +.byte 0x6c,0x03,0xb0,0xf3 @ aesd q0,q14 +.byte 0xc0,0x03,0xb0,0xf3 @ aesimc q0,q0 +.byte 0x6c,0x23,0xb0,0xf3 @ aesd q1,q14 +.byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1 +.byte 0x6c,0x43,0xf0,0xf3 @ aesd q10,q14 +.byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10 + vld1.8 {q11},[r0]! +.byte 0x6e,0x03,0xb0,0xf3 @ aesd q0,q15 +.byte 0x6e,0x23,0xb0,0xf3 @ aesd q1,q15 +.byte 0x6e,0x43,0xf0,0xf3 @ aesd q10,q15 + vld1.32 {q8},[r7]! @ re-pre-load rndkey[0] + add r6,r5,#2 + veor q4,q4,q0 + veor q5,q5,q1 + veor q10,q10,q9 + vld1.32 {q9},[r7]! @ re-pre-load rndkey[1] + vst1.8 {q4},[r1]! + vorr q0,q2,q2 + vst1.8 {q5},[r1]! + vorr q1,q3,q3 + vst1.8 {q10},[r1]! + vorr q10,q11,q11 + bhs .Loop3x_cbc_dec + + cmn r2,#0x30 + beq .Lcbc_done + nop + +.Lcbc_dec_tail: +.byte 0x60,0x23,0xb0,0xf3 @ aesd q1,q8 +.byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1 +.byte 0x60,0x43,0xf0,0xf3 @ aesd q10,q8 +.byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10 + vld1.32 {q8},[r7]! + subs r6,r6,#2 +.byte 0x62,0x23,0xb0,0xf3 @ aesd q1,q9 +.byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1 +.byte 0x62,0x43,0xf0,0xf3 @ aesd q10,q9 +.byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10 + vld1.32 {q9},[r7]! + bgt .Lcbc_dec_tail + +.byte 0x60,0x23,0xb0,0xf3 @ aesd q1,q8 +.byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1 +.byte 0x60,0x43,0xf0,0xf3 @ aesd q10,q8 +.byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10 +.byte 0x62,0x23,0xb0,0xf3 @ aesd q1,q9 +.byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1 +.byte 0x62,0x43,0xf0,0xf3 @ aesd q10,q9 +.byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10 +.byte 0x68,0x23,0xb0,0xf3 @ aesd q1,q12 +.byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1 +.byte 0x68,0x43,0xf0,0xf3 @ aesd q10,q12 +.byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10 + cmn r2,#0x20 +.byte 0x6a,0x23,0xb0,0xf3 @ aesd q1,q13 +.byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1 +.byte 0x6a,0x43,0xf0,0xf3 @ aesd q10,q13 +.byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10 + veor q5,q6,q7 +.byte 0x6c,0x23,0xb0,0xf3 @ aesd q1,q14 +.byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1 +.byte 0x6c,0x43,0xf0,0xf3 @ aesd q10,q14 +.byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10 + veor q9,q3,q7 +.byte 0x6e,0x23,0xb0,0xf3 @ aesd q1,q15 +.byte 0x6e,0x43,0xf0,0xf3 @ aesd q10,q15 + beq .Lcbc_dec_one + veor q5,q5,q1 + veor q9,q9,q10 + vorr q6,q11,q11 + vst1.8 {q5},[r1]! + vst1.8 {q9},[r1]! + b .Lcbc_done + +.Lcbc_dec_one: + veor q5,q5,q10 + vorr q6,q11,q11 + vst1.8 {q5},[r1]! + +.Lcbc_done: + vst1.8 {q6},[r4] +.Lcbc_abort: + vldmia sp!,{d8,d9,d10,d11,d12,d13,d14,d15} + ldmia sp!,{r4,r5,r6,r7,r8,pc} +.size aes_v8_cbc_encrypt,.-aes_v8_cbc_encrypt +.globl aes_v8_ctr32_encrypt_blocks +.type aes_v8_ctr32_encrypt_blocks,%function +.align 5 +aes_v8_ctr32_encrypt_blocks: + mov ip,sp + stmdb sp!,{r4,r5,r6,r7,r8,r9,r10,lr} + vstmdb sp!,{d8,d9,d10,d11,d12,d13,d14,d15} @ ABI specification says so + ldr r4, [ip] @ load remaining arg + ldr r5,[r3,#240] + + ldr r8, [r4, #12] + vld1.32 {q0},[r4] + + vld1.32 {q8,q9},[r3] @ load key schedule... + sub r5,r5,#4 + mov r12,#16 + cmp r2,#2 + add r7,r3,r5,lsl#4 @ pointer to last 5 round keys + sub r5,r5,#2 + vld1.32 {q12,q13},[r7]! + vld1.32 {q14,q15},[r7]! + vld1.32 {q7},[r7] + add r7,r3,#32 + mov r6,r5 + movlo r12,#0 +#ifndef __ARMEB__ + rev r8, r8 +#endif + vorr q1,q0,q0 + add r10, r8, #1 + vorr q10,q0,q0 + add r8, r8, #2 + vorr q6,q0,q0 + rev r10, r10 + vmov.32 d3[1],r10 + bls .Lctr32_tail + rev r12, r8 + sub r2,r2,#3 @ bias + vmov.32 d21[1],r12 + b .Loop3x_ctr32 + +.align 4 +.Loop3x_ctr32: +.byte 0x20,0x03,0xb0,0xf3 @ aese q0,q8 +.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 +.byte 0x20,0x23,0xb0,0xf3 @ aese q1,q8 +.byte 0x82,0x23,0xb0,0xf3 @ aesmc q1,q1 +.byte 0x20,0x43,0xf0,0xf3 @ aese q10,q8 +.byte 0xa4,0x43,0xf0,0xf3 @ aesmc q10,q10 + vld1.32 {q8},[r7]! + subs r6,r6,#2 +.byte 0x22,0x03,0xb0,0xf3 @ aese q0,q9 +.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 +.byte 0x22,0x23,0xb0,0xf3 @ aese q1,q9 +.byte 0x82,0x23,0xb0,0xf3 @ aesmc q1,q1 +.byte 0x22,0x43,0xf0,0xf3 @ aese q10,q9 +.byte 0xa4,0x43,0xf0,0xf3 @ aesmc q10,q10 + vld1.32 {q9},[r7]! + bgt .Loop3x_ctr32 + +.byte 0x20,0x03,0xb0,0xf3 @ aese q0,q8 +.byte 0x80,0x83,0xb0,0xf3 @ aesmc q4,q0 +.byte 0x20,0x23,0xb0,0xf3 @ aese q1,q8 +.byte 0x82,0xa3,0xb0,0xf3 @ aesmc q5,q1 + vld1.8 {q2},[r0]! + vorr q0,q6,q6 +.byte 0x20,0x43,0xf0,0xf3 @ aese q10,q8 +.byte 0xa4,0x43,0xf0,0xf3 @ aesmc q10,q10 + vld1.8 {q3},[r0]! + vorr q1,q6,q6 +.byte 0x22,0x83,0xb0,0xf3 @ aese q4,q9 +.byte 0x88,0x83,0xb0,0xf3 @ aesmc q4,q4 +.byte 0x22,0xa3,0xb0,0xf3 @ aese q5,q9 +.byte 0x8a,0xa3,0xb0,0xf3 @ aesmc q5,q5 + vld1.8 {q11},[r0]! + mov r7,r3 +.byte 0x22,0x43,0xf0,0xf3 @ aese q10,q9 +.byte 0xa4,0x23,0xf0,0xf3 @ aesmc q9,q10 + vorr q10,q6,q6 + add r9,r8,#1 +.byte 0x28,0x83,0xb0,0xf3 @ aese q4,q12 +.byte 0x88,0x83,0xb0,0xf3 @ aesmc q4,q4 +.byte 0x28,0xa3,0xb0,0xf3 @ aese q5,q12 +.byte 0x8a,0xa3,0xb0,0xf3 @ aesmc q5,q5 + veor q2,q2,q7 + add r10,r8,#2 +.byte 0x28,0x23,0xf0,0xf3 @ aese q9,q12 +.byte 0xa2,0x23,0xf0,0xf3 @ aesmc q9,q9 + veor q3,q3,q7 + add r8,r8,#3 +.byte 0x2a,0x83,0xb0,0xf3 @ aese q4,q13 +.byte 0x88,0x83,0xb0,0xf3 @ aesmc q4,q4 +.byte 0x2a,0xa3,0xb0,0xf3 @ aese q5,q13 +.byte 0x8a,0xa3,0xb0,0xf3 @ aesmc q5,q5 + veor q11,q11,q7 + rev r9,r9 +.byte 0x2a,0x23,0xf0,0xf3 @ aese q9,q13 +.byte 0xa2,0x23,0xf0,0xf3 @ aesmc q9,q9 + vmov.32 d1[1], r9 + rev r10,r10 +.byte 0x2c,0x83,0xb0,0xf3 @ aese q4,q14 +.byte 0x88,0x83,0xb0,0xf3 @ aesmc q4,q4 +.byte 0x2c,0xa3,0xb0,0xf3 @ aese q5,q14 +.byte 0x8a,0xa3,0xb0,0xf3 @ aesmc q5,q5 + vmov.32 d3[1], r10 + rev r12,r8 +.byte 0x2c,0x23,0xf0,0xf3 @ aese q9,q14 +.byte 0xa2,0x23,0xf0,0xf3 @ aesmc q9,q9 + vmov.32 d21[1], r12 + subs r2,r2,#3 +.byte 0x2e,0x83,0xb0,0xf3 @ aese q4,q15 +.byte 0x2e,0xa3,0xb0,0xf3 @ aese q5,q15 +.byte 0x2e,0x23,0xf0,0xf3 @ aese q9,q15 + + veor q2,q2,q4 + vld1.32 {q8},[r7]! @ re-pre-load rndkey[0] + vst1.8 {q2},[r1]! + veor q3,q3,q5 + mov r6,r5 + vst1.8 {q3},[r1]! + veor q11,q11,q9 + vld1.32 {q9},[r7]! @ re-pre-load rndkey[1] + vst1.8 {q11},[r1]! + bhs .Loop3x_ctr32 + + adds r2,r2,#3 + beq .Lctr32_done + cmp r2,#1 + mov r12,#16 + moveq r12,#0 + +.Lctr32_tail: +.byte 0x20,0x03,0xb0,0xf3 @ aese q0,q8 +.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 +.byte 0x20,0x23,0xb0,0xf3 @ aese q1,q8 +.byte 0x82,0x23,0xb0,0xf3 @ aesmc q1,q1 + vld1.32 {q8},[r7]! + subs r6,r6,#2 +.byte 0x22,0x03,0xb0,0xf3 @ aese q0,q9 +.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 +.byte 0x22,0x23,0xb0,0xf3 @ aese q1,q9 +.byte 0x82,0x23,0xb0,0xf3 @ aesmc q1,q1 + vld1.32 {q9},[r7]! + bgt .Lctr32_tail + +.byte 0x20,0x03,0xb0,0xf3 @ aese q0,q8 +.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 +.byte 0x20,0x23,0xb0,0xf3 @ aese q1,q8 +.byte 0x82,0x23,0xb0,0xf3 @ aesmc q1,q1 +.byte 0x22,0x03,0xb0,0xf3 @ aese q0,q9 +.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 +.byte 0x22,0x23,0xb0,0xf3 @ aese q1,q9 +.byte 0x82,0x23,0xb0,0xf3 @ aesmc q1,q1 + vld1.8 {q2},[r0],r12 +.byte 0x28,0x03,0xb0,0xf3 @ aese q0,q12 +.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 +.byte 0x28,0x23,0xb0,0xf3 @ aese q1,q12 +.byte 0x82,0x23,0xb0,0xf3 @ aesmc q1,q1 + vld1.8 {q3},[r0] +.byte 0x2a,0x03,0xb0,0xf3 @ aese q0,q13 +.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 +.byte 0x2a,0x23,0xb0,0xf3 @ aese q1,q13 +.byte 0x82,0x23,0xb0,0xf3 @ aesmc q1,q1 + veor q2,q2,q7 +.byte 0x2c,0x03,0xb0,0xf3 @ aese q0,q14 +.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0 +.byte 0x2c,0x23,0xb0,0xf3 @ aese q1,q14 +.byte 0x82,0x23,0xb0,0xf3 @ aesmc q1,q1 + veor q3,q3,q7 +.byte 0x2e,0x03,0xb0,0xf3 @ aese q0,q15 +.byte 0x2e,0x23,0xb0,0xf3 @ aese q1,q15 + + cmp r2,#1 + veor q2,q2,q0 + veor q3,q3,q1 + vst1.8 {q2},[r1]! + beq .Lctr32_done + vst1.8 {q3},[r1] + +.Lctr32_done: + vldmia sp!,{d8,d9,d10,d11,d12,d13,d14,d15} + ldmia sp!,{r4,r5,r6,r7,r8,r9,r10,pc} +.size aes_v8_ctr32_encrypt_blocks,.-aes_v8_ctr32_encrypt_blocks +#endif +#endif \ No newline at end of file diff --git a/third_party/boringssl/linux-arm/crypto/aes/bsaes-armv7.S b/third_party/boringssl/linux-arm/crypto/aes/bsaes-armv7.S index cbc32fb57f6ae..dd84f3589ddda 100644 --- a/third_party/boringssl/linux-arm/crypto/aes/bsaes-armv7.S +++ b/third_party/boringssl/linux-arm/crypto/aes/bsaes-armv7.S @@ -1,3 +1,4 @@ +#if defined(__arm__) @ ==================================================================== @ Written by Andy Polyakov for the OpenSSL @@ -60,135 +61,141 @@ # define BSAES_ASM_EXTENDED_KEY # define XTS_CHAIN_TWEAK # define __ARM_ARCH__ __LINUX_ARM_ARCH__ +# define __ARM_MAX_ARCH__ 7 #endif #ifdef __thumb__ # define adrl adr #endif -#if __ARM_ARCH__>=7 +#if __ARM_MAX_ARCH__>=7 +.arch armv7-a +.fpu neon + .text .syntax unified @ ARMv7-capable assembler is expected to handle this -#ifdef __thumb2__ +#if defined(__thumb2__) && !defined(__APPLE__) .thumb #else -.code 32 +.code 32 #endif -.fpu neon - .type _bsaes_decrypt8,%function .align 4 _bsaes_decrypt8: adr r6,_bsaes_decrypt8 vldmia r4!, {q9} @ round 0 key +#ifdef __APPLE__ + adr r6,.LM0ISR +#else add r6,r6,#.LM0ISR-_bsaes_decrypt8 +#endif vldmia r6!, {q8} @ .LM0ISR veor q10, q0, q9 @ xor with round0 key veor q11, q1, q9 - vtbl.8 d0, {q10}, d16 - vtbl.8 d1, {q10}, d17 + vtbl.8 d0, {q10}, d16 + vtbl.8 d1, {q10}, d17 veor q12, q2, q9 - vtbl.8 d2, {q11}, d16 - vtbl.8 d3, {q11}, d17 + vtbl.8 d2, {q11}, d16 + vtbl.8 d3, {q11}, d17 veor q13, q3, q9 - vtbl.8 d4, {q12}, d16 - vtbl.8 d5, {q12}, d17 + vtbl.8 d4, {q12}, d16 + vtbl.8 d5, {q12}, d17 veor q14, q4, q9 - vtbl.8 d6, {q13}, d16 - vtbl.8 d7, {q13}, d17 + vtbl.8 d6, {q13}, d16 + vtbl.8 d7, {q13}, d17 veor q15, q5, q9 - vtbl.8 d8, {q14}, d16 - vtbl.8 d9, {q14}, d17 + vtbl.8 d8, {q14}, d16 + vtbl.8 d9, {q14}, d17 veor q10, q6, q9 - vtbl.8 d10, {q15}, d16 - vtbl.8 d11, {q15}, d17 + vtbl.8 d10, {q15}, d16 + vtbl.8 d11, {q15}, d17 veor q11, q7, q9 - vtbl.8 d12, {q10}, d16 - vtbl.8 d13, {q10}, d17 - vtbl.8 d14, {q11}, d16 - vtbl.8 d15, {q11}, d17 + vtbl.8 d12, {q10}, d16 + vtbl.8 d13, {q10}, d17 + vtbl.8 d14, {q11}, d16 + vtbl.8 d15, {q11}, d17 vmov.i8 q8,#0x55 @ compose .LBS0 vmov.i8 q9,#0x33 @ compose .LBS1 vshr.u64 q10, q6, #1 - vshr.u64 q11, q4, #1 - veor q10, q10, q7 - veor q11, q11, q5 - vand q10, q10, q8 - vand q11, q11, q8 - veor q7, q7, q10 + vshr.u64 q11, q4, #1 + veor q10, q10, q7 + veor q11, q11, q5 + vand q10, q10, q8 + vand q11, q11, q8 + veor q7, q7, q10 vshl.u64 q10, q10, #1 - veor q5, q5, q11 - vshl.u64 q11, q11, #1 - veor q6, q6, q10 - veor q4, q4, q11 + veor q5, q5, q11 + vshl.u64 q11, q11, #1 + veor q6, q6, q10 + veor q4, q4, q11 vshr.u64 q10, q2, #1 - vshr.u64 q11, q0, #1 - veor q10, q10, q3 - veor q11, q11, q1 - vand q10, q10, q8 - vand q11, q11, q8 - veor q3, q3, q10 + vshr.u64 q11, q0, #1 + veor q10, q10, q3 + veor q11, q11, q1 + vand q10, q10, q8 + vand q11, q11, q8 + veor q3, q3, q10 vshl.u64 q10, q10, #1 - veor q1, q1, q11 - vshl.u64 q11, q11, #1 - veor q2, q2, q10 - veor q0, q0, q11 + veor q1, q1, q11 + vshl.u64 q11, q11, #1 + veor q2, q2, q10 + veor q0, q0, q11 vmov.i8 q8,#0x0f @ compose .LBS2 vshr.u64 q10, q5, #2 - vshr.u64 q11, q4, #2 - veor q10, q10, q7 - veor q11, q11, q6 - vand q10, q10, q9 - vand q11, q11, q9 - veor q7, q7, q10 + vshr.u64 q11, q4, #2 + veor q10, q10, q7 + veor q11, q11, q6 + vand q10, q10, q9 + vand q11, q11, q9 + veor q7, q7, q10 vshl.u64 q10, q10, #2 - veor q6, q6, q11 - vshl.u64 q11, q11, #2 - veor q5, q5, q10 - veor q4, q4, q11 + veor q6, q6, q11 + vshl.u64 q11, q11, #2 + veor q5, q5, q10 + veor q4, q4, q11 vshr.u64 q10, q1, #2 - vshr.u64 q11, q0, #2 - veor q10, q10, q3 - veor q11, q11, q2 - vand q10, q10, q9 - vand q11, q11, q9 - veor q3, q3, q10 + vshr.u64 q11, q0, #2 + veor q10, q10, q3 + veor q11, q11, q2 + vand q10, q10, q9 + vand q11, q11, q9 + veor q3, q3, q10 vshl.u64 q10, q10, #2 - veor q2, q2, q11 - vshl.u64 q11, q11, #2 - veor q1, q1, q10 - veor q0, q0, q11 + veor q2, q2, q11 + vshl.u64 q11, q11, #2 + veor q1, q1, q10 + veor q0, q0, q11 vshr.u64 q10, q3, #4 - vshr.u64 q11, q2, #4 - veor q10, q10, q7 - veor q11, q11, q6 - vand q10, q10, q8 - vand q11, q11, q8 - veor q7, q7, q10 + vshr.u64 q11, q2, #4 + veor q10, q10, q7 + veor q11, q11, q6 + vand q10, q10, q8 + vand q11, q11, q8 + veor q7, q7, q10 vshl.u64 q10, q10, #4 - veor q6, q6, q11 - vshl.u64 q11, q11, #4 - veor q3, q3, q10 - veor q2, q2, q11 + veor q6, q6, q11 + vshl.u64 q11, q11, #4 + veor q3, q3, q10 + veor q2, q2, q11 vshr.u64 q10, q1, #4 - vshr.u64 q11, q0, #4 - veor q10, q10, q5 - veor q11, q11, q4 - vand q10, q10, q8 - vand q11, q11, q8 - veor q5, q5, q10 + vshr.u64 q11, q0, #4 + veor q10, q10, q5 + veor q11, q11, q4 + vand q10, q10, q8 + vand q11, q11, q8 + veor q5, q5, q10 vshl.u64 q10, q10, #4 - veor q4, q4, q11 - vshl.u64 q11, q11, #4 - veor q1, q1, q10 - veor q0, q0, q11 + veor q4, q4, q11 + vshl.u64 q11, q11, #4 + veor q1, q1, q10 + veor q0, q0, q11 sub r5,r5,#1 b .Ldec_sbox .align 4 .Ldec_loop: - vldmia r4!, {q8-q11} + vldmia r4!, {q8,q9,q10,q11} veor q8, q8, q0 veor q9, q9, q1 vtbl.8 d0, {q8}, d24 @@ -218,17 +225,17 @@ _bsaes_decrypt8: vtbl.8 d14, {q11}, d24 vtbl.8 d15, {q11}, d25 .Ldec_sbox: - veor q1, q1, q4 + veor q1, q1, q4 veor q3, q3, q4 veor q4, q4, q7 - veor q1, q1, q6 + veor q1, q1, q6 veor q2, q2, q7 veor q6, q6, q4 veor q0, q0, q1 veor q2, q2, q5 - veor q7, q7, q6 + veor q7, q7, q6 veor q3, q3, q0 veor q5, q5, q0 veor q1, q1, q3 @@ -236,7 +243,7 @@ _bsaes_decrypt8: veor q10, q7, q4 veor q9, q1, q6 veor q13, q4, q0 - vmov q8, q10 + vmov q8, q10 veor q12, q5, q2 vorr q10, q10, q9 @@ -293,7 +300,7 @@ _bsaes_decrypt8: veor q14, q14, q11 veor q12, q5, q2 veor q8, q1, q6 - veor q10, q15, q14 + veor q10, q15, q14 vand q10, q10, q5 veor q5, q5, q1 vand q11, q1, q15 @@ -303,19 +310,19 @@ _bsaes_decrypt8: veor q15, q15, q13 veor q14, q14, q9 veor q11, q15, q14 - veor q10, q13, q9 + veor q10, q13, q9 vand q11, q11, q12 - vand q10, q10, q2 + vand q10, q10, q2 veor q12, q12, q8 - veor q2, q2, q6 + veor q2, q2, q6 vand q8, q8, q15 - vand q6, q6, q13 + vand q6, q6, q13 vand q12, q12, q14 - vand q2, q2, q9 + vand q2, q2, q9 veor q8, q8, q12 - veor q2, q2, q6 + veor q2, q2, q6 veor q12, q12, q11 - veor q6, q6, q10 + veor q6, q6, q10 veor q5, q5, q12 veor q2, q2, q12 veor q1, q1, q8 @@ -324,22 +331,22 @@ _bsaes_decrypt8: veor q12, q3, q0 veor q8, q7, q4 veor q11, q15, q14 - veor q10, q13, q9 + veor q10, q13, q9 vand q11, q11, q12 - vand q10, q10, q0 + vand q10, q10, q0 veor q12, q12, q8 - veor q0, q0, q4 + veor q0, q0, q4 vand q8, q8, q15 - vand q4, q4, q13 + vand q4, q4, q13 vand q12, q12, q14 - vand q0, q0, q9 + vand q0, q0, q9 veor q8, q8, q12 - veor q0, q0, q4 + veor q0, q0, q4 veor q12, q12, q11 - veor q4, q4, q10 + veor q4, q4, q10 veor q15, q15, q13 veor q14, q14, q9 - veor q10, q15, q14 + veor q10, q15, q14 vand q10, q10, q3 veor q3, q3, q7 vand q11, q7, q15 @@ -357,10 +364,10 @@ _bsaes_decrypt8: veor q2, q2, q7 veor q5, q5, q7 veor q4, q4, q2 - veor q7, q7, q0 + veor q7, q7, q0 veor q4, q4, q5 - veor q3, q3, q6 - veor q6, q6, q1 + veor q3, q3, q6 + veor q6, q6, q1 veor q3, q3, q4 veor q4, q4, q0 @@ -385,58 +392,58 @@ _bsaes_decrypt8: veor q12, q12, q2 veor q13, q13, q7 - veor q0, q0, q14 - veor q1, q1, q14 - veor q6, q6, q8 - veor q2, q2, q10 - veor q4, q4, q9 - veor q1, q1, q15 - veor q6, q6, q15 - veor q2, q2, q14 - veor q7, q7, q11 - veor q4, q4, q14 - veor q3, q3, q12 - veor q2, q2, q15 - veor q7, q7, q15 - veor q5, q5, q13 + veor q0, q0, q14 + veor q1, q1, q14 + veor q6, q6, q8 + veor q2, q2, q10 + veor q4, q4, q9 + veor q1, q1, q15 + veor q6, q6, q15 + veor q2, q2, q14 + veor q7, q7, q11 + veor q4, q4, q14 + veor q3, q3, q12 + veor q2, q2, q15 + veor q7, q7, q15 + veor q5, q5, q13 vext.8 q8, q0, q0, #12 @ x0 <<< 32 vext.8 q9, q1, q1, #12 - veor q0, q0, q8 @ x0 ^ (x0 <<< 32) + veor q0, q0, q8 @ x0 ^ (x0 <<< 32) vext.8 q10, q6, q6, #12 - veor q1, q1, q9 + veor q1, q1, q9 vext.8 q11, q4, q4, #12 - veor q6, q6, q10 + veor q6, q6, q10 vext.8 q12, q2, q2, #12 - veor q4, q4, q11 + veor q4, q4, q11 vext.8 q13, q7, q7, #12 - veor q2, q2, q12 + veor q2, q2, q12 vext.8 q14, q3, q3, #12 - veor q7, q7, q13 + veor q7, q7, q13 vext.8 q15, q5, q5, #12 - veor q3, q3, q14 + veor q3, q3, q14 veor q9, q9, q0 - veor q5, q5, q15 - vext.8 q0, q0, q0, #8 @ (x0 ^ (x0 <<< 32)) <<< 64) + veor q5, q5, q15 + vext.8 q0, q0, q0, #8 @ (x0 ^ (x0 <<< 32)) <<< 64) veor q10, q10, q1 veor q8, q8, q5 veor q9, q9, q5 - vext.8 q1, q1, q1, #8 + vext.8 q1, q1, q1, #8 veor q13, q13, q2 - veor q0, q0, q8 + veor q0, q0, q8 veor q14, q14, q7 - veor q1, q1, q9 - vext.8 q8, q2, q2, #8 + veor q1, q1, q9 + vext.8 q8, q2, q2, #8 veor q12, q12, q4 - vext.8 q9, q7, q7, #8 + vext.8 q9, q7, q7, #8 veor q15, q15, q3 - vext.8 q2, q4, q4, #8 + vext.8 q2, q4, q4, #8 veor q11, q11, q6 - vext.8 q7, q5, q5, #8 + vext.8 q7, q5, q5, #8 veor q12, q12, q5 - vext.8 q4, q3, q3, #8 + vext.8 q4, q3, q3, #8 veor q11, q11, q5 - vext.8 q3, q6, q6, #8 + vext.8 q3, q6, q6, #8 veor q5, q9, q13 veor q11, q11, q2 veor q7, q7, q15 @@ -456,78 +463,78 @@ _bsaes_decrypt8: vmov.i8 q8,#0x55 @ compose .LBS0 vmov.i8 q9,#0x33 @ compose .LBS1 vshr.u64 q10, q3, #1 - vshr.u64 q11, q2, #1 - veor q10, q10, q5 - veor q11, q11, q7 - vand q10, q10, q8 - vand q11, q11, q8 - veor q5, q5, q10 + vshr.u64 q11, q2, #1 + veor q10, q10, q5 + veor q11, q11, q7 + vand q10, q10, q8 + vand q11, q11, q8 + veor q5, q5, q10 vshl.u64 q10, q10, #1 - veor q7, q7, q11 - vshl.u64 q11, q11, #1 - veor q3, q3, q10 - veor q2, q2, q11 + veor q7, q7, q11 + vshl.u64 q11, q11, #1 + veor q3, q3, q10 + veor q2, q2, q11 vshr.u64 q10, q6, #1 - vshr.u64 q11, q0, #1 - veor q10, q10, q4 - veor q11, q11, q1 - vand q10, q10, q8 - vand q11, q11, q8 - veor q4, q4, q10 + vshr.u64 q11, q0, #1 + veor q10, q10, q4 + veor q11, q11, q1 + vand q10, q10, q8 + vand q11, q11, q8 + veor q4, q4, q10 vshl.u64 q10, q10, #1 - veor q1, q1, q11 - vshl.u64 q11, q11, #1 - veor q6, q6, q10 - veor q0, q0, q11 + veor q1, q1, q11 + vshl.u64 q11, q11, #1 + veor q6, q6, q10 + veor q0, q0, q11 vmov.i8 q8,#0x0f @ compose .LBS2 vshr.u64 q10, q7, #2 - vshr.u64 q11, q2, #2 - veor q10, q10, q5 - veor q11, q11, q3 - vand q10, q10, q9 - vand q11, q11, q9 - veor q5, q5, q10 + vshr.u64 q11, q2, #2 + veor q10, q10, q5 + veor q11, q11, q3 + vand q10, q10, q9 + vand q11, q11, q9 + veor q5, q5, q10 vshl.u64 q10, q10, #2 - veor q3, q3, q11 - vshl.u64 q11, q11, #2 - veor q7, q7, q10 - veor q2, q2, q11 + veor q3, q3, q11 + vshl.u64 q11, q11, #2 + veor q7, q7, q10 + veor q2, q2, q11 vshr.u64 q10, q1, #2 - vshr.u64 q11, q0, #2 - veor q10, q10, q4 - veor q11, q11, q6 - vand q10, q10, q9 - vand q11, q11, q9 - veor q4, q4, q10 + vshr.u64 q11, q0, #2 + veor q10, q10, q4 + veor q11, q11, q6 + vand q10, q10, q9 + vand q11, q11, q9 + veor q4, q4, q10 vshl.u64 q10, q10, #2 - veor q6, q6, q11 - vshl.u64 q11, q11, #2 - veor q1, q1, q10 - veor q0, q0, q11 + veor q6, q6, q11 + vshl.u64 q11, q11, #2 + veor q1, q1, q10 + veor q0, q0, q11 vshr.u64 q10, q4, #4 - vshr.u64 q11, q6, #4 - veor q10, q10, q5 - veor q11, q11, q3 - vand q10, q10, q8 - vand q11, q11, q8 - veor q5, q5, q10 + vshr.u64 q11, q6, #4 + veor q10, q10, q5 + veor q11, q11, q3 + vand q10, q10, q8 + vand q11, q11, q8 + veor q5, q5, q10 vshl.u64 q10, q10, #4 - veor q3, q3, q11 - vshl.u64 q11, q11, #4 - veor q4, q4, q10 - veor q6, q6, q11 + veor q3, q3, q11 + vshl.u64 q11, q11, #4 + veor q4, q4, q10 + veor q6, q6, q11 vshr.u64 q10, q1, #4 - vshr.u64 q11, q0, #4 - veor q10, q10, q7 - veor q11, q11, q2 - vand q10, q10, q8 - vand q11, q11, q8 - veor q7, q7, q10 + vshr.u64 q11, q0, #4 + veor q10, q10, q7 + veor q11, q11, q2 + vand q10, q10, q8 + vand q11, q11, q8 + veor q7, q7, q10 vshl.u64 q10, q10, #4 - veor q2, q2, q11 - vshl.u64 q11, q11, #4 - veor q1, q1, q10 - veor q0, q0, q11 + veor q2, q2, q11 + vshl.u64 q11, q11, #4 + veor q1, q1, q10 + veor q0, q0, q11 vldmia r4, {q8} @ last round key veor q6, q6, q8 veor q4, q4, q8 @@ -543,23 +550,24 @@ _bsaes_decrypt8: .type _bsaes_const,%object .align 6 _bsaes_const: -.LM0ISR: @ InvShiftRows constants - .quad 0x0a0e0206070b0f03, 0x0004080c0d010509 +.LM0ISR:@ InvShiftRows constants +.quad 0x0a0e0206070b0f03, 0x0004080c0d010509 .LISR: - .quad 0x0504070602010003, 0x0f0e0d0c080b0a09 +.quad 0x0504070602010003, 0x0f0e0d0c080b0a09 .LISRM0: - .quad 0x01040b0e0205080f, 0x0306090c00070a0d -.LM0SR: @ ShiftRows constants - .quad 0x0a0e02060f03070b, 0x0004080c05090d01 +.quad 0x01040b0e0205080f, 0x0306090c00070a0d +.LM0SR:@ ShiftRows constants +.quad 0x0a0e02060f03070b, 0x0004080c05090d01 .LSR: - .quad 0x0504070600030201, 0x0f0e0d0c0a09080b +.quad 0x0504070600030201, 0x0f0e0d0c0a09080b .LSRM0: - .quad 0x0304090e00050a0f, 0x01060b0c0207080d +.quad 0x0304090e00050a0f, 0x01060b0c0207080d .LM0: - .quad 0x02060a0e03070b0f, 0x0004080c0105090d +.quad 0x02060a0e03070b0f, 0x0004080c0105090d .LREVM0SR: - .quad 0x090d01050c000408, 0x03070b0f060a0e02 -.asciz "Bit-sliced AES for NEON, CRYPTOGAMS by " +.quad 0x090d01050c000408, 0x03070b0f060a0e02 +.byte 66,105,116,45,115,108,105,99,101,100,32,65,69,83,32,102,111,114,32,78,69,79,78,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0 +.align 2 .align 6 .size _bsaes_const,.-_bsaes_const @@ -568,115 +576,119 @@ _bsaes_const: _bsaes_encrypt8: adr r6,_bsaes_encrypt8 vldmia r4!, {q9} @ round 0 key +#ifdef __APPLE__ + adr r6,.LM0SR +#else sub r6,r6,#_bsaes_encrypt8-.LM0SR +#endif vldmia r6!, {q8} @ .LM0SR _bsaes_encrypt8_alt: veor q10, q0, q9 @ xor with round0 key veor q11, q1, q9 - vtbl.8 d0, {q10}, d16 - vtbl.8 d1, {q10}, d17 + vtbl.8 d0, {q10}, d16 + vtbl.8 d1, {q10}, d17 veor q12, q2, q9 - vtbl.8 d2, {q11}, d16 - vtbl.8 d3, {q11}, d17 + vtbl.8 d2, {q11}, d16 + vtbl.8 d3, {q11}, d17 veor q13, q3, q9 - vtbl.8 d4, {q12}, d16 - vtbl.8 d5, {q12}, d17 + vtbl.8 d4, {q12}, d16 + vtbl.8 d5, {q12}, d17 veor q14, q4, q9 - vtbl.8 d6, {q13}, d16 - vtbl.8 d7, {q13}, d17 + vtbl.8 d6, {q13}, d16 + vtbl.8 d7, {q13}, d17 veor q15, q5, q9 - vtbl.8 d8, {q14}, d16 - vtbl.8 d9, {q14}, d17 + vtbl.8 d8, {q14}, d16 + vtbl.8 d9, {q14}, d17 veor q10, q6, q9 - vtbl.8 d10, {q15}, d16 - vtbl.8 d11, {q15}, d17 + vtbl.8 d10, {q15}, d16 + vtbl.8 d11, {q15}, d17 veor q11, q7, q9 - vtbl.8 d12, {q10}, d16 - vtbl.8 d13, {q10}, d17 - vtbl.8 d14, {q11}, d16 - vtbl.8 d15, {q11}, d17 + vtbl.8 d12, {q10}, d16 + vtbl.8 d13, {q10}, d17 + vtbl.8 d14, {q11}, d16 + vtbl.8 d15, {q11}, d17 _bsaes_encrypt8_bitslice: vmov.i8 q8,#0x55 @ compose .LBS0 vmov.i8 q9,#0x33 @ compose .LBS1 vshr.u64 q10, q6, #1 - vshr.u64 q11, q4, #1 - veor q10, q10, q7 - veor q11, q11, q5 - vand q10, q10, q8 - vand q11, q11, q8 - veor q7, q7, q10 + vshr.u64 q11, q4, #1 + veor q10, q10, q7 + veor q11, q11, q5 + vand q10, q10, q8 + vand q11, q11, q8 + veor q7, q7, q10 vshl.u64 q10, q10, #1 - veor q5, q5, q11 - vshl.u64 q11, q11, #1 - veor q6, q6, q10 - veor q4, q4, q11 + veor q5, q5, q11 + vshl.u64 q11, q11, #1 + veor q6, q6, q10 + veor q4, q4, q11 vshr.u64 q10, q2, #1 - vshr.u64 q11, q0, #1 - veor q10, q10, q3 - veor q11, q11, q1 - vand q10, q10, q8 - vand q11, q11, q8 - veor q3, q3, q10 + vshr.u64 q11, q0, #1 + veor q10, q10, q3 + veor q11, q11, q1 + vand q10, q10, q8 + vand q11, q11, q8 + veor q3, q3, q10 vshl.u64 q10, q10, #1 - veor q1, q1, q11 - vshl.u64 q11, q11, #1 - veor q2, q2, q10 - veor q0, q0, q11 + veor q1, q1, q11 + vshl.u64 q11, q11, #1 + veor q2, q2, q10 + veor q0, q0, q11 vmov.i8 q8,#0x0f @ compose .LBS2 vshr.u64 q10, q5, #2 - vshr.u64 q11, q4, #2 - veor q10, q10, q7 - veor q11, q11, q6 - vand q10, q10, q9 - vand q11, q11, q9 - veor q7, q7, q10 + vshr.u64 q11, q4, #2 + veor q10, q10, q7 + veor q11, q11, q6 + vand q10, q10, q9 + vand q11, q11, q9 + veor q7, q7, q10 vshl.u64 q10, q10, #2 - veor q6, q6, q11 - vshl.u64 q11, q11, #2 - veor q5, q5, q10 - veor q4, q4, q11 + veor q6, q6, q11 + vshl.u64 q11, q11, #2 + veor q5, q5, q10 + veor q4, q4, q11 vshr.u64 q10, q1, #2 - vshr.u64 q11, q0, #2 - veor q10, q10, q3 - veor q11, q11, q2 - vand q10, q10, q9 - vand q11, q11, q9 - veor q3, q3, q10 + vshr.u64 q11, q0, #2 + veor q10, q10, q3 + veor q11, q11, q2 + vand q10, q10, q9 + vand q11, q11, q9 + veor q3, q3, q10 vshl.u64 q10, q10, #2 - veor q2, q2, q11 - vshl.u64 q11, q11, #2 - veor q1, q1, q10 - veor q0, q0, q11 + veor q2, q2, q11 + vshl.u64 q11, q11, #2 + veor q1, q1, q10 + veor q0, q0, q11 vshr.u64 q10, q3, #4 - vshr.u64 q11, q2, #4 - veor q10, q10, q7 - veor q11, q11, q6 - vand q10, q10, q8 - vand q11, q11, q8 - veor q7, q7, q10 + vshr.u64 q11, q2, #4 + veor q10, q10, q7 + veor q11, q11, q6 + vand q10, q10, q8 + vand q11, q11, q8 + veor q7, q7, q10 vshl.u64 q10, q10, #4 - veor q6, q6, q11 - vshl.u64 q11, q11, #4 - veor q3, q3, q10 - veor q2, q2, q11 + veor q6, q6, q11 + vshl.u64 q11, q11, #4 + veor q3, q3, q10 + veor q2, q2, q11 vshr.u64 q10, q1, #4 - vshr.u64 q11, q0, #4 - veor q10, q10, q5 - veor q11, q11, q4 - vand q10, q10, q8 - vand q11, q11, q8 - veor q5, q5, q10 + vshr.u64 q11, q0, #4 + veor q10, q10, q5 + veor q11, q11, q4 + vand q10, q10, q8 + vand q11, q11, q8 + veor q5, q5, q10 vshl.u64 q10, q10, #4 - veor q4, q4, q11 - vshl.u64 q11, q11, #4 - veor q1, q1, q10 - veor q0, q0, q11 + veor q4, q4, q11 + vshl.u64 q11, q11, #4 + veor q1, q1, q10 + veor q0, q0, q11 sub r5,r5,#1 b .Lenc_sbox .align 4 .Lenc_loop: - vldmia r4!, {q8-q11} + vldmia r4!, {q8,q9,q10,q11} veor q8, q8, q0 veor q9, q9, q1 vtbl.8 d0, {q8}, d24 @@ -725,7 +737,7 @@ _bsaes_encrypt8_bitslice: veor q10, q1, q2 veor q9, q5, q3 veor q13, q2, q4 - vmov q8, q10 + vmov q8, q10 veor q12, q6, q0 vorr q10, q10, q9 @@ -782,7 +794,7 @@ _bsaes_encrypt8_bitslice: veor q14, q14, q11 veor q12, q6, q0 veor q8, q5, q3 - veor q10, q15, q14 + veor q10, q15, q14 vand q10, q10, q6 veor q6, q6, q5 vand q11, q5, q15 @@ -792,19 +804,19 @@ _bsaes_encrypt8_bitslice: veor q15, q15, q13 veor q14, q14, q9 veor q11, q15, q14 - veor q10, q13, q9 + veor q10, q13, q9 vand q11, q11, q12 - vand q10, q10, q0 + vand q10, q10, q0 veor q12, q12, q8 - veor q0, q0, q3 + veor q0, q0, q3 vand q8, q8, q15 - vand q3, q3, q13 + vand q3, q3, q13 vand q12, q12, q14 - vand q0, q0, q9 + vand q0, q0, q9 veor q8, q8, q12 - veor q0, q0, q3 + veor q0, q0, q3 veor q12, q12, q11 - veor q3, q3, q10 + veor q3, q3, q10 veor q6, q6, q12 veor q0, q0, q12 veor q5, q5, q8 @@ -813,22 +825,22 @@ _bsaes_encrypt8_bitslice: veor q12, q7, q4 veor q8, q1, q2 veor q11, q15, q14 - veor q10, q13, q9 + veor q10, q13, q9 vand q11, q11, q12 - vand q10, q10, q4 + vand q10, q10, q4 veor q12, q12, q8 - veor q4, q4, q2 + veor q4, q4, q2 vand q8, q8, q15 - vand q2, q2, q13 + vand q2, q2, q13 vand q12, q12, q14 - vand q4, q4, q9 + vand q4, q4, q9 veor q8, q8, q12 - veor q4, q4, q2 + veor q4, q4, q2 veor q12, q12, q11 - veor q2, q2, q10 + veor q2, q2, q10 veor q15, q15, q13 veor q14, q14, q9 - veor q10, q15, q14 + veor q10, q15, q14 vand q10, q10, q7 veor q7, q7, q1 vand q11, q1, q15 @@ -856,42 +868,42 @@ _bsaes_encrypt8_bitslice: bcc .Lenc_done vext.8 q8, q0, q0, #12 @ x0 <<< 32 vext.8 q9, q1, q1, #12 - veor q0, q0, q8 @ x0 ^ (x0 <<< 32) + veor q0, q0, q8 @ x0 ^ (x0 <<< 32) vext.8 q10, q4, q4, #12 - veor q1, q1, q9 + veor q1, q1, q9 vext.8 q11, q6, q6, #12 - veor q4, q4, q10 + veor q4, q4, q10 vext.8 q12, q3, q3, #12 - veor q6, q6, q11 + veor q6, q6, q11 vext.8 q13, q7, q7, #12 - veor q3, q3, q12 + veor q3, q3, q12 vext.8 q14, q2, q2, #12 - veor q7, q7, q13 + veor q7, q7, q13 vext.8 q15, q5, q5, #12 - veor q2, q2, q14 + veor q2, q2, q14 veor q9, q9, q0 - veor q5, q5, q15 - vext.8 q0, q0, q0, #8 @ (x0 ^ (x0 <<< 32)) <<< 64) + veor q5, q5, q15 + vext.8 q0, q0, q0, #8 @ (x0 ^ (x0 <<< 32)) <<< 64) veor q10, q10, q1 veor q8, q8, q5 veor q9, q9, q5 - vext.8 q1, q1, q1, #8 + vext.8 q1, q1, q1, #8 veor q13, q13, q3 - veor q0, q0, q8 + veor q0, q0, q8 veor q14, q14, q7 - veor q1, q1, q9 - vext.8 q8, q3, q3, #8 + veor q1, q1, q9 + vext.8 q8, q3, q3, #8 veor q12, q12, q6 - vext.8 q9, q7, q7, #8 + vext.8 q9, q7, q7, #8 veor q15, q15, q2 - vext.8 q3, q6, q6, #8 + vext.8 q3, q6, q6, #8 veor q11, q11, q4 - vext.8 q7, q5, q5, #8 + vext.8 q7, q5, q5, #8 veor q12, q12, q5 - vext.8 q6, q2, q2, #8 + vext.8 q6, q2, q2, #8 veor q11, q11, q5 - vext.8 q2, q4, q4, #8 + vext.8 q2, q4, q4, #8 veor q5, q9, q13 veor q4, q8, q12 veor q3, q3, q11 @@ -911,78 +923,78 @@ _bsaes_encrypt8_bitslice: vmov.i8 q8,#0x55 @ compose .LBS0 vmov.i8 q9,#0x33 @ compose .LBS1 vshr.u64 q10, q2, #1 - vshr.u64 q11, q3, #1 - veor q10, q10, q5 - veor q11, q11, q7 - vand q10, q10, q8 - vand q11, q11, q8 - veor q5, q5, q10 + vshr.u64 q11, q3, #1 + veor q10, q10, q5 + veor q11, q11, q7 + vand q10, q10, q8 + vand q11, q11, q8 + veor q5, q5, q10 vshl.u64 q10, q10, #1 - veor q7, q7, q11 - vshl.u64 q11, q11, #1 - veor q2, q2, q10 - veor q3, q3, q11 + veor q7, q7, q11 + vshl.u64 q11, q11, #1 + veor q2, q2, q10 + veor q3, q3, q11 vshr.u64 q10, q4, #1 - vshr.u64 q11, q0, #1 - veor q10, q10, q6 - veor q11, q11, q1 - vand q10, q10, q8 - vand q11, q11, q8 - veor q6, q6, q10 + vshr.u64 q11, q0, #1 + veor q10, q10, q6 + veor q11, q11, q1 + vand q10, q10, q8 + vand q11, q11, q8 + veor q6, q6, q10 vshl.u64 q10, q10, #1 - veor q1, q1, q11 - vshl.u64 q11, q11, #1 - veor q4, q4, q10 - veor q0, q0, q11 + veor q1, q1, q11 + vshl.u64 q11, q11, #1 + veor q4, q4, q10 + veor q0, q0, q11 vmov.i8 q8,#0x0f @ compose .LBS2 vshr.u64 q10, q7, #2 - vshr.u64 q11, q3, #2 - veor q10, q10, q5 - veor q11, q11, q2 - vand q10, q10, q9 - vand q11, q11, q9 - veor q5, q5, q10 + vshr.u64 q11, q3, #2 + veor q10, q10, q5 + veor q11, q11, q2 + vand q10, q10, q9 + vand q11, q11, q9 + veor q5, q5, q10 vshl.u64 q10, q10, #2 - veor q2, q2, q11 - vshl.u64 q11, q11, #2 - veor q7, q7, q10 - veor q3, q3, q11 + veor q2, q2, q11 + vshl.u64 q11, q11, #2 + veor q7, q7, q10 + veor q3, q3, q11 vshr.u64 q10, q1, #2 - vshr.u64 q11, q0, #2 - veor q10, q10, q6 - veor q11, q11, q4 - vand q10, q10, q9 - vand q11, q11, q9 - veor q6, q6, q10 + vshr.u64 q11, q0, #2 + veor q10, q10, q6 + veor q11, q11, q4 + vand q10, q10, q9 + vand q11, q11, q9 + veor q6, q6, q10 vshl.u64 q10, q10, #2 - veor q4, q4, q11 - vshl.u64 q11, q11, #2 - veor q1, q1, q10 - veor q0, q0, q11 + veor q4, q4, q11 + vshl.u64 q11, q11, #2 + veor q1, q1, q10 + veor q0, q0, q11 vshr.u64 q10, q6, #4 - vshr.u64 q11, q4, #4 - veor q10, q10, q5 - veor q11, q11, q2 - vand q10, q10, q8 - vand q11, q11, q8 - veor q5, q5, q10 + vshr.u64 q11, q4, #4 + veor q10, q10, q5 + veor q11, q11, q2 + vand q10, q10, q8 + vand q11, q11, q8 + veor q5, q5, q10 vshl.u64 q10, q10, #4 - veor q2, q2, q11 - vshl.u64 q11, q11, #4 - veor q6, q6, q10 - veor q4, q4, q11 + veor q2, q2, q11 + vshl.u64 q11, q11, #4 + veor q6, q6, q10 + veor q4, q4, q11 vshr.u64 q10, q1, #4 - vshr.u64 q11, q0, #4 - veor q10, q10, q7 - veor q11, q11, q3 - vand q10, q10, q8 - vand q11, q11, q8 - veor q7, q7, q10 + vshr.u64 q11, q0, #4 + veor q10, q10, q7 + veor q11, q11, q3 + vand q10, q10, q8 + vand q11, q11, q8 + veor q7, q7, q10 vshl.u64 q10, q10, #4 - veor q3, q3, q11 - vshl.u64 q11, q11, #4 - veor q1, q1, q10 - veor q0, q0, q11 + veor q3, q3, q11 + vshl.u64 q11, q11, #4 + veor q1, q1, q10 + veor q0, q0, q11 vldmia r4, {q8} @ last round key veor q4, q4, q8 veor q6, q6, q8 @@ -999,7 +1011,11 @@ _bsaes_encrypt8_bitslice: _bsaes_key_convert: adr r6,_bsaes_key_convert vld1.8 {q7}, [r4]! @ load round 0 key +#ifdef __APPLE__ + adr r6,.LM0 +#else sub r6,r6,#_bsaes_key_convert-.LM0 +#endif vld1.8 {q15}, [r4]! @ load round 1 key vmov.i8 q8, #0x01 @ bit masks @@ -1042,17 +1058,17 @@ _bsaes_key_convert: vrev32.8 q15, q15 #endif subs r5,r5,#1 - vstmia r12!,{q0-q7} @ write bit-sliced round key + vstmia r12!,{q0,q1,q2,q3,q4,q5,q6,q7} @ write bit-sliced round key bne .Lkey_loop vmov.i8 q7,#0x63 @ compose .L63 @ don't save last round key bx lr .size _bsaes_key_convert,.-_bsaes_key_convert -.extern AES_cbc_encrypt -.extern AES_decrypt -.global bsaes_cbc_encrypt + + +.globl bsaes_cbc_encrypt .hidden bsaes_cbc_encrypt .type bsaes_cbc_encrypt,%function .align 5 @@ -1071,7 +1087,7 @@ bsaes_cbc_encrypt: @ it is up to the caller to make sure we are called with enc == 0 mov ip, sp - stmdb sp!, {r4-r10, lr} + stmdb sp!, {r4,r5,r6,r7,r8,r9,r10, lr} VFP_ABI_PUSH ldr r8, [ip] @ IV is 1st arg on the stack mov r2, r2, lsr#4 @ len in 16 byte blocks @@ -1111,7 +1127,7 @@ bsaes_cbc_encrypt: vstmia r4, {q7} .align 2 -0: + #endif vld1.8 {q15}, [r8] @ load IV @@ -1122,33 +1138,33 @@ bsaes_cbc_encrypt: subs r2, r2, #0x8 bmi .Lcbc_dec_loop_finish - vld1.8 {q0-q1}, [r0]! @ load input - vld1.8 {q2-q3}, [r0]! + vld1.8 {q0,q1}, [r0]! @ load input + vld1.8 {q2,q3}, [r0]! #ifndef BSAES_ASM_EXTENDED_KEY mov r4, sp @ pass the key #else add r4, r3, #248 #endif - vld1.8 {q4-q5}, [r0]! + vld1.8 {q4,q5}, [r0]! mov r5, r10 - vld1.8 {q6-q7}, [r0] + vld1.8 {q6,q7}, [r0] sub r0, r0, #0x60 vstmia r9, {q15} @ put aside IV bl _bsaes_decrypt8 vldmia r9, {q14} @ reload IV - vld1.8 {q8-q9}, [r0]! @ reload input + vld1.8 {q8,q9}, [r0]! @ reload input veor q0, q0, q14 @ ^= IV - vld1.8 {q10-q11}, [r0]! + vld1.8 {q10,q11}, [r0]! veor q1, q1, q8 veor q6, q6, q9 - vld1.8 {q12-q13}, [r0]! + vld1.8 {q12,q13}, [r0]! veor q4, q4, q10 veor q2, q2, q11 - vld1.8 {q14-q15}, [r0]! + vld1.8 {q14,q15}, [r0]! veor q7, q7, q12 - vst1.8 {q0-q1}, [r1]! @ write output + vst1.8 {q0,q1}, [r1]! @ write output veor q3, q3, q13 vst1.8 {q6}, [r1]! veor q5, q5, q14 @@ -1192,17 +1208,17 @@ bsaes_cbc_encrypt: bl _bsaes_decrypt8 vldmia r9, {q14} @ reload IV - vld1.8 {q8-q9}, [r0]! @ reload input + vld1.8 {q8,q9}, [r0]! @ reload input veor q0, q0, q14 @ ^= IV - vld1.8 {q10-q11}, [r0]! + vld1.8 {q10,q11}, [r0]! veor q1, q1, q8 veor q6, q6, q9 - vld1.8 {q12-q13}, [r0]! + vld1.8 {q12,q13}, [r0]! veor q4, q4, q10 veor q2, q2, q11 vld1.8 {q15}, [r0]! veor q7, q7, q12 - vst1.8 {q0-q1}, [r1]! @ write output + vst1.8 {q0,q1}, [r1]! @ write output veor q3, q3, q13 vst1.8 {q6}, [r1]! vst1.8 {q4}, [r1]! @@ -1215,9 +1231,9 @@ bsaes_cbc_encrypt: sub r0, r0, #0x60 bl _bsaes_decrypt8 vldmia r9,{q14} @ reload IV - vld1.8 {q8-q9}, [r0]! @ reload input + vld1.8 {q8,q9}, [r0]! @ reload input veor q0, q0, q14 @ ^= IV - vld1.8 {q10-q11}, [r0]! + vld1.8 {q10,q11}, [r0]! veor q1, q1, q8 veor q6, q6, q9 vld1.8 {q12}, [r0]! @@ -1225,7 +1241,7 @@ bsaes_cbc_encrypt: veor q2, q2, q11 vld1.8 {q15}, [r0]! veor q7, q7, q12 - vst1.8 {q0-q1}, [r1]! @ write output + vst1.8 {q0,q1}, [r1]! @ write output vst1.8 {q6}, [r1]! vst1.8 {q4}, [r1]! vst1.8 {q2}, [r1]! @@ -1236,14 +1252,14 @@ bsaes_cbc_encrypt: sub r0, r0, #0x50 bl _bsaes_decrypt8 vldmia r9, {q14} @ reload IV - vld1.8 {q8-q9}, [r0]! @ reload input + vld1.8 {q8,q9}, [r0]! @ reload input veor q0, q0, q14 @ ^= IV - vld1.8 {q10-q11}, [r0]! + vld1.8 {q10,q11}, [r0]! veor q1, q1, q8 veor q6, q6, q9 vld1.8 {q15}, [r0]! veor q4, q4, q10 - vst1.8 {q0-q1}, [r1]! @ write output + vst1.8 {q0,q1}, [r1]! @ write output veor q2, q2, q11 vst1.8 {q6}, [r1]! vst1.8 {q4}, [r1]! @@ -1254,14 +1270,14 @@ bsaes_cbc_encrypt: sub r0, r0, #0x40 bl _bsaes_decrypt8 vldmia r9, {q14} @ reload IV - vld1.8 {q8-q9}, [r0]! @ reload input + vld1.8 {q8,q9}, [r0]! @ reload input veor q0, q0, q14 @ ^= IV vld1.8 {q10}, [r0]! veor q1, q1, q8 veor q6, q6, q9 vld1.8 {q15}, [r0]! veor q4, q4, q10 - vst1.8 {q0-q1}, [r1]! @ write output + vst1.8 {q0,q1}, [r1]! @ write output vst1.8 {q6}, [r1]! vst1.8 {q4}, [r1]! b .Lcbc_dec_done @@ -1270,12 +1286,12 @@ bsaes_cbc_encrypt: sub r0, r0, #0x30 bl _bsaes_decrypt8 vldmia r9, {q14} @ reload IV - vld1.8 {q8-q9}, [r0]! @ reload input + vld1.8 {q8,q9}, [r0]! @ reload input veor q0, q0, q14 @ ^= IV vld1.8 {q15}, [r0]! veor q1, q1, q8 veor q6, q6, q9 - vst1.8 {q0-q1}, [r1]! @ write output + vst1.8 {q0,q1}, [r1]! @ write output vst1.8 {q6}, [r1]! b .Lcbc_dec_done .align 4 @@ -1287,7 +1303,7 @@ bsaes_cbc_encrypt: veor q0, q0, q14 @ ^= IV vld1.8 {q15}, [r0]! @ reload input veor q1, q1, q8 - vst1.8 {q0-q1}, [r1]! @ write output + vst1.8 {q0,q1}, [r1]! @ write output b .Lcbc_dec_done .align 4 .Lcbc_dec_one: @@ -1307,20 +1323,20 @@ bsaes_cbc_encrypt: #ifndef BSAES_ASM_EXTENDED_KEY vmov.i32 q0, #0 vmov.i32 q1, #0 -.Lcbc_dec_bzero: @ wipe key schedule [if any] - vstmia sp!, {q0-q1} - cmp sp, r9 - bne .Lcbc_dec_bzero +.Lcbc_dec_bzero:@ wipe key schedule [if any] + vstmia sp!, {q0,q1} + cmp sp, r9 + bne .Lcbc_dec_bzero #endif mov sp, r9 add sp, #0x10 @ add sp,r9,#0x10 is no good for thumb vst1.8 {q15}, [r8] @ return IV VFP_ABI_POP - ldmia sp!, {r4-r10, pc} + ldmia sp!, {r4,r5,r6,r7,r8,r9,r10, pc} .size bsaes_cbc_encrypt,.-bsaes_cbc_encrypt -.extern AES_encrypt -.global bsaes_ctr32_encrypt_blocks + +.globl bsaes_ctr32_encrypt_blocks .hidden bsaes_ctr32_encrypt_blocks .type bsaes_ctr32_encrypt_blocks,%function .align 5 @@ -1329,7 +1345,7 @@ bsaes_ctr32_encrypt_blocks: blo .Lctr_enc_short @ small sizes mov ip, sp - stmdb sp!, {r4-r10, lr} + stmdb sp!, {r4,r5,r6,r7,r8,r9,r10, lr} VFP_ABI_PUSH ldr r8, [ip] @ ctr is 1st arg on the stack sub sp, sp, #0x10 @ scratch space to carry over the ctr @@ -1350,7 +1366,12 @@ bsaes_ctr32_encrypt_blocks: vstmia r12, {q7} @ save last round key vld1.8 {q0}, [r8] @ load counter +#ifdef __APPLE__ + mov r8, #:lower16:(.LREVM0SR-.LM0) + add r8, r6, r8 +#else add r8, r6, #.LREVM0SR-.LM0 @ borrow r8 +#endif vldmia sp, {q4} @ load round0 key #else ldr r12, [r3, #244] @@ -1367,7 +1388,7 @@ bsaes_ctr32_encrypt_blocks: vstmia r12, {q7} @ save last round key .align 2 -0: add r12, r3, #248 + add r12, r3, #248 vld1.8 {q0}, [r8] @ load counter adrl r8, .LREVM0SR @ borrow r8 vldmia r12, {q4} @ load round0 key @@ -1375,9 +1396,9 @@ bsaes_ctr32_encrypt_blocks: #endif vmov.i32 q8,#1 @ compose 1<<96 - veor q9,q9,q9 + veor q9,q9,q9 vrev32.8 q0,q0 - vext.8 q8,q9,q8,#4 + vext.8 q8,q9,q8,#4 vrev32.8 q4,q4 vadd.u32 q9,q8,q8 @ compose 2<<96 vstmia sp, {q4} @ save adjusted round0 key @@ -1398,117 +1419,122 @@ bsaes_ctr32_encrypt_blocks: @ Borrow prologue from _bsaes_encrypt8 to use the opportunity @ to flip byte order in 32-bit counter - vldmia sp, {q9} @ load round0 key + vldmia sp, {q9} @ load round0 key #ifndef BSAES_ASM_EXTENDED_KEY - add r4, sp, #0x10 @ pass next round key + add r4, sp, #0x10 @ pass next round key #else - add r4, r3, #264 + add r4, r3, #264 #endif - vldmia r8, {q8} @ .LREVM0SR - mov r5, r10 @ pass rounds - vstmia r9, {q10} @ save next counter - sub r6, r8, #.LREVM0SR-.LSR @ pass constants - - bl _bsaes_encrypt8_alt - - subs r2, r2, #8 - blo .Lctr_enc_loop_done - - vld1.8 {q8-q9}, [r0]! @ load input - vld1.8 {q10-q11}, [r0]! - veor q0, q8 - veor q1, q9 - vld1.8 {q12-q13}, [r0]! - veor q4, q10 - veor q6, q11 - vld1.8 {q14-q15}, [r0]! - veor q3, q12 - vst1.8 {q0-q1}, [r1]! @ write output - veor q7, q13 - veor q2, q14 - vst1.8 {q4}, [r1]! - veor q5, q15 - vst1.8 {q6}, [r1]! + vldmia r8, {q8} @ .LREVM0SR + mov r5, r10 @ pass rounds + vstmia r9, {q10} @ save next counter +#ifdef __APPLE__ + mov r6, #:lower16:(.LREVM0SR-.LSR) + sub r6, r8, r6 +#else + sub r6, r8, #.LREVM0SR-.LSR @ pass constants +#endif + + bl _bsaes_encrypt8_alt + + subs r2, r2, #8 + blo .Lctr_enc_loop_done + + vld1.8 {q8,q9}, [r0]! @ load input + vld1.8 {q10,q11}, [r0]! + veor q0, q8 + veor q1, q9 + vld1.8 {q12,q13}, [r0]! + veor q4, q10 + veor q6, q11 + vld1.8 {q14,q15}, [r0]! + veor q3, q12 + vst1.8 {q0,q1}, [r1]! @ write output + veor q7, q13 + veor q2, q14 + vst1.8 {q4}, [r1]! + veor q5, q15 + vst1.8 {q6}, [r1]! vmov.i32 q8, #1 @ compose 1<<96 - vst1.8 {q3}, [r1]! - veor q9, q9, q9 - vst1.8 {q7}, [r1]! - vext.8 q8, q9, q8, #4 - vst1.8 {q2}, [r1]! + vst1.8 {q3}, [r1]! + veor q9, q9, q9 + vst1.8 {q7}, [r1]! + vext.8 q8, q9, q8, #4 + vst1.8 {q2}, [r1]! vadd.u32 q9,q8,q8 @ compose 2<<96 - vst1.8 {q5}, [r1]! - vldmia r9, {q0} @ load counter + vst1.8 {q5}, [r1]! + vldmia r9, {q0} @ load counter - bne .Lctr_enc_loop - b .Lctr_enc_done + bne .Lctr_enc_loop + b .Lctr_enc_done .align 4 .Lctr_enc_loop_done: - add r2, r2, #8 - vld1.8 {q8}, [r0]! @ load input - veor q0, q8 - vst1.8 {q0}, [r1]! @ write output - cmp r2, #2 - blo .Lctr_enc_done - vld1.8 {q9}, [r0]! - veor q1, q9 - vst1.8 {q1}, [r1]! - beq .Lctr_enc_done - vld1.8 {q10}, [r0]! - veor q4, q10 - vst1.8 {q4}, [r1]! - cmp r2, #4 - blo .Lctr_enc_done - vld1.8 {q11}, [r0]! - veor q6, q11 - vst1.8 {q6}, [r1]! - beq .Lctr_enc_done - vld1.8 {q12}, [r0]! - veor q3, q12 - vst1.8 {q3}, [r1]! - cmp r2, #6 - blo .Lctr_enc_done - vld1.8 {q13}, [r0]! - veor q7, q13 - vst1.8 {q7}, [r1]! - beq .Lctr_enc_done - vld1.8 {q14}, [r0] - veor q2, q14 - vst1.8 {q2}, [r1]! + add r2, r2, #8 + vld1.8 {q8}, [r0]! @ load input + veor q0, q8 + vst1.8 {q0}, [r1]! @ write output + cmp r2, #2 + blo .Lctr_enc_done + vld1.8 {q9}, [r0]! + veor q1, q9 + vst1.8 {q1}, [r1]! + beq .Lctr_enc_done + vld1.8 {q10}, [r0]! + veor q4, q10 + vst1.8 {q4}, [r1]! + cmp r2, #4 + blo .Lctr_enc_done + vld1.8 {q11}, [r0]! + veor q6, q11 + vst1.8 {q6}, [r1]! + beq .Lctr_enc_done + vld1.8 {q12}, [r0]! + veor q3, q12 + vst1.8 {q3}, [r1]! + cmp r2, #6 + blo .Lctr_enc_done + vld1.8 {q13}, [r0]! + veor q7, q13 + vst1.8 {q7}, [r1]! + beq .Lctr_enc_done + vld1.8 {q14}, [r0] + veor q2, q14 + vst1.8 {q2}, [r1]! .Lctr_enc_done: vmov.i32 q0, #0 vmov.i32 q1, #0 #ifndef BSAES_ASM_EXTENDED_KEY -.Lctr_enc_bzero: @ wipe key schedule [if any] - vstmia sp!, {q0-q1} - cmp sp, r9 - bne .Lctr_enc_bzero +.Lctr_enc_bzero:@ wipe key schedule [if any] + vstmia sp!, {q0,q1} + cmp sp, r9 + bne .Lctr_enc_bzero #else - vstmia sp, {q0-q1} + vstmia sp, {q0,q1} #endif mov sp, r9 add sp, #0x10 @ add sp,r9,#0x10 is no good for thumb VFP_ABI_POP - ldmia sp!, {r4-r10, pc} @ return + ldmia sp!, {r4,r5,r6,r7,r8,r9,r10, pc} @ return .align 4 .Lctr_enc_short: ldr ip, [sp] @ ctr pointer is passed on stack - stmdb sp!, {r4-r8, lr} + stmdb sp!, {r4,r5,r6,r7,r8, lr} mov r4, r0 @ copy arguments mov r5, r1 mov r6, r2 mov r7, r3 - ldr r8, [ip, #12] @ load counter LSW + ldr r8, [ip, #12] @ load counter .LSW vld1.8 {q1}, [ip] @ load whole counter value #ifdef __ARMEL__ rev r8, r8 #endif sub sp, sp, #0x10 - vst1.8 {q1}, [sp,:64] @ copy counter value + vst1.8 {q1}, [sp] @ copy counter value sub sp, sp, #0x10 .Lctr_enc_short_loop: @@ -1519,7 +1545,7 @@ bsaes_ctr32_encrypt_blocks: bl AES_encrypt vld1.8 {q0}, [r4]! @ load input - vld1.8 {q1}, [sp,:64] @ load encrypted counter + vld1.8 {q1}, [sp] @ load encrypted counter add r8, r8, #1 #ifdef __ARMEL__ rev r0, r8 @@ -1534,9 +1560,9 @@ bsaes_ctr32_encrypt_blocks: vmov.i32 q0, #0 vmov.i32 q1, #0 - vstmia sp!, {q0-q1} + vstmia sp!, {q0,q1} - ldmia sp!, {r4-r8, pc} + ldmia sp!, {r4,r5,r6,r7,r8, pc} .size bsaes_ctr32_encrypt_blocks,.-bsaes_ctr32_encrypt_blocks .globl bsaes_xts_encrypt .hidden bsaes_xts_encrypt @@ -1544,7 +1570,7 @@ bsaes_ctr32_encrypt_blocks: .align 4 bsaes_xts_encrypt: mov ip, sp - stmdb sp!, {r4-r10, lr} @ 0x20 + stmdb sp!, {r4,r5,r6,r7,r8,r9,r10, lr} @ 0x20 VFP_ABI_PUSH mov r6, sp @ future r3 @@ -1598,7 +1624,7 @@ bsaes_xts_encrypt: vstmia r12, {q7} .align 2 -0: sub sp, #0x90 @ place for tweak[9] + sub sp, #0x90 @ place for tweak[9] #endif vld1.8 {q8}, [r0] @ initial tweak @@ -1610,422 +1636,422 @@ bsaes_xts_encrypt: .align 4 .Lxts_enc_loop: - vldmia r2, {q5} @ load XTS magic + vldmia r2, {q5} @ load XTS magic vshr.s64 q6, q8, #63 - mov r0, sp - vand q6, q6, q5 + mov r0, sp + vand q6, q6, q5 vadd.u64 q9, q8, q8 - vst1.64 {q8}, [r0,:128]! - vswp d13,d12 + vst1.64 {q8}, [r0,:128]! + vswp d13,d12 vshr.s64 q7, q9, #63 - veor q9, q9, q6 - vand q7, q7, q5 + veor q9, q9, q6 + vand q7, q7, q5 vadd.u64 q10, q9, q9 - vst1.64 {q9}, [r0,:128]! - vswp d15,d14 + vst1.64 {q9}, [r0,:128]! + vswp d15,d14 vshr.s64 q6, q10, #63 - veor q10, q10, q7 - vand q6, q6, q5 - vld1.8 {q0}, [r7]! + veor q10, q10, q7 + vand q6, q6, q5 + vld1.8 {q0}, [r7]! vadd.u64 q11, q10, q10 - vst1.64 {q10}, [r0,:128]! - vswp d13,d12 + vst1.64 {q10}, [r0,:128]! + vswp d13,d12 vshr.s64 q7, q11, #63 - veor q11, q11, q6 - vand q7, q7, q5 - vld1.8 {q1}, [r7]! - veor q0, q0, q8 + veor q11, q11, q6 + vand q7, q7, q5 + vld1.8 {q1}, [r7]! + veor q0, q0, q8 vadd.u64 q12, q11, q11 - vst1.64 {q11}, [r0,:128]! - vswp d15,d14 + vst1.64 {q11}, [r0,:128]! + vswp d15,d14 vshr.s64 q6, q12, #63 - veor q12, q12, q7 - vand q6, q6, q5 - vld1.8 {q2}, [r7]! - veor q1, q1, q9 + veor q12, q12, q7 + vand q6, q6, q5 + vld1.8 {q2}, [r7]! + veor q1, q1, q9 vadd.u64 q13, q12, q12 - vst1.64 {q12}, [r0,:128]! - vswp d13,d12 + vst1.64 {q12}, [r0,:128]! + vswp d13,d12 vshr.s64 q7, q13, #63 - veor q13, q13, q6 - vand q7, q7, q5 - vld1.8 {q3}, [r7]! - veor q2, q2, q10 + veor q13, q13, q6 + vand q7, q7, q5 + vld1.8 {q3}, [r7]! + veor q2, q2, q10 vadd.u64 q14, q13, q13 - vst1.64 {q13}, [r0,:128]! - vswp d15,d14 + vst1.64 {q13}, [r0,:128]! + vswp d15,d14 vshr.s64 q6, q14, #63 - veor q14, q14, q7 - vand q6, q6, q5 - vld1.8 {q4}, [r7]! - veor q3, q3, q11 + veor q14, q14, q7 + vand q6, q6, q5 + vld1.8 {q4}, [r7]! + veor q3, q3, q11 vadd.u64 q15, q14, q14 - vst1.64 {q14}, [r0,:128]! - vswp d13,d12 + vst1.64 {q14}, [r0,:128]! + vswp d13,d12 vshr.s64 q7, q15, #63 - veor q15, q15, q6 - vand q7, q7, q5 - vld1.8 {q5}, [r7]! - veor q4, q4, q12 + veor q15, q15, q6 + vand q7, q7, q5 + vld1.8 {q5}, [r7]! + veor q4, q4, q12 vadd.u64 q8, q15, q15 - vst1.64 {q15}, [r0,:128]! - vswp d15,d14 - veor q8, q8, q7 - vst1.64 {q8}, [r0,:128] @ next round tweak + vst1.64 {q15}, [r0,:128]! + vswp d15,d14 + veor q8, q8, q7 + vst1.64 {q8}, [r0,:128] @ next round tweak - vld1.8 {q6-q7}, [r7]! - veor q5, q5, q13 + vld1.8 {q6,q7}, [r7]! + veor q5, q5, q13 #ifndef BSAES_ASM_EXTENDED_KEY - add r4, sp, #0x90 @ pass key schedule + add r4, sp, #0x90 @ pass key schedule #else - add r4, r10, #248 @ pass key schedule + add r4, r10, #248 @ pass key schedule #endif - veor q6, q6, q14 - mov r5, r1 @ pass rounds - veor q7, q7, q15 - mov r0, sp - - bl _bsaes_encrypt8 - - vld1.64 {q8-q9}, [r0,:128]! - vld1.64 {q10-q11}, [r0,:128]! - veor q0, q0, q8 - vld1.64 {q12-q13}, [r0,:128]! - veor q1, q1, q9 - veor q8, q4, q10 - vst1.8 {q0-q1}, [r8]! - veor q9, q6, q11 - vld1.64 {q14-q15}, [r0,:128]! - veor q10, q3, q12 - vst1.8 {q8-q9}, [r8]! - veor q11, q7, q13 - veor q12, q2, q14 - vst1.8 {q10-q11}, [r8]! - veor q13, q5, q15 - vst1.8 {q12-q13}, [r8]! - - vld1.64 {q8}, [r0,:128] @ next round tweak - - subs r9, #0x80 - bpl .Lxts_enc_loop + veor q6, q6, q14 + mov r5, r1 @ pass rounds + veor q7, q7, q15 + mov r0, sp + + bl _bsaes_encrypt8 + + vld1.64 {q8,q9}, [r0,:128]! + vld1.64 {q10,q11}, [r0,:128]! + veor q0, q0, q8 + vld1.64 {q12,q13}, [r0,:128]! + veor q1, q1, q9 + veor q8, q4, q10 + vst1.8 {q0,q1}, [r8]! + veor q9, q6, q11 + vld1.64 {q14,q15}, [r0,:128]! + veor q10, q3, q12 + vst1.8 {q8,q9}, [r8]! + veor q11, q7, q13 + veor q12, q2, q14 + vst1.8 {q10,q11}, [r8]! + veor q13, q5, q15 + vst1.8 {q12,q13}, [r8]! + + vld1.64 {q8}, [r0,:128] @ next round tweak + + subs r9, #0x80 + bpl .Lxts_enc_loop .Lxts_enc_short: - adds r9, #0x70 - bmi .Lxts_enc_done + adds r9, #0x70 + bmi .Lxts_enc_done - vldmia r2, {q5} @ load XTS magic + vldmia r2, {q5} @ load XTS magic vshr.s64 q7, q8, #63 - mov r0, sp - vand q7, q7, q5 + mov r0, sp + vand q7, q7, q5 vadd.u64 q9, q8, q8 - vst1.64 {q8}, [r0,:128]! - vswp d15,d14 + vst1.64 {q8}, [r0,:128]! + vswp d15,d14 vshr.s64 q6, q9, #63 - veor q9, q9, q7 - vand q6, q6, q5 + veor q9, q9, q7 + vand q6, q6, q5 vadd.u64 q10, q9, q9 - vst1.64 {q9}, [r0,:128]! - vswp d13,d12 + vst1.64 {q9}, [r0,:128]! + vswp d13,d12 vshr.s64 q7, q10, #63 - veor q10, q10, q6 - vand q7, q7, q5 - vld1.8 {q0}, [r7]! - subs r9, #0x10 - bmi .Lxts_enc_1 + veor q10, q10, q6 + vand q7, q7, q5 + vld1.8 {q0}, [r7]! + subs r9, #0x10 + bmi .Lxts_enc_1 vadd.u64 q11, q10, q10 - vst1.64 {q10}, [r0,:128]! - vswp d15,d14 + vst1.64 {q10}, [r0,:128]! + vswp d15,d14 vshr.s64 q6, q11, #63 - veor q11, q11, q7 - vand q6, q6, q5 - vld1.8 {q1}, [r7]! - subs r9, #0x10 - bmi .Lxts_enc_2 - veor q0, q0, q8 + veor q11, q11, q7 + vand q6, q6, q5 + vld1.8 {q1}, [r7]! + subs r9, #0x10 + bmi .Lxts_enc_2 + veor q0, q0, q8 vadd.u64 q12, q11, q11 - vst1.64 {q11}, [r0,:128]! - vswp d13,d12 + vst1.64 {q11}, [r0,:128]! + vswp d13,d12 vshr.s64 q7, q12, #63 - veor q12, q12, q6 - vand q7, q7, q5 - vld1.8 {q2}, [r7]! - subs r9, #0x10 - bmi .Lxts_enc_3 - veor q1, q1, q9 + veor q12, q12, q6 + vand q7, q7, q5 + vld1.8 {q2}, [r7]! + subs r9, #0x10 + bmi .Lxts_enc_3 + veor q1, q1, q9 vadd.u64 q13, q12, q12 - vst1.64 {q12}, [r0,:128]! - vswp d15,d14 + vst1.64 {q12}, [r0,:128]! + vswp d15,d14 vshr.s64 q6, q13, #63 - veor q13, q13, q7 - vand q6, q6, q5 - vld1.8 {q3}, [r7]! - subs r9, #0x10 - bmi .Lxts_enc_4 - veor q2, q2, q10 + veor q13, q13, q7 + vand q6, q6, q5 + vld1.8 {q3}, [r7]! + subs r9, #0x10 + bmi .Lxts_enc_4 + veor q2, q2, q10 vadd.u64 q14, q13, q13 - vst1.64 {q13}, [r0,:128]! - vswp d13,d12 + vst1.64 {q13}, [r0,:128]! + vswp d13,d12 vshr.s64 q7, q14, #63 - veor q14, q14, q6 - vand q7, q7, q5 - vld1.8 {q4}, [r7]! - subs r9, #0x10 - bmi .Lxts_enc_5 - veor q3, q3, q11 + veor q14, q14, q6 + vand q7, q7, q5 + vld1.8 {q4}, [r7]! + subs r9, #0x10 + bmi .Lxts_enc_5 + veor q3, q3, q11 vadd.u64 q15, q14, q14 - vst1.64 {q14}, [r0,:128]! - vswp d15,d14 + vst1.64 {q14}, [r0,:128]! + vswp d15,d14 vshr.s64 q6, q15, #63 - veor q15, q15, q7 - vand q6, q6, q5 - vld1.8 {q5}, [r7]! - subs r9, #0x10 - bmi .Lxts_enc_6 - veor q4, q4, q12 - sub r9, #0x10 - vst1.64 {q15}, [r0,:128] @ next round tweak - - vld1.8 {q6}, [r7]! - veor q5, q5, q13 + veor q15, q15, q7 + vand q6, q6, q5 + vld1.8 {q5}, [r7]! + subs r9, #0x10 + bmi .Lxts_enc_6 + veor q4, q4, q12 + sub r9, #0x10 + vst1.64 {q15}, [r0,:128] @ next round tweak + + vld1.8 {q6}, [r7]! + veor q5, q5, q13 #ifndef BSAES_ASM_EXTENDED_KEY - add r4, sp, #0x90 @ pass key schedule + add r4, sp, #0x90 @ pass key schedule #else - add r4, r10, #248 @ pass key schedule + add r4, r10, #248 @ pass key schedule #endif - veor q6, q6, q14 - mov r5, r1 @ pass rounds - mov r0, sp - - bl _bsaes_encrypt8 - - vld1.64 {q8-q9}, [r0,:128]! - vld1.64 {q10-q11}, [r0,:128]! - veor q0, q0, q8 - vld1.64 {q12-q13}, [r0,:128]! - veor q1, q1, q9 - veor q8, q4, q10 - vst1.8 {q0-q1}, [r8]! - veor q9, q6, q11 - vld1.64 {q14}, [r0,:128]! - veor q10, q3, q12 - vst1.8 {q8-q9}, [r8]! - veor q11, q7, q13 - veor q12, q2, q14 - vst1.8 {q10-q11}, [r8]! - vst1.8 {q12}, [r8]! - - vld1.64 {q8}, [r0,:128] @ next round tweak - b .Lxts_enc_done + veor q6, q6, q14 + mov r5, r1 @ pass rounds + mov r0, sp + + bl _bsaes_encrypt8 + + vld1.64 {q8,q9}, [r0,:128]! + vld1.64 {q10,q11}, [r0,:128]! + veor q0, q0, q8 + vld1.64 {q12,q13}, [r0,:128]! + veor q1, q1, q9 + veor q8, q4, q10 + vst1.8 {q0,q1}, [r8]! + veor q9, q6, q11 + vld1.64 {q14}, [r0,:128]! + veor q10, q3, q12 + vst1.8 {q8,q9}, [r8]! + veor q11, q7, q13 + veor q12, q2, q14 + vst1.8 {q10,q11}, [r8]! + vst1.8 {q12}, [r8]! + + vld1.64 {q8}, [r0,:128] @ next round tweak + b .Lxts_enc_done .align 4 .Lxts_enc_6: - vst1.64 {q14}, [r0,:128] @ next round tweak + vst1.64 {q14}, [r0,:128] @ next round tweak - veor q4, q4, q12 + veor q4, q4, q12 #ifndef BSAES_ASM_EXTENDED_KEY - add r4, sp, #0x90 @ pass key schedule + add r4, sp, #0x90 @ pass key schedule #else - add r4, r10, #248 @ pass key schedule + add r4, r10, #248 @ pass key schedule #endif - veor q5, q5, q13 - mov r5, r1 @ pass rounds - mov r0, sp - - bl _bsaes_encrypt8 - - vld1.64 {q8-q9}, [r0,:128]! - vld1.64 {q10-q11}, [r0,:128]! - veor q0, q0, q8 - vld1.64 {q12-q13}, [r0,:128]! - veor q1, q1, q9 - veor q8, q4, q10 - vst1.8 {q0-q1}, [r8]! - veor q9, q6, q11 - veor q10, q3, q12 - vst1.8 {q8-q9}, [r8]! - veor q11, q7, q13 - vst1.8 {q10-q11}, [r8]! - - vld1.64 {q8}, [r0,:128] @ next round tweak - b .Lxts_enc_done + veor q5, q5, q13 + mov r5, r1 @ pass rounds + mov r0, sp + + bl _bsaes_encrypt8 + + vld1.64 {q8,q9}, [r0,:128]! + vld1.64 {q10,q11}, [r0,:128]! + veor q0, q0, q8 + vld1.64 {q12,q13}, [r0,:128]! + veor q1, q1, q9 + veor q8, q4, q10 + vst1.8 {q0,q1}, [r8]! + veor q9, q6, q11 + veor q10, q3, q12 + vst1.8 {q8,q9}, [r8]! + veor q11, q7, q13 + vst1.8 {q10,q11}, [r8]! + + vld1.64 {q8}, [r0,:128] @ next round tweak + b .Lxts_enc_done @ put this in range for both ARM and Thumb mode adr instructions .align 5 .Lxts_magic: - .quad 1, 0x87 +.quad 1, 0x87 .align 5 .Lxts_enc_5: - vst1.64 {q13}, [r0,:128] @ next round tweak + vst1.64 {q13}, [r0,:128] @ next round tweak - veor q3, q3, q11 + veor q3, q3, q11 #ifndef BSAES_ASM_EXTENDED_KEY - add r4, sp, #0x90 @ pass key schedule + add r4, sp, #0x90 @ pass key schedule #else - add r4, r10, #248 @ pass key schedule + add r4, r10, #248 @ pass key schedule #endif - veor q4, q4, q12 - mov r5, r1 @ pass rounds - mov r0, sp - - bl _bsaes_encrypt8 - - vld1.64 {q8-q9}, [r0,:128]! - vld1.64 {q10-q11}, [r0,:128]! - veor q0, q0, q8 - vld1.64 {q12}, [r0,:128]! - veor q1, q1, q9 - veor q8, q4, q10 - vst1.8 {q0-q1}, [r8]! - veor q9, q6, q11 - veor q10, q3, q12 - vst1.8 {q8-q9}, [r8]! - vst1.8 {q10}, [r8]! - - vld1.64 {q8}, [r0,:128] @ next round tweak - b .Lxts_enc_done + veor q4, q4, q12 + mov r5, r1 @ pass rounds + mov r0, sp + + bl _bsaes_encrypt8 + + vld1.64 {q8,q9}, [r0,:128]! + vld1.64 {q10,q11}, [r0,:128]! + veor q0, q0, q8 + vld1.64 {q12}, [r0,:128]! + veor q1, q1, q9 + veor q8, q4, q10 + vst1.8 {q0,q1}, [r8]! + veor q9, q6, q11 + veor q10, q3, q12 + vst1.8 {q8,q9}, [r8]! + vst1.8 {q10}, [r8]! + + vld1.64 {q8}, [r0,:128] @ next round tweak + b .Lxts_enc_done .align 4 .Lxts_enc_4: - vst1.64 {q12}, [r0,:128] @ next round tweak + vst1.64 {q12}, [r0,:128] @ next round tweak - veor q2, q2, q10 + veor q2, q2, q10 #ifndef BSAES_ASM_EXTENDED_KEY - add r4, sp, #0x90 @ pass key schedule + add r4, sp, #0x90 @ pass key schedule #else - add r4, r10, #248 @ pass key schedule + add r4, r10, #248 @ pass key schedule #endif - veor q3, q3, q11 - mov r5, r1 @ pass rounds - mov r0, sp - - bl _bsaes_encrypt8 - - vld1.64 {q8-q9}, [r0,:128]! - vld1.64 {q10-q11}, [r0,:128]! - veor q0, q0, q8 - veor q1, q1, q9 - veor q8, q4, q10 - vst1.8 {q0-q1}, [r8]! - veor q9, q6, q11 - vst1.8 {q8-q9}, [r8]! - - vld1.64 {q8}, [r0,:128] @ next round tweak - b .Lxts_enc_done + veor q3, q3, q11 + mov r5, r1 @ pass rounds + mov r0, sp + + bl _bsaes_encrypt8 + + vld1.64 {q8,q9}, [r0,:128]! + vld1.64 {q10,q11}, [r0,:128]! + veor q0, q0, q8 + veor q1, q1, q9 + veor q8, q4, q10 + vst1.8 {q0,q1}, [r8]! + veor q9, q6, q11 + vst1.8 {q8,q9}, [r8]! + + vld1.64 {q8}, [r0,:128] @ next round tweak + b .Lxts_enc_done .align 4 .Lxts_enc_3: - vst1.64 {q11}, [r0,:128] @ next round tweak + vst1.64 {q11}, [r0,:128] @ next round tweak - veor q1, q1, q9 + veor q1, q1, q9 #ifndef BSAES_ASM_EXTENDED_KEY - add r4, sp, #0x90 @ pass key schedule + add r4, sp, #0x90 @ pass key schedule #else - add r4, r10, #248 @ pass key schedule + add r4, r10, #248 @ pass key schedule #endif - veor q2, q2, q10 - mov r5, r1 @ pass rounds - mov r0, sp - - bl _bsaes_encrypt8 - - vld1.64 {q8-q9}, [r0,:128]! - vld1.64 {q10}, [r0,:128]! - veor q0, q0, q8 - veor q1, q1, q9 - veor q8, q4, q10 - vst1.8 {q0-q1}, [r8]! - vst1.8 {q8}, [r8]! - - vld1.64 {q8}, [r0,:128] @ next round tweak - b .Lxts_enc_done + veor q2, q2, q10 + mov r5, r1 @ pass rounds + mov r0, sp + + bl _bsaes_encrypt8 + + vld1.64 {q8,q9}, [r0,:128]! + vld1.64 {q10}, [r0,:128]! + veor q0, q0, q8 + veor q1, q1, q9 + veor q8, q4, q10 + vst1.8 {q0,q1}, [r8]! + vst1.8 {q8}, [r8]! + + vld1.64 {q8}, [r0,:128] @ next round tweak + b .Lxts_enc_done .align 4 .Lxts_enc_2: - vst1.64 {q10}, [r0,:128] @ next round tweak + vst1.64 {q10}, [r0,:128] @ next round tweak - veor q0, q0, q8 + veor q0, q0, q8 #ifndef BSAES_ASM_EXTENDED_KEY - add r4, sp, #0x90 @ pass key schedule + add r4, sp, #0x90 @ pass key schedule #else - add r4, r10, #248 @ pass key schedule + add r4, r10, #248 @ pass key schedule #endif - veor q1, q1, q9 - mov r5, r1 @ pass rounds - mov r0, sp + veor q1, q1, q9 + mov r5, r1 @ pass rounds + mov r0, sp - bl _bsaes_encrypt8 + bl _bsaes_encrypt8 - vld1.64 {q8-q9}, [r0,:128]! - veor q0, q0, q8 - veor q1, q1, q9 - vst1.8 {q0-q1}, [r8]! + vld1.64 {q8,q9}, [r0,:128]! + veor q0, q0, q8 + veor q1, q1, q9 + vst1.8 {q0,q1}, [r8]! - vld1.64 {q8}, [r0,:128] @ next round tweak - b .Lxts_enc_done + vld1.64 {q8}, [r0,:128] @ next round tweak + b .Lxts_enc_done .align 4 .Lxts_enc_1: - mov r0, sp - veor q0, q8 - mov r1, sp - vst1.8 {q0}, [sp,:128] - mov r2, r10 - mov r4, r3 @ preserve fp + mov r0, sp + veor q0, q8 + mov r1, sp + vst1.8 {q0}, [sp,:128] + mov r2, r10 + mov r4, r3 @ preserve fp - bl AES_encrypt + bl AES_encrypt - vld1.8 {q0}, [sp,:128] - veor q0, q0, q8 - vst1.8 {q0}, [r8]! - mov r3, r4 + vld1.8 {q0}, [sp,:128] + veor q0, q0, q8 + vst1.8 {q0}, [r8]! + mov r3, r4 - vmov q8, q9 @ next round tweak + vmov q8, q9 @ next round tweak .Lxts_enc_done: #ifndef XTS_CHAIN_TWEAK - adds r9, #0x10 - beq .Lxts_enc_ret - sub r6, r8, #0x10 + adds r9, #0x10 + beq .Lxts_enc_ret + sub r6, r8, #0x10 .Lxts_enc_steal: - ldrb r0, [r7], #1 - ldrb r1, [r8, #-0x10] - strb r0, [r8, #-0x10] - strb r1, [r8], #1 - - subs r9, #1 - bhi .Lxts_enc_steal - - vld1.8 {q0}, [r6] - mov r0, sp - veor q0, q0, q8 - mov r1, sp - vst1.8 {q0}, [sp,:128] - mov r2, r10 - mov r4, r3 @ preserve fp - - bl AES_encrypt - - vld1.8 {q0}, [sp,:128] - veor q0, q0, q8 - vst1.8 {q0}, [r6] - mov r3, r4 + ldrb r0, [r7], #1 + ldrb r1, [r8, #-0x10] + strb r0, [r8, #-0x10] + strb r1, [r8], #1 + + subs r9, #1 + bhi .Lxts_enc_steal + + vld1.8 {q0}, [r6] + mov r0, sp + veor q0, q0, q8 + mov r1, sp + vst1.8 {q0}, [sp,:128] + mov r2, r10 + mov r4, r3 @ preserve fp + + bl AES_encrypt + + vld1.8 {q0}, [sp,:128] + veor q0, q0, q8 + vst1.8 {q0}, [r6] + mov r3, r4 #endif .Lxts_enc_ret: - bic r0, r3, #0xf + bic r0, r3, #0xf vmov.i32 q0, #0 vmov.i32 q1, #0 #ifdef XTS_CHAIN_TWEAK - ldr r1, [r3, #0x20+VFP_ABI_FRAME] @ chain tweak + ldr r1, [r3, #0x20+VFP_ABI_FRAME] @ chain tweak #endif -.Lxts_enc_bzero: @ wipe key schedule [if any] - vstmia sp!, {q0-q1} - cmp sp, r0 - bne .Lxts_enc_bzero +.Lxts_enc_bzero:@ wipe key schedule [if any] + vstmia sp!, {q0,q1} + cmp sp, r0 + bne .Lxts_enc_bzero - mov sp, r3 + mov sp, r3 #ifdef XTS_CHAIN_TWEAK - vst1.8 {q8}, [r1] + vst1.8 {q8}, [r1] #endif VFP_ABI_POP - ldmia sp!, {r4-r10, pc} @ return + ldmia sp!, {r4,r5,r6,r7,r8,r9,r10, pc} @ return .size bsaes_xts_encrypt,.-bsaes_xts_encrypt @@ -2035,7 +2061,7 @@ bsaes_xts_encrypt: .align 4 bsaes_xts_decrypt: mov ip, sp - stmdb sp!, {r4-r10, lr} @ 0x20 + stmdb sp!, {r4,r5,r6,r7,r8,r9,r10, lr} @ 0x20 VFP_ABI_PUSH mov r6, sp @ future r3 @@ -2095,14 +2121,16 @@ bsaes_xts_decrypt: vstmia r4, {q7} .align 2 -0: sub sp, #0x90 @ place for tweak[9] + sub sp, #0x90 @ place for tweak[9] #endif vld1.8 {q8}, [r0] @ initial tweak adr r2, .Lxts_magic +#ifndef XTS_CHAIN_TWEAK tst r9, #0xf @ if not multiple of 16 it ne @ Thumb2 thing, sanity check in ARM subne r9, #0x10 @ subtract another 16 bytes +#endif subs r9, #0x80 blo .Lxts_dec_short @@ -2110,441 +2138,442 @@ bsaes_xts_decrypt: .align 4 .Lxts_dec_loop: - vldmia r2, {q5} @ load XTS magic + vldmia r2, {q5} @ load XTS magic vshr.s64 q6, q8, #63 - mov r0, sp - vand q6, q6, q5 + mov r0, sp + vand q6, q6, q5 vadd.u64 q9, q8, q8 - vst1.64 {q8}, [r0,:128]! - vswp d13,d12 + vst1.64 {q8}, [r0,:128]! + vswp d13,d12 vshr.s64 q7, q9, #63 - veor q9, q9, q6 - vand q7, q7, q5 + veor q9, q9, q6 + vand q7, q7, q5 vadd.u64 q10, q9, q9 - vst1.64 {q9}, [r0,:128]! - vswp d15,d14 + vst1.64 {q9}, [r0,:128]! + vswp d15,d14 vshr.s64 q6, q10, #63 - veor q10, q10, q7 - vand q6, q6, q5 - vld1.8 {q0}, [r7]! + veor q10, q10, q7 + vand q6, q6, q5 + vld1.8 {q0}, [r7]! vadd.u64 q11, q10, q10 - vst1.64 {q10}, [r0,:128]! - vswp d13,d12 + vst1.64 {q10}, [r0,:128]! + vswp d13,d12 vshr.s64 q7, q11, #63 - veor q11, q11, q6 - vand q7, q7, q5 - vld1.8 {q1}, [r7]! - veor q0, q0, q8 + veor q11, q11, q6 + vand q7, q7, q5 + vld1.8 {q1}, [r7]! + veor q0, q0, q8 vadd.u64 q12, q11, q11 - vst1.64 {q11}, [r0,:128]! - vswp d15,d14 + vst1.64 {q11}, [r0,:128]! + vswp d15,d14 vshr.s64 q6, q12, #63 - veor q12, q12, q7 - vand q6, q6, q5 - vld1.8 {q2}, [r7]! - veor q1, q1, q9 + veor q12, q12, q7 + vand q6, q6, q5 + vld1.8 {q2}, [r7]! + veor q1, q1, q9 vadd.u64 q13, q12, q12 - vst1.64 {q12}, [r0,:128]! - vswp d13,d12 + vst1.64 {q12}, [r0,:128]! + vswp d13,d12 vshr.s64 q7, q13, #63 - veor q13, q13, q6 - vand q7, q7, q5 - vld1.8 {q3}, [r7]! - veor q2, q2, q10 + veor q13, q13, q6 + vand q7, q7, q5 + vld1.8 {q3}, [r7]! + veor q2, q2, q10 vadd.u64 q14, q13, q13 - vst1.64 {q13}, [r0,:128]! - vswp d15,d14 + vst1.64 {q13}, [r0,:128]! + vswp d15,d14 vshr.s64 q6, q14, #63 - veor q14, q14, q7 - vand q6, q6, q5 - vld1.8 {q4}, [r7]! - veor q3, q3, q11 + veor q14, q14, q7 + vand q6, q6, q5 + vld1.8 {q4}, [r7]! + veor q3, q3, q11 vadd.u64 q15, q14, q14 - vst1.64 {q14}, [r0,:128]! - vswp d13,d12 + vst1.64 {q14}, [r0,:128]! + vswp d13,d12 vshr.s64 q7, q15, #63 - veor q15, q15, q6 - vand q7, q7, q5 - vld1.8 {q5}, [r7]! - veor q4, q4, q12 + veor q15, q15, q6 + vand q7, q7, q5 + vld1.8 {q5}, [r7]! + veor q4, q4, q12 vadd.u64 q8, q15, q15 - vst1.64 {q15}, [r0,:128]! - vswp d15,d14 - veor q8, q8, q7 - vst1.64 {q8}, [r0,:128] @ next round tweak + vst1.64 {q15}, [r0,:128]! + vswp d15,d14 + veor q8, q8, q7 + vst1.64 {q8}, [r0,:128] @ next round tweak - vld1.8 {q6-q7}, [r7]! - veor q5, q5, q13 + vld1.8 {q6,q7}, [r7]! + veor q5, q5, q13 #ifndef BSAES_ASM_EXTENDED_KEY - add r4, sp, #0x90 @ pass key schedule + add r4, sp, #0x90 @ pass key schedule #else - add r4, r10, #248 @ pass key schedule + add r4, r10, #248 @ pass key schedule #endif - veor q6, q6, q14 - mov r5, r1 @ pass rounds - veor q7, q7, q15 - mov r0, sp - - bl _bsaes_decrypt8 - - vld1.64 {q8-q9}, [r0,:128]! - vld1.64 {q10-q11}, [r0,:128]! - veor q0, q0, q8 - vld1.64 {q12-q13}, [r0,:128]! - veor q1, q1, q9 - veor q8, q6, q10 - vst1.8 {q0-q1}, [r8]! - veor q9, q4, q11 - vld1.64 {q14-q15}, [r0,:128]! - veor q10, q2, q12 - vst1.8 {q8-q9}, [r8]! - veor q11, q7, q13 - veor q12, q3, q14 - vst1.8 {q10-q11}, [r8]! - veor q13, q5, q15 - vst1.8 {q12-q13}, [r8]! - - vld1.64 {q8}, [r0,:128] @ next round tweak - - subs r9, #0x80 - bpl .Lxts_dec_loop + veor q6, q6, q14 + mov r5, r1 @ pass rounds + veor q7, q7, q15 + mov r0, sp + + bl _bsaes_decrypt8 + + vld1.64 {q8,q9}, [r0,:128]! + vld1.64 {q10,q11}, [r0,:128]! + veor q0, q0, q8 + vld1.64 {q12,q13}, [r0,:128]! + veor q1, q1, q9 + veor q8, q6, q10 + vst1.8 {q0,q1}, [r8]! + veor q9, q4, q11 + vld1.64 {q14,q15}, [r0,:128]! + veor q10, q2, q12 + vst1.8 {q8,q9}, [r8]! + veor q11, q7, q13 + veor q12, q3, q14 + vst1.8 {q10,q11}, [r8]! + veor q13, q5, q15 + vst1.8 {q12,q13}, [r8]! + + vld1.64 {q8}, [r0,:128] @ next round tweak + + subs r9, #0x80 + bpl .Lxts_dec_loop .Lxts_dec_short: - adds r9, #0x70 - bmi .Lxts_dec_done + adds r9, #0x70 + bmi .Lxts_dec_done - vldmia r2, {q5} @ load XTS magic + vldmia r2, {q5} @ load XTS magic vshr.s64 q7, q8, #63 - mov r0, sp - vand q7, q7, q5 + mov r0, sp + vand q7, q7, q5 vadd.u64 q9, q8, q8 - vst1.64 {q8}, [r0,:128]! - vswp d15,d14 + vst1.64 {q8}, [r0,:128]! + vswp d15,d14 vshr.s64 q6, q9, #63 - veor q9, q9, q7 - vand q6, q6, q5 + veor q9, q9, q7 + vand q6, q6, q5 vadd.u64 q10, q9, q9 - vst1.64 {q9}, [r0,:128]! - vswp d13,d12 + vst1.64 {q9}, [r0,:128]! + vswp d13,d12 vshr.s64 q7, q10, #63 - veor q10, q10, q6 - vand q7, q7, q5 - vld1.8 {q0}, [r7]! - subs r9, #0x10 - bmi .Lxts_dec_1 + veor q10, q10, q6 + vand q7, q7, q5 + vld1.8 {q0}, [r7]! + subs r9, #0x10 + bmi .Lxts_dec_1 vadd.u64 q11, q10, q10 - vst1.64 {q10}, [r0,:128]! - vswp d15,d14 + vst1.64 {q10}, [r0,:128]! + vswp d15,d14 vshr.s64 q6, q11, #63 - veor q11, q11, q7 - vand q6, q6, q5 - vld1.8 {q1}, [r7]! - subs r9, #0x10 - bmi .Lxts_dec_2 - veor q0, q0, q8 + veor q11, q11, q7 + vand q6, q6, q5 + vld1.8 {q1}, [r7]! + subs r9, #0x10 + bmi .Lxts_dec_2 + veor q0, q0, q8 vadd.u64 q12, q11, q11 - vst1.64 {q11}, [r0,:128]! - vswp d13,d12 + vst1.64 {q11}, [r0,:128]! + vswp d13,d12 vshr.s64 q7, q12, #63 - veor q12, q12, q6 - vand q7, q7, q5 - vld1.8 {q2}, [r7]! - subs r9, #0x10 - bmi .Lxts_dec_3 - veor q1, q1, q9 + veor q12, q12, q6 + vand q7, q7, q5 + vld1.8 {q2}, [r7]! + subs r9, #0x10 + bmi .Lxts_dec_3 + veor q1, q1, q9 vadd.u64 q13, q12, q12 - vst1.64 {q12}, [r0,:128]! - vswp d15,d14 + vst1.64 {q12}, [r0,:128]! + vswp d15,d14 vshr.s64 q6, q13, #63 - veor q13, q13, q7 - vand q6, q6, q5 - vld1.8 {q3}, [r7]! - subs r9, #0x10 - bmi .Lxts_dec_4 - veor q2, q2, q10 + veor q13, q13, q7 + vand q6, q6, q5 + vld1.8 {q3}, [r7]! + subs r9, #0x10 + bmi .Lxts_dec_4 + veor q2, q2, q10 vadd.u64 q14, q13, q13 - vst1.64 {q13}, [r0,:128]! - vswp d13,d12 + vst1.64 {q13}, [r0,:128]! + vswp d13,d12 vshr.s64 q7, q14, #63 - veor q14, q14, q6 - vand q7, q7, q5 - vld1.8 {q4}, [r7]! - subs r9, #0x10 - bmi .Lxts_dec_5 - veor q3, q3, q11 + veor q14, q14, q6 + vand q7, q7, q5 + vld1.8 {q4}, [r7]! + subs r9, #0x10 + bmi .Lxts_dec_5 + veor q3, q3, q11 vadd.u64 q15, q14, q14 - vst1.64 {q14}, [r0,:128]! - vswp d15,d14 + vst1.64 {q14}, [r0,:128]! + vswp d15,d14 vshr.s64 q6, q15, #63 - veor q15, q15, q7 - vand q6, q6, q5 - vld1.8 {q5}, [r7]! - subs r9, #0x10 - bmi .Lxts_dec_6 - veor q4, q4, q12 - sub r9, #0x10 - vst1.64 {q15}, [r0,:128] @ next round tweak - - vld1.8 {q6}, [r7]! - veor q5, q5, q13 + veor q15, q15, q7 + vand q6, q6, q5 + vld1.8 {q5}, [r7]! + subs r9, #0x10 + bmi .Lxts_dec_6 + veor q4, q4, q12 + sub r9, #0x10 + vst1.64 {q15}, [r0,:128] @ next round tweak + + vld1.8 {q6}, [r7]! + veor q5, q5, q13 #ifndef BSAES_ASM_EXTENDED_KEY - add r4, sp, #0x90 @ pass key schedule + add r4, sp, #0x90 @ pass key schedule #else - add r4, r10, #248 @ pass key schedule + add r4, r10, #248 @ pass key schedule #endif - veor q6, q6, q14 - mov r5, r1 @ pass rounds - mov r0, sp - - bl _bsaes_decrypt8 - - vld1.64 {q8-q9}, [r0,:128]! - vld1.64 {q10-q11}, [r0,:128]! - veor q0, q0, q8 - vld1.64 {q12-q13}, [r0,:128]! - veor q1, q1, q9 - veor q8, q6, q10 - vst1.8 {q0-q1}, [r8]! - veor q9, q4, q11 - vld1.64 {q14}, [r0,:128]! - veor q10, q2, q12 - vst1.8 {q8-q9}, [r8]! - veor q11, q7, q13 - veor q12, q3, q14 - vst1.8 {q10-q11}, [r8]! - vst1.8 {q12}, [r8]! - - vld1.64 {q8}, [r0,:128] @ next round tweak - b .Lxts_dec_done + veor q6, q6, q14 + mov r5, r1 @ pass rounds + mov r0, sp + + bl _bsaes_decrypt8 + + vld1.64 {q8,q9}, [r0,:128]! + vld1.64 {q10,q11}, [r0,:128]! + veor q0, q0, q8 + vld1.64 {q12,q13}, [r0,:128]! + veor q1, q1, q9 + veor q8, q6, q10 + vst1.8 {q0,q1}, [r8]! + veor q9, q4, q11 + vld1.64 {q14}, [r0,:128]! + veor q10, q2, q12 + vst1.8 {q8,q9}, [r8]! + veor q11, q7, q13 + veor q12, q3, q14 + vst1.8 {q10,q11}, [r8]! + vst1.8 {q12}, [r8]! + + vld1.64 {q8}, [r0,:128] @ next round tweak + b .Lxts_dec_done .align 4 .Lxts_dec_6: - vst1.64 {q14}, [r0,:128] @ next round tweak + vst1.64 {q14}, [r0,:128] @ next round tweak - veor q4, q4, q12 + veor q4, q4, q12 #ifndef BSAES_ASM_EXTENDED_KEY - add r4, sp, #0x90 @ pass key schedule + add r4, sp, #0x90 @ pass key schedule #else - add r4, r10, #248 @ pass key schedule + add r4, r10, #248 @ pass key schedule #endif - veor q5, q5, q13 - mov r5, r1 @ pass rounds - mov r0, sp - - bl _bsaes_decrypt8 - - vld1.64 {q8-q9}, [r0,:128]! - vld1.64 {q10-q11}, [r0,:128]! - veor q0, q0, q8 - vld1.64 {q12-q13}, [r0,:128]! - veor q1, q1, q9 - veor q8, q6, q10 - vst1.8 {q0-q1}, [r8]! - veor q9, q4, q11 - veor q10, q2, q12 - vst1.8 {q8-q9}, [r8]! - veor q11, q7, q13 - vst1.8 {q10-q11}, [r8]! - - vld1.64 {q8}, [r0,:128] @ next round tweak - b .Lxts_dec_done + veor q5, q5, q13 + mov r5, r1 @ pass rounds + mov r0, sp + + bl _bsaes_decrypt8 + + vld1.64 {q8,q9}, [r0,:128]! + vld1.64 {q10,q11}, [r0,:128]! + veor q0, q0, q8 + vld1.64 {q12,q13}, [r0,:128]! + veor q1, q1, q9 + veor q8, q6, q10 + vst1.8 {q0,q1}, [r8]! + veor q9, q4, q11 + veor q10, q2, q12 + vst1.8 {q8,q9}, [r8]! + veor q11, q7, q13 + vst1.8 {q10,q11}, [r8]! + + vld1.64 {q8}, [r0,:128] @ next round tweak + b .Lxts_dec_done .align 4 .Lxts_dec_5: - vst1.64 {q13}, [r0,:128] @ next round tweak + vst1.64 {q13}, [r0,:128] @ next round tweak - veor q3, q3, q11 + veor q3, q3, q11 #ifndef BSAES_ASM_EXTENDED_KEY - add r4, sp, #0x90 @ pass key schedule + add r4, sp, #0x90 @ pass key schedule #else - add r4, r10, #248 @ pass key schedule + add r4, r10, #248 @ pass key schedule #endif - veor q4, q4, q12 - mov r5, r1 @ pass rounds - mov r0, sp - - bl _bsaes_decrypt8 - - vld1.64 {q8-q9}, [r0,:128]! - vld1.64 {q10-q11}, [r0,:128]! - veor q0, q0, q8 - vld1.64 {q12}, [r0,:128]! - veor q1, q1, q9 - veor q8, q6, q10 - vst1.8 {q0-q1}, [r8]! - veor q9, q4, q11 - veor q10, q2, q12 - vst1.8 {q8-q9}, [r8]! - vst1.8 {q10}, [r8]! - - vld1.64 {q8}, [r0,:128] @ next round tweak - b .Lxts_dec_done + veor q4, q4, q12 + mov r5, r1 @ pass rounds + mov r0, sp + + bl _bsaes_decrypt8 + + vld1.64 {q8,q9}, [r0,:128]! + vld1.64 {q10,q11}, [r0,:128]! + veor q0, q0, q8 + vld1.64 {q12}, [r0,:128]! + veor q1, q1, q9 + veor q8, q6, q10 + vst1.8 {q0,q1}, [r8]! + veor q9, q4, q11 + veor q10, q2, q12 + vst1.8 {q8,q9}, [r8]! + vst1.8 {q10}, [r8]! + + vld1.64 {q8}, [r0,:128] @ next round tweak + b .Lxts_dec_done .align 4 .Lxts_dec_4: - vst1.64 {q12}, [r0,:128] @ next round tweak + vst1.64 {q12}, [r0,:128] @ next round tweak - veor q2, q2, q10 + veor q2, q2, q10 #ifndef BSAES_ASM_EXTENDED_KEY - add r4, sp, #0x90 @ pass key schedule + add r4, sp, #0x90 @ pass key schedule #else - add r4, r10, #248 @ pass key schedule + add r4, r10, #248 @ pass key schedule #endif - veor q3, q3, q11 - mov r5, r1 @ pass rounds - mov r0, sp - - bl _bsaes_decrypt8 - - vld1.64 {q8-q9}, [r0,:128]! - vld1.64 {q10-q11}, [r0,:128]! - veor q0, q0, q8 - veor q1, q1, q9 - veor q8, q6, q10 - vst1.8 {q0-q1}, [r8]! - veor q9, q4, q11 - vst1.8 {q8-q9}, [r8]! - - vld1.64 {q8}, [r0,:128] @ next round tweak - b .Lxts_dec_done + veor q3, q3, q11 + mov r5, r1 @ pass rounds + mov r0, sp + + bl _bsaes_decrypt8 + + vld1.64 {q8,q9}, [r0,:128]! + vld1.64 {q10,q11}, [r0,:128]! + veor q0, q0, q8 + veor q1, q1, q9 + veor q8, q6, q10 + vst1.8 {q0,q1}, [r8]! + veor q9, q4, q11 + vst1.8 {q8,q9}, [r8]! + + vld1.64 {q8}, [r0,:128] @ next round tweak + b .Lxts_dec_done .align 4 .Lxts_dec_3: - vst1.64 {q11}, [r0,:128] @ next round tweak + vst1.64 {q11}, [r0,:128] @ next round tweak - veor q1, q1, q9 + veor q1, q1, q9 #ifndef BSAES_ASM_EXTENDED_KEY - add r4, sp, #0x90 @ pass key schedule + add r4, sp, #0x90 @ pass key schedule #else - add r4, r10, #248 @ pass key schedule + add r4, r10, #248 @ pass key schedule #endif - veor q2, q2, q10 - mov r5, r1 @ pass rounds - mov r0, sp - - bl _bsaes_decrypt8 - - vld1.64 {q8-q9}, [r0,:128]! - vld1.64 {q10}, [r0,:128]! - veor q0, q0, q8 - veor q1, q1, q9 - veor q8, q6, q10 - vst1.8 {q0-q1}, [r8]! - vst1.8 {q8}, [r8]! - - vld1.64 {q8}, [r0,:128] @ next round tweak - b .Lxts_dec_done + veor q2, q2, q10 + mov r5, r1 @ pass rounds + mov r0, sp + + bl _bsaes_decrypt8 + + vld1.64 {q8,q9}, [r0,:128]! + vld1.64 {q10}, [r0,:128]! + veor q0, q0, q8 + veor q1, q1, q9 + veor q8, q6, q10 + vst1.8 {q0,q1}, [r8]! + vst1.8 {q8}, [r8]! + + vld1.64 {q8}, [r0,:128] @ next round tweak + b .Lxts_dec_done .align 4 .Lxts_dec_2: - vst1.64 {q10}, [r0,:128] @ next round tweak + vst1.64 {q10}, [r0,:128] @ next round tweak - veor q0, q0, q8 + veor q0, q0, q8 #ifndef BSAES_ASM_EXTENDED_KEY - add r4, sp, #0x90 @ pass key schedule + add r4, sp, #0x90 @ pass key schedule #else - add r4, r10, #248 @ pass key schedule + add r4, r10, #248 @ pass key schedule #endif - veor q1, q1, q9 - mov r5, r1 @ pass rounds - mov r0, sp + veor q1, q1, q9 + mov r5, r1 @ pass rounds + mov r0, sp - bl _bsaes_decrypt8 + bl _bsaes_decrypt8 - vld1.64 {q8-q9}, [r0,:128]! - veor q0, q0, q8 - veor q1, q1, q9 - vst1.8 {q0-q1}, [r8]! + vld1.64 {q8,q9}, [r0,:128]! + veor q0, q0, q8 + veor q1, q1, q9 + vst1.8 {q0,q1}, [r8]! - vld1.64 {q8}, [r0,:128] @ next round tweak - b .Lxts_dec_done + vld1.64 {q8}, [r0,:128] @ next round tweak + b .Lxts_dec_done .align 4 .Lxts_dec_1: - mov r0, sp - veor q0, q8 - mov r1, sp - vst1.8 {q0}, [sp,:128] - mov r2, r10 - mov r4, r3 @ preserve fp - mov r5, r2 @ preserve magic + mov r0, sp + veor q0, q8 + mov r1, sp + vst1.8 {q0}, [sp,:128] + mov r2, r10 + mov r4, r3 @ preserve fp + mov r5, r2 @ preserve magic - bl AES_decrypt + bl AES_decrypt - vld1.8 {q0}, [sp,:128] - veor q0, q0, q8 - vst1.8 {q0}, [r8]! - mov r3, r4 - mov r2, r5 + vld1.8 {q0}, [sp,:128] + veor q0, q0, q8 + vst1.8 {q0}, [r8]! + mov r3, r4 + mov r2, r5 - vmov q8, q9 @ next round tweak + vmov q8, q9 @ next round tweak .Lxts_dec_done: #ifndef XTS_CHAIN_TWEAK - adds r9, #0x10 - beq .Lxts_dec_ret + adds r9, #0x10 + beq .Lxts_dec_ret @ calculate one round of extra tweak for the stolen ciphertext - vldmia r2, {q5} + vldmia r2, {q5} vshr.s64 q6, q8, #63 - vand q6, q6, q5 + vand q6, q6, q5 vadd.u64 q9, q8, q8 - vswp d13,d12 - veor q9, q9, q6 + vswp d13,d12 + veor q9, q9, q6 @ perform the final decryption with the last tweak value - vld1.8 {q0}, [r7]! - mov r0, sp - veor q0, q0, q9 - mov r1, sp - vst1.8 {q0}, [sp,:128] - mov r2, r10 - mov r4, r3 @ preserve fp + vld1.8 {q0}, [r7]! + mov r0, sp + veor q0, q0, q9 + mov r1, sp + vst1.8 {q0}, [sp,:128] + mov r2, r10 + mov r4, r3 @ preserve fp - bl AES_decrypt + bl AES_decrypt - vld1.8 {q0}, [sp,:128] - veor q0, q0, q9 - vst1.8 {q0}, [r8] + vld1.8 {q0}, [sp,:128] + veor q0, q0, q9 + vst1.8 {q0}, [r8] - mov r6, r8 + mov r6, r8 .Lxts_dec_steal: - ldrb r1, [r8] - ldrb r0, [r7], #1 - strb r1, [r8, #0x10] - strb r0, [r8], #1 - - subs r9, #1 - bhi .Lxts_dec_steal - - vld1.8 {q0}, [r6] - mov r0, sp - veor q0, q8 - mov r1, sp - vst1.8 {q0}, [sp,:128] - mov r2, r10 - - bl AES_decrypt - - vld1.8 {q0}, [sp,:128] - veor q0, q0, q8 - vst1.8 {q0}, [r6] - mov r3, r4 + ldrb r1, [r8] + ldrb r0, [r7], #1 + strb r1, [r8, #0x10] + strb r0, [r8], #1 + + subs r9, #1 + bhi .Lxts_dec_steal + + vld1.8 {q0}, [r6] + mov r0, sp + veor q0, q8 + mov r1, sp + vst1.8 {q0}, [sp,:128] + mov r2, r10 + + bl AES_decrypt + + vld1.8 {q0}, [sp,:128] + veor q0, q0, q8 + vst1.8 {q0}, [r6] + mov r3, r4 #endif .Lxts_dec_ret: - bic r0, r3, #0xf + bic r0, r3, #0xf vmov.i32 q0, #0 vmov.i32 q1, #0 #ifdef XTS_CHAIN_TWEAK - ldr r1, [r3, #0x20+VFP_ABI_FRAME] @ chain tweak + ldr r1, [r3, #0x20+VFP_ABI_FRAME] @ chain tweak #endif -.Lxts_dec_bzero: @ wipe key schedule [if any] - vstmia sp!, {q0-q1} - cmp sp, r0 - bne .Lxts_dec_bzero +.Lxts_dec_bzero:@ wipe key schedule [if any] + vstmia sp!, {q0,q1} + cmp sp, r0 + bne .Lxts_dec_bzero - mov sp, r3 + mov sp, r3 #ifdef XTS_CHAIN_TWEAK - vst1.8 {q8}, [r1] + vst1.8 {q8}, [r1] #endif VFP_ABI_POP - ldmia sp!, {r4-r10, pc} @ return + ldmia sp!, {r4,r5,r6,r7,r8,r9,r10, pc} @ return .size bsaes_xts_decrypt,.-bsaes_xts_decrypt #endif #endif +#endif \ No newline at end of file diff --git a/third_party/boringssl/linux-arm/crypto/bn/armv4-mont.S b/third_party/boringssl/linux-arm/crypto/bn/armv4-mont.S index aafc4500fe441..68dfb2c1724b0 100644 --- a/third_party/boringssl/linux-arm/crypto/bn/armv4-mont.S +++ b/third_party/boringssl/linux-arm/crypto/bn/armv4-mont.S @@ -1,28 +1,33 @@ +#if defined(__arm__) #include "arm_arch.h" .text .code 32 -#if __ARM_ARCH__>=7 +#if __ARM_MAX_ARCH__>=7 .align 5 .LOPENSSL_armcap: -.word OPENSSL_armcap_P-bn_mul_mont +.word OPENSSL_armcap_P-.Lbn_mul_mont #endif -.global bn_mul_mont +.globl bn_mul_mont .hidden bn_mul_mont .type bn_mul_mont,%function .align 5 bn_mul_mont: +.Lbn_mul_mont: ldr ip,[sp,#4] @ load num stmdb sp!,{r0,r2} @ sp points at argument block -#if __ARM_ARCH__>=7 +#if __ARM_MAX_ARCH__>=7 tst ip,#7 bne .Lialu adr r0,bn_mul_mont ldr r2,.LOPENSSL_armcap ldr r0,[r0,r2] +#ifdef __APPLE__ + ldr r0,[r0] +#endif tst r0,#1 @ NEON available? ldmia sp, {r0,r2} beq .Lialu @@ -37,7 +42,7 @@ bn_mul_mont: addlt sp,sp,#2*4 blt .Labrt - stmdb sp!,{r4-r12,lr} @ save 10 registers + stmdb sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,lr} @ save 10 registers mov r0,r0,lsl#2 @ rescale r0 for byte count sub sp,sp,r0 @ alloca(4*num) @@ -81,7 +86,7 @@ bn_mul_mont: adc r14,r14,#0 str r12,[r0] @ tp[num-1]= str r14,[r0,#4] @ tp[num]= - + .Louter: sub r7,r0,sp @ "original" r0-1 value sub r1,r1,r7 @ "rewind" ap to &ap[1] @@ -129,7 +134,7 @@ bn_mul_mont: cmp r4,r7 bne .Louter - + ldr r2,[r0,#12*4] @ pull rp add r0,r0,#4 @ r0 to point at &tp[num] sub r5,r0,sp @ "original" num value @@ -159,34 +164,40 @@ bn_mul_mont: bne .Lcopy add sp,r0,#4 @ skip over tp[num+1] - ldmia sp!,{r4-r12,lr} @ restore registers + ldmia sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,lr} @ restore registers add sp,sp,#2*4 @ skip over {r0,r2} mov r0,#1 -.Labrt: tst lr,#1 +.Labrt: +#if __ARM_ARCH__>=5 + bx lr @ .word 0xe12fff1e +#else + tst lr,#1 moveq pc,lr @ be binary compatible with V4, yet - .word 0xe12fff1e @ interoperable with Thumb ISA:-) +.word 0xe12fff1e @ interoperable with Thumb ISA:-) +#endif .size bn_mul_mont,.-bn_mul_mont -#if __ARM_ARCH__>=7 +#if __ARM_MAX_ARCH__>=7 +.arch armv7-a .fpu neon .type bn_mul8x_mont_neon,%function .align 5 bn_mul8x_mont_neon: mov ip,sp - stmdb sp!,{r4-r11} - vstmdb sp!,{d8-d15} @ ABI specification says so - ldmia ip,{r4-r5} @ load rest of parameter block - - sub r7,sp,#16 - vld1.32 {d28[0]}, [r2,:32]! - sub r7,r7,r5,lsl#4 - vld1.32 {d0-d3}, [r1]! @ can't specify :32 :-( - and r7,r7,#-64 - vld1.32 {d30[0]}, [r4,:32] - mov sp,r7 @ alloca - veor d8,d8,d8 - subs r8,r5,#8 - vzip.16 d28,d8 + stmdb sp!,{r4,r5,r6,r7,r8,r9,r10,r11} + vstmdb sp!,{d8,d9,d10,d11,d12,d13,d14,d15} @ ABI specification says so + ldmia ip,{r4,r5} @ load rest of parameter block + + sub r7,sp,#16 + vld1.32 {d28[0]}, [r2,:32]! + sub r7,r7,r5,lsl#4 + vld1.32 {d0,d1,d2,d3}, [r1]! @ can't specify :32 :-( + and r7,r7,#-64 + vld1.32 {d30[0]}, [r4,:32] + mov sp,r7 @ alloca + veor d8,d8,d8 + subs r8,r5,#8 + vzip.16 d28,d8 vmull.u32 q6,d28,d0[0] vmull.u32 q7,d28,d0[1] @@ -195,14 +206,14 @@ bn_mul8x_mont_neon: vmull.u32 q9,d28,d1[1] vadd.u64 d10,d10,d12 - veor d8,d8,d8 + veor d8,d8,d8 vmul.u32 d29,d10,d30 vmull.u32 q10,d28,d2[0] - vld1.32 {d4-d7}, [r3]! + vld1.32 {d4,d5,d6,d7}, [r3]! vmull.u32 q11,d28,d2[1] vmull.u32 q12,d28,d3[0] - vzip.16 d29,d8 + vzip.16 d29,d8 vmull.u32 q13,d28,d3[1] bne .LNEON_1st @@ -210,35 +221,35 @@ bn_mul8x_mont_neon: @ special case for num=8, everything is in register bank... vmlal.u32 q6,d29,d4[0] - sub r9,r5,#1 + sub r9,r5,#1 vmlal.u32 q7,d29,d4[1] vmlal.u32 q8,d29,d5[0] vmlal.u32 q9,d29,d5[1] vmlal.u32 q10,d29,d6[0] - vmov q5,q6 + vmov q5,q6 vmlal.u32 q11,d29,d6[1] - vmov q6,q7 + vmov q6,q7 vmlal.u32 q12,d29,d7[0] - vmov q7,q8 + vmov q7,q8 vmlal.u32 q13,d29,d7[1] - vmov q8,q9 - vmov q9,q10 + vmov q8,q9 + vmov q9,q10 vshr.u64 d10,d10,#16 - vmov q10,q11 - vmov q11,q12 + vmov q10,q11 + vmov q11,q12 vadd.u64 d10,d10,d11 - vmov q12,q13 - veor q13,q13 + vmov q12,q13 + veor q13,q13 vshr.u64 d10,d10,#16 b .LNEON_outer8 .align 4 .LNEON_outer8: - vld1.32 {d28[0]}, [r2,:32]! - veor d8,d8,d8 - vzip.16 d28,d8 + vld1.32 {d28[0]}, [r2,:32]! + veor d8,d8,d8 + vzip.16 d28,d8 vadd.u64 d12,d12,d10 vmlal.u32 q6,d28,d0[0] @@ -248,14 +259,14 @@ bn_mul8x_mont_neon: vmlal.u32 q9,d28,d1[1] vadd.u64 d10,d10,d12 - veor d8,d8,d8 - subs r9,r9,#1 + veor d8,d8,d8 + subs r9,r9,#1 vmul.u32 d29,d10,d30 vmlal.u32 q10,d28,d2[0] vmlal.u32 q11,d28,d2[1] vmlal.u32 q12,d28,d3[0] - vzip.16 d29,d8 + vzip.16 d29,d8 vmlal.u32 q13,d28,d3[1] vmlal.u32 q6,d29,d4[0] @@ -264,59 +275,59 @@ bn_mul8x_mont_neon: vmlal.u32 q9,d29,d5[1] vmlal.u32 q10,d29,d6[0] - vmov q5,q6 + vmov q5,q6 vmlal.u32 q11,d29,d6[1] - vmov q6,q7 + vmov q6,q7 vmlal.u32 q12,d29,d7[0] - vmov q7,q8 + vmov q7,q8 vmlal.u32 q13,d29,d7[1] - vmov q8,q9 - vmov q9,q10 + vmov q8,q9 + vmov q9,q10 vshr.u64 d10,d10,#16 - vmov q10,q11 - vmov q11,q12 + vmov q10,q11 + vmov q11,q12 vadd.u64 d10,d10,d11 - vmov q12,q13 - veor q13,q13 + vmov q12,q13 + veor q13,q13 vshr.u64 d10,d10,#16 bne .LNEON_outer8 vadd.u64 d12,d12,d10 - mov r7,sp + mov r7,sp vshr.u64 d10,d12,#16 - mov r8,r5 + mov r8,r5 vadd.u64 d13,d13,d10 - add r6,sp,#16 + add r6,sp,#16 vshr.u64 d10,d13,#16 - vzip.16 d12,d13 + vzip.16 d12,d13 b .LNEON_tail2 .align 4 .LNEON_1st: vmlal.u32 q6,d29,d4[0] - vld1.32 {d0-d3}, [r1]! + vld1.32 {d0,d1,d2,d3}, [r1]! vmlal.u32 q7,d29,d4[1] - subs r8,r8,#8 + subs r8,r8,#8 vmlal.u32 q8,d29,d5[0] vmlal.u32 q9,d29,d5[1] vmlal.u32 q10,d29,d6[0] - vld1.32 {d4-d5}, [r3]! + vld1.32 {d4,d5}, [r3]! vmlal.u32 q11,d29,d6[1] - vst1.64 {q6-q7}, [r7,:256]! + vst1.64 {q6,q7}, [r7,:256]! vmlal.u32 q12,d29,d7[0] vmlal.u32 q13,d29,d7[1] - vst1.64 {q8-q9}, [r7,:256]! + vst1.64 {q8,q9}, [r7,:256]! vmull.u32 q6,d28,d0[0] - vld1.32 {d6-d7}, [r3]! + vld1.32 {d6,d7}, [r3]! vmull.u32 q7,d28,d0[1] - vst1.64 {q10-q11}, [r7,:256]! + vst1.64 {q10,q11}, [r7,:256]! vmull.u32 q8,d28,d1[0] vmull.u32 q9,d28,d1[1] - vst1.64 {q12-q13}, [r7,:256]! + vst1.64 {q12,q13}, [r7,:256]! vmull.u32 q10,d28,d2[0] vmull.u32 q11,d28,d2[1] @@ -326,93 +337,93 @@ bn_mul8x_mont_neon: bne .LNEON_1st vmlal.u32 q6,d29,d4[0] - add r6,sp,#16 + add r6,sp,#16 vmlal.u32 q7,d29,d4[1] - sub r1,r1,r5,lsl#2 @ rewind r1 + sub r1,r1,r5,lsl#2 @ rewind r1 vmlal.u32 q8,d29,d5[0] - vld1.64 {q5}, [sp,:128] + vld1.64 {q5}, [sp,:128] vmlal.u32 q9,d29,d5[1] - sub r9,r5,#1 + sub r9,r5,#1 vmlal.u32 q10,d29,d6[0] - vst1.64 {q6-q7}, [r7,:256]! + vst1.64 {q6,q7}, [r7,:256]! vmlal.u32 q11,d29,d6[1] vshr.u64 d10,d10,#16 - vld1.64 {q6}, [r6, :128]! + vld1.64 {q6}, [r6, :128]! vmlal.u32 q12,d29,d7[0] - vst1.64 {q8-q9}, [r7,:256]! + vst1.64 {q8,q9}, [r7,:256]! vmlal.u32 q13,d29,d7[1] - vst1.64 {q10-q11}, [r7,:256]! + vst1.64 {q10,q11}, [r7,:256]! vadd.u64 d10,d10,d11 - veor q4,q4,q4 - vst1.64 {q12-q13}, [r7,:256]! - vld1.64 {q7-q8}, [r6, :256]! - vst1.64 {q4}, [r7,:128] + veor q4,q4,q4 + vst1.64 {q12,q13}, [r7,:256]! + vld1.64 {q7,q8}, [r6, :256]! + vst1.64 {q4}, [r7,:128] vshr.u64 d10,d10,#16 - b .LNEON_outer + b .LNEON_outer .align 4 .LNEON_outer: - vld1.32 {d28[0]}, [r2,:32]! - sub r3,r3,r5,lsl#2 @ rewind r3 - vld1.32 {d0-d3}, [r1]! - veor d8,d8,d8 - mov r7,sp - vzip.16 d28,d8 - sub r8,r5,#8 + vld1.32 {d28[0]}, [r2,:32]! + sub r3,r3,r5,lsl#2 @ rewind r3 + vld1.32 {d0,d1,d2,d3}, [r1]! + veor d8,d8,d8 + mov r7,sp + vzip.16 d28,d8 + sub r8,r5,#8 vadd.u64 d12,d12,d10 vmlal.u32 q6,d28,d0[0] - vld1.64 {q9-q10},[r6,:256]! + vld1.64 {q9,q10},[r6,:256]! vmlal.u32 q7,d28,d0[1] vmlal.u32 q8,d28,d1[0] - vld1.64 {q11-q12},[r6,:256]! + vld1.64 {q11,q12},[r6,:256]! vmlal.u32 q9,d28,d1[1] vshl.i64 d10,d13,#16 - veor d8,d8,d8 + veor d8,d8,d8 vadd.u64 d10,d10,d12 - vld1.64 {q13},[r6,:128]! + vld1.64 {q13},[r6,:128]! vmul.u32 d29,d10,d30 vmlal.u32 q10,d28,d2[0] - vld1.32 {d4-d7}, [r3]! + vld1.32 {d4,d5,d6,d7}, [r3]! vmlal.u32 q11,d28,d2[1] vmlal.u32 q12,d28,d3[0] - vzip.16 d29,d8 + vzip.16 d29,d8 vmlal.u32 q13,d28,d3[1] .LNEON_inner: vmlal.u32 q6,d29,d4[0] - vld1.32 {d0-d3}, [r1]! + vld1.32 {d0,d1,d2,d3}, [r1]! vmlal.u32 q7,d29,d4[1] - subs r8,r8,#8 + subs r8,r8,#8 vmlal.u32 q8,d29,d5[0] vmlal.u32 q9,d29,d5[1] - vst1.64 {q6-q7}, [r7,:256]! + vst1.64 {q6,q7}, [r7,:256]! vmlal.u32 q10,d29,d6[0] - vld1.64 {q6}, [r6, :128]! + vld1.64 {q6}, [r6, :128]! vmlal.u32 q11,d29,d6[1] - vst1.64 {q8-q9}, [r7,:256]! + vst1.64 {q8,q9}, [r7,:256]! vmlal.u32 q12,d29,d7[0] - vld1.64 {q7-q8}, [r6, :256]! + vld1.64 {q7,q8}, [r6, :256]! vmlal.u32 q13,d29,d7[1] - vst1.64 {q10-q11}, [r7,:256]! + vst1.64 {q10,q11}, [r7,:256]! vmlal.u32 q6,d28,d0[0] - vld1.64 {q9-q10}, [r6, :256]! + vld1.64 {q9,q10}, [r6, :256]! vmlal.u32 q7,d28,d0[1] - vst1.64 {q12-q13}, [r7,:256]! + vst1.64 {q12,q13}, [r7,:256]! vmlal.u32 q8,d28,d1[0] - vld1.64 {q11-q12}, [r6, :256]! + vld1.64 {q11,q12}, [r6, :256]! vmlal.u32 q9,d28,d1[1] - vld1.32 {d4-d7}, [r3]! + vld1.32 {d4,d5,d6,d7}, [r3]! vmlal.u32 q10,d28,d2[0] - vld1.64 {q13}, [r6, :128]! + vld1.64 {q13}, [r6, :128]! vmlal.u32 q11,d28,d2[1] vmlal.u32 q12,d28,d3[0] vmlal.u32 q13,d28,d3[1] @@ -420,97 +431,97 @@ bn_mul8x_mont_neon: bne .LNEON_inner vmlal.u32 q6,d29,d4[0] - add r6,sp,#16 + add r6,sp,#16 vmlal.u32 q7,d29,d4[1] - sub r1,r1,r5,lsl#2 @ rewind r1 + sub r1,r1,r5,lsl#2 @ rewind r1 vmlal.u32 q8,d29,d5[0] - vld1.64 {q5}, [sp,:128] + vld1.64 {q5}, [sp,:128] vmlal.u32 q9,d29,d5[1] - subs r9,r9,#1 + subs r9,r9,#1 vmlal.u32 q10,d29,d6[0] - vst1.64 {q6-q7}, [r7,:256]! + vst1.64 {q6,q7}, [r7,:256]! vmlal.u32 q11,d29,d6[1] - vld1.64 {q6}, [r6, :128]! + vld1.64 {q6}, [r6, :128]! vshr.u64 d10,d10,#16 - vst1.64 {q8-q9}, [r7,:256]! + vst1.64 {q8,q9}, [r7,:256]! vmlal.u32 q12,d29,d7[0] - vld1.64 {q7-q8}, [r6, :256]! + vld1.64 {q7,q8}, [r6, :256]! vmlal.u32 q13,d29,d7[1] - vst1.64 {q10-q11}, [r7,:256]! + vst1.64 {q10,q11}, [r7,:256]! vadd.u64 d10,d10,d11 - vst1.64 {q12-q13}, [r7,:256]! + vst1.64 {q12,q13}, [r7,:256]! vshr.u64 d10,d10,#16 bne .LNEON_outer - mov r7,sp - mov r8,r5 + mov r7,sp + mov r8,r5 .LNEON_tail: vadd.u64 d12,d12,d10 - vld1.64 {q9-q10}, [r6, :256]! + vld1.64 {q9,q10}, [r6, :256]! vshr.u64 d10,d12,#16 vadd.u64 d13,d13,d10 - vld1.64 {q11-q12}, [r6, :256]! + vld1.64 {q11,q12}, [r6, :256]! vshr.u64 d10,d13,#16 - vld1.64 {q13}, [r6, :128]! - vzip.16 d12,d13 + vld1.64 {q13}, [r6, :128]! + vzip.16 d12,d13 .LNEON_tail2: vadd.u64 d14,d14,d10 - vst1.32 {d12[0]}, [r7, :32]! + vst1.32 {d12[0]}, [r7, :32]! vshr.u64 d10,d14,#16 vadd.u64 d15,d15,d10 vshr.u64 d10,d15,#16 - vzip.16 d14,d15 + vzip.16 d14,d15 vadd.u64 d16,d16,d10 - vst1.32 {d14[0]}, [r7, :32]! + vst1.32 {d14[0]}, [r7, :32]! vshr.u64 d10,d16,#16 vadd.u64 d17,d17,d10 vshr.u64 d10,d17,#16 - vzip.16 d16,d17 + vzip.16 d16,d17 vadd.u64 d18,d18,d10 - vst1.32 {d16[0]}, [r7, :32]! + vst1.32 {d16[0]}, [r7, :32]! vshr.u64 d10,d18,#16 vadd.u64 d19,d19,d10 vshr.u64 d10,d19,#16 - vzip.16 d18,d19 + vzip.16 d18,d19 vadd.u64 d20,d20,d10 - vst1.32 {d18[0]}, [r7, :32]! + vst1.32 {d18[0]}, [r7, :32]! vshr.u64 d10,d20,#16 vadd.u64 d21,d21,d10 vshr.u64 d10,d21,#16 - vzip.16 d20,d21 + vzip.16 d20,d21 vadd.u64 d22,d22,d10 - vst1.32 {d20[0]}, [r7, :32]! + vst1.32 {d20[0]}, [r7, :32]! vshr.u64 d10,d22,#16 vadd.u64 d23,d23,d10 vshr.u64 d10,d23,#16 - vzip.16 d22,d23 + vzip.16 d22,d23 vadd.u64 d24,d24,d10 - vst1.32 {d22[0]}, [r7, :32]! + vst1.32 {d22[0]}, [r7, :32]! vshr.u64 d10,d24,#16 vadd.u64 d25,d25,d10 - vld1.64 {q6}, [r6, :128]! + vld1.64 {q6}, [r6, :128]! vshr.u64 d10,d25,#16 - vzip.16 d24,d25 + vzip.16 d24,d25 vadd.u64 d26,d26,d10 - vst1.32 {d24[0]}, [r7, :32]! + vst1.32 {d24[0]}, [r7, :32]! vshr.u64 d10,d26,#16 vadd.u64 d27,d27,d10 - vld1.64 {q7-q8}, [r6, :256]! + vld1.64 {q7,q8}, [r6, :256]! vshr.u64 d10,d27,#16 - vzip.16 d26,d27 - subs r8,r8,#8 - vst1.32 {d26[0]}, [r7, :32]! + vzip.16 d26,d27 + subs r8,r8,#8 + vst1.32 {d26[0]}, [r7, :32]! bne .LNEON_tail @@ -520,14 +531,14 @@ bn_mul8x_mont_neon: add r2,sp,r5,lsl#2 .LNEON_sub: - ldmia r1!, {r4-r7} - ldmia r3!, {r8-r11} + ldmia r1!, {r4,r5,r6,r7} + ldmia r3!, {r8,r9,r10,r11} sbcs r8, r4,r8 sbcs r9, r5,r9 sbcs r10,r6,r10 sbcs r11,r7,r11 teq r1,r2 @ preserves carry - stmia r0!, {r8-r11} + stmia r0!, {r8,r9,r10,r11} bne .LNEON_sub ldr r10, [r1] @ load top-most bit @@ -540,37 +551,39 @@ bn_mul8x_mont_neon: sbcs r10,r10,#0 @ result is carry flag .LNEON_copy_n_zap: - ldmia r1!, {r4-r7} - ldmia r0, {r8-r11} + ldmia r1!, {r4,r5,r6,r7} + ldmia r0, {r8,r9,r10,r11} movcc r8, r4 - vst1.64 {q0-q1}, [r3,:256]! @ wipe + vst1.64 {q0,q1}, [r3,:256]! @ wipe movcc r9, r5 movcc r10,r6 - vst1.64 {q0-q1}, [r3,:256]! @ wipe + vst1.64 {q0,q1}, [r3,:256]! @ wipe movcc r11,r7 - ldmia r1, {r4-r7} - stmia r0!, {r8-r11} + ldmia r1, {r4,r5,r6,r7} + stmia r0!, {r8,r9,r10,r11} sub r1,r1,#16 - ldmia r0, {r8-r11} + ldmia r0, {r8,r9,r10,r11} movcc r8, r4 - vst1.64 {q0-q1}, [r1,:256]! @ wipe + vst1.64 {q0,q1}, [r1,:256]! @ wipe movcc r9, r5 movcc r10,r6 - vst1.64 {q0-q1}, [r3,:256]! @ wipe + vst1.64 {q0,q1}, [r3,:256]! @ wipe movcc r11,r7 teq r1,r2 @ preserves carry - stmia r0!, {r8-r11} + stmia r0!, {r8,r9,r10,r11} bne .LNEON_copy_n_zap sub sp,ip,#96 - vldmia sp!,{d8-d15} - ldmia sp!,{r4-r11} - .word 0xe12fff1e + vldmia sp!,{d8,d9,d10,d11,d12,d13,d14,d15} + ldmia sp!,{r4,r5,r6,r7,r8,r9,r10,r11} + bx lr @ .word 0xe12fff1e .size bn_mul8x_mont_neon,.-bn_mul8x_mont_neon #endif -.asciz "Montgomery multiplication for ARMv4/NEON, CRYPTOGAMS by " +.byte 77,111,110,116,103,111,109,101,114,121,32,109,117,108,116,105,112,108,105,99,97,116,105,111,110,32,102,111,114,32,65,82,77,118,52,47,78,69,79,78,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0 +.align 2 .align 2 -#if __ARM_ARCH__>=7 +#if __ARM_MAX_ARCH__>=7 .comm OPENSSL_armcap_P,4,4 .hidden OPENSSL_armcap_P #endif +#endif \ No newline at end of file diff --git a/third_party/boringssl/linux-arm/crypto/modes/ghash-armv4.S b/third_party/boringssl/linux-arm/crypto/modes/ghash-armv4.S index 8c81975521fad..c6f025d75974f 100644 --- a/third_party/boringssl/linux-arm/crypto/modes/ghash-armv4.S +++ b/third_party/boringssl/linux-arm/crypto/modes/ghash-armv4.S @@ -1,11 +1,17 @@ #if defined(__arm__) +#if defined(__arm__) #include "arm_arch.h" -.syntax unified +.syntax unified .text .code 32 +#ifdef __APPLE__ +#define ldrplb ldrbpl +#define ldrneb ldrbne +#endif + .type rem_4bit,%object .align 5 rem_4bit: @@ -23,17 +29,17 @@ rem_4bit_get: nop .size rem_4bit_get,.-rem_4bit_get -.global gcm_ghash_4bit +.globl gcm_ghash_4bit .hidden gcm_ghash_4bit .type gcm_ghash_4bit,%function gcm_ghash_4bit: sub r12,pc,#8 add r3,r2,r3 @ r3 to point at the end - stmdb sp!,{r3-r11,lr} @ save r3/end too + stmdb sp!,{r3,r4,r5,r6,r7,r8,r9,r10,r11,lr} @ save r3/end too sub r12,r12,#48 @ &rem_4bit - ldmia r12,{r4-r11} @ copy rem_4bit ... - stmdb sp!,{r4-r11} @ ... to stack + ldmia r12,{r4,r5,r6,r7,r8,r9,r10,r11} @ copy rem_4bit ... + stmdb sp!,{r4,r5,r6,r7,r8,r9,r10,r11} @ ... to stack ldrb r12,[r2,#15] ldrb r14,[r0,#15] @@ -44,12 +50,12 @@ gcm_ghash_4bit: mov r3,#14 add r7,r1,r12,lsl#4 - ldmia r7,{r4-r7} @ load Htbl[nlo] + ldmia r7,{r4,r5,r6,r7} @ load Htbl[nlo] add r11,r1,r14 ldrb r12,[r2,#14] and r14,r4,#0xf @ rem - ldmia r11,{r8-r11} @ load Htbl[nhi] + ldmia r11,{r8,r9,r10,r11} @ load Htbl[nhi] add r14,r14,r14 eor r4,r8,r4,lsr#4 ldrh r8,[sp,r14] @ rem_4bit[rem] @@ -70,7 +76,7 @@ gcm_ghash_4bit: and r12,r4,#0xf @ rem subs r3,r3,#1 add r12,r12,r12 - ldmia r11,{r8-r11} @ load Htbl[nlo] + ldmia r11,{r8,r9,r10,r11} @ load Htbl[nlo] eor r4,r8,r4,lsr#4 eor r4,r4,r5,lsl#28 eor r5,r9,r5,lsr#4 @@ -85,7 +91,7 @@ gcm_ghash_4bit: and r14,r4,#0xf @ rem eor r7,r7,r8,lsl#16 @ ^= rem_4bit[rem] add r14,r14,r14 - ldmia r11,{r8-r11} @ load Htbl[nhi] + ldmia r11,{r8,r9,r10,r11} @ load Htbl[nhi] eor r4,r8,r4,lsr#4 ldrbpl r8,[r0,r3] eor r4,r4,r5,lsl#28 @@ -148,7 +154,7 @@ gcm_ghash_4bit: strb r10,[r0,#4+1] strb r11,[r0,#4] #endif - + #if __ARM_ARCH__>=7 && defined(__ARMEL__) rev r7,r7 str r7,[r0,#0] @@ -163,25 +169,25 @@ gcm_ghash_4bit: strb r10,[r0,#0+1] strb r11,[r0,#0] #endif - + bne .Louter add sp,sp,#36 #if __ARM_ARCH__>=5 - ldmia sp!,{r4-r11,pc} + ldmia sp!,{r4,r5,r6,r7,r8,r9,r10,r11,pc} #else - ldmia sp!,{r4-r11,lr} + ldmia sp!,{r4,r5,r6,r7,r8,r9,r10,r11,lr} tst lr,#1 moveq pc,lr @ be binary compatible with V4, yet - .word 0xe12fff1e @ interoperable with Thumb ISA:-) +.word 0xe12fff1e @ interoperable with Thumb ISA:-) #endif .size gcm_ghash_4bit,.-gcm_ghash_4bit -.global gcm_gmult_4bit +.globl gcm_gmult_4bit .hidden gcm_gmult_4bit .type gcm_gmult_4bit,%function gcm_gmult_4bit: - stmdb sp!,{r4-r11,lr} + stmdb sp!,{r4,r5,r6,r7,r8,r9,r10,r11,lr} ldrb r12,[r0,#15] b rem_4bit_get .Lrem_4bit_got: @@ -190,12 +196,12 @@ gcm_gmult_4bit: mov r3,#14 add r7,r1,r12,lsl#4 - ldmia r7,{r4-r7} @ load Htbl[nlo] + ldmia r7,{r4,r5,r6,r7} @ load Htbl[nlo] ldrb r12,[r0,#14] add r11,r1,r14 and r14,r4,#0xf @ rem - ldmia r11,{r8-r11} @ load Htbl[nhi] + ldmia r11,{r8,r9,r10,r11} @ load Htbl[nhi] add r14,r14,r14 eor r4,r8,r4,lsr#4 ldrh r8,[r2,r14] @ rem_4bit[rem] @@ -214,7 +220,7 @@ gcm_gmult_4bit: and r12,r4,#0xf @ rem subs r3,r3,#1 add r12,r12,r12 - ldmia r11,{r8-r11} @ load Htbl[nlo] + ldmia r11,{r8,r9,r10,r11} @ load Htbl[nlo] eor r4,r8,r4,lsr#4 eor r4,r4,r5,lsl#28 eor r5,r9,r5,lsr#4 @@ -229,7 +235,7 @@ gcm_gmult_4bit: and r14,r4,#0xf @ rem eor r7,r7,r8,lsl#16 @ ^= rem_4bit[rem] add r14,r14,r14 - ldmia r11,{r8-r11} @ load Htbl[nhi] + ldmia r11,{r8,r9,r10,r11} @ load Htbl[nhi] eor r4,r8,r4,lsr#4 eor r4,r4,r5,lsl#28 eor r5,r9,r5,lsr#4 @@ -256,7 +262,7 @@ gcm_gmult_4bit: strb r10,[r0,#12+1] strb r11,[r0,#12] #endif - + #if __ARM_ARCH__>=7 && defined(__ARMEL__) rev r5,r5 str r5,[r0,#8] @@ -271,7 +277,7 @@ gcm_gmult_4bit: strb r10,[r0,#8+1] strb r11,[r0,#8] #endif - + #if __ARM_ARCH__>=7 && defined(__ARMEL__) rev r6,r6 str r6,[r0,#4] @@ -286,7 +292,7 @@ gcm_gmult_4bit: strb r10,[r0,#4+1] strb r11,[r0,#4] #endif - + #if __ARM_ARCH__>=7 && defined(__ARMEL__) rev r7,r7 str r7,[r0,#0] @@ -301,232 +307,235 @@ gcm_gmult_4bit: strb r10,[r0,#0+1] strb r11,[r0,#0] #endif - + #if __ARM_ARCH__>=5 - ldmia sp!,{r4-r11,pc} + ldmia sp!,{r4,r5,r6,r7,r8,r9,r10,r11,pc} #else - ldmia sp!,{r4-r11,lr} + ldmia sp!,{r4,r5,r6,r7,r8,r9,r10,r11,lr} tst lr,#1 moveq pc,lr @ be binary compatible with V4, yet - .word 0xe12fff1e @ interoperable with Thumb ISA:-) +.word 0xe12fff1e @ interoperable with Thumb ISA:-) #endif .size gcm_gmult_4bit,.-gcm_gmult_4bit -#if __ARM_ARCH__>=7 +#if __ARM_MAX_ARCH__>=7 +.arch armv7-a .fpu neon -.global gcm_init_neon +.globl gcm_init_neon .hidden gcm_init_neon .type gcm_init_neon,%function .align 4 gcm_init_neon: - vld1.64 d7,[r1,:64]! @ load H - vmov.i8 q8,#0xe1 - vld1.64 d6,[r1,:64] + vld1.64 d7,[r1]! @ load H + vmov.i8 q8,#0xe1 + vld1.64 d6,[r1] vshl.i64 d17,#57 vshr.u64 d16,#63 @ t0=0xc2....01 - vdup.8 q9,d7[7] + vdup.8 q9,d7[7] vshr.u64 d26,d6,#63 - vshr.s8 q9,#7 @ broadcast carry bit + vshr.s8 q9,#7 @ broadcast carry bit vshl.i64 q3,q3,#1 - vand q8,q8,q9 - vorr d7,d26 @ H<<<=1 - veor q3,q3,q8 @ twisted H - vstmia r0,{q3} + vand q8,q8,q9 + vorr d7,d26 @ H<<<=1 + veor q3,q3,q8 @ twisted H + vstmia r0,{q3} - .word 0xe12fff1e + bx lr @ bx lr .size gcm_init_neon,.-gcm_init_neon -.global gcm_gmult_neon +.globl gcm_gmult_neon .hidden gcm_gmult_neon .type gcm_gmult_neon,%function .align 4 gcm_gmult_neon: - vld1.64 d7,[r0,:64]! @ load Xi - vld1.64 d6,[r0,:64]! + vld1.64 d7,[r0]! @ load Xi + vld1.64 d6,[r0]! vmov.i64 d29,#0x0000ffffffffffff - vldmia r1,{d26-d27} @ load twisted H + vldmia r1,{d26,d27} @ load twisted H vmov.i64 d30,#0x00000000ffffffff #ifdef __ARMEL__ vrev64.8 q3,q3 #endif vmov.i64 d31,#0x000000000000ffff - veor d28,d26,d27 @ Karatsuba pre-processing - mov r3,#16 - b .Lgmult_neon + veor d28,d26,d27 @ Karatsuba pre-processing + mov r3,#16 + b .Lgmult_neon .size gcm_gmult_neon,.-gcm_gmult_neon -.global gcm_ghash_neon +.globl gcm_ghash_neon .hidden gcm_ghash_neon .type gcm_ghash_neon,%function .align 4 gcm_ghash_neon: - vld1.64 d1,[r0,:64]! @ load Xi - vld1.64 d0,[r0,:64]! + vld1.64 d1,[r0]! @ load Xi + vld1.64 d0,[r0]! vmov.i64 d29,#0x0000ffffffffffff - vldmia r1,{d26-d27} @ load twisted H + vldmia r1,{d26,d27} @ load twisted H vmov.i64 d30,#0x00000000ffffffff #ifdef __ARMEL__ vrev64.8 q0,q0 #endif vmov.i64 d31,#0x000000000000ffff - veor d28,d26,d27 @ Karatsuba pre-processing + veor d28,d26,d27 @ Karatsuba pre-processing .Loop_neon: - vld1.64 d7,[r2]! @ load inp - vld1.64 d6,[r2]! + vld1.64 d7,[r2]! @ load inp + vld1.64 d6,[r2]! #ifdef __ARMEL__ vrev64.8 q3,q3 #endif - veor q3,q0 @ inp^=Xi + veor q3,q0 @ inp^=Xi .Lgmult_neon: - vext.8 d16, d26, d26, #1 @ A1 + vext.8 d16, d26, d26, #1 @ A1 vmull.p8 q8, d16, d6 @ F = A1*B - vext.8 d0, d6, d6, #1 @ B1 + vext.8 d0, d6, d6, #1 @ B1 vmull.p8 q0, d26, d0 @ E = A*B1 - vext.8 d18, d26, d26, #2 @ A2 + vext.8 d18, d26, d26, #2 @ A2 vmull.p8 q9, d18, d6 @ H = A2*B - vext.8 d22, d6, d6, #2 @ B2 + vext.8 d22, d6, d6, #2 @ B2 vmull.p8 q11, d26, d22 @ G = A*B2 - vext.8 d20, d26, d26, #3 @ A3 - veor q8, q8, q0 @ L = E + F + vext.8 d20, d26, d26, #3 @ A3 + veor q8, q8, q0 @ L = E + F vmull.p8 q10, d20, d6 @ J = A3*B - vext.8 d0, d6, d6, #3 @ B3 - veor q9, q9, q11 @ M = G + H + vext.8 d0, d6, d6, #3 @ B3 + veor q9, q9, q11 @ M = G + H vmull.p8 q0, d26, d0 @ I = A*B3 - veor d16, d16, d17 @ t0 = (L) (P0 + P1) << 8 - vand d17, d17, d29 - vext.8 d22, d6, d6, #4 @ B4 - veor d18, d18, d19 @ t1 = (M) (P2 + P3) << 16 - vand d19, d19, d30 + veor d16, d16, d17 @ t0 = (L) (P0 + P1) << 8 + vand d17, d17, d29 + vext.8 d22, d6, d6, #4 @ B4 + veor d18, d18, d19 @ t1 = (M) (P2 + P3) << 16 + vand d19, d19, d30 vmull.p8 q11, d26, d22 @ K = A*B4 - veor q10, q10, q0 @ N = I + J - veor d16, d16, d17 - veor d18, d18, d19 - veor d20, d20, d21 @ t2 = (N) (P4 + P5) << 24 - vand d21, d21, d31 - vext.8 q8, q8, q8, #15 - veor d22, d22, d23 @ t3 = (K) (P6 + P7) << 32 + veor q10, q10, q0 @ N = I + J + veor d16, d16, d17 + veor d18, d18, d19 + veor d20, d20, d21 @ t2 = (N) (P4 + P5) << 24 + vand d21, d21, d31 + vext.8 q8, q8, q8, #15 + veor d22, d22, d23 @ t3 = (K) (P6 + P7) << 32 vmov.i64 d23, #0 - vext.8 q9, q9, q9, #14 - veor d20, d20, d21 + vext.8 q9, q9, q9, #14 + veor d20, d20, d21 vmull.p8 q0, d26, d6 @ D = A*B - vext.8 q11, q11, q11, #12 - vext.8 q10, q10, q10, #13 - veor q8, q8, q9 - veor q10, q10, q11 - veor q0, q0, q8 - veor q0, q0, q10 - veor d6,d6,d7 @ Karatsuba pre-processing - vext.8 d16, d28, d28, #1 @ A1 + vext.8 q11, q11, q11, #12 + vext.8 q10, q10, q10, #13 + veor q8, q8, q9 + veor q10, q10, q11 + veor q0, q0, q8 + veor q0, q0, q10 + veor d6,d6,d7 @ Karatsuba pre-processing + vext.8 d16, d28, d28, #1 @ A1 vmull.p8 q8, d16, d6 @ F = A1*B - vext.8 d2, d6, d6, #1 @ B1 + vext.8 d2, d6, d6, #1 @ B1 vmull.p8 q1, d28, d2 @ E = A*B1 - vext.8 d18, d28, d28, #2 @ A2 + vext.8 d18, d28, d28, #2 @ A2 vmull.p8 q9, d18, d6 @ H = A2*B - vext.8 d22, d6, d6, #2 @ B2 + vext.8 d22, d6, d6, #2 @ B2 vmull.p8 q11, d28, d22 @ G = A*B2 - vext.8 d20, d28, d28, #3 @ A3 - veor q8, q8, q1 @ L = E + F + vext.8 d20, d28, d28, #3 @ A3 + veor q8, q8, q1 @ L = E + F vmull.p8 q10, d20, d6 @ J = A3*B - vext.8 d2, d6, d6, #3 @ B3 - veor q9, q9, q11 @ M = G + H + vext.8 d2, d6, d6, #3 @ B3 + veor q9, q9, q11 @ M = G + H vmull.p8 q1, d28, d2 @ I = A*B3 - veor d16, d16, d17 @ t0 = (L) (P0 + P1) << 8 - vand d17, d17, d29 - vext.8 d22, d6, d6, #4 @ B4 - veor d18, d18, d19 @ t1 = (M) (P2 + P3) << 16 - vand d19, d19, d30 + veor d16, d16, d17 @ t0 = (L) (P0 + P1) << 8 + vand d17, d17, d29 + vext.8 d22, d6, d6, #4 @ B4 + veor d18, d18, d19 @ t1 = (M) (P2 + P3) << 16 + vand d19, d19, d30 vmull.p8 q11, d28, d22 @ K = A*B4 - veor q10, q10, q1 @ N = I + J - veor d16, d16, d17 - veor d18, d18, d19 - veor d20, d20, d21 @ t2 = (N) (P4 + P5) << 24 - vand d21, d21, d31 - vext.8 q8, q8, q8, #15 - veor d22, d22, d23 @ t3 = (K) (P6 + P7) << 32 + veor q10, q10, q1 @ N = I + J + veor d16, d16, d17 + veor d18, d18, d19 + veor d20, d20, d21 @ t2 = (N) (P4 + P5) << 24 + vand d21, d21, d31 + vext.8 q8, q8, q8, #15 + veor d22, d22, d23 @ t3 = (K) (P6 + P7) << 32 vmov.i64 d23, #0 - vext.8 q9, q9, q9, #14 - veor d20, d20, d21 + vext.8 q9, q9, q9, #14 + veor d20, d20, d21 vmull.p8 q1, d28, d6 @ D = A*B - vext.8 q11, q11, q11, #12 - vext.8 q10, q10, q10, #13 - veor q8, q8, q9 - veor q10, q10, q11 - veor q1, q1, q8 - veor q1, q1, q10 - vext.8 d16, d27, d27, #1 @ A1 + vext.8 q11, q11, q11, #12 + vext.8 q10, q10, q10, #13 + veor q8, q8, q9 + veor q10, q10, q11 + veor q1, q1, q8 + veor q1, q1, q10 + vext.8 d16, d27, d27, #1 @ A1 vmull.p8 q8, d16, d7 @ F = A1*B - vext.8 d4, d7, d7, #1 @ B1 + vext.8 d4, d7, d7, #1 @ B1 vmull.p8 q2, d27, d4 @ E = A*B1 - vext.8 d18, d27, d27, #2 @ A2 + vext.8 d18, d27, d27, #2 @ A2 vmull.p8 q9, d18, d7 @ H = A2*B - vext.8 d22, d7, d7, #2 @ B2 + vext.8 d22, d7, d7, #2 @ B2 vmull.p8 q11, d27, d22 @ G = A*B2 - vext.8 d20, d27, d27, #3 @ A3 - veor q8, q8, q2 @ L = E + F + vext.8 d20, d27, d27, #3 @ A3 + veor q8, q8, q2 @ L = E + F vmull.p8 q10, d20, d7 @ J = A3*B - vext.8 d4, d7, d7, #3 @ B3 - veor q9, q9, q11 @ M = G + H + vext.8 d4, d7, d7, #3 @ B3 + veor q9, q9, q11 @ M = G + H vmull.p8 q2, d27, d4 @ I = A*B3 - veor d16, d16, d17 @ t0 = (L) (P0 + P1) << 8 - vand d17, d17, d29 - vext.8 d22, d7, d7, #4 @ B4 - veor d18, d18, d19 @ t1 = (M) (P2 + P3) << 16 - vand d19, d19, d30 + veor d16, d16, d17 @ t0 = (L) (P0 + P1) << 8 + vand d17, d17, d29 + vext.8 d22, d7, d7, #4 @ B4 + veor d18, d18, d19 @ t1 = (M) (P2 + P3) << 16 + vand d19, d19, d30 vmull.p8 q11, d27, d22 @ K = A*B4 - veor q10, q10, q2 @ N = I + J - veor d16, d16, d17 - veor d18, d18, d19 - veor d20, d20, d21 @ t2 = (N) (P4 + P5) << 24 - vand d21, d21, d31 - vext.8 q8, q8, q8, #15 - veor d22, d22, d23 @ t3 = (K) (P6 + P7) << 32 + veor q10, q10, q2 @ N = I + J + veor d16, d16, d17 + veor d18, d18, d19 + veor d20, d20, d21 @ t2 = (N) (P4 + P5) << 24 + vand d21, d21, d31 + vext.8 q8, q8, q8, #15 + veor d22, d22, d23 @ t3 = (K) (P6 + P7) << 32 vmov.i64 d23, #0 - vext.8 q9, q9, q9, #14 - veor d20, d20, d21 + vext.8 q9, q9, q9, #14 + veor d20, d20, d21 vmull.p8 q2, d27, d7 @ D = A*B - vext.8 q11, q11, q11, #12 - vext.8 q10, q10, q10, #13 - veor q8, q8, q9 - veor q10, q10, q11 - veor q2, q2, q8 - veor q2, q2, q10 - veor q1,q1,q0 @ Karatsuba post-processing - veor q1,q1,q2 - veor d1,d1,d2 - veor d4,d4,d3 @ Xh|Xl - 256-bit result + vext.8 q11, q11, q11, #12 + vext.8 q10, q10, q10, #13 + veor q8, q8, q9 + veor q10, q10, q11 + veor q2, q2, q8 + veor q2, q2, q10 + veor q1,q1,q0 @ Karatsuba post-processing + veor q1,q1,q2 + veor d1,d1,d2 + veor d4,d4,d3 @ Xh|Xl - 256-bit result @ equivalent of reduction_avx from ghash-x86_64.pl vshl.i64 q9,q0,#57 @ 1st phase vshl.i64 q10,q0,#62 - veor q10,q10,q9 @ + veor q10,q10,q9 @ vshl.i64 q9,q0,#63 - veor q10, q10, q9 @ - veor d1,d1,d20 @ - veor d4,d4,d21 + veor q10, q10, q9 @ + veor d1,d1,d20 @ + veor d4,d4,d21 vshr.u64 q10,q0,#1 @ 2nd phase - veor q2,q2,q0 - veor q0,q0,q10 @ + veor q2,q2,q0 + veor q0,q0,q10 @ vshr.u64 q10,q10,#6 vshr.u64 q0,q0,#1 @ - veor q0,q0,q2 @ - veor q0,q0,q10 @ + veor q0,q0,q2 @ + veor q0,q0,q10 @ - subs r3,#16 - bne .Loop_neon + subs r3,#16 + bne .Loop_neon #ifdef __ARMEL__ vrev64.8 q0,q0 #endif - sub r0,#16 - vst1.64 d1,[r0,:64]! @ write out Xi - vst1.64 d0,[r0,:64] + sub r0,#16 + vst1.64 d1,[r0]! @ write out Xi + vst1.64 d0,[r0] - .word 0xe12fff1e + bx lr @ bx lr .size gcm_ghash_neon,.-gcm_ghash_neon #endif -.asciz "GHASH for ARMv4/NEON, CRYPTOGAMS by " -.align 2 +.byte 71,72,65,83,72,32,102,111,114,32,65,82,77,118,52,47,78,69,79,78,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0 +.align 2 +.align 2 #endif +#endif \ No newline at end of file diff --git a/third_party/boringssl/linux-arm/crypto/modes/ghashv8-armx.S b/third_party/boringssl/linux-arm/crypto/modes/ghashv8-armx.S deleted file mode 100644 index 570d9175c4760..0000000000000 --- a/third_party/boringssl/linux-arm/crypto/modes/ghashv8-armx.S +++ /dev/null @@ -1,116 +0,0 @@ -#include "arm_arch.h" - -.text -.fpu neon -.code 32 -.global gcm_init_v8 -.type gcm_init_v8,%function -.align 4 -gcm_init_v8: - vld1.64 {q9},[r1] @ load H - vmov.i8 q8,#0xe1 - vext.8 q3,q9,q9,#8 - vshl.i64 q8,q8,#57 - vshr.u64 q10,q8,#63 - vext.8 q8,q10,q8,#8 @ t0=0xc2....01 - vdup.32 q9,d18[1] - vshr.u64 q11,q3,#63 - vshr.s32 q9,q9,#31 @ broadcast carry bit - vand q11,q11,q8 - vshl.i64 q3,q3,#1 - vext.8 q11,q11,q11,#8 - vand q8,q8,q9 - vorr q3,q3,q11 @ H<<<=1 - veor q3,q3,q8 @ twisted H - vst1.64 {q3},[r0] - - bx lr -.size gcm_init_v8,.-gcm_init_v8 - -.global gcm_gmult_v8 -.type gcm_gmult_v8,%function -.align 4 -gcm_gmult_v8: - vld1.64 {q9},[r0] @ load Xi - vmov.i8 q11,#0xe1 - vld1.64 {q12},[r1] @ load twisted H - vshl.u64 q11,q11,#57 -#ifndef __ARMEB__ - vrev64.8 q9,q9 -#endif - vext.8 q13,q12,q12,#8 - mov r3,#0 - vext.8 q3,q9,q9,#8 - mov r12,#0 - veor q13,q13,q12 @ Karatsuba pre-processing - mov r2,r0 - b .Lgmult_v8 -.size gcm_gmult_v8,.-gcm_gmult_v8 - -.global gcm_ghash_v8 -.type gcm_ghash_v8,%function -.align 4 -gcm_ghash_v8: - vld1.64 {q0},[r0] @ load [rotated] Xi - subs r3,r3,#16 - vmov.i8 q11,#0xe1 - mov r12,#16 - vld1.64 {q12},[r1] @ load twisted H - moveq r12,#0 - vext.8 q0,q0,q0,#8 - vshl.u64 q11,q11,#57 - vld1.64 {q9},[r2],r12 @ load [rotated] inp - vext.8 q13,q12,q12,#8 -#ifndef __ARMEB__ - vrev64.8 q0,q0 - vrev64.8 q9,q9 -#endif - veor q13,q13,q12 @ Karatsuba pre-processing - vext.8 q3,q9,q9,#8 - b .Loop_v8 - -.align 4 -.Loop_v8: - vext.8 q10,q0,q0,#8 - veor q3,q3,q0 @ inp^=Xi - veor q9,q9,q10 @ q9 is rotated inp^Xi - -.Lgmult_v8: - .byte 0x86,0x0e,0xa8,0xf2 @ pmull q0,q12,q3 @ H.lo�Xi.lo - veor q9,q9,q3 @ Karatsuba pre-processing - .byte 0x87,0x4e,0xa9,0xf2 @ pmull2 q2,q12,q3 @ H.hi�Xi.hi - subs r3,r3,#16 - .byte 0xa2,0x2e,0xaa,0xf2 @ pmull q1,q13,q9 @ (H.lo+H.hi)�(Xi.lo+Xi.hi) - moveq r12,#0 - - vext.8 q9,q0,q2,#8 @ Karatsuba post-processing - veor q10,q0,q2 - veor q1,q1,q9 - vld1.64 {q9},[r2],r12 @ load [rotated] inp - veor q1,q1,q10 - .byte 0x26,0x4e,0xe0,0xf2 @ pmull q10,q0,q11 @ 1st phase - - vmov d4,d3 @ Xh|Xm - 256-bit result - vmov d3,d0 @ Xm is rotated Xl -#ifndef __ARMEB__ - vrev64.8 q9,q9 -#endif - veor q0,q1,q10 - vext.8 q3,q9,q9,#8 - - vext.8 q10,q0,q0,#8 @ 2nd phase - .byte 0x26,0x0e,0xa0,0xf2 @ pmull q0,q0,q11 - veor q10,q10,q2 - veor q0,q0,q10 - bhs .Loop_v8 - -#ifndef __ARMEB__ - vrev64.8 q0,q0 -#endif - vext.8 q0,q0,q0,#8 - vst1.64 {q0},[r0] @ write out Xi - - bx lr -.size gcm_ghash_v8,.-gcm_ghash_v8 -.asciz "GHASH for ARMv8, CRYPTOGAMS by " -.align 2 diff --git a/third_party/boringssl/linux-arm/crypto/modes/ghashv8-armx32.S b/third_party/boringssl/linux-arm/crypto/modes/ghashv8-armx32.S new file mode 100644 index 0000000000000..bdbbae90d4da7 --- /dev/null +++ b/third_party/boringssl/linux-arm/crypto/modes/ghashv8-armx32.S @@ -0,0 +1,233 @@ +#if defined(__arm__) +#include "arm_arch.h" + +.text +.fpu neon +.code 32 +.globl gcm_init_v8 +.type gcm_init_v8,%function +.align 4 +gcm_init_v8: + vld1.64 {q9},[r1] @ load input H + vmov.i8 q11,#0xe1 + vshl.i64 q11,q11,#57 @ 0xc2.0 + vext.8 q3,q9,q9,#8 + vshr.u64 q10,q11,#63 + vdup.32 q9,d18[1] + vext.8 q8,q10,q11,#8 @ t0=0xc2....01 + vshr.u64 q10,q3,#63 + vshr.s32 q9,q9,#31 @ broadcast carry bit + vand q10,q10,q8 + vshl.i64 q3,q3,#1 + vext.8 q10,q10,q10,#8 + vand q8,q8,q9 + vorr q3,q3,q10 @ H<<<=1 + veor q12,q3,q8 @ twisted H + vst1.64 {q12},[r0]! @ store Htable[0] + + @ calculate H^2 + vext.8 q8,q12,q12,#8 @ Karatsuba pre-processing +.byte 0xa8,0x0e,0xa8,0xf2 @ pmull q0,q12,q12 + veor q8,q8,q12 +.byte 0xa9,0x4e,0xa9,0xf2 @ pmull2 q2,q12,q12 +.byte 0xa0,0x2e,0xa0,0xf2 @ pmull q1,q8,q8 + + vext.8 q9,q0,q2,#8 @ Karatsuba post-processing + veor q10,q0,q2 + veor q1,q1,q9 + veor q1,q1,q10 +.byte 0x26,0x4e,0xe0,0xf2 @ pmull q10,q0,q11 @ 1st phase + + vmov d4,d3 @ Xh|Xm - 256-bit result + vmov d3,d0 @ Xm is rotated Xl + veor q0,q1,q10 + + vext.8 q10,q0,q0,#8 @ 2nd phase +.byte 0x26,0x0e,0xa0,0xf2 @ pmull q0,q0,q11 + veor q10,q10,q2 + veor q14,q0,q10 + + vext.8 q9,q14,q14,#8 @ Karatsuba pre-processing + veor q9,q9,q14 + vext.8 q13,q8,q9,#8 @ pack Karatsuba pre-processed + vst1.64 {q13,q14},[r0] @ store Htable[1..2] + + bx lr +.size gcm_init_v8,.-gcm_init_v8 +.globl gcm_gmult_v8 +.type gcm_gmult_v8,%function +.align 4 +gcm_gmult_v8: + vld1.64 {q9},[r0] @ load Xi + vmov.i8 q11,#0xe1 + vld1.64 {q12,q13},[r1] @ load twisted H, ... + vshl.u64 q11,q11,#57 +#ifndef __ARMEB__ + vrev64.8 q9,q9 +#endif + vext.8 q3,q9,q9,#8 + +.byte 0x86,0x0e,0xa8,0xf2 @ pmull q0,q12,q3 @ H.lo�Xi.lo + veor q9,q9,q3 @ Karatsuba pre-processing +.byte 0x87,0x4e,0xa9,0xf2 @ pmull2 q2,q12,q3 @ H.hi�Xi.hi +.byte 0xa2,0x2e,0xaa,0xf2 @ pmull q1,q13,q9 @ (H.lo+H.hi)�(Xi.lo+Xi.hi) + + vext.8 q9,q0,q2,#8 @ Karatsuba post-processing + veor q10,q0,q2 + veor q1,q1,q9 + veor q1,q1,q10 +.byte 0x26,0x4e,0xe0,0xf2 @ pmull q10,q0,q11 @ 1st phase of reduction + + vmov d4,d3 @ Xh|Xm - 256-bit result + vmov d3,d0 @ Xm is rotated Xl + veor q0,q1,q10 + + vext.8 q10,q0,q0,#8 @ 2nd phase of reduction +.byte 0x26,0x0e,0xa0,0xf2 @ pmull q0,q0,q11 + veor q10,q10,q2 + veor q0,q0,q10 + +#ifndef __ARMEB__ + vrev64.8 q0,q0 +#endif + vext.8 q0,q0,q0,#8 + vst1.64 {q0},[r0] @ write out Xi + + bx lr +.size gcm_gmult_v8,.-gcm_gmult_v8 +.globl gcm_ghash_v8 +.type gcm_ghash_v8,%function +.align 4 +gcm_ghash_v8: + vstmdb sp!,{d8,d9,d10,d11,d12,d13,d14,d15} @ 32-bit ABI says so + vld1.64 {q0},[r0] @ load [rotated] Xi + @ "[rotated]" means that + @ loaded value would have + @ to be rotated in order to + @ make it appear as in + @ alorithm specification + subs r3,r3,#32 @ see if r3 is 32 or larger + mov r12,#16 @ r12 is used as post- + @ increment for input pointer; + @ as loop is modulo-scheduled + @ r12 is zeroed just in time + @ to preclude oversteping + @ inp[len], which means that + @ last block[s] are actually + @ loaded twice, but last + @ copy is not processed + vld1.64 {q12,q13},[r1]! @ load twisted H, ..., H^2 + vmov.i8 q11,#0xe1 + vld1.64 {q14},[r1] + moveq r12,#0 @ is it time to zero r12? + vext.8 q0,q0,q0,#8 @ rotate Xi + vld1.64 {q8},[r2]! @ load [rotated] I[0] + vshl.u64 q11,q11,#57 @ compose 0xc2.0 constant +#ifndef __ARMEB__ + vrev64.8 q8,q8 + vrev64.8 q0,q0 +#endif + vext.8 q3,q8,q8,#8 @ rotate I[0] + blo .Lodd_tail_v8 @ r3 was less than 32 + vld1.64 {q9},[r2],r12 @ load [rotated] I[1] +#ifndef __ARMEB__ + vrev64.8 q9,q9 +#endif + vext.8 q7,q9,q9,#8 + veor q3,q3,q0 @ I[i]^=Xi +.byte 0x8e,0x8e,0xa8,0xf2 @ pmull q4,q12,q7 @ H�Ii+1 + veor q9,q9,q7 @ Karatsuba pre-processing +.byte 0x8f,0xce,0xa9,0xf2 @ pmull2 q6,q12,q7 + b .Loop_mod2x_v8 + +.align 4 +.Loop_mod2x_v8: + vext.8 q10,q3,q3,#8 + subs r3,r3,#32 @ is there more data? +.byte 0x86,0x0e,0xac,0xf2 @ pmull q0,q14,q3 @ H^2.lo�Xi.lo + movlo r12,#0 @ is it time to zero r12? + +.byte 0xa2,0xae,0xaa,0xf2 @ pmull q5,q13,q9 + veor q10,q10,q3 @ Karatsuba pre-processing +.byte 0x87,0x4e,0xad,0xf2 @ pmull2 q2,q14,q3 @ H^2.hi�Xi.hi + veor q0,q0,q4 @ accumulate +.byte 0xa5,0x2e,0xab,0xf2 @ pmull2 q1,q13,q10 @ (H^2.lo+H^2.hi)�(Xi.lo+Xi.hi) + vld1.64 {q8},[r2],r12 @ load [rotated] I[i+2] + + veor q2,q2,q6 + moveq r12,#0 @ is it time to zero r12? + veor q1,q1,q5 + + vext.8 q9,q0,q2,#8 @ Karatsuba post-processing + veor q10,q0,q2 + veor q1,q1,q9 + vld1.64 {q9},[r2],r12 @ load [rotated] I[i+3] +#ifndef __ARMEB__ + vrev64.8 q8,q8 +#endif + veor q1,q1,q10 +.byte 0x26,0x4e,0xe0,0xf2 @ pmull q10,q0,q11 @ 1st phase of reduction + +#ifndef __ARMEB__ + vrev64.8 q9,q9 +#endif + vmov d4,d3 @ Xh|Xm - 256-bit result + vmov d3,d0 @ Xm is rotated Xl + vext.8 q7,q9,q9,#8 + vext.8 q3,q8,q8,#8 + veor q0,q1,q10 +.byte 0x8e,0x8e,0xa8,0xf2 @ pmull q4,q12,q7 @ H�Ii+1 + veor q3,q3,q2 @ accumulate q3 early + + vext.8 q10,q0,q0,#8 @ 2nd phase of reduction +.byte 0x26,0x0e,0xa0,0xf2 @ pmull q0,q0,q11 + veor q3,q3,q10 + veor q9,q9,q7 @ Karatsuba pre-processing + veor q3,q3,q0 +.byte 0x8f,0xce,0xa9,0xf2 @ pmull2 q6,q12,q7 + bhs .Loop_mod2x_v8 @ there was at least 32 more bytes + + veor q2,q2,q10 + vext.8 q3,q8,q8,#8 @ re-construct q3 + adds r3,r3,#32 @ re-construct r3 + veor q0,q0,q2 @ re-construct q0 + beq .Ldone_v8 @ is r3 zero? +.Lodd_tail_v8: + vext.8 q10,q0,q0,#8 + veor q3,q3,q0 @ inp^=Xi + veor q9,q8,q10 @ q9 is rotated inp^Xi + +.byte 0x86,0x0e,0xa8,0xf2 @ pmull q0,q12,q3 @ H.lo�Xi.lo + veor q9,q9,q3 @ Karatsuba pre-processing +.byte 0x87,0x4e,0xa9,0xf2 @ pmull2 q2,q12,q3 @ H.hi�Xi.hi +.byte 0xa2,0x2e,0xaa,0xf2 @ pmull q1,q13,q9 @ (H.lo+H.hi)�(Xi.lo+Xi.hi) + + vext.8 q9,q0,q2,#8 @ Karatsuba post-processing + veor q10,q0,q2 + veor q1,q1,q9 + veor q1,q1,q10 +.byte 0x26,0x4e,0xe0,0xf2 @ pmull q10,q0,q11 @ 1st phase of reduction + + vmov d4,d3 @ Xh|Xm - 256-bit result + vmov d3,d0 @ Xm is rotated Xl + veor q0,q1,q10 + + vext.8 q10,q0,q0,#8 @ 2nd phase of reduction +.byte 0x26,0x0e,0xa0,0xf2 @ pmull q0,q0,q11 + veor q10,q10,q2 + veor q0,q0,q10 + +.Ldone_v8: +#ifndef __ARMEB__ + vrev64.8 q0,q0 +#endif + vext.8 q0,q0,q0,#8 + vst1.64 {q0},[r0] @ write out Xi + + vldmia sp!,{d8,d9,d10,d11,d12,d13,d14,d15} @ 32-bit ABI says so + bx lr +.size gcm_ghash_v8,.-gcm_ghash_v8 +.byte 71,72,65,83,72,32,102,111,114,32,65,82,77,118,56,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0 +.align 2 +.align 2 +#endif \ No newline at end of file diff --git a/third_party/boringssl/linux-arm/crypto/sha/sha1-armv4-large.S b/third_party/boringssl/linux-arm/crypto/sha/sha1-armv4-large.S index 5abc32815c29d..4911458b26277 100644 --- a/third_party/boringssl/linux-arm/crypto/sha/sha1-armv4-large.S +++ b/third_party/boringssl/linux-arm/crypto/sha/sha1-armv4-large.S @@ -1,9 +1,10 @@ +#if defined(__arm__) #include "arm_arch.h" .text .code 32 -.global sha1_block_data_order +.globl sha1_block_data_order .type sha1_block_data_order,%function .align 5 @@ -12,12 +13,15 @@ sha1_block_data_order: sub r3,pc,#8 @ sha1_block_data_order ldr r12,.LOPENSSL_armcap ldr r12,[r3,r12] @ OPENSSL_armcap_P +#ifdef __APPLE__ + ldr r12,[r12] +#endif tst r12,#ARMV8_SHA1 bne .LARMv8 tst r12,#ARMV7_NEON bne .LNEON #endif - stmdb sp!,{r4-r12,lr} + stmdb sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,lr} add r2,r1,r2,lsl#6 @ r2 to point at the end of r1 ldmia r0,{r3,r4,r5,r6,r7} .Lloop: @@ -193,7 +197,7 @@ sha1_block_data_order: add r6,r6,r7,ror#27 @ E+=ROR(A,27) eor r9,r9,r11,ror#31 str r9,[r14,#-4]! - and r10,r3,r10,ror#2 @ F_xx_xx + and r10,r3,r10,ror#2 @ F_xx_xx @ F_xx_xx add r6,r6,r9 @ E+=X[i] eor r10,r10,r5,ror#2 @ F_00_19(B,C,D) @@ -210,7 +214,7 @@ sha1_block_data_order: add r5,r5,r6,ror#27 @ E+=ROR(A,27) eor r9,r9,r11,ror#31 str r9,[r14,#-4]! - and r10,r7,r10,ror#2 @ F_xx_xx + and r10,r7,r10,ror#2 @ F_xx_xx @ F_xx_xx add r5,r5,r9 @ E+=X[i] eor r10,r10,r4,ror#2 @ F_00_19(B,C,D) @@ -227,7 +231,7 @@ sha1_block_data_order: add r4,r4,r5,ror#27 @ E+=ROR(A,27) eor r9,r9,r11,ror#31 str r9,[r14,#-4]! - and r10,r6,r10,ror#2 @ F_xx_xx + and r10,r6,r10,ror#2 @ F_xx_xx @ F_xx_xx add r4,r4,r9 @ E+=X[i] eor r10,r10,r3,ror#2 @ F_00_19(B,C,D) @@ -244,7 +248,7 @@ sha1_block_data_order: add r3,r3,r4,ror#27 @ E+=ROR(A,27) eor r9,r9,r11,ror#31 str r9,[r14,#-4]! - and r10,r5,r10,ror#2 @ F_xx_xx + and r10,r5,r10,ror#2 @ F_xx_xx @ F_xx_xx add r3,r3,r9 @ E+=X[i] eor r10,r10,r7,ror#2 @ F_00_19(B,C,D) @@ -265,7 +269,7 @@ sha1_block_data_order: add r7,r7,r3,ror#27 @ E+=ROR(A,27) eor r9,r9,r11,ror#31 str r9,[r14,#-4]! - eor r10,r4,r10,ror#2 @ F_xx_xx + eor r10,r4,r10,ror#2 @ F_xx_xx @ F_xx_xx add r7,r7,r9 @ E+=X[i] add r7,r7,r10 @ E+=F_20_39(B,C,D) @@ -281,7 +285,7 @@ sha1_block_data_order: add r6,r6,r7,ror#27 @ E+=ROR(A,27) eor r9,r9,r11,ror#31 str r9,[r14,#-4]! - eor r10,r3,r10,ror#2 @ F_xx_xx + eor r10,r3,r10,ror#2 @ F_xx_xx @ F_xx_xx add r6,r6,r9 @ E+=X[i] add r6,r6,r10 @ E+=F_20_39(B,C,D) @@ -297,7 +301,7 @@ sha1_block_data_order: add r5,r5,r6,ror#27 @ E+=ROR(A,27) eor r9,r9,r11,ror#31 str r9,[r14,#-4]! - eor r10,r7,r10,ror#2 @ F_xx_xx + eor r10,r7,r10,ror#2 @ F_xx_xx @ F_xx_xx add r5,r5,r9 @ E+=X[i] add r5,r5,r10 @ E+=F_20_39(B,C,D) @@ -313,7 +317,7 @@ sha1_block_data_order: add r4,r4,r5,ror#27 @ E+=ROR(A,27) eor r9,r9,r11,ror#31 str r9,[r14,#-4]! - eor r10,r6,r10,ror#2 @ F_xx_xx + eor r10,r6,r10,ror#2 @ F_xx_xx @ F_xx_xx add r4,r4,r9 @ E+=X[i] add r4,r4,r10 @ E+=F_20_39(B,C,D) @@ -329,7 +333,7 @@ sha1_block_data_order: add r3,r3,r4,ror#27 @ E+=ROR(A,27) eor r9,r9,r11,ror#31 str r9,[r14,#-4]! - eor r10,r5,r10,ror#2 @ F_xx_xx + eor r10,r5,r10,ror#2 @ F_xx_xx @ F_xx_xx add r3,r3,r9 @ E+=X[i] add r3,r3,r10 @ E+=F_20_39(B,C,D) @@ -352,8 +356,8 @@ sha1_block_data_order: add r7,r7,r3,ror#27 @ E+=ROR(A,27) eor r9,r9,r11,ror#31 str r9,[r14,#-4]! - and r10,r4,r10,ror#2 @ F_xx_xx - and r11,r5,r6 @ F_xx_xx + and r10,r4,r10,ror#2 @ F_xx_xx + and r11,r5,r6 @ F_xx_xx add r7,r7,r9 @ E+=X[i] add r7,r7,r10 @ E+=F_40_59(B,C,D) add r7,r7,r11,ror#2 @@ -369,8 +373,8 @@ sha1_block_data_order: add r6,r6,r7,ror#27 @ E+=ROR(A,27) eor r9,r9,r11,ror#31 str r9,[r14,#-4]! - and r10,r3,r10,ror#2 @ F_xx_xx - and r11,r4,r5 @ F_xx_xx + and r10,r3,r10,ror#2 @ F_xx_xx + and r11,r4,r5 @ F_xx_xx add r6,r6,r9 @ E+=X[i] add r6,r6,r10 @ E+=F_40_59(B,C,D) add r6,r6,r11,ror#2 @@ -386,8 +390,8 @@ sha1_block_data_order: add r5,r5,r6,ror#27 @ E+=ROR(A,27) eor r9,r9,r11,ror#31 str r9,[r14,#-4]! - and r10,r7,r10,ror#2 @ F_xx_xx - and r11,r3,r4 @ F_xx_xx + and r10,r7,r10,ror#2 @ F_xx_xx + and r11,r3,r4 @ F_xx_xx add r5,r5,r9 @ E+=X[i] add r5,r5,r10 @ E+=F_40_59(B,C,D) add r5,r5,r11,ror#2 @@ -403,8 +407,8 @@ sha1_block_data_order: add r4,r4,r5,ror#27 @ E+=ROR(A,27) eor r9,r9,r11,ror#31 str r9,[r14,#-4]! - and r10,r6,r10,ror#2 @ F_xx_xx - and r11,r7,r3 @ F_xx_xx + and r10,r6,r10,ror#2 @ F_xx_xx + and r11,r7,r3 @ F_xx_xx add r4,r4,r9 @ E+=X[i] add r4,r4,r10 @ E+=F_40_59(B,C,D) add r4,r4,r11,ror#2 @@ -420,8 +424,8 @@ sha1_block_data_order: add r3,r3,r4,ror#27 @ E+=ROR(A,27) eor r9,r9,r11,ror#31 str r9,[r14,#-4]! - and r10,r5,r10,ror#2 @ F_xx_xx - and r11,r6,r7 @ F_xx_xx + and r10,r5,r10,ror#2 @ F_xx_xx + and r11,r6,r7 @ F_xx_xx add r3,r3,r9 @ E+=X[i] add r3,r3,r10 @ E+=F_40_59(B,C,D) add r3,r3,r11,ror#2 @@ -445,25 +449,26 @@ sha1_block_data_order: bne .Lloop @ [+18], total 1307 #if __ARM_ARCH__>=5 - ldmia sp!,{r4-r12,pc} + ldmia sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,pc} #else - ldmia sp!,{r4-r12,lr} + ldmia sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,lr} tst lr,#1 moveq pc,lr @ be binary compatible with V4, yet - .word 0xe12fff1e @ interoperable with Thumb ISA:-) +.word 0xe12fff1e @ interoperable with Thumb ISA:-) #endif .size sha1_block_data_order,.-sha1_block_data_order .align 5 -.LK_00_19: .word 0x5a827999 -.LK_20_39: .word 0x6ed9eba1 -.LK_40_59: .word 0x8f1bbcdc -.LK_60_79: .word 0xca62c1d6 +.LK_00_19:.word 0x5a827999 +.LK_20_39:.word 0x6ed9eba1 +.LK_40_59:.word 0x8f1bbcdc +.LK_60_79:.word 0xca62c1d6 #if __ARM_MAX_ARCH__>=7 .LOPENSSL_armcap: .word OPENSSL_armcap_P-sha1_block_data_order #endif -.asciz "SHA1 block transform for ARMv4/NEON/ARMv8, CRYPTOGAMS by " +.byte 83,72,65,49,32,98,108,111,99,107,32,116,114,97,110,115,102,111,114,109,32,102,111,114,32,65,82,77,118,52,47,78,69,79,78,47,65,82,77,118,56,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0 +.align 2 .align 5 #if __ARM_MAX_ARCH__>=7 .arch armv7-a @@ -473,7 +478,7 @@ sha1_block_data_order: .align 4 sha1_block_data_order_neon: .LNEON: - stmdb sp!,{r4-r12,lr} + stmdb sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,lr} add r2,r1,r2,lsl#6 @ r2 to point at the end of r1 @ dmb @ errata #451034 on early Cortex A8 @ vstmdb sp!,{d8-d15} @ ABI specification says so @@ -485,21 +490,21 @@ sha1_block_data_order_neon: ldmia r0,{r3,r4,r5,r6,r7} @ load context mov r12,sp - vld1.8 {q0-q1},[r1]! @ handles unaligned - veor q15,q15,q15 - vld1.8 {q2-q3},[r1]! - vld1.32 {d28[],d29[]},[r8,:32]! @ load K_00_19 + vld1.8 {q0,q1},[r1]! @ handles unaligned + veor q15,q15,q15 + vld1.8 {q2,q3},[r1]! + vld1.32 {d28[],d29[]},[r8,:32]! @ load K_00_19 vrev32.8 q0,q0 @ yes, even on vrev32.8 q1,q1 @ big-endian... vrev32.8 q2,q2 vadd.i32 q8,q0,q14 vrev32.8 q3,q3 vadd.i32 q9,q1,q14 - vst1.32 {q8},[r12,:128]! + vst1.32 {q8},[r12,:128]! vadd.i32 q10,q2,q14 - vst1.32 {q9},[r12,:128]! - vst1.32 {q10},[r12,:128]! - ldr r9,[sp] @ big RAW stall + vst1.32 {q9},[r12,:128]! + vst1.32 {q10},[r12,:128]! + ldr r9,[sp] @ big RAW stall .Loop_neon: vext.8 q8,q0,q1,#8 @@ -1177,10 +1182,10 @@ sha1_block_data_order_neon: teq r1,r2 sub r8,r8,#16 subeq r1,r1,#64 - vld1.8 {q0-q1},[r1]! + vld1.8 {q0,q1},[r1]! ldr r9,[sp,#4] eor r11,r10,r6 - vld1.8 {q2-q3},[r1]! + vld1.8 {q2,q3},[r1]! add r3,r3,r4,ror#27 mov r5,r5,ror#2 vld1.32 {d28[],d29[]},[r8,:32]! @@ -1313,7 +1318,7 @@ sha1_block_data_order_neon: bne .Loop_neon @ vldmia sp!,{d8-d15} - ldmia sp!,{r4-r12,pc} + ldmia sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,pc} .size sha1_block_data_order_neon,.-sha1_block_data_order_neon #endif #if __ARM_MAX_ARCH__>=7 @@ -1321,7 +1326,7 @@ sha1_block_data_order_neon: .align 5 sha1_block_data_order_armv8: .LARMv8: - vstmdb sp!,{d8-d15} @ ABI specification says so + vstmdb sp!,{d8,d9,d10,d11,d12,d13,d14,d15} @ ABI specification says so veor q1,q1,q1 adr r3,.LK_00_19 @@ -1334,119 +1339,119 @@ sha1_block_data_order_armv8: vld1.32 {d22[],d23[]},[r3,:32] .Loop_v8: - vld1.8 {q4-q5},[r1]! - vld1.8 {q6-q7},[r1]! + vld1.8 {q4,q5},[r1]! + vld1.8 {q6,q7},[r1]! vrev32.8 q4,q4 vrev32.8 q5,q5 vadd.i32 q12,q8,q4 vrev32.8 q6,q6 - vmov q14,q0 @ offload - subs r2,r2,#1 + vmov q14,q0 @ offload + subs r2,r2,#1 vadd.i32 q13,q8,q5 vrev32.8 q7,q7 - .byte 0xc0,0x62,0xb9,0xf3 @ sha1h q3,q0 @ 0 - .byte 0x68,0x0c,0x02,0xf2 @ sha1c q0,q1,q12 +.byte 0xc0,0x62,0xb9,0xf3 @ sha1h q3,q0 @ 0 +.byte 0x68,0x0c,0x02,0xf2 @ sha1c q0,q1,q12 vadd.i32 q12,q8,q6 - .byte 0x4c,0x8c,0x3a,0xf2 @ sha1su0 q4,q5,q6 - .byte 0xc0,0x42,0xb9,0xf3 @ sha1h q2,q0 @ 1 - .byte 0x6a,0x0c,0x06,0xf2 @ sha1c q0,q3,q13 +.byte 0x4c,0x8c,0x3a,0xf2 @ sha1su0 q4,q5,q6 +.byte 0xc0,0x42,0xb9,0xf3 @ sha1h q2,q0 @ 1 +.byte 0x6a,0x0c,0x06,0xf2 @ sha1c q0,q3,q13 vadd.i32 q13,q8,q7 - .byte 0x8e,0x83,0xba,0xf3 @ sha1su1 q4,q7 - .byte 0x4e,0xac,0x3c,0xf2 @ sha1su0 q5,q6,q7 - .byte 0xc0,0x62,0xb9,0xf3 @ sha1h q3,q0 @ 2 - .byte 0x68,0x0c,0x04,0xf2 @ sha1c q0,q2,q12 +.byte 0x8e,0x83,0xba,0xf3 @ sha1su1 q4,q7 +.byte 0x4e,0xac,0x3c,0xf2 @ sha1su0 q5,q6,q7 +.byte 0xc0,0x62,0xb9,0xf3 @ sha1h q3,q0 @ 2 +.byte 0x68,0x0c,0x04,0xf2 @ sha1c q0,q2,q12 vadd.i32 q12,q8,q4 - .byte 0x88,0xa3,0xba,0xf3 @ sha1su1 q5,q4 - .byte 0x48,0xcc,0x3e,0xf2 @ sha1su0 q6,q7,q4 - .byte 0xc0,0x42,0xb9,0xf3 @ sha1h q2,q0 @ 3 - .byte 0x6a,0x0c,0x06,0xf2 @ sha1c q0,q3,q13 +.byte 0x88,0xa3,0xba,0xf3 @ sha1su1 q5,q4 +.byte 0x48,0xcc,0x3e,0xf2 @ sha1su0 q6,q7,q4 +.byte 0xc0,0x42,0xb9,0xf3 @ sha1h q2,q0 @ 3 +.byte 0x6a,0x0c,0x06,0xf2 @ sha1c q0,q3,q13 vadd.i32 q13,q9,q5 - .byte 0x8a,0xc3,0xba,0xf3 @ sha1su1 q6,q5 - .byte 0x4a,0xec,0x38,0xf2 @ sha1su0 q7,q4,q5 - .byte 0xc0,0x62,0xb9,0xf3 @ sha1h q3,q0 @ 4 - .byte 0x68,0x0c,0x04,0xf2 @ sha1c q0,q2,q12 +.byte 0x8a,0xc3,0xba,0xf3 @ sha1su1 q6,q5 +.byte 0x4a,0xec,0x38,0xf2 @ sha1su0 q7,q4,q5 +.byte 0xc0,0x62,0xb9,0xf3 @ sha1h q3,q0 @ 4 +.byte 0x68,0x0c,0x04,0xf2 @ sha1c q0,q2,q12 vadd.i32 q12,q9,q6 - .byte 0x8c,0xe3,0xba,0xf3 @ sha1su1 q7,q6 - .byte 0x4c,0x8c,0x3a,0xf2 @ sha1su0 q4,q5,q6 - .byte 0xc0,0x42,0xb9,0xf3 @ sha1h q2,q0 @ 5 - .byte 0x6a,0x0c,0x16,0xf2 @ sha1p q0,q3,q13 +.byte 0x8c,0xe3,0xba,0xf3 @ sha1su1 q7,q6 +.byte 0x4c,0x8c,0x3a,0xf2 @ sha1su0 q4,q5,q6 +.byte 0xc0,0x42,0xb9,0xf3 @ sha1h q2,q0 @ 5 +.byte 0x6a,0x0c,0x16,0xf2 @ sha1p q0,q3,q13 vadd.i32 q13,q9,q7 - .byte 0x8e,0x83,0xba,0xf3 @ sha1su1 q4,q7 - .byte 0x4e,0xac,0x3c,0xf2 @ sha1su0 q5,q6,q7 - .byte 0xc0,0x62,0xb9,0xf3 @ sha1h q3,q0 @ 6 - .byte 0x68,0x0c,0x14,0xf2 @ sha1p q0,q2,q12 +.byte 0x8e,0x83,0xba,0xf3 @ sha1su1 q4,q7 +.byte 0x4e,0xac,0x3c,0xf2 @ sha1su0 q5,q6,q7 +.byte 0xc0,0x62,0xb9,0xf3 @ sha1h q3,q0 @ 6 +.byte 0x68,0x0c,0x14,0xf2 @ sha1p q0,q2,q12 vadd.i32 q12,q9,q4 - .byte 0x88,0xa3,0xba,0xf3 @ sha1su1 q5,q4 - .byte 0x48,0xcc,0x3e,0xf2 @ sha1su0 q6,q7,q4 - .byte 0xc0,0x42,0xb9,0xf3 @ sha1h q2,q0 @ 7 - .byte 0x6a,0x0c,0x16,0xf2 @ sha1p q0,q3,q13 +.byte 0x88,0xa3,0xba,0xf3 @ sha1su1 q5,q4 +.byte 0x48,0xcc,0x3e,0xf2 @ sha1su0 q6,q7,q4 +.byte 0xc0,0x42,0xb9,0xf3 @ sha1h q2,q0 @ 7 +.byte 0x6a,0x0c,0x16,0xf2 @ sha1p q0,q3,q13 vadd.i32 q13,q9,q5 - .byte 0x8a,0xc3,0xba,0xf3 @ sha1su1 q6,q5 - .byte 0x4a,0xec,0x38,0xf2 @ sha1su0 q7,q4,q5 - .byte 0xc0,0x62,0xb9,0xf3 @ sha1h q3,q0 @ 8 - .byte 0x68,0x0c,0x14,0xf2 @ sha1p q0,q2,q12 +.byte 0x8a,0xc3,0xba,0xf3 @ sha1su1 q6,q5 +.byte 0x4a,0xec,0x38,0xf2 @ sha1su0 q7,q4,q5 +.byte 0xc0,0x62,0xb9,0xf3 @ sha1h q3,q0 @ 8 +.byte 0x68,0x0c,0x14,0xf2 @ sha1p q0,q2,q12 vadd.i32 q12,q10,q6 - .byte 0x8c,0xe3,0xba,0xf3 @ sha1su1 q7,q6 - .byte 0x4c,0x8c,0x3a,0xf2 @ sha1su0 q4,q5,q6 - .byte 0xc0,0x42,0xb9,0xf3 @ sha1h q2,q0 @ 9 - .byte 0x6a,0x0c,0x16,0xf2 @ sha1p q0,q3,q13 +.byte 0x8c,0xe3,0xba,0xf3 @ sha1su1 q7,q6 +.byte 0x4c,0x8c,0x3a,0xf2 @ sha1su0 q4,q5,q6 +.byte 0xc0,0x42,0xb9,0xf3 @ sha1h q2,q0 @ 9 +.byte 0x6a,0x0c,0x16,0xf2 @ sha1p q0,q3,q13 vadd.i32 q13,q10,q7 - .byte 0x8e,0x83,0xba,0xf3 @ sha1su1 q4,q7 - .byte 0x4e,0xac,0x3c,0xf2 @ sha1su0 q5,q6,q7 - .byte 0xc0,0x62,0xb9,0xf3 @ sha1h q3,q0 @ 10 - .byte 0x68,0x0c,0x24,0xf2 @ sha1m q0,q2,q12 +.byte 0x8e,0x83,0xba,0xf3 @ sha1su1 q4,q7 +.byte 0x4e,0xac,0x3c,0xf2 @ sha1su0 q5,q6,q7 +.byte 0xc0,0x62,0xb9,0xf3 @ sha1h q3,q0 @ 10 +.byte 0x68,0x0c,0x24,0xf2 @ sha1m q0,q2,q12 vadd.i32 q12,q10,q4 - .byte 0x88,0xa3,0xba,0xf3 @ sha1su1 q5,q4 - .byte 0x48,0xcc,0x3e,0xf2 @ sha1su0 q6,q7,q4 - .byte 0xc0,0x42,0xb9,0xf3 @ sha1h q2,q0 @ 11 - .byte 0x6a,0x0c,0x26,0xf2 @ sha1m q0,q3,q13 +.byte 0x88,0xa3,0xba,0xf3 @ sha1su1 q5,q4 +.byte 0x48,0xcc,0x3e,0xf2 @ sha1su0 q6,q7,q4 +.byte 0xc0,0x42,0xb9,0xf3 @ sha1h q2,q0 @ 11 +.byte 0x6a,0x0c,0x26,0xf2 @ sha1m q0,q3,q13 vadd.i32 q13,q10,q5 - .byte 0x8a,0xc3,0xba,0xf3 @ sha1su1 q6,q5 - .byte 0x4a,0xec,0x38,0xf2 @ sha1su0 q7,q4,q5 - .byte 0xc0,0x62,0xb9,0xf3 @ sha1h q3,q0 @ 12 - .byte 0x68,0x0c,0x24,0xf2 @ sha1m q0,q2,q12 +.byte 0x8a,0xc3,0xba,0xf3 @ sha1su1 q6,q5 +.byte 0x4a,0xec,0x38,0xf2 @ sha1su0 q7,q4,q5 +.byte 0xc0,0x62,0xb9,0xf3 @ sha1h q3,q0 @ 12 +.byte 0x68,0x0c,0x24,0xf2 @ sha1m q0,q2,q12 vadd.i32 q12,q10,q6 - .byte 0x8c,0xe3,0xba,0xf3 @ sha1su1 q7,q6 - .byte 0x4c,0x8c,0x3a,0xf2 @ sha1su0 q4,q5,q6 - .byte 0xc0,0x42,0xb9,0xf3 @ sha1h q2,q0 @ 13 - .byte 0x6a,0x0c,0x26,0xf2 @ sha1m q0,q3,q13 +.byte 0x8c,0xe3,0xba,0xf3 @ sha1su1 q7,q6 +.byte 0x4c,0x8c,0x3a,0xf2 @ sha1su0 q4,q5,q6 +.byte 0xc0,0x42,0xb9,0xf3 @ sha1h q2,q0 @ 13 +.byte 0x6a,0x0c,0x26,0xf2 @ sha1m q0,q3,q13 vadd.i32 q13,q11,q7 - .byte 0x8e,0x83,0xba,0xf3 @ sha1su1 q4,q7 - .byte 0x4e,0xac,0x3c,0xf2 @ sha1su0 q5,q6,q7 - .byte 0xc0,0x62,0xb9,0xf3 @ sha1h q3,q0 @ 14 - .byte 0x68,0x0c,0x24,0xf2 @ sha1m q0,q2,q12 +.byte 0x8e,0x83,0xba,0xf3 @ sha1su1 q4,q7 +.byte 0x4e,0xac,0x3c,0xf2 @ sha1su0 q5,q6,q7 +.byte 0xc0,0x62,0xb9,0xf3 @ sha1h q3,q0 @ 14 +.byte 0x68,0x0c,0x24,0xf2 @ sha1m q0,q2,q12 vadd.i32 q12,q11,q4 - .byte 0x88,0xa3,0xba,0xf3 @ sha1su1 q5,q4 - .byte 0x48,0xcc,0x3e,0xf2 @ sha1su0 q6,q7,q4 - .byte 0xc0,0x42,0xb9,0xf3 @ sha1h q2,q0 @ 15 - .byte 0x6a,0x0c,0x16,0xf2 @ sha1p q0,q3,q13 +.byte 0x88,0xa3,0xba,0xf3 @ sha1su1 q5,q4 +.byte 0x48,0xcc,0x3e,0xf2 @ sha1su0 q6,q7,q4 +.byte 0xc0,0x42,0xb9,0xf3 @ sha1h q2,q0 @ 15 +.byte 0x6a,0x0c,0x16,0xf2 @ sha1p q0,q3,q13 vadd.i32 q13,q11,q5 - .byte 0x8a,0xc3,0xba,0xf3 @ sha1su1 q6,q5 - .byte 0x4a,0xec,0x38,0xf2 @ sha1su0 q7,q4,q5 - .byte 0xc0,0x62,0xb9,0xf3 @ sha1h q3,q0 @ 16 - .byte 0x68,0x0c,0x14,0xf2 @ sha1p q0,q2,q12 +.byte 0x8a,0xc3,0xba,0xf3 @ sha1su1 q6,q5 +.byte 0x4a,0xec,0x38,0xf2 @ sha1su0 q7,q4,q5 +.byte 0xc0,0x62,0xb9,0xf3 @ sha1h q3,q0 @ 16 +.byte 0x68,0x0c,0x14,0xf2 @ sha1p q0,q2,q12 vadd.i32 q12,q11,q6 - .byte 0x8c,0xe3,0xba,0xf3 @ sha1su1 q7,q6 - .byte 0xc0,0x42,0xb9,0xf3 @ sha1h q2,q0 @ 17 - .byte 0x6a,0x0c,0x16,0xf2 @ sha1p q0,q3,q13 +.byte 0x8c,0xe3,0xba,0xf3 @ sha1su1 q7,q6 +.byte 0xc0,0x42,0xb9,0xf3 @ sha1h q2,q0 @ 17 +.byte 0x6a,0x0c,0x16,0xf2 @ sha1p q0,q3,q13 vadd.i32 q13,q11,q7 - .byte 0xc0,0x62,0xb9,0xf3 @ sha1h q3,q0 @ 18 - .byte 0x68,0x0c,0x14,0xf2 @ sha1p q0,q2,q12 +.byte 0xc0,0x62,0xb9,0xf3 @ sha1h q3,q0 @ 18 +.byte 0x68,0x0c,0x14,0xf2 @ sha1p q0,q2,q12 - .byte 0xc0,0x42,0xb9,0xf3 @ sha1h q2,q0 @ 19 - .byte 0x6a,0x0c,0x16,0xf2 @ sha1p q0,q3,q13 +.byte 0xc0,0x42,0xb9,0xf3 @ sha1h q2,q0 @ 19 +.byte 0x6a,0x0c,0x16,0xf2 @ sha1p q0,q3,q13 vadd.i32 q1,q1,q2 vadd.i32 q0,q0,q14 - bne .Loop_v8 + bne .Loop_v8 - vst1.32 {q0},[r0]! - vst1.32 {d2[0]},[r0] + vst1.32 {q0},[r0]! + vst1.32 {d2[0]},[r0] - vldmia sp!,{d8-d15} + vldmia sp!,{d8,d9,d10,d11,d12,d13,d14,d15} bx lr @ bx lr .size sha1_block_data_order_armv8,.-sha1_block_data_order_armv8 #endif @@ -1454,3 +1459,4 @@ sha1_block_data_order_armv8: .comm OPENSSL_armcap_P,4,4 .hidden OPENSSL_armcap_P #endif +#endif \ No newline at end of file diff --git a/third_party/boringssl/linux-arm/crypto/sha/sha256-armv4.S b/third_party/boringssl/linux-arm/crypto/sha/sha256-armv4.S index 3c41010722915..ac9f2f164d854 100644 --- a/third_party/boringssl/linux-arm/crypto/sha/sha256-armv4.S +++ b/third_party/boringssl/linux-arm/crypto/sha/sha256-armv4.S @@ -1,7 +1,61 @@ -#include "arm_arch.h" +#if defined(__arm__) + +@ ==================================================================== +@ Written by Andy Polyakov for the OpenSSL +@ project. The module is, however, dual licensed under OpenSSL and +@ CRYPTOGAMS licenses depending on where you obtain it. For further +@ details see http://www.openssl.org/~appro/cryptogams/. +@ +@ Permission to use under GPL terms is granted. +@ ==================================================================== + +@ SHA256 block procedure for ARMv4. May 2007. + +@ Performance is ~2x better than gcc 3.4 generated code and in "abso- +@ lute" terms is ~2250 cycles per 64-byte block or ~35 cycles per +@ byte [on single-issue Xscale PXA250 core]. + +@ July 2010. +@ +@ Rescheduling for dual-issue pipeline resulted in 22% improvement on +@ Cortex A8 core and ~20 cycles per processed byte. + +@ February 2011. +@ +@ Profiler-assisted and platform-specific optimization resulted in 16% +@ improvement on Cortex A8 core and ~15.4 cycles per processed byte. + +@ September 2013. +@ +@ Add NEON implementation. On Cortex A8 it was measured to process one +@ byte in 12.5 cycles or 23% faster than integer-only code. Snapdragon +@ S4 does it in 12.5 cycles too, but it's 50% faster than integer-only +@ code (meaning that latter performs sub-optimally, nothing was done +@ about it). + +@ May 2014. +@ +@ Add ARMv8 code path performing at 2.0 cpb on Apple A7. + +#ifndef __KERNEL__ +# include "arm_arch.h" +#else +# define __ARM_ARCH__ __LINUX_ARM_ARCH__ +# define __ARM_MAX_ARCH__ 7 +#endif .text +#if __ARM_ARCH__<7 .code 32 +#else +.syntax unified +# if defined(__thumb2__) && !defined(__APPLE__) +# define adrl adr +.thumb +# else +.code 32 +# endif +#endif .type K256,%object .align 5 @@ -24,25 +78,33 @@ K256: .word 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 .size K256,.-K256 .word 0 @ terminator -#if __ARM_MAX_ARCH__>=7 +#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) .LOPENSSL_armcap: -.word OPENSSL_armcap_P-sha256_block_data_order +.word OPENSSL_armcap_P-.Lsha256_block_data_order #endif .align 5 -.global sha256_block_data_order +.globl sha256_block_data_order .type sha256_block_data_order,%function sha256_block_data_order: +.Lsha256_block_data_order: +#if __ARM_ARCH__<7 sub r3,pc,#8 @ sha256_block_data_order - add r2,r1,r2,lsl#6 @ len to point at the end of inp -#if __ARM_MAX_ARCH__>=7 +#else + adr r3,sha256_block_data_order +#endif +#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) ldr r12,.LOPENSSL_armcap ldr r12,[r3,r12] @ OPENSSL_armcap_P +#ifdef __APPLE__ + ldr r12,[r12] +#endif tst r12,#ARMV8_SHA256 bne .LARMv8 tst r12,#ARMV7_NEON bne .LNEON #endif + add r2,r1,r2,lsl#6 @ len to point at the end of inp stmdb sp!,{r0,r1,r2,r4-r11,lr} ldmia r0,{r4,r5,r6,r7,r8,r9,r10,r11} sub r14,r3,#256+32 @ K256 @@ -63,7 +125,9 @@ sha256_block_data_order: eor r0,r8,r8,ror#5 add r4,r4,r12 @ h+=Maj(a,b,c) from the past eor r0,r0,r8,ror#19 @ Sigma1(e) +# ifndef __ARMEB__ rev r2,r2 +# endif #else @ ldrb r2,[r1,#3] @ 0 add r4,r4,r12 @ h+=Maj(a,b,c) from the past @@ -119,7 +183,9 @@ sha256_block_data_order: eor r0,r7,r7,ror#5 add r11,r11,r3 @ h+=Maj(a,b,c) from the past eor r0,r0,r7,ror#19 @ Sigma1(e) +# ifndef __ARMEB__ rev r2,r2 +# endif #else @ ldrb r2,[r1,#3] @ 1 add r11,r11,r3 @ h+=Maj(a,b,c) from the past @@ -175,7 +241,9 @@ sha256_block_data_order: eor r0,r6,r6,ror#5 add r10,r10,r12 @ h+=Maj(a,b,c) from the past eor r0,r0,r6,ror#19 @ Sigma1(e) +# ifndef __ARMEB__ rev r2,r2 +# endif #else @ ldrb r2,[r1,#3] @ 2 add r10,r10,r12 @ h+=Maj(a,b,c) from the past @@ -231,7 +299,9 @@ sha256_block_data_order: eor r0,r5,r5,ror#5 add r9,r9,r3 @ h+=Maj(a,b,c) from the past eor r0,r0,r5,ror#19 @ Sigma1(e) +# ifndef __ARMEB__ rev r2,r2 +# endif #else @ ldrb r2,[r1,#3] @ 3 add r9,r9,r3 @ h+=Maj(a,b,c) from the past @@ -287,7 +357,9 @@ sha256_block_data_order: eor r0,r4,r4,ror#5 add r8,r8,r12 @ h+=Maj(a,b,c) from the past eor r0,r0,r4,ror#19 @ Sigma1(e) +# ifndef __ARMEB__ rev r2,r2 +# endif #else @ ldrb r2,[r1,#3] @ 4 add r8,r8,r12 @ h+=Maj(a,b,c) from the past @@ -343,7 +415,9 @@ sha256_block_data_order: eor r0,r11,r11,ror#5 add r7,r7,r3 @ h+=Maj(a,b,c) from the past eor r0,r0,r11,ror#19 @ Sigma1(e) +# ifndef __ARMEB__ rev r2,r2 +# endif #else @ ldrb r2,[r1,#3] @ 5 add r7,r7,r3 @ h+=Maj(a,b,c) from the past @@ -399,7 +473,9 @@ sha256_block_data_order: eor r0,r10,r10,ror#5 add r6,r6,r12 @ h+=Maj(a,b,c) from the past eor r0,r0,r10,ror#19 @ Sigma1(e) +# ifndef __ARMEB__ rev r2,r2 +# endif #else @ ldrb r2,[r1,#3] @ 6 add r6,r6,r12 @ h+=Maj(a,b,c) from the past @@ -455,7 +531,9 @@ sha256_block_data_order: eor r0,r9,r9,ror#5 add r5,r5,r3 @ h+=Maj(a,b,c) from the past eor r0,r0,r9,ror#19 @ Sigma1(e) +# ifndef __ARMEB__ rev r2,r2 +# endif #else @ ldrb r2,[r1,#3] @ 7 add r5,r5,r3 @ h+=Maj(a,b,c) from the past @@ -511,7 +589,9 @@ sha256_block_data_order: eor r0,r8,r8,ror#5 add r4,r4,r12 @ h+=Maj(a,b,c) from the past eor r0,r0,r8,ror#19 @ Sigma1(e) +# ifndef __ARMEB__ rev r2,r2 +# endif #else @ ldrb r2,[r1,#3] @ 8 add r4,r4,r12 @ h+=Maj(a,b,c) from the past @@ -567,7 +647,9 @@ sha256_block_data_order: eor r0,r7,r7,ror#5 add r11,r11,r3 @ h+=Maj(a,b,c) from the past eor r0,r0,r7,ror#19 @ Sigma1(e) +# ifndef __ARMEB__ rev r2,r2 +# endif #else @ ldrb r2,[r1,#3] @ 9 add r11,r11,r3 @ h+=Maj(a,b,c) from the past @@ -623,7 +705,9 @@ sha256_block_data_order: eor r0,r6,r6,ror#5 add r10,r10,r12 @ h+=Maj(a,b,c) from the past eor r0,r0,r6,ror#19 @ Sigma1(e) +# ifndef __ARMEB__ rev r2,r2 +# endif #else @ ldrb r2,[r1,#3] @ 10 add r10,r10,r12 @ h+=Maj(a,b,c) from the past @@ -679,7 +763,9 @@ sha256_block_data_order: eor r0,r5,r5,ror#5 add r9,r9,r3 @ h+=Maj(a,b,c) from the past eor r0,r0,r5,ror#19 @ Sigma1(e) +# ifndef __ARMEB__ rev r2,r2 +# endif #else @ ldrb r2,[r1,#3] @ 11 add r9,r9,r3 @ h+=Maj(a,b,c) from the past @@ -735,7 +821,9 @@ sha256_block_data_order: eor r0,r4,r4,ror#5 add r8,r8,r12 @ h+=Maj(a,b,c) from the past eor r0,r0,r4,ror#19 @ Sigma1(e) +# ifndef __ARMEB__ rev r2,r2 +# endif #else @ ldrb r2,[r1,#3] @ 12 add r8,r8,r12 @ h+=Maj(a,b,c) from the past @@ -791,7 +879,9 @@ sha256_block_data_order: eor r0,r11,r11,ror#5 add r7,r7,r3 @ h+=Maj(a,b,c) from the past eor r0,r0,r11,ror#19 @ Sigma1(e) +# ifndef __ARMEB__ rev r2,r2 +# endif #else @ ldrb r2,[r1,#3] @ 13 add r7,r7,r3 @ h+=Maj(a,b,c) from the past @@ -847,7 +937,9 @@ sha256_block_data_order: eor r0,r10,r10,ror#5 add r6,r6,r12 @ h+=Maj(a,b,c) from the past eor r0,r0,r10,ror#19 @ Sigma1(e) +# ifndef __ARMEB__ rev r2,r2 +# endif #else @ ldrb r2,[r1,#3] @ 14 add r6,r6,r12 @ h+=Maj(a,b,c) from the past @@ -903,7 +995,9 @@ sha256_block_data_order: eor r0,r9,r9,ror#5 add r5,r5,r3 @ h+=Maj(a,b,c) from the past eor r0,r0,r9,ror#19 @ Sigma1(e) +# ifndef __ARMEB__ rev r2,r2 +# endif #else @ ldrb r2,[r1,#3] @ 15 add r5,r5,r3 @ h+=Maj(a,b,c) from the past @@ -1736,6 +1830,9 @@ sha256_block_data_order: eor r12,r12,r6 @ Maj(a,b,c) add r4,r4,r0,ror#2 @ h+=Sigma0(a) @ add r4,r4,r12 @ h+=Maj(a,b,c) +#if __ARM_ARCH__>=7 + ite eq @ Thumb2 thing, sanity check in ARM +#endif ldreq r3,[sp,#16*4] @ pull ctx bne .Lrounds_16_xx @@ -1765,61 +1862,64 @@ sha256_block_data_order: add sp,sp,#19*4 @ destroy frame #if __ARM_ARCH__>=5 - ldmia sp!,{r4-r11,pc} + ldmia sp!,{r4,r5,r6,r7,r8,r9,r10,r11,pc} #else - ldmia sp!,{r4-r11,lr} + ldmia sp!,{r4,r5,r6,r7,r8,r9,r10,r11,lr} tst lr,#1 moveq pc,lr @ be binary compatible with V4, yet - .word 0xe12fff1e @ interoperable with Thumb ISA:-) +.word 0xe12fff1e @ interoperable with Thumb ISA:-) #endif .size sha256_block_data_order,.-sha256_block_data_order #if __ARM_MAX_ARCH__>=7 .arch armv7-a .fpu neon +.globl sha256_block_data_order_neon .type sha256_block_data_order_neon,%function .align 4 sha256_block_data_order_neon: .LNEON: - stmdb sp!,{r4-r12,lr} + stmdb sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,lr} + sub r11,sp,#16*4+16 + adrl r14,K256 + bic r11,r11,#15 @ align for 128-bit stores mov r12,sp - sub sp,sp,#16*4+16 @ alloca - sub r14,r3,#256+32 @ K256 - bic sp,sp,#15 @ align for 128-bit stores + mov sp,r11 @ alloca + add r2,r1,r2,lsl#6 @ len to point at the end of inp - vld1.8 {q0},[r1]! - vld1.8 {q1},[r1]! - vld1.8 {q2},[r1]! - vld1.8 {q3},[r1]! - vld1.32 {q8},[r14,:128]! - vld1.32 {q9},[r14,:128]! - vld1.32 {q10},[r14,:128]! - vld1.32 {q11},[r14,:128]! + vld1.8 {q0},[r1]! + vld1.8 {q1},[r1]! + vld1.8 {q2},[r1]! + vld1.8 {q3},[r1]! + vld1.32 {q8},[r14,:128]! + vld1.32 {q9},[r14,:128]! + vld1.32 {q10},[r14,:128]! + vld1.32 {q11},[r14,:128]! vrev32.8 q0,q0 @ yes, even on - str r0,[sp,#64] + str r0,[sp,#64] vrev32.8 q1,q1 @ big-endian - str r1,[sp,#68] - mov r1,sp + str r1,[sp,#68] + mov r1,sp vrev32.8 q2,q2 - str r2,[sp,#72] + str r2,[sp,#72] vrev32.8 q3,q3 - str r12,[sp,#76] @ save original sp + str r12,[sp,#76] @ save original sp vadd.i32 q8,q8,q0 vadd.i32 q9,q9,q1 - vst1.32 {q8},[r1,:128]! + vst1.32 {q8},[r1,:128]! vadd.i32 q10,q10,q2 - vst1.32 {q9},[r1,:128]! + vst1.32 {q9},[r1,:128]! vadd.i32 q11,q11,q3 - vst1.32 {q10},[r1,:128]! - vst1.32 {q11},[r1,:128]! + vst1.32 {q10},[r1,:128]! + vst1.32 {q11},[r1,:128]! - ldmia r0,{r4-r11} - sub r1,r1,#64 - ldr r2,[sp,#0] - eor r12,r12,r12 - eor r3,r5,r6 - b .L_00_48 + ldmia r0,{r4,r5,r6,r7,r8,r9,r10,r11} + sub r1,r1,#64 + ldr r2,[sp,#0] + eor r12,r12,r12 + eor r3,r5,r6 + b .L_00_48 .align 4 .L_00_48: @@ -2220,17 +2320,19 @@ sha256_block_data_order_neon: sub r1,r1,#64 bne .L_00_48 - ldr r1,[sp,#68] - ldr r0,[sp,#72] - sub r14,r14,#256 @ rewind r14 - teq r1,r0 - subeq r1,r1,#64 @ avoid SEGV - vld1.8 {q0},[r1]! @ load next input block - vld1.8 {q1},[r1]! - vld1.8 {q2},[r1]! - vld1.8 {q3},[r1]! - strne r1,[sp,#68] - mov r1,sp + ldr r1,[sp,#68] + ldr r0,[sp,#72] + sub r14,r14,#256 @ rewind r14 + teq r1,r0 + it eq + subeq r1,r1,#64 @ avoid SEGV + vld1.8 {q0},[r1]! @ load next input block + vld1.8 {q1},[r1]! + vld1.8 {q2},[r1]! + vld1.8 {q3},[r1]! + it ne + strne r1,[sp,#68] + mov r1,sp add r11,r11,r2 eor r2,r9,r10 eor r0,r8,r8,ror#5 @@ -2540,157 +2642,177 @@ sha256_block_data_order_neon: str r6,[r2],#4 add r11,r11,r1 str r7,[r2],#4 - stmia r2,{r8-r11} + stmia r2,{r8,r9,r10,r11} + ittte ne movne r1,sp ldrne r2,[sp,#0] eorne r12,r12,r12 ldreq sp,[sp,#76] @ restore original sp + itt ne eorne r3,r5,r6 bne .L_00_48 - ldmia sp!,{r4-r12,pc} + ldmia sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,pc} .size sha256_block_data_order_neon,.-sha256_block_data_order_neon #endif -#if __ARM_MAX_ARCH__>=7 +#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) + +# if defined(__thumb2__) && !defined(__APPLE__) +# define INST(a,b,c,d) .byte c,d|0xc,a,b +# else +# define INST(a,b,c,d) .byte a,b,c,d +# endif + .type sha256_block_data_order_armv8,%function .align 5 sha256_block_data_order_armv8: .LARMv8: vld1.32 {q0,q1},[r0] - sub r3,r3,#sha256_block_data_order-K256 +# ifdef __APPLE__ + sub r3,r3,#256+32 +# elif defined(__thumb2__) + adr r3,.LARMv8 + sub r3,r3,#.LARMv8-K256 +# else + adrl r3,K256 +# endif + add r2,r1,r2,lsl#6 @ len to point at the end of inp .Loop_v8: - vld1.8 {q8-q9},[r1]! - vld1.8 {q10-q11},[r1]! - vld1.32 {q12},[r3]! + vld1.8 {q8,q9},[r1]! + vld1.8 {q10,q11},[r1]! + vld1.32 {q12},[r3]! vrev32.8 q8,q8 vrev32.8 q9,q9 vrev32.8 q10,q10 vrev32.8 q11,q11 - vmov q14,q0 @ offload - vmov q15,q1 - teq r1,r2 - vld1.32 {q13},[r3]! + vmov q14,q0 @ offload + vmov q15,q1 + teq r1,r2 + vld1.32 {q13},[r3]! vadd.i32 q12,q12,q8 - .byte 0xe2,0x03,0xfa,0xf3 @ sha256su0 q8,q9 - vmov q2,q0 - .byte 0x68,0x0c,0x02,0xf3 @ sha256h q0,q1,q12 - .byte 0x68,0x2c,0x14,0xf3 @ sha256h2 q1,q2,q12 - .byte 0xe6,0x0c,0x64,0xf3 @ sha256su1 q8,q10,q11 - vld1.32 {q12},[r3]! + INST(0xe2,0x03,0xfa,0xf3) @ sha256su0 q8,q9 + vmov q2,q0 + INST(0x68,0x0c,0x02,0xf3) @ sha256h q0,q1,q12 + INST(0x68,0x2c,0x14,0xf3) @ sha256h2 q1,q2,q12 + INST(0xe6,0x0c,0x64,0xf3) @ sha256su1 q8,q10,q11 + vld1.32 {q12},[r3]! vadd.i32 q13,q13,q9 - .byte 0xe4,0x23,0xfa,0xf3 @ sha256su0 q9,q10 - vmov q2,q0 - .byte 0x6a,0x0c,0x02,0xf3 @ sha256h q0,q1,q13 - .byte 0x6a,0x2c,0x14,0xf3 @ sha256h2 q1,q2,q13 - .byte 0xe0,0x2c,0x66,0xf3 @ sha256su1 q9,q11,q8 - vld1.32 {q13},[r3]! + INST(0xe4,0x23,0xfa,0xf3) @ sha256su0 q9,q10 + vmov q2,q0 + INST(0x6a,0x0c,0x02,0xf3) @ sha256h q0,q1,q13 + INST(0x6a,0x2c,0x14,0xf3) @ sha256h2 q1,q2,q13 + INST(0xe0,0x2c,0x66,0xf3) @ sha256su1 q9,q11,q8 + vld1.32 {q13},[r3]! vadd.i32 q12,q12,q10 - .byte 0xe6,0x43,0xfa,0xf3 @ sha256su0 q10,q11 - vmov q2,q0 - .byte 0x68,0x0c,0x02,0xf3 @ sha256h q0,q1,q12 - .byte 0x68,0x2c,0x14,0xf3 @ sha256h2 q1,q2,q12 - .byte 0xe2,0x4c,0x60,0xf3 @ sha256su1 q10,q8,q9 - vld1.32 {q12},[r3]! + INST(0xe6,0x43,0xfa,0xf3) @ sha256su0 q10,q11 + vmov q2,q0 + INST(0x68,0x0c,0x02,0xf3) @ sha256h q0,q1,q12 + INST(0x68,0x2c,0x14,0xf3) @ sha256h2 q1,q2,q12 + INST(0xe2,0x4c,0x60,0xf3) @ sha256su1 q10,q8,q9 + vld1.32 {q12},[r3]! vadd.i32 q13,q13,q11 - .byte 0xe0,0x63,0xfa,0xf3 @ sha256su0 q11,q8 - vmov q2,q0 - .byte 0x6a,0x0c,0x02,0xf3 @ sha256h q0,q1,q13 - .byte 0x6a,0x2c,0x14,0xf3 @ sha256h2 q1,q2,q13 - .byte 0xe4,0x6c,0x62,0xf3 @ sha256su1 q11,q9,q10 - vld1.32 {q13},[r3]! + INST(0xe0,0x63,0xfa,0xf3) @ sha256su0 q11,q8 + vmov q2,q0 + INST(0x6a,0x0c,0x02,0xf3) @ sha256h q0,q1,q13 + INST(0x6a,0x2c,0x14,0xf3) @ sha256h2 q1,q2,q13 + INST(0xe4,0x6c,0x62,0xf3) @ sha256su1 q11,q9,q10 + vld1.32 {q13},[r3]! vadd.i32 q12,q12,q8 - .byte 0xe2,0x03,0xfa,0xf3 @ sha256su0 q8,q9 - vmov q2,q0 - .byte 0x68,0x0c,0x02,0xf3 @ sha256h q0,q1,q12 - .byte 0x68,0x2c,0x14,0xf3 @ sha256h2 q1,q2,q12 - .byte 0xe6,0x0c,0x64,0xf3 @ sha256su1 q8,q10,q11 - vld1.32 {q12},[r3]! + INST(0xe2,0x03,0xfa,0xf3) @ sha256su0 q8,q9 + vmov q2,q0 + INST(0x68,0x0c,0x02,0xf3) @ sha256h q0,q1,q12 + INST(0x68,0x2c,0x14,0xf3) @ sha256h2 q1,q2,q12 + INST(0xe6,0x0c,0x64,0xf3) @ sha256su1 q8,q10,q11 + vld1.32 {q12},[r3]! vadd.i32 q13,q13,q9 - .byte 0xe4,0x23,0xfa,0xf3 @ sha256su0 q9,q10 - vmov q2,q0 - .byte 0x6a,0x0c,0x02,0xf3 @ sha256h q0,q1,q13 - .byte 0x6a,0x2c,0x14,0xf3 @ sha256h2 q1,q2,q13 - .byte 0xe0,0x2c,0x66,0xf3 @ sha256su1 q9,q11,q8 - vld1.32 {q13},[r3]! + INST(0xe4,0x23,0xfa,0xf3) @ sha256su0 q9,q10 + vmov q2,q0 + INST(0x6a,0x0c,0x02,0xf3) @ sha256h q0,q1,q13 + INST(0x6a,0x2c,0x14,0xf3) @ sha256h2 q1,q2,q13 + INST(0xe0,0x2c,0x66,0xf3) @ sha256su1 q9,q11,q8 + vld1.32 {q13},[r3]! vadd.i32 q12,q12,q10 - .byte 0xe6,0x43,0xfa,0xf3 @ sha256su0 q10,q11 - vmov q2,q0 - .byte 0x68,0x0c,0x02,0xf3 @ sha256h q0,q1,q12 - .byte 0x68,0x2c,0x14,0xf3 @ sha256h2 q1,q2,q12 - .byte 0xe2,0x4c,0x60,0xf3 @ sha256su1 q10,q8,q9 - vld1.32 {q12},[r3]! + INST(0xe6,0x43,0xfa,0xf3) @ sha256su0 q10,q11 + vmov q2,q0 + INST(0x68,0x0c,0x02,0xf3) @ sha256h q0,q1,q12 + INST(0x68,0x2c,0x14,0xf3) @ sha256h2 q1,q2,q12 + INST(0xe2,0x4c,0x60,0xf3) @ sha256su1 q10,q8,q9 + vld1.32 {q12},[r3]! vadd.i32 q13,q13,q11 - .byte 0xe0,0x63,0xfa,0xf3 @ sha256su0 q11,q8 - vmov q2,q0 - .byte 0x6a,0x0c,0x02,0xf3 @ sha256h q0,q1,q13 - .byte 0x6a,0x2c,0x14,0xf3 @ sha256h2 q1,q2,q13 - .byte 0xe4,0x6c,0x62,0xf3 @ sha256su1 q11,q9,q10 - vld1.32 {q13},[r3]! + INST(0xe0,0x63,0xfa,0xf3) @ sha256su0 q11,q8 + vmov q2,q0 + INST(0x6a,0x0c,0x02,0xf3) @ sha256h q0,q1,q13 + INST(0x6a,0x2c,0x14,0xf3) @ sha256h2 q1,q2,q13 + INST(0xe4,0x6c,0x62,0xf3) @ sha256su1 q11,q9,q10 + vld1.32 {q13},[r3]! vadd.i32 q12,q12,q8 - .byte 0xe2,0x03,0xfa,0xf3 @ sha256su0 q8,q9 - vmov q2,q0 - .byte 0x68,0x0c,0x02,0xf3 @ sha256h q0,q1,q12 - .byte 0x68,0x2c,0x14,0xf3 @ sha256h2 q1,q2,q12 - .byte 0xe6,0x0c,0x64,0xf3 @ sha256su1 q8,q10,q11 - vld1.32 {q12},[r3]! + INST(0xe2,0x03,0xfa,0xf3) @ sha256su0 q8,q9 + vmov q2,q0 + INST(0x68,0x0c,0x02,0xf3) @ sha256h q0,q1,q12 + INST(0x68,0x2c,0x14,0xf3) @ sha256h2 q1,q2,q12 + INST(0xe6,0x0c,0x64,0xf3) @ sha256su1 q8,q10,q11 + vld1.32 {q12},[r3]! vadd.i32 q13,q13,q9 - .byte 0xe4,0x23,0xfa,0xf3 @ sha256su0 q9,q10 - vmov q2,q0 - .byte 0x6a,0x0c,0x02,0xf3 @ sha256h q0,q1,q13 - .byte 0x6a,0x2c,0x14,0xf3 @ sha256h2 q1,q2,q13 - .byte 0xe0,0x2c,0x66,0xf3 @ sha256su1 q9,q11,q8 - vld1.32 {q13},[r3]! + INST(0xe4,0x23,0xfa,0xf3) @ sha256su0 q9,q10 + vmov q2,q0 + INST(0x6a,0x0c,0x02,0xf3) @ sha256h q0,q1,q13 + INST(0x6a,0x2c,0x14,0xf3) @ sha256h2 q1,q2,q13 + INST(0xe0,0x2c,0x66,0xf3) @ sha256su1 q9,q11,q8 + vld1.32 {q13},[r3]! vadd.i32 q12,q12,q10 - .byte 0xe6,0x43,0xfa,0xf3 @ sha256su0 q10,q11 - vmov q2,q0 - .byte 0x68,0x0c,0x02,0xf3 @ sha256h q0,q1,q12 - .byte 0x68,0x2c,0x14,0xf3 @ sha256h2 q1,q2,q12 - .byte 0xe2,0x4c,0x60,0xf3 @ sha256su1 q10,q8,q9 - vld1.32 {q12},[r3]! + INST(0xe6,0x43,0xfa,0xf3) @ sha256su0 q10,q11 + vmov q2,q0 + INST(0x68,0x0c,0x02,0xf3) @ sha256h q0,q1,q12 + INST(0x68,0x2c,0x14,0xf3) @ sha256h2 q1,q2,q12 + INST(0xe2,0x4c,0x60,0xf3) @ sha256su1 q10,q8,q9 + vld1.32 {q12},[r3]! vadd.i32 q13,q13,q11 - .byte 0xe0,0x63,0xfa,0xf3 @ sha256su0 q11,q8 - vmov q2,q0 - .byte 0x6a,0x0c,0x02,0xf3 @ sha256h q0,q1,q13 - .byte 0x6a,0x2c,0x14,0xf3 @ sha256h2 q1,q2,q13 - .byte 0xe4,0x6c,0x62,0xf3 @ sha256su1 q11,q9,q10 - vld1.32 {q13},[r3]! + INST(0xe0,0x63,0xfa,0xf3) @ sha256su0 q11,q8 + vmov q2,q0 + INST(0x6a,0x0c,0x02,0xf3) @ sha256h q0,q1,q13 + INST(0x6a,0x2c,0x14,0xf3) @ sha256h2 q1,q2,q13 + INST(0xe4,0x6c,0x62,0xf3) @ sha256su1 q11,q9,q10 + vld1.32 {q13},[r3]! vadd.i32 q12,q12,q8 - vmov q2,q0 - .byte 0x68,0x0c,0x02,0xf3 @ sha256h q0,q1,q12 - .byte 0x68,0x2c,0x14,0xf3 @ sha256h2 q1,q2,q12 + vmov q2,q0 + INST(0x68,0x0c,0x02,0xf3) @ sha256h q0,q1,q12 + INST(0x68,0x2c,0x14,0xf3) @ sha256h2 q1,q2,q12 - vld1.32 {q12},[r3]! + vld1.32 {q12},[r3]! vadd.i32 q13,q13,q9 - vmov q2,q0 - .byte 0x6a,0x0c,0x02,0xf3 @ sha256h q0,q1,q13 - .byte 0x6a,0x2c,0x14,0xf3 @ sha256h2 q1,q2,q13 + vmov q2,q0 + INST(0x6a,0x0c,0x02,0xf3) @ sha256h q0,q1,q13 + INST(0x6a,0x2c,0x14,0xf3) @ sha256h2 q1,q2,q13 - vld1.32 {q13},[r3] + vld1.32 {q13},[r3] vadd.i32 q12,q12,q10 - sub r3,r3,#256-16 @ rewind - vmov q2,q0 - .byte 0x68,0x0c,0x02,0xf3 @ sha256h q0,q1,q12 - .byte 0x68,0x2c,0x14,0xf3 @ sha256h2 q1,q2,q12 + sub r3,r3,#256-16 @ rewind + vmov q2,q0 + INST(0x68,0x0c,0x02,0xf3) @ sha256h q0,q1,q12 + INST(0x68,0x2c,0x14,0xf3) @ sha256h2 q1,q2,q12 vadd.i32 q13,q13,q11 - vmov q2,q0 - .byte 0x6a,0x0c,0x02,0xf3 @ sha256h q0,q1,q13 - .byte 0x6a,0x2c,0x14,0xf3 @ sha256h2 q1,q2,q13 + vmov q2,q0 + INST(0x6a,0x0c,0x02,0xf3) @ sha256h q0,q1,q13 + INST(0x6a,0x2c,0x14,0xf3) @ sha256h2 q1,q2,q13 vadd.i32 q0,q0,q14 vadd.i32 q1,q1,q15 - bne .Loop_v8 + it ne + bne .Loop_v8 - vst1.32 {q0,q1},[r0] + vst1.32 {q0,q1},[r0] bx lr @ bx lr .size sha256_block_data_order_armv8,.-sha256_block_data_order_armv8 #endif -.asciz "SHA256 block transform for ARMv4/NEON/ARMv8, CRYPTOGAMS by " +.byte 83,72,65,50,53,54,32,98,108,111,99,107,32,116,114,97,110,115,102,111,114,109,32,102,111,114,32,65,82,77,118,52,47,78,69,79,78,47,65,82,77,118,56,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0 .align 2 -#if __ARM_MAX_ARCH__>=7 -.comm OPENSSL_armcap_P,4,4 -.hidden OPENSSL_armcap_P +.align 2 +#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) +.comm OPENSSL_armcap_P,4,4 +.hidden OPENSSL_armcap_P #endif +#endif \ No newline at end of file diff --git a/third_party/boringssl/linux-arm/crypto/sha/sha512-armv4.S b/third_party/boringssl/linux-arm/crypto/sha/sha512-armv4.S index 37cfca37debec..c794f87fcff76 100644 --- a/third_party/boringssl/linux-arm/crypto/sha/sha512-armv4.S +++ b/third_party/boringssl/linux-arm/crypto/sha/sha512-armv4.S @@ -1,4 +1,62 @@ -#include "arm_arch.h" +#if defined(__arm__) + +@ ==================================================================== +@ Written by Andy Polyakov for the OpenSSL +@ project. The module is, however, dual licensed under OpenSSL and +@ CRYPTOGAMS licenses depending on where you obtain it. For further +@ details see http://www.openssl.org/~appro/cryptogams/. +@ +@ Permission to use under GPL terms is granted. +@ ==================================================================== + +@ SHA512 block procedure for ARMv4. September 2007. + +@ This code is ~4.5 (four and a half) times faster than code generated +@ by gcc 3.4 and it spends ~72 clock cycles per byte [on single-issue +@ Xscale PXA250 core]. +@ +@ July 2010. +@ +@ Rescheduling for dual-issue pipeline resulted in 6% improvement on +@ Cortex A8 core and ~40 cycles per processed byte. + +@ February 2011. +@ +@ Profiler-assisted and platform-specific optimization resulted in 7% +@ improvement on Coxtex A8 core and ~38 cycles per byte. + +@ March 2011. +@ +@ Add NEON implementation. On Cortex A8 it was measured to process +@ one byte in 23.3 cycles or ~60% faster than integer-only code. + +@ August 2012. +@ +@ Improve NEON performance by 12% on Snapdragon S4. In absolute +@ terms it's 22.6 cycles per byte, which is disappointing result. +@ Technical writers asserted that 3-way S4 pipeline can sustain +@ multiple NEON instructions per cycle, but dual NEON issue could +@ not be observed, see http://www.openssl.org/~appro/Snapdragon-S4.html +@ for further details. On side note Cortex-A15 processes one byte in +@ 16 cycles. + +@ Byte order [in]dependence. ========================================= +@ +@ Originally caller was expected to maintain specific *dword* order in +@ h[0-7], namely with most significant dword at *lower* address, which +@ was reflected in below two parameters as 0 and 4. Now caller is +@ expected to maintain native byte order for whole 64-bit values. +#ifndef __KERNEL__ +# include "arm_arch.h" +# define VFP_ABI_PUSH vstmdb sp!,{d8-d15} +# define VFP_ABI_POP vldmia sp!,{d8-d15} +#else +# define __ARM_ARCH__ __LINUX_ARM_ARCH__ +# define __ARM_MAX_ARCH__ 7 +# define VFP_ABI_PUSH +# define VFP_ABI_POP +#endif + #ifdef __ARMEL__ # define LO 0 # define HI 4 @@ -10,71 +68,90 @@ #endif .text +#if __ARM_ARCH__<7 || defined(__APPLE__) +.code 32 +#else +.syntax unified +# ifdef __thumb2__ +# define adrl adr +.thumb +# else .code 32 +# endif +#endif + .type K512,%object .align 5 K512: -WORD64(0x428a2f98,0xd728ae22, 0x71374491,0x23ef65cd) -WORD64(0xb5c0fbcf,0xec4d3b2f, 0xe9b5dba5,0x8189dbbc) -WORD64(0x3956c25b,0xf348b538, 0x59f111f1,0xb605d019) -WORD64(0x923f82a4,0xaf194f9b, 0xab1c5ed5,0xda6d8118) -WORD64(0xd807aa98,0xa3030242, 0x12835b01,0x45706fbe) -WORD64(0x243185be,0x4ee4b28c, 0x550c7dc3,0xd5ffb4e2) -WORD64(0x72be5d74,0xf27b896f, 0x80deb1fe,0x3b1696b1) -WORD64(0x9bdc06a7,0x25c71235, 0xc19bf174,0xcf692694) -WORD64(0xe49b69c1,0x9ef14ad2, 0xefbe4786,0x384f25e3) -WORD64(0x0fc19dc6,0x8b8cd5b5, 0x240ca1cc,0x77ac9c65) -WORD64(0x2de92c6f,0x592b0275, 0x4a7484aa,0x6ea6e483) -WORD64(0x5cb0a9dc,0xbd41fbd4, 0x76f988da,0x831153b5) -WORD64(0x983e5152,0xee66dfab, 0xa831c66d,0x2db43210) -WORD64(0xb00327c8,0x98fb213f, 0xbf597fc7,0xbeef0ee4) -WORD64(0xc6e00bf3,0x3da88fc2, 0xd5a79147,0x930aa725) -WORD64(0x06ca6351,0xe003826f, 0x14292967,0x0a0e6e70) -WORD64(0x27b70a85,0x46d22ffc, 0x2e1b2138,0x5c26c926) -WORD64(0x4d2c6dfc,0x5ac42aed, 0x53380d13,0x9d95b3df) -WORD64(0x650a7354,0x8baf63de, 0x766a0abb,0x3c77b2a8) -WORD64(0x81c2c92e,0x47edaee6, 0x92722c85,0x1482353b) -WORD64(0xa2bfe8a1,0x4cf10364, 0xa81a664b,0xbc423001) -WORD64(0xc24b8b70,0xd0f89791, 0xc76c51a3,0x0654be30) -WORD64(0xd192e819,0xd6ef5218, 0xd6990624,0x5565a910) -WORD64(0xf40e3585,0x5771202a, 0x106aa070,0x32bbd1b8) -WORD64(0x19a4c116,0xb8d2d0c8, 0x1e376c08,0x5141ab53) -WORD64(0x2748774c,0xdf8eeb99, 0x34b0bcb5,0xe19b48a8) -WORD64(0x391c0cb3,0xc5c95a63, 0x4ed8aa4a,0xe3418acb) -WORD64(0x5b9cca4f,0x7763e373, 0x682e6ff3,0xd6b2b8a3) -WORD64(0x748f82ee,0x5defb2fc, 0x78a5636f,0x43172f60) -WORD64(0x84c87814,0xa1f0ab72, 0x8cc70208,0x1a6439ec) -WORD64(0x90befffa,0x23631e28, 0xa4506ceb,0xde82bde9) -WORD64(0xbef9a3f7,0xb2c67915, 0xc67178f2,0xe372532b) -WORD64(0xca273ece,0xea26619c, 0xd186b8c7,0x21c0c207) -WORD64(0xeada7dd6,0xcde0eb1e, 0xf57d4f7f,0xee6ed178) -WORD64(0x06f067aa,0x72176fba, 0x0a637dc5,0xa2c898a6) -WORD64(0x113f9804,0xbef90dae, 0x1b710b35,0x131c471b) -WORD64(0x28db77f5,0x23047d84, 0x32caab7b,0x40c72493) -WORD64(0x3c9ebe0a,0x15c9bebc, 0x431d67c4,0x9c100d4c) -WORD64(0x4cc5d4be,0xcb3e42b6, 0x597f299c,0xfc657e2a) -WORD64(0x5fcb6fab,0x3ad6faec, 0x6c44198c,0x4a475817) + WORD64(0x428a2f98,0xd728ae22, 0x71374491,0x23ef65cd) + WORD64(0xb5c0fbcf,0xec4d3b2f, 0xe9b5dba5,0x8189dbbc) + WORD64(0x3956c25b,0xf348b538, 0x59f111f1,0xb605d019) + WORD64(0x923f82a4,0xaf194f9b, 0xab1c5ed5,0xda6d8118) + WORD64(0xd807aa98,0xa3030242, 0x12835b01,0x45706fbe) + WORD64(0x243185be,0x4ee4b28c, 0x550c7dc3,0xd5ffb4e2) + WORD64(0x72be5d74,0xf27b896f, 0x80deb1fe,0x3b1696b1) + WORD64(0x9bdc06a7,0x25c71235, 0xc19bf174,0xcf692694) + WORD64(0xe49b69c1,0x9ef14ad2, 0xefbe4786,0x384f25e3) + WORD64(0x0fc19dc6,0x8b8cd5b5, 0x240ca1cc,0x77ac9c65) + WORD64(0x2de92c6f,0x592b0275, 0x4a7484aa,0x6ea6e483) + WORD64(0x5cb0a9dc,0xbd41fbd4, 0x76f988da,0x831153b5) + WORD64(0x983e5152,0xee66dfab, 0xa831c66d,0x2db43210) + WORD64(0xb00327c8,0x98fb213f, 0xbf597fc7,0xbeef0ee4) + WORD64(0xc6e00bf3,0x3da88fc2, 0xd5a79147,0x930aa725) + WORD64(0x06ca6351,0xe003826f, 0x14292967,0x0a0e6e70) + WORD64(0x27b70a85,0x46d22ffc, 0x2e1b2138,0x5c26c926) + WORD64(0x4d2c6dfc,0x5ac42aed, 0x53380d13,0x9d95b3df) + WORD64(0x650a7354,0x8baf63de, 0x766a0abb,0x3c77b2a8) + WORD64(0x81c2c92e,0x47edaee6, 0x92722c85,0x1482353b) + WORD64(0xa2bfe8a1,0x4cf10364, 0xa81a664b,0xbc423001) + WORD64(0xc24b8b70,0xd0f89791, 0xc76c51a3,0x0654be30) + WORD64(0xd192e819,0xd6ef5218, 0xd6990624,0x5565a910) + WORD64(0xf40e3585,0x5771202a, 0x106aa070,0x32bbd1b8) + WORD64(0x19a4c116,0xb8d2d0c8, 0x1e376c08,0x5141ab53) + WORD64(0x2748774c,0xdf8eeb99, 0x34b0bcb5,0xe19b48a8) + WORD64(0x391c0cb3,0xc5c95a63, 0x4ed8aa4a,0xe3418acb) + WORD64(0x5b9cca4f,0x7763e373, 0x682e6ff3,0xd6b2b8a3) + WORD64(0x748f82ee,0x5defb2fc, 0x78a5636f,0x43172f60) + WORD64(0x84c87814,0xa1f0ab72, 0x8cc70208,0x1a6439ec) + WORD64(0x90befffa,0x23631e28, 0xa4506ceb,0xde82bde9) + WORD64(0xbef9a3f7,0xb2c67915, 0xc67178f2,0xe372532b) + WORD64(0xca273ece,0xea26619c, 0xd186b8c7,0x21c0c207) + WORD64(0xeada7dd6,0xcde0eb1e, 0xf57d4f7f,0xee6ed178) + WORD64(0x06f067aa,0x72176fba, 0x0a637dc5,0xa2c898a6) + WORD64(0x113f9804,0xbef90dae, 0x1b710b35,0x131c471b) + WORD64(0x28db77f5,0x23047d84, 0x32caab7b,0x40c72493) + WORD64(0x3c9ebe0a,0x15c9bebc, 0x431d67c4,0x9c100d4c) + WORD64(0x4cc5d4be,0xcb3e42b6, 0x597f299c,0xfc657e2a) + WORD64(0x5fcb6fab,0x3ad6faec, 0x6c44198c,0x4a475817) .size K512,.-K512 -#if __ARM_MAX_ARCH__>=7 +#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) .LOPENSSL_armcap: -.word OPENSSL_armcap_P-sha512_block_data_order +.word OPENSSL_armcap_P-.Lsha512_block_data_order .skip 32-4 #else .skip 32 #endif -.global sha512_block_data_order +.globl sha512_block_data_order .type sha512_block_data_order,%function sha512_block_data_order: +.Lsha512_block_data_order: +#if __ARM_ARCH__<7 sub r3,pc,#8 @ sha512_block_data_order - add r2,r1,r2,lsl#7 @ len to point at the end of inp -#if __ARM_MAX_ARCH__>=7 +#else + adr r3,sha512_block_data_order +#endif +#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) ldr r12,.LOPENSSL_armcap ldr r12,[r3,r12] @ OPENSSL_armcap_P +#ifdef __APPLE__ + ldr r12,[r12] +#endif tst r12,#1 bne .LNEON #endif - stmdb sp!,{r4-r12,lr} + add r2,r1,r2,lsl#7 @ len to point at the end of inp + stmdb sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,lr} sub r14,r3,#672 @ K512 sub sp,sp,#9*8 @@ -186,6 +263,9 @@ sha512_block_data_order: teq r9,#148 ldr r12,[sp,#16+0] @ c.lo +#if __ARM_ARCH__>=7 + it eq @ Thumb2 thing, sanity check in ARM +#endif orreq r14,r14,#1 @ Sigma0(x) (ROTR((x),28) ^ ROTR((x),34) ^ ROTR((x),39)) @ LO lo>>28^hi<<4 ^ hi>>2^lo<<30 ^ hi>>7^lo<<25 @@ -323,6 +403,9 @@ sha512_block_data_order: teq r9,#23 ldr r12,[sp,#16+0] @ c.lo +#if __ARM_ARCH__>=7 + it eq @ Thumb2 thing, sanity check in ARM +#endif orreq r14,r14,#1 @ Sigma0(x) (ROTR((x),28) ^ ROTR((x),34) ^ ROTR((x),39)) @ LO lo>>28^hi<<4 ^ hi>>2^lo<<30 ^ hi>>7^lo<<25 @@ -357,6 +440,9 @@ sha512_block_data_order: adc r6,r6,r4 @ h += T tst r14,#1 add r14,r14,#8 +#if __ARM_ARCH__>=7 + ittt eq @ Thumb2 thing, sanity check in ARM +#endif ldreq r9,[sp,#184+0] ldreq r10,[sp,#184+4] beq .L16_79 @@ -434,1343 +520,1350 @@ sha512_block_data_order: add sp,sp,#8*9 @ destroy frame #if __ARM_ARCH__>=5 - ldmia sp!,{r4-r12,pc} + ldmia sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,pc} #else - ldmia sp!,{r4-r12,lr} + ldmia sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,lr} tst lr,#1 moveq pc,lr @ be binary compatible with V4, yet - .word 0xe12fff1e @ interoperable with Thumb ISA:-) +.word 0xe12fff1e @ interoperable with Thumb ISA:-) #endif +.size sha512_block_data_order,.-sha512_block_data_order #if __ARM_MAX_ARCH__>=7 .arch armv7-a .fpu neon +.globl sha512_block_data_order_neon +.type sha512_block_data_order_neon,%function .align 4 +sha512_block_data_order_neon: .LNEON: - dmb @ errata #451034 on early Cortex A8 - vstmdb sp!,{d8-d15} @ ABI specification says so - sub r3,r3,#672 @ K512 - vldmia r0,{d16-d23} @ load context + dmb @ errata #451034 on early Cortex A8 + add r2,r1,r2,lsl#7 @ len to point at the end of inp + adr r3,K512 + VFP_ABI_PUSH + vldmia r0,{d16,d17,d18,d19,d20,d21,d22,d23} @ load context .Loop_neon: vshr.u64 d24,d20,#14 @ 0 #if 0<16 - vld1.64 {d0},[r1]! @ handles unaligned + vld1.64 {d0},[r1]! @ handles unaligned #endif vshr.u64 d25,d20,#18 #if 0>0 - vadd.i64 d16,d30 @ h+=Maj from the past + vadd.i64 d16,d30 @ h+=Maj from the past #endif vshr.u64 d26,d20,#41 - vld1.64 {d28},[r3,:64]! @ K[i++] - vsli.64 d24,d20,#50 - vsli.64 d25,d20,#46 - vmov d29,d20 - vsli.64 d26,d20,#23 + vld1.64 {d28},[r3,:64]! @ K[i++] + vsli.64 d24,d20,#50 + vsli.64 d25,d20,#46 + vmov d29,d20 + vsli.64 d26,d20,#23 #if 0<16 && defined(__ARMEL__) vrev64.8 d0,d0 #endif - veor d25,d24 - vbsl d29,d21,d22 @ Ch(e,f,g) + veor d25,d24 + vbsl d29,d21,d22 @ Ch(e,f,g) vshr.u64 d24,d16,#28 - veor d26,d25 @ Sigma1(e) + veor d26,d25 @ Sigma1(e) vadd.i64 d27,d29,d23 vshr.u64 d25,d16,#34 - vsli.64 d24,d16,#36 + vsli.64 d24,d16,#36 vadd.i64 d27,d26 vshr.u64 d26,d16,#39 vadd.i64 d28,d0 - vsli.64 d25,d16,#30 - veor d30,d16,d17 - vsli.64 d26,d16,#25 - veor d23,d24,d25 + vsli.64 d25,d16,#30 + veor d30,d16,d17 + vsli.64 d26,d16,#25 + veor d23,d24,d25 vadd.i64 d27,d28 - vbsl d30,d18,d17 @ Maj(a,b,c) - veor d23,d26 @ Sigma0(a) + vbsl d30,d18,d17 @ Maj(a,b,c) + veor d23,d26 @ Sigma0(a) vadd.i64 d19,d27 vadd.i64 d30,d27 @ vadd.i64 d23,d30 vshr.u64 d24,d19,#14 @ 1 #if 1<16 - vld1.64 {d1},[r1]! @ handles unaligned + vld1.64 {d1},[r1]! @ handles unaligned #endif vshr.u64 d25,d19,#18 #if 1>0 - vadd.i64 d23,d30 @ h+=Maj from the past + vadd.i64 d23,d30 @ h+=Maj from the past #endif vshr.u64 d26,d19,#41 - vld1.64 {d28},[r3,:64]! @ K[i++] - vsli.64 d24,d19,#50 - vsli.64 d25,d19,#46 - vmov d29,d19 - vsli.64 d26,d19,#23 + vld1.64 {d28},[r3,:64]! @ K[i++] + vsli.64 d24,d19,#50 + vsli.64 d25,d19,#46 + vmov d29,d19 + vsli.64 d26,d19,#23 #if 1<16 && defined(__ARMEL__) vrev64.8 d1,d1 #endif - veor d25,d24 - vbsl d29,d20,d21 @ Ch(e,f,g) + veor d25,d24 + vbsl d29,d20,d21 @ Ch(e,f,g) vshr.u64 d24,d23,#28 - veor d26,d25 @ Sigma1(e) + veor d26,d25 @ Sigma1(e) vadd.i64 d27,d29,d22 vshr.u64 d25,d23,#34 - vsli.64 d24,d23,#36 + vsli.64 d24,d23,#36 vadd.i64 d27,d26 vshr.u64 d26,d23,#39 vadd.i64 d28,d1 - vsli.64 d25,d23,#30 - veor d30,d23,d16 - vsli.64 d26,d23,#25 - veor d22,d24,d25 + vsli.64 d25,d23,#30 + veor d30,d23,d16 + vsli.64 d26,d23,#25 + veor d22,d24,d25 vadd.i64 d27,d28 - vbsl d30,d17,d16 @ Maj(a,b,c) - veor d22,d26 @ Sigma0(a) + vbsl d30,d17,d16 @ Maj(a,b,c) + veor d22,d26 @ Sigma0(a) vadd.i64 d18,d27 vadd.i64 d30,d27 @ vadd.i64 d22,d30 vshr.u64 d24,d18,#14 @ 2 #if 2<16 - vld1.64 {d2},[r1]! @ handles unaligned + vld1.64 {d2},[r1]! @ handles unaligned #endif vshr.u64 d25,d18,#18 #if 2>0 - vadd.i64 d22,d30 @ h+=Maj from the past + vadd.i64 d22,d30 @ h+=Maj from the past #endif vshr.u64 d26,d18,#41 - vld1.64 {d28},[r3,:64]! @ K[i++] - vsli.64 d24,d18,#50 - vsli.64 d25,d18,#46 - vmov d29,d18 - vsli.64 d26,d18,#23 + vld1.64 {d28},[r3,:64]! @ K[i++] + vsli.64 d24,d18,#50 + vsli.64 d25,d18,#46 + vmov d29,d18 + vsli.64 d26,d18,#23 #if 2<16 && defined(__ARMEL__) vrev64.8 d2,d2 #endif - veor d25,d24 - vbsl d29,d19,d20 @ Ch(e,f,g) + veor d25,d24 + vbsl d29,d19,d20 @ Ch(e,f,g) vshr.u64 d24,d22,#28 - veor d26,d25 @ Sigma1(e) + veor d26,d25 @ Sigma1(e) vadd.i64 d27,d29,d21 vshr.u64 d25,d22,#34 - vsli.64 d24,d22,#36 + vsli.64 d24,d22,#36 vadd.i64 d27,d26 vshr.u64 d26,d22,#39 vadd.i64 d28,d2 - vsli.64 d25,d22,#30 - veor d30,d22,d23 - vsli.64 d26,d22,#25 - veor d21,d24,d25 + vsli.64 d25,d22,#30 + veor d30,d22,d23 + vsli.64 d26,d22,#25 + veor d21,d24,d25 vadd.i64 d27,d28 - vbsl d30,d16,d23 @ Maj(a,b,c) - veor d21,d26 @ Sigma0(a) + vbsl d30,d16,d23 @ Maj(a,b,c) + veor d21,d26 @ Sigma0(a) vadd.i64 d17,d27 vadd.i64 d30,d27 @ vadd.i64 d21,d30 vshr.u64 d24,d17,#14 @ 3 #if 3<16 - vld1.64 {d3},[r1]! @ handles unaligned + vld1.64 {d3},[r1]! @ handles unaligned #endif vshr.u64 d25,d17,#18 #if 3>0 - vadd.i64 d21,d30 @ h+=Maj from the past + vadd.i64 d21,d30 @ h+=Maj from the past #endif vshr.u64 d26,d17,#41 - vld1.64 {d28},[r3,:64]! @ K[i++] - vsli.64 d24,d17,#50 - vsli.64 d25,d17,#46 - vmov d29,d17 - vsli.64 d26,d17,#23 + vld1.64 {d28},[r3,:64]! @ K[i++] + vsli.64 d24,d17,#50 + vsli.64 d25,d17,#46 + vmov d29,d17 + vsli.64 d26,d17,#23 #if 3<16 && defined(__ARMEL__) vrev64.8 d3,d3 #endif - veor d25,d24 - vbsl d29,d18,d19 @ Ch(e,f,g) + veor d25,d24 + vbsl d29,d18,d19 @ Ch(e,f,g) vshr.u64 d24,d21,#28 - veor d26,d25 @ Sigma1(e) + veor d26,d25 @ Sigma1(e) vadd.i64 d27,d29,d20 vshr.u64 d25,d21,#34 - vsli.64 d24,d21,#36 + vsli.64 d24,d21,#36 vadd.i64 d27,d26 vshr.u64 d26,d21,#39 vadd.i64 d28,d3 - vsli.64 d25,d21,#30 - veor d30,d21,d22 - vsli.64 d26,d21,#25 - veor d20,d24,d25 + vsli.64 d25,d21,#30 + veor d30,d21,d22 + vsli.64 d26,d21,#25 + veor d20,d24,d25 vadd.i64 d27,d28 - vbsl d30,d23,d22 @ Maj(a,b,c) - veor d20,d26 @ Sigma0(a) + vbsl d30,d23,d22 @ Maj(a,b,c) + veor d20,d26 @ Sigma0(a) vadd.i64 d16,d27 vadd.i64 d30,d27 @ vadd.i64 d20,d30 vshr.u64 d24,d16,#14 @ 4 #if 4<16 - vld1.64 {d4},[r1]! @ handles unaligned + vld1.64 {d4},[r1]! @ handles unaligned #endif vshr.u64 d25,d16,#18 #if 4>0 - vadd.i64 d20,d30 @ h+=Maj from the past + vadd.i64 d20,d30 @ h+=Maj from the past #endif vshr.u64 d26,d16,#41 - vld1.64 {d28},[r3,:64]! @ K[i++] - vsli.64 d24,d16,#50 - vsli.64 d25,d16,#46 - vmov d29,d16 - vsli.64 d26,d16,#23 + vld1.64 {d28},[r3,:64]! @ K[i++] + vsli.64 d24,d16,#50 + vsli.64 d25,d16,#46 + vmov d29,d16 + vsli.64 d26,d16,#23 #if 4<16 && defined(__ARMEL__) vrev64.8 d4,d4 #endif - veor d25,d24 - vbsl d29,d17,d18 @ Ch(e,f,g) + veor d25,d24 + vbsl d29,d17,d18 @ Ch(e,f,g) vshr.u64 d24,d20,#28 - veor d26,d25 @ Sigma1(e) + veor d26,d25 @ Sigma1(e) vadd.i64 d27,d29,d19 vshr.u64 d25,d20,#34 - vsli.64 d24,d20,#36 + vsli.64 d24,d20,#36 vadd.i64 d27,d26 vshr.u64 d26,d20,#39 vadd.i64 d28,d4 - vsli.64 d25,d20,#30 - veor d30,d20,d21 - vsli.64 d26,d20,#25 - veor d19,d24,d25 + vsli.64 d25,d20,#30 + veor d30,d20,d21 + vsli.64 d26,d20,#25 + veor d19,d24,d25 vadd.i64 d27,d28 - vbsl d30,d22,d21 @ Maj(a,b,c) - veor d19,d26 @ Sigma0(a) + vbsl d30,d22,d21 @ Maj(a,b,c) + veor d19,d26 @ Sigma0(a) vadd.i64 d23,d27 vadd.i64 d30,d27 @ vadd.i64 d19,d30 vshr.u64 d24,d23,#14 @ 5 #if 5<16 - vld1.64 {d5},[r1]! @ handles unaligned + vld1.64 {d5},[r1]! @ handles unaligned #endif vshr.u64 d25,d23,#18 #if 5>0 - vadd.i64 d19,d30 @ h+=Maj from the past + vadd.i64 d19,d30 @ h+=Maj from the past #endif vshr.u64 d26,d23,#41 - vld1.64 {d28},[r3,:64]! @ K[i++] - vsli.64 d24,d23,#50 - vsli.64 d25,d23,#46 - vmov d29,d23 - vsli.64 d26,d23,#23 + vld1.64 {d28},[r3,:64]! @ K[i++] + vsli.64 d24,d23,#50 + vsli.64 d25,d23,#46 + vmov d29,d23 + vsli.64 d26,d23,#23 #if 5<16 && defined(__ARMEL__) vrev64.8 d5,d5 #endif - veor d25,d24 - vbsl d29,d16,d17 @ Ch(e,f,g) + veor d25,d24 + vbsl d29,d16,d17 @ Ch(e,f,g) vshr.u64 d24,d19,#28 - veor d26,d25 @ Sigma1(e) + veor d26,d25 @ Sigma1(e) vadd.i64 d27,d29,d18 vshr.u64 d25,d19,#34 - vsli.64 d24,d19,#36 + vsli.64 d24,d19,#36 vadd.i64 d27,d26 vshr.u64 d26,d19,#39 vadd.i64 d28,d5 - vsli.64 d25,d19,#30 - veor d30,d19,d20 - vsli.64 d26,d19,#25 - veor d18,d24,d25 + vsli.64 d25,d19,#30 + veor d30,d19,d20 + vsli.64 d26,d19,#25 + veor d18,d24,d25 vadd.i64 d27,d28 - vbsl d30,d21,d20 @ Maj(a,b,c) - veor d18,d26 @ Sigma0(a) + vbsl d30,d21,d20 @ Maj(a,b,c) + veor d18,d26 @ Sigma0(a) vadd.i64 d22,d27 vadd.i64 d30,d27 @ vadd.i64 d18,d30 vshr.u64 d24,d22,#14 @ 6 #if 6<16 - vld1.64 {d6},[r1]! @ handles unaligned + vld1.64 {d6},[r1]! @ handles unaligned #endif vshr.u64 d25,d22,#18 #if 6>0 - vadd.i64 d18,d30 @ h+=Maj from the past + vadd.i64 d18,d30 @ h+=Maj from the past #endif vshr.u64 d26,d22,#41 - vld1.64 {d28},[r3,:64]! @ K[i++] - vsli.64 d24,d22,#50 - vsli.64 d25,d22,#46 - vmov d29,d22 - vsli.64 d26,d22,#23 + vld1.64 {d28},[r3,:64]! @ K[i++] + vsli.64 d24,d22,#50 + vsli.64 d25,d22,#46 + vmov d29,d22 + vsli.64 d26,d22,#23 #if 6<16 && defined(__ARMEL__) vrev64.8 d6,d6 #endif - veor d25,d24 - vbsl d29,d23,d16 @ Ch(e,f,g) + veor d25,d24 + vbsl d29,d23,d16 @ Ch(e,f,g) vshr.u64 d24,d18,#28 - veor d26,d25 @ Sigma1(e) + veor d26,d25 @ Sigma1(e) vadd.i64 d27,d29,d17 vshr.u64 d25,d18,#34 - vsli.64 d24,d18,#36 + vsli.64 d24,d18,#36 vadd.i64 d27,d26 vshr.u64 d26,d18,#39 vadd.i64 d28,d6 - vsli.64 d25,d18,#30 - veor d30,d18,d19 - vsli.64 d26,d18,#25 - veor d17,d24,d25 + vsli.64 d25,d18,#30 + veor d30,d18,d19 + vsli.64 d26,d18,#25 + veor d17,d24,d25 vadd.i64 d27,d28 - vbsl d30,d20,d19 @ Maj(a,b,c) - veor d17,d26 @ Sigma0(a) + vbsl d30,d20,d19 @ Maj(a,b,c) + veor d17,d26 @ Sigma0(a) vadd.i64 d21,d27 vadd.i64 d30,d27 @ vadd.i64 d17,d30 vshr.u64 d24,d21,#14 @ 7 #if 7<16 - vld1.64 {d7},[r1]! @ handles unaligned + vld1.64 {d7},[r1]! @ handles unaligned #endif vshr.u64 d25,d21,#18 #if 7>0 - vadd.i64 d17,d30 @ h+=Maj from the past + vadd.i64 d17,d30 @ h+=Maj from the past #endif vshr.u64 d26,d21,#41 - vld1.64 {d28},[r3,:64]! @ K[i++] - vsli.64 d24,d21,#50 - vsli.64 d25,d21,#46 - vmov d29,d21 - vsli.64 d26,d21,#23 + vld1.64 {d28},[r3,:64]! @ K[i++] + vsli.64 d24,d21,#50 + vsli.64 d25,d21,#46 + vmov d29,d21 + vsli.64 d26,d21,#23 #if 7<16 && defined(__ARMEL__) vrev64.8 d7,d7 #endif - veor d25,d24 - vbsl d29,d22,d23 @ Ch(e,f,g) + veor d25,d24 + vbsl d29,d22,d23 @ Ch(e,f,g) vshr.u64 d24,d17,#28 - veor d26,d25 @ Sigma1(e) + veor d26,d25 @ Sigma1(e) vadd.i64 d27,d29,d16 vshr.u64 d25,d17,#34 - vsli.64 d24,d17,#36 + vsli.64 d24,d17,#36 vadd.i64 d27,d26 vshr.u64 d26,d17,#39 vadd.i64 d28,d7 - vsli.64 d25,d17,#30 - veor d30,d17,d18 - vsli.64 d26,d17,#25 - veor d16,d24,d25 + vsli.64 d25,d17,#30 + veor d30,d17,d18 + vsli.64 d26,d17,#25 + veor d16,d24,d25 vadd.i64 d27,d28 - vbsl d30,d19,d18 @ Maj(a,b,c) - veor d16,d26 @ Sigma0(a) + vbsl d30,d19,d18 @ Maj(a,b,c) + veor d16,d26 @ Sigma0(a) vadd.i64 d20,d27 vadd.i64 d30,d27 @ vadd.i64 d16,d30 vshr.u64 d24,d20,#14 @ 8 #if 8<16 - vld1.64 {d8},[r1]! @ handles unaligned + vld1.64 {d8},[r1]! @ handles unaligned #endif vshr.u64 d25,d20,#18 #if 8>0 - vadd.i64 d16,d30 @ h+=Maj from the past + vadd.i64 d16,d30 @ h+=Maj from the past #endif vshr.u64 d26,d20,#41 - vld1.64 {d28},[r3,:64]! @ K[i++] - vsli.64 d24,d20,#50 - vsli.64 d25,d20,#46 - vmov d29,d20 - vsli.64 d26,d20,#23 + vld1.64 {d28},[r3,:64]! @ K[i++] + vsli.64 d24,d20,#50 + vsli.64 d25,d20,#46 + vmov d29,d20 + vsli.64 d26,d20,#23 #if 8<16 && defined(__ARMEL__) vrev64.8 d8,d8 #endif - veor d25,d24 - vbsl d29,d21,d22 @ Ch(e,f,g) + veor d25,d24 + vbsl d29,d21,d22 @ Ch(e,f,g) vshr.u64 d24,d16,#28 - veor d26,d25 @ Sigma1(e) + veor d26,d25 @ Sigma1(e) vadd.i64 d27,d29,d23 vshr.u64 d25,d16,#34 - vsli.64 d24,d16,#36 + vsli.64 d24,d16,#36 vadd.i64 d27,d26 vshr.u64 d26,d16,#39 vadd.i64 d28,d8 - vsli.64 d25,d16,#30 - veor d30,d16,d17 - vsli.64 d26,d16,#25 - veor d23,d24,d25 + vsli.64 d25,d16,#30 + veor d30,d16,d17 + vsli.64 d26,d16,#25 + veor d23,d24,d25 vadd.i64 d27,d28 - vbsl d30,d18,d17 @ Maj(a,b,c) - veor d23,d26 @ Sigma0(a) + vbsl d30,d18,d17 @ Maj(a,b,c) + veor d23,d26 @ Sigma0(a) vadd.i64 d19,d27 vadd.i64 d30,d27 @ vadd.i64 d23,d30 vshr.u64 d24,d19,#14 @ 9 #if 9<16 - vld1.64 {d9},[r1]! @ handles unaligned + vld1.64 {d9},[r1]! @ handles unaligned #endif vshr.u64 d25,d19,#18 #if 9>0 - vadd.i64 d23,d30 @ h+=Maj from the past + vadd.i64 d23,d30 @ h+=Maj from the past #endif vshr.u64 d26,d19,#41 - vld1.64 {d28},[r3,:64]! @ K[i++] - vsli.64 d24,d19,#50 - vsli.64 d25,d19,#46 - vmov d29,d19 - vsli.64 d26,d19,#23 + vld1.64 {d28},[r3,:64]! @ K[i++] + vsli.64 d24,d19,#50 + vsli.64 d25,d19,#46 + vmov d29,d19 + vsli.64 d26,d19,#23 #if 9<16 && defined(__ARMEL__) vrev64.8 d9,d9 #endif - veor d25,d24 - vbsl d29,d20,d21 @ Ch(e,f,g) + veor d25,d24 + vbsl d29,d20,d21 @ Ch(e,f,g) vshr.u64 d24,d23,#28 - veor d26,d25 @ Sigma1(e) + veor d26,d25 @ Sigma1(e) vadd.i64 d27,d29,d22 vshr.u64 d25,d23,#34 - vsli.64 d24,d23,#36 + vsli.64 d24,d23,#36 vadd.i64 d27,d26 vshr.u64 d26,d23,#39 vadd.i64 d28,d9 - vsli.64 d25,d23,#30 - veor d30,d23,d16 - vsli.64 d26,d23,#25 - veor d22,d24,d25 + vsli.64 d25,d23,#30 + veor d30,d23,d16 + vsli.64 d26,d23,#25 + veor d22,d24,d25 vadd.i64 d27,d28 - vbsl d30,d17,d16 @ Maj(a,b,c) - veor d22,d26 @ Sigma0(a) + vbsl d30,d17,d16 @ Maj(a,b,c) + veor d22,d26 @ Sigma0(a) vadd.i64 d18,d27 vadd.i64 d30,d27 @ vadd.i64 d22,d30 vshr.u64 d24,d18,#14 @ 10 #if 10<16 - vld1.64 {d10},[r1]! @ handles unaligned + vld1.64 {d10},[r1]! @ handles unaligned #endif vshr.u64 d25,d18,#18 #if 10>0 - vadd.i64 d22,d30 @ h+=Maj from the past + vadd.i64 d22,d30 @ h+=Maj from the past #endif vshr.u64 d26,d18,#41 - vld1.64 {d28},[r3,:64]! @ K[i++] - vsli.64 d24,d18,#50 - vsli.64 d25,d18,#46 - vmov d29,d18 - vsli.64 d26,d18,#23 + vld1.64 {d28},[r3,:64]! @ K[i++] + vsli.64 d24,d18,#50 + vsli.64 d25,d18,#46 + vmov d29,d18 + vsli.64 d26,d18,#23 #if 10<16 && defined(__ARMEL__) vrev64.8 d10,d10 #endif - veor d25,d24 - vbsl d29,d19,d20 @ Ch(e,f,g) + veor d25,d24 + vbsl d29,d19,d20 @ Ch(e,f,g) vshr.u64 d24,d22,#28 - veor d26,d25 @ Sigma1(e) + veor d26,d25 @ Sigma1(e) vadd.i64 d27,d29,d21 vshr.u64 d25,d22,#34 - vsli.64 d24,d22,#36 + vsli.64 d24,d22,#36 vadd.i64 d27,d26 vshr.u64 d26,d22,#39 vadd.i64 d28,d10 - vsli.64 d25,d22,#30 - veor d30,d22,d23 - vsli.64 d26,d22,#25 - veor d21,d24,d25 + vsli.64 d25,d22,#30 + veor d30,d22,d23 + vsli.64 d26,d22,#25 + veor d21,d24,d25 vadd.i64 d27,d28 - vbsl d30,d16,d23 @ Maj(a,b,c) - veor d21,d26 @ Sigma0(a) + vbsl d30,d16,d23 @ Maj(a,b,c) + veor d21,d26 @ Sigma0(a) vadd.i64 d17,d27 vadd.i64 d30,d27 @ vadd.i64 d21,d30 vshr.u64 d24,d17,#14 @ 11 #if 11<16 - vld1.64 {d11},[r1]! @ handles unaligned + vld1.64 {d11},[r1]! @ handles unaligned #endif vshr.u64 d25,d17,#18 #if 11>0 - vadd.i64 d21,d30 @ h+=Maj from the past + vadd.i64 d21,d30 @ h+=Maj from the past #endif vshr.u64 d26,d17,#41 - vld1.64 {d28},[r3,:64]! @ K[i++] - vsli.64 d24,d17,#50 - vsli.64 d25,d17,#46 - vmov d29,d17 - vsli.64 d26,d17,#23 + vld1.64 {d28},[r3,:64]! @ K[i++] + vsli.64 d24,d17,#50 + vsli.64 d25,d17,#46 + vmov d29,d17 + vsli.64 d26,d17,#23 #if 11<16 && defined(__ARMEL__) vrev64.8 d11,d11 #endif - veor d25,d24 - vbsl d29,d18,d19 @ Ch(e,f,g) + veor d25,d24 + vbsl d29,d18,d19 @ Ch(e,f,g) vshr.u64 d24,d21,#28 - veor d26,d25 @ Sigma1(e) + veor d26,d25 @ Sigma1(e) vadd.i64 d27,d29,d20 vshr.u64 d25,d21,#34 - vsli.64 d24,d21,#36 + vsli.64 d24,d21,#36 vadd.i64 d27,d26 vshr.u64 d26,d21,#39 vadd.i64 d28,d11 - vsli.64 d25,d21,#30 - veor d30,d21,d22 - vsli.64 d26,d21,#25 - veor d20,d24,d25 + vsli.64 d25,d21,#30 + veor d30,d21,d22 + vsli.64 d26,d21,#25 + veor d20,d24,d25 vadd.i64 d27,d28 - vbsl d30,d23,d22 @ Maj(a,b,c) - veor d20,d26 @ Sigma0(a) + vbsl d30,d23,d22 @ Maj(a,b,c) + veor d20,d26 @ Sigma0(a) vadd.i64 d16,d27 vadd.i64 d30,d27 @ vadd.i64 d20,d30 vshr.u64 d24,d16,#14 @ 12 #if 12<16 - vld1.64 {d12},[r1]! @ handles unaligned + vld1.64 {d12},[r1]! @ handles unaligned #endif vshr.u64 d25,d16,#18 #if 12>0 - vadd.i64 d20,d30 @ h+=Maj from the past + vadd.i64 d20,d30 @ h+=Maj from the past #endif vshr.u64 d26,d16,#41 - vld1.64 {d28},[r3,:64]! @ K[i++] - vsli.64 d24,d16,#50 - vsli.64 d25,d16,#46 - vmov d29,d16 - vsli.64 d26,d16,#23 + vld1.64 {d28},[r3,:64]! @ K[i++] + vsli.64 d24,d16,#50 + vsli.64 d25,d16,#46 + vmov d29,d16 + vsli.64 d26,d16,#23 #if 12<16 && defined(__ARMEL__) vrev64.8 d12,d12 #endif - veor d25,d24 - vbsl d29,d17,d18 @ Ch(e,f,g) + veor d25,d24 + vbsl d29,d17,d18 @ Ch(e,f,g) vshr.u64 d24,d20,#28 - veor d26,d25 @ Sigma1(e) + veor d26,d25 @ Sigma1(e) vadd.i64 d27,d29,d19 vshr.u64 d25,d20,#34 - vsli.64 d24,d20,#36 + vsli.64 d24,d20,#36 vadd.i64 d27,d26 vshr.u64 d26,d20,#39 vadd.i64 d28,d12 - vsli.64 d25,d20,#30 - veor d30,d20,d21 - vsli.64 d26,d20,#25 - veor d19,d24,d25 + vsli.64 d25,d20,#30 + veor d30,d20,d21 + vsli.64 d26,d20,#25 + veor d19,d24,d25 vadd.i64 d27,d28 - vbsl d30,d22,d21 @ Maj(a,b,c) - veor d19,d26 @ Sigma0(a) + vbsl d30,d22,d21 @ Maj(a,b,c) + veor d19,d26 @ Sigma0(a) vadd.i64 d23,d27 vadd.i64 d30,d27 @ vadd.i64 d19,d30 vshr.u64 d24,d23,#14 @ 13 #if 13<16 - vld1.64 {d13},[r1]! @ handles unaligned + vld1.64 {d13},[r1]! @ handles unaligned #endif vshr.u64 d25,d23,#18 #if 13>0 - vadd.i64 d19,d30 @ h+=Maj from the past + vadd.i64 d19,d30 @ h+=Maj from the past #endif vshr.u64 d26,d23,#41 - vld1.64 {d28},[r3,:64]! @ K[i++] - vsli.64 d24,d23,#50 - vsli.64 d25,d23,#46 - vmov d29,d23 - vsli.64 d26,d23,#23 + vld1.64 {d28},[r3,:64]! @ K[i++] + vsli.64 d24,d23,#50 + vsli.64 d25,d23,#46 + vmov d29,d23 + vsli.64 d26,d23,#23 #if 13<16 && defined(__ARMEL__) vrev64.8 d13,d13 #endif - veor d25,d24 - vbsl d29,d16,d17 @ Ch(e,f,g) + veor d25,d24 + vbsl d29,d16,d17 @ Ch(e,f,g) vshr.u64 d24,d19,#28 - veor d26,d25 @ Sigma1(e) + veor d26,d25 @ Sigma1(e) vadd.i64 d27,d29,d18 vshr.u64 d25,d19,#34 - vsli.64 d24,d19,#36 + vsli.64 d24,d19,#36 vadd.i64 d27,d26 vshr.u64 d26,d19,#39 vadd.i64 d28,d13 - vsli.64 d25,d19,#30 - veor d30,d19,d20 - vsli.64 d26,d19,#25 - veor d18,d24,d25 + vsli.64 d25,d19,#30 + veor d30,d19,d20 + vsli.64 d26,d19,#25 + veor d18,d24,d25 vadd.i64 d27,d28 - vbsl d30,d21,d20 @ Maj(a,b,c) - veor d18,d26 @ Sigma0(a) + vbsl d30,d21,d20 @ Maj(a,b,c) + veor d18,d26 @ Sigma0(a) vadd.i64 d22,d27 vadd.i64 d30,d27 @ vadd.i64 d18,d30 vshr.u64 d24,d22,#14 @ 14 #if 14<16 - vld1.64 {d14},[r1]! @ handles unaligned + vld1.64 {d14},[r1]! @ handles unaligned #endif vshr.u64 d25,d22,#18 #if 14>0 - vadd.i64 d18,d30 @ h+=Maj from the past + vadd.i64 d18,d30 @ h+=Maj from the past #endif vshr.u64 d26,d22,#41 - vld1.64 {d28},[r3,:64]! @ K[i++] - vsli.64 d24,d22,#50 - vsli.64 d25,d22,#46 - vmov d29,d22 - vsli.64 d26,d22,#23 + vld1.64 {d28},[r3,:64]! @ K[i++] + vsli.64 d24,d22,#50 + vsli.64 d25,d22,#46 + vmov d29,d22 + vsli.64 d26,d22,#23 #if 14<16 && defined(__ARMEL__) vrev64.8 d14,d14 #endif - veor d25,d24 - vbsl d29,d23,d16 @ Ch(e,f,g) + veor d25,d24 + vbsl d29,d23,d16 @ Ch(e,f,g) vshr.u64 d24,d18,#28 - veor d26,d25 @ Sigma1(e) + veor d26,d25 @ Sigma1(e) vadd.i64 d27,d29,d17 vshr.u64 d25,d18,#34 - vsli.64 d24,d18,#36 + vsli.64 d24,d18,#36 vadd.i64 d27,d26 vshr.u64 d26,d18,#39 vadd.i64 d28,d14 - vsli.64 d25,d18,#30 - veor d30,d18,d19 - vsli.64 d26,d18,#25 - veor d17,d24,d25 + vsli.64 d25,d18,#30 + veor d30,d18,d19 + vsli.64 d26,d18,#25 + veor d17,d24,d25 vadd.i64 d27,d28 - vbsl d30,d20,d19 @ Maj(a,b,c) - veor d17,d26 @ Sigma0(a) + vbsl d30,d20,d19 @ Maj(a,b,c) + veor d17,d26 @ Sigma0(a) vadd.i64 d21,d27 vadd.i64 d30,d27 @ vadd.i64 d17,d30 vshr.u64 d24,d21,#14 @ 15 #if 15<16 - vld1.64 {d15},[r1]! @ handles unaligned + vld1.64 {d15},[r1]! @ handles unaligned #endif vshr.u64 d25,d21,#18 #if 15>0 - vadd.i64 d17,d30 @ h+=Maj from the past + vadd.i64 d17,d30 @ h+=Maj from the past #endif vshr.u64 d26,d21,#41 - vld1.64 {d28},[r3,:64]! @ K[i++] - vsli.64 d24,d21,#50 - vsli.64 d25,d21,#46 - vmov d29,d21 - vsli.64 d26,d21,#23 + vld1.64 {d28},[r3,:64]! @ K[i++] + vsli.64 d24,d21,#50 + vsli.64 d25,d21,#46 + vmov d29,d21 + vsli.64 d26,d21,#23 #if 15<16 && defined(__ARMEL__) vrev64.8 d15,d15 #endif - veor d25,d24 - vbsl d29,d22,d23 @ Ch(e,f,g) + veor d25,d24 + vbsl d29,d22,d23 @ Ch(e,f,g) vshr.u64 d24,d17,#28 - veor d26,d25 @ Sigma1(e) + veor d26,d25 @ Sigma1(e) vadd.i64 d27,d29,d16 vshr.u64 d25,d17,#34 - vsli.64 d24,d17,#36 + vsli.64 d24,d17,#36 vadd.i64 d27,d26 vshr.u64 d26,d17,#39 vadd.i64 d28,d15 - vsli.64 d25,d17,#30 - veor d30,d17,d18 - vsli.64 d26,d17,#25 - veor d16,d24,d25 + vsli.64 d25,d17,#30 + veor d30,d17,d18 + vsli.64 d26,d17,#25 + veor d16,d24,d25 vadd.i64 d27,d28 - vbsl d30,d19,d18 @ Maj(a,b,c) - veor d16,d26 @ Sigma0(a) + vbsl d30,d19,d18 @ Maj(a,b,c) + veor d16,d26 @ Sigma0(a) vadd.i64 d20,d27 vadd.i64 d30,d27 @ vadd.i64 d16,d30 - mov r12,#4 + mov r12,#4 .L16_79_neon: - subs r12,#1 + subs r12,#1 vshr.u64 q12,q7,#19 vshr.u64 q13,q7,#61 - vadd.i64 d16,d30 @ h+=Maj from the past + vadd.i64 d16,d30 @ h+=Maj from the past vshr.u64 q15,q7,#6 - vsli.64 q12,q7,#45 - vext.8 q14,q0,q1,#8 @ X[i+1] - vsli.64 q13,q7,#3 - veor q15,q12 + vsli.64 q12,q7,#45 + vext.8 q14,q0,q1,#8 @ X[i+1] + vsli.64 q13,q7,#3 + veor q15,q12 vshr.u64 q12,q14,#1 - veor q15,q13 @ sigma1(X[i+14]) + veor q15,q13 @ sigma1(X[i+14]) vshr.u64 q13,q14,#8 vadd.i64 q0,q15 vshr.u64 q15,q14,#7 - vsli.64 q12,q14,#63 - vsli.64 q13,q14,#56 - vext.8 q14,q4,q5,#8 @ X[i+9] - veor q15,q12 + vsli.64 q12,q14,#63 + vsli.64 q13,q14,#56 + vext.8 q14,q4,q5,#8 @ X[i+9] + veor q15,q12 vshr.u64 d24,d20,#14 @ from NEON_00_15 vadd.i64 q0,q14 vshr.u64 d25,d20,#18 @ from NEON_00_15 - veor q15,q13 @ sigma0(X[i+1]) + veor q15,q13 @ sigma0(X[i+1]) vshr.u64 d26,d20,#41 @ from NEON_00_15 vadd.i64 q0,q15 - vld1.64 {d28},[r3,:64]! @ K[i++] - vsli.64 d24,d20,#50 - vsli.64 d25,d20,#46 - vmov d29,d20 - vsli.64 d26,d20,#23 + vld1.64 {d28},[r3,:64]! @ K[i++] + vsli.64 d24,d20,#50 + vsli.64 d25,d20,#46 + vmov d29,d20 + vsli.64 d26,d20,#23 #if 16<16 && defined(__ARMEL__) vrev64.8 , #endif - veor d25,d24 - vbsl d29,d21,d22 @ Ch(e,f,g) + veor d25,d24 + vbsl d29,d21,d22 @ Ch(e,f,g) vshr.u64 d24,d16,#28 - veor d26,d25 @ Sigma1(e) + veor d26,d25 @ Sigma1(e) vadd.i64 d27,d29,d23 vshr.u64 d25,d16,#34 - vsli.64 d24,d16,#36 + vsli.64 d24,d16,#36 vadd.i64 d27,d26 vshr.u64 d26,d16,#39 vadd.i64 d28,d0 - vsli.64 d25,d16,#30 - veor d30,d16,d17 - vsli.64 d26,d16,#25 - veor d23,d24,d25 + vsli.64 d25,d16,#30 + veor d30,d16,d17 + vsli.64 d26,d16,#25 + veor d23,d24,d25 vadd.i64 d27,d28 - vbsl d30,d18,d17 @ Maj(a,b,c) - veor d23,d26 @ Sigma0(a) + vbsl d30,d18,d17 @ Maj(a,b,c) + veor d23,d26 @ Sigma0(a) vadd.i64 d19,d27 vadd.i64 d30,d27 @ vadd.i64 d23,d30 vshr.u64 d24,d19,#14 @ 17 #if 17<16 - vld1.64 {d1},[r1]! @ handles unaligned + vld1.64 {d1},[r1]! @ handles unaligned #endif vshr.u64 d25,d19,#18 #if 17>0 - vadd.i64 d23,d30 @ h+=Maj from the past + vadd.i64 d23,d30 @ h+=Maj from the past #endif vshr.u64 d26,d19,#41 - vld1.64 {d28},[r3,:64]! @ K[i++] - vsli.64 d24,d19,#50 - vsli.64 d25,d19,#46 - vmov d29,d19 - vsli.64 d26,d19,#23 + vld1.64 {d28},[r3,:64]! @ K[i++] + vsli.64 d24,d19,#50 + vsli.64 d25,d19,#46 + vmov d29,d19 + vsli.64 d26,d19,#23 #if 17<16 && defined(__ARMEL__) vrev64.8 , #endif - veor d25,d24 - vbsl d29,d20,d21 @ Ch(e,f,g) + veor d25,d24 + vbsl d29,d20,d21 @ Ch(e,f,g) vshr.u64 d24,d23,#28 - veor d26,d25 @ Sigma1(e) + veor d26,d25 @ Sigma1(e) vadd.i64 d27,d29,d22 vshr.u64 d25,d23,#34 - vsli.64 d24,d23,#36 + vsli.64 d24,d23,#36 vadd.i64 d27,d26 vshr.u64 d26,d23,#39 vadd.i64 d28,d1 - vsli.64 d25,d23,#30 - veor d30,d23,d16 - vsli.64 d26,d23,#25 - veor d22,d24,d25 + vsli.64 d25,d23,#30 + veor d30,d23,d16 + vsli.64 d26,d23,#25 + veor d22,d24,d25 vadd.i64 d27,d28 - vbsl d30,d17,d16 @ Maj(a,b,c) - veor d22,d26 @ Sigma0(a) + vbsl d30,d17,d16 @ Maj(a,b,c) + veor d22,d26 @ Sigma0(a) vadd.i64 d18,d27 vadd.i64 d30,d27 @ vadd.i64 d22,d30 vshr.u64 q12,q0,#19 vshr.u64 q13,q0,#61 - vadd.i64 d22,d30 @ h+=Maj from the past + vadd.i64 d22,d30 @ h+=Maj from the past vshr.u64 q15,q0,#6 - vsli.64 q12,q0,#45 - vext.8 q14,q1,q2,#8 @ X[i+1] - vsli.64 q13,q0,#3 - veor q15,q12 + vsli.64 q12,q0,#45 + vext.8 q14,q1,q2,#8 @ X[i+1] + vsli.64 q13,q0,#3 + veor q15,q12 vshr.u64 q12,q14,#1 - veor q15,q13 @ sigma1(X[i+14]) + veor q15,q13 @ sigma1(X[i+14]) vshr.u64 q13,q14,#8 vadd.i64 q1,q15 vshr.u64 q15,q14,#7 - vsli.64 q12,q14,#63 - vsli.64 q13,q14,#56 - vext.8 q14,q5,q6,#8 @ X[i+9] - veor q15,q12 + vsli.64 q12,q14,#63 + vsli.64 q13,q14,#56 + vext.8 q14,q5,q6,#8 @ X[i+9] + veor q15,q12 vshr.u64 d24,d18,#14 @ from NEON_00_15 vadd.i64 q1,q14 vshr.u64 d25,d18,#18 @ from NEON_00_15 - veor q15,q13 @ sigma0(X[i+1]) + veor q15,q13 @ sigma0(X[i+1]) vshr.u64 d26,d18,#41 @ from NEON_00_15 vadd.i64 q1,q15 - vld1.64 {d28},[r3,:64]! @ K[i++] - vsli.64 d24,d18,#50 - vsli.64 d25,d18,#46 - vmov d29,d18 - vsli.64 d26,d18,#23 + vld1.64 {d28},[r3,:64]! @ K[i++] + vsli.64 d24,d18,#50 + vsli.64 d25,d18,#46 + vmov d29,d18 + vsli.64 d26,d18,#23 #if 18<16 && defined(__ARMEL__) vrev64.8 , #endif - veor d25,d24 - vbsl d29,d19,d20 @ Ch(e,f,g) + veor d25,d24 + vbsl d29,d19,d20 @ Ch(e,f,g) vshr.u64 d24,d22,#28 - veor d26,d25 @ Sigma1(e) + veor d26,d25 @ Sigma1(e) vadd.i64 d27,d29,d21 vshr.u64 d25,d22,#34 - vsli.64 d24,d22,#36 + vsli.64 d24,d22,#36 vadd.i64 d27,d26 vshr.u64 d26,d22,#39 vadd.i64 d28,d2 - vsli.64 d25,d22,#30 - veor d30,d22,d23 - vsli.64 d26,d22,#25 - veor d21,d24,d25 + vsli.64 d25,d22,#30 + veor d30,d22,d23 + vsli.64 d26,d22,#25 + veor d21,d24,d25 vadd.i64 d27,d28 - vbsl d30,d16,d23 @ Maj(a,b,c) - veor d21,d26 @ Sigma0(a) + vbsl d30,d16,d23 @ Maj(a,b,c) + veor d21,d26 @ Sigma0(a) vadd.i64 d17,d27 vadd.i64 d30,d27 @ vadd.i64 d21,d30 vshr.u64 d24,d17,#14 @ 19 #if 19<16 - vld1.64 {d3},[r1]! @ handles unaligned + vld1.64 {d3},[r1]! @ handles unaligned #endif vshr.u64 d25,d17,#18 #if 19>0 - vadd.i64 d21,d30 @ h+=Maj from the past + vadd.i64 d21,d30 @ h+=Maj from the past #endif vshr.u64 d26,d17,#41 - vld1.64 {d28},[r3,:64]! @ K[i++] - vsli.64 d24,d17,#50 - vsli.64 d25,d17,#46 - vmov d29,d17 - vsli.64 d26,d17,#23 + vld1.64 {d28},[r3,:64]! @ K[i++] + vsli.64 d24,d17,#50 + vsli.64 d25,d17,#46 + vmov d29,d17 + vsli.64 d26,d17,#23 #if 19<16 && defined(__ARMEL__) vrev64.8 , #endif - veor d25,d24 - vbsl d29,d18,d19 @ Ch(e,f,g) + veor d25,d24 + vbsl d29,d18,d19 @ Ch(e,f,g) vshr.u64 d24,d21,#28 - veor d26,d25 @ Sigma1(e) + veor d26,d25 @ Sigma1(e) vadd.i64 d27,d29,d20 vshr.u64 d25,d21,#34 - vsli.64 d24,d21,#36 + vsli.64 d24,d21,#36 vadd.i64 d27,d26 vshr.u64 d26,d21,#39 vadd.i64 d28,d3 - vsli.64 d25,d21,#30 - veor d30,d21,d22 - vsli.64 d26,d21,#25 - veor d20,d24,d25 + vsli.64 d25,d21,#30 + veor d30,d21,d22 + vsli.64 d26,d21,#25 + veor d20,d24,d25 vadd.i64 d27,d28 - vbsl d30,d23,d22 @ Maj(a,b,c) - veor d20,d26 @ Sigma0(a) + vbsl d30,d23,d22 @ Maj(a,b,c) + veor d20,d26 @ Sigma0(a) vadd.i64 d16,d27 vadd.i64 d30,d27 @ vadd.i64 d20,d30 vshr.u64 q12,q1,#19 vshr.u64 q13,q1,#61 - vadd.i64 d20,d30 @ h+=Maj from the past + vadd.i64 d20,d30 @ h+=Maj from the past vshr.u64 q15,q1,#6 - vsli.64 q12,q1,#45 - vext.8 q14,q2,q3,#8 @ X[i+1] - vsli.64 q13,q1,#3 - veor q15,q12 + vsli.64 q12,q1,#45 + vext.8 q14,q2,q3,#8 @ X[i+1] + vsli.64 q13,q1,#3 + veor q15,q12 vshr.u64 q12,q14,#1 - veor q15,q13 @ sigma1(X[i+14]) + veor q15,q13 @ sigma1(X[i+14]) vshr.u64 q13,q14,#8 vadd.i64 q2,q15 vshr.u64 q15,q14,#7 - vsli.64 q12,q14,#63 - vsli.64 q13,q14,#56 - vext.8 q14,q6,q7,#8 @ X[i+9] - veor q15,q12 + vsli.64 q12,q14,#63 + vsli.64 q13,q14,#56 + vext.8 q14,q6,q7,#8 @ X[i+9] + veor q15,q12 vshr.u64 d24,d16,#14 @ from NEON_00_15 vadd.i64 q2,q14 vshr.u64 d25,d16,#18 @ from NEON_00_15 - veor q15,q13 @ sigma0(X[i+1]) + veor q15,q13 @ sigma0(X[i+1]) vshr.u64 d26,d16,#41 @ from NEON_00_15 vadd.i64 q2,q15 - vld1.64 {d28},[r3,:64]! @ K[i++] - vsli.64 d24,d16,#50 - vsli.64 d25,d16,#46 - vmov d29,d16 - vsli.64 d26,d16,#23 + vld1.64 {d28},[r3,:64]! @ K[i++] + vsli.64 d24,d16,#50 + vsli.64 d25,d16,#46 + vmov d29,d16 + vsli.64 d26,d16,#23 #if 20<16 && defined(__ARMEL__) vrev64.8 , #endif - veor d25,d24 - vbsl d29,d17,d18 @ Ch(e,f,g) + veor d25,d24 + vbsl d29,d17,d18 @ Ch(e,f,g) vshr.u64 d24,d20,#28 - veor d26,d25 @ Sigma1(e) + veor d26,d25 @ Sigma1(e) vadd.i64 d27,d29,d19 vshr.u64 d25,d20,#34 - vsli.64 d24,d20,#36 + vsli.64 d24,d20,#36 vadd.i64 d27,d26 vshr.u64 d26,d20,#39 vadd.i64 d28,d4 - vsli.64 d25,d20,#30 - veor d30,d20,d21 - vsli.64 d26,d20,#25 - veor d19,d24,d25 + vsli.64 d25,d20,#30 + veor d30,d20,d21 + vsli.64 d26,d20,#25 + veor d19,d24,d25 vadd.i64 d27,d28 - vbsl d30,d22,d21 @ Maj(a,b,c) - veor d19,d26 @ Sigma0(a) + vbsl d30,d22,d21 @ Maj(a,b,c) + veor d19,d26 @ Sigma0(a) vadd.i64 d23,d27 vadd.i64 d30,d27 @ vadd.i64 d19,d30 vshr.u64 d24,d23,#14 @ 21 #if 21<16 - vld1.64 {d5},[r1]! @ handles unaligned + vld1.64 {d5},[r1]! @ handles unaligned #endif vshr.u64 d25,d23,#18 #if 21>0 - vadd.i64 d19,d30 @ h+=Maj from the past + vadd.i64 d19,d30 @ h+=Maj from the past #endif vshr.u64 d26,d23,#41 - vld1.64 {d28},[r3,:64]! @ K[i++] - vsli.64 d24,d23,#50 - vsli.64 d25,d23,#46 - vmov d29,d23 - vsli.64 d26,d23,#23 + vld1.64 {d28},[r3,:64]! @ K[i++] + vsli.64 d24,d23,#50 + vsli.64 d25,d23,#46 + vmov d29,d23 + vsli.64 d26,d23,#23 #if 21<16 && defined(__ARMEL__) vrev64.8 , #endif - veor d25,d24 - vbsl d29,d16,d17 @ Ch(e,f,g) + veor d25,d24 + vbsl d29,d16,d17 @ Ch(e,f,g) vshr.u64 d24,d19,#28 - veor d26,d25 @ Sigma1(e) + veor d26,d25 @ Sigma1(e) vadd.i64 d27,d29,d18 vshr.u64 d25,d19,#34 - vsli.64 d24,d19,#36 + vsli.64 d24,d19,#36 vadd.i64 d27,d26 vshr.u64 d26,d19,#39 vadd.i64 d28,d5 - vsli.64 d25,d19,#30 - veor d30,d19,d20 - vsli.64 d26,d19,#25 - veor d18,d24,d25 + vsli.64 d25,d19,#30 + veor d30,d19,d20 + vsli.64 d26,d19,#25 + veor d18,d24,d25 vadd.i64 d27,d28 - vbsl d30,d21,d20 @ Maj(a,b,c) - veor d18,d26 @ Sigma0(a) + vbsl d30,d21,d20 @ Maj(a,b,c) + veor d18,d26 @ Sigma0(a) vadd.i64 d22,d27 vadd.i64 d30,d27 @ vadd.i64 d18,d30 vshr.u64 q12,q2,#19 vshr.u64 q13,q2,#61 - vadd.i64 d18,d30 @ h+=Maj from the past + vadd.i64 d18,d30 @ h+=Maj from the past vshr.u64 q15,q2,#6 - vsli.64 q12,q2,#45 - vext.8 q14,q3,q4,#8 @ X[i+1] - vsli.64 q13,q2,#3 - veor q15,q12 + vsli.64 q12,q2,#45 + vext.8 q14,q3,q4,#8 @ X[i+1] + vsli.64 q13,q2,#3 + veor q15,q12 vshr.u64 q12,q14,#1 - veor q15,q13 @ sigma1(X[i+14]) + veor q15,q13 @ sigma1(X[i+14]) vshr.u64 q13,q14,#8 vadd.i64 q3,q15 vshr.u64 q15,q14,#7 - vsli.64 q12,q14,#63 - vsli.64 q13,q14,#56 - vext.8 q14,q7,q0,#8 @ X[i+9] - veor q15,q12 + vsli.64 q12,q14,#63 + vsli.64 q13,q14,#56 + vext.8 q14,q7,q0,#8 @ X[i+9] + veor q15,q12 vshr.u64 d24,d22,#14 @ from NEON_00_15 vadd.i64 q3,q14 vshr.u64 d25,d22,#18 @ from NEON_00_15 - veor q15,q13 @ sigma0(X[i+1]) + veor q15,q13 @ sigma0(X[i+1]) vshr.u64 d26,d22,#41 @ from NEON_00_15 vadd.i64 q3,q15 - vld1.64 {d28},[r3,:64]! @ K[i++] - vsli.64 d24,d22,#50 - vsli.64 d25,d22,#46 - vmov d29,d22 - vsli.64 d26,d22,#23 + vld1.64 {d28},[r3,:64]! @ K[i++] + vsli.64 d24,d22,#50 + vsli.64 d25,d22,#46 + vmov d29,d22 + vsli.64 d26,d22,#23 #if 22<16 && defined(__ARMEL__) vrev64.8 , #endif - veor d25,d24 - vbsl d29,d23,d16 @ Ch(e,f,g) + veor d25,d24 + vbsl d29,d23,d16 @ Ch(e,f,g) vshr.u64 d24,d18,#28 - veor d26,d25 @ Sigma1(e) + veor d26,d25 @ Sigma1(e) vadd.i64 d27,d29,d17 vshr.u64 d25,d18,#34 - vsli.64 d24,d18,#36 + vsli.64 d24,d18,#36 vadd.i64 d27,d26 vshr.u64 d26,d18,#39 vadd.i64 d28,d6 - vsli.64 d25,d18,#30 - veor d30,d18,d19 - vsli.64 d26,d18,#25 - veor d17,d24,d25 + vsli.64 d25,d18,#30 + veor d30,d18,d19 + vsli.64 d26,d18,#25 + veor d17,d24,d25 vadd.i64 d27,d28 - vbsl d30,d20,d19 @ Maj(a,b,c) - veor d17,d26 @ Sigma0(a) + vbsl d30,d20,d19 @ Maj(a,b,c) + veor d17,d26 @ Sigma0(a) vadd.i64 d21,d27 vadd.i64 d30,d27 @ vadd.i64 d17,d30 vshr.u64 d24,d21,#14 @ 23 #if 23<16 - vld1.64 {d7},[r1]! @ handles unaligned + vld1.64 {d7},[r1]! @ handles unaligned #endif vshr.u64 d25,d21,#18 #if 23>0 - vadd.i64 d17,d30 @ h+=Maj from the past + vadd.i64 d17,d30 @ h+=Maj from the past #endif vshr.u64 d26,d21,#41 - vld1.64 {d28},[r3,:64]! @ K[i++] - vsli.64 d24,d21,#50 - vsli.64 d25,d21,#46 - vmov d29,d21 - vsli.64 d26,d21,#23 + vld1.64 {d28},[r3,:64]! @ K[i++] + vsli.64 d24,d21,#50 + vsli.64 d25,d21,#46 + vmov d29,d21 + vsli.64 d26,d21,#23 #if 23<16 && defined(__ARMEL__) vrev64.8 , #endif - veor d25,d24 - vbsl d29,d22,d23 @ Ch(e,f,g) + veor d25,d24 + vbsl d29,d22,d23 @ Ch(e,f,g) vshr.u64 d24,d17,#28 - veor d26,d25 @ Sigma1(e) + veor d26,d25 @ Sigma1(e) vadd.i64 d27,d29,d16 vshr.u64 d25,d17,#34 - vsli.64 d24,d17,#36 + vsli.64 d24,d17,#36 vadd.i64 d27,d26 vshr.u64 d26,d17,#39 vadd.i64 d28,d7 - vsli.64 d25,d17,#30 - veor d30,d17,d18 - vsli.64 d26,d17,#25 - veor d16,d24,d25 + vsli.64 d25,d17,#30 + veor d30,d17,d18 + vsli.64 d26,d17,#25 + veor d16,d24,d25 vadd.i64 d27,d28 - vbsl d30,d19,d18 @ Maj(a,b,c) - veor d16,d26 @ Sigma0(a) + vbsl d30,d19,d18 @ Maj(a,b,c) + veor d16,d26 @ Sigma0(a) vadd.i64 d20,d27 vadd.i64 d30,d27 @ vadd.i64 d16,d30 vshr.u64 q12,q3,#19 vshr.u64 q13,q3,#61 - vadd.i64 d16,d30 @ h+=Maj from the past + vadd.i64 d16,d30 @ h+=Maj from the past vshr.u64 q15,q3,#6 - vsli.64 q12,q3,#45 - vext.8 q14,q4,q5,#8 @ X[i+1] - vsli.64 q13,q3,#3 - veor q15,q12 + vsli.64 q12,q3,#45 + vext.8 q14,q4,q5,#8 @ X[i+1] + vsli.64 q13,q3,#3 + veor q15,q12 vshr.u64 q12,q14,#1 - veor q15,q13 @ sigma1(X[i+14]) + veor q15,q13 @ sigma1(X[i+14]) vshr.u64 q13,q14,#8 vadd.i64 q4,q15 vshr.u64 q15,q14,#7 - vsli.64 q12,q14,#63 - vsli.64 q13,q14,#56 - vext.8 q14,q0,q1,#8 @ X[i+9] - veor q15,q12 + vsli.64 q12,q14,#63 + vsli.64 q13,q14,#56 + vext.8 q14,q0,q1,#8 @ X[i+9] + veor q15,q12 vshr.u64 d24,d20,#14 @ from NEON_00_15 vadd.i64 q4,q14 vshr.u64 d25,d20,#18 @ from NEON_00_15 - veor q15,q13 @ sigma0(X[i+1]) + veor q15,q13 @ sigma0(X[i+1]) vshr.u64 d26,d20,#41 @ from NEON_00_15 vadd.i64 q4,q15 - vld1.64 {d28},[r3,:64]! @ K[i++] - vsli.64 d24,d20,#50 - vsli.64 d25,d20,#46 - vmov d29,d20 - vsli.64 d26,d20,#23 + vld1.64 {d28},[r3,:64]! @ K[i++] + vsli.64 d24,d20,#50 + vsli.64 d25,d20,#46 + vmov d29,d20 + vsli.64 d26,d20,#23 #if 24<16 && defined(__ARMEL__) vrev64.8 , #endif - veor d25,d24 - vbsl d29,d21,d22 @ Ch(e,f,g) + veor d25,d24 + vbsl d29,d21,d22 @ Ch(e,f,g) vshr.u64 d24,d16,#28 - veor d26,d25 @ Sigma1(e) + veor d26,d25 @ Sigma1(e) vadd.i64 d27,d29,d23 vshr.u64 d25,d16,#34 - vsli.64 d24,d16,#36 + vsli.64 d24,d16,#36 vadd.i64 d27,d26 vshr.u64 d26,d16,#39 vadd.i64 d28,d8 - vsli.64 d25,d16,#30 - veor d30,d16,d17 - vsli.64 d26,d16,#25 - veor d23,d24,d25 + vsli.64 d25,d16,#30 + veor d30,d16,d17 + vsli.64 d26,d16,#25 + veor d23,d24,d25 vadd.i64 d27,d28 - vbsl d30,d18,d17 @ Maj(a,b,c) - veor d23,d26 @ Sigma0(a) + vbsl d30,d18,d17 @ Maj(a,b,c) + veor d23,d26 @ Sigma0(a) vadd.i64 d19,d27 vadd.i64 d30,d27 @ vadd.i64 d23,d30 vshr.u64 d24,d19,#14 @ 25 #if 25<16 - vld1.64 {d9},[r1]! @ handles unaligned + vld1.64 {d9},[r1]! @ handles unaligned #endif vshr.u64 d25,d19,#18 #if 25>0 - vadd.i64 d23,d30 @ h+=Maj from the past + vadd.i64 d23,d30 @ h+=Maj from the past #endif vshr.u64 d26,d19,#41 - vld1.64 {d28},[r3,:64]! @ K[i++] - vsli.64 d24,d19,#50 - vsli.64 d25,d19,#46 - vmov d29,d19 - vsli.64 d26,d19,#23 + vld1.64 {d28},[r3,:64]! @ K[i++] + vsli.64 d24,d19,#50 + vsli.64 d25,d19,#46 + vmov d29,d19 + vsli.64 d26,d19,#23 #if 25<16 && defined(__ARMEL__) vrev64.8 , #endif - veor d25,d24 - vbsl d29,d20,d21 @ Ch(e,f,g) + veor d25,d24 + vbsl d29,d20,d21 @ Ch(e,f,g) vshr.u64 d24,d23,#28 - veor d26,d25 @ Sigma1(e) + veor d26,d25 @ Sigma1(e) vadd.i64 d27,d29,d22 vshr.u64 d25,d23,#34 - vsli.64 d24,d23,#36 + vsli.64 d24,d23,#36 vadd.i64 d27,d26 vshr.u64 d26,d23,#39 vadd.i64 d28,d9 - vsli.64 d25,d23,#30 - veor d30,d23,d16 - vsli.64 d26,d23,#25 - veor d22,d24,d25 + vsli.64 d25,d23,#30 + veor d30,d23,d16 + vsli.64 d26,d23,#25 + veor d22,d24,d25 vadd.i64 d27,d28 - vbsl d30,d17,d16 @ Maj(a,b,c) - veor d22,d26 @ Sigma0(a) + vbsl d30,d17,d16 @ Maj(a,b,c) + veor d22,d26 @ Sigma0(a) vadd.i64 d18,d27 vadd.i64 d30,d27 @ vadd.i64 d22,d30 vshr.u64 q12,q4,#19 vshr.u64 q13,q4,#61 - vadd.i64 d22,d30 @ h+=Maj from the past + vadd.i64 d22,d30 @ h+=Maj from the past vshr.u64 q15,q4,#6 - vsli.64 q12,q4,#45 - vext.8 q14,q5,q6,#8 @ X[i+1] - vsli.64 q13,q4,#3 - veor q15,q12 + vsli.64 q12,q4,#45 + vext.8 q14,q5,q6,#8 @ X[i+1] + vsli.64 q13,q4,#3 + veor q15,q12 vshr.u64 q12,q14,#1 - veor q15,q13 @ sigma1(X[i+14]) + veor q15,q13 @ sigma1(X[i+14]) vshr.u64 q13,q14,#8 vadd.i64 q5,q15 vshr.u64 q15,q14,#7 - vsli.64 q12,q14,#63 - vsli.64 q13,q14,#56 - vext.8 q14,q1,q2,#8 @ X[i+9] - veor q15,q12 + vsli.64 q12,q14,#63 + vsli.64 q13,q14,#56 + vext.8 q14,q1,q2,#8 @ X[i+9] + veor q15,q12 vshr.u64 d24,d18,#14 @ from NEON_00_15 vadd.i64 q5,q14 vshr.u64 d25,d18,#18 @ from NEON_00_15 - veor q15,q13 @ sigma0(X[i+1]) + veor q15,q13 @ sigma0(X[i+1]) vshr.u64 d26,d18,#41 @ from NEON_00_15 vadd.i64 q5,q15 - vld1.64 {d28},[r3,:64]! @ K[i++] - vsli.64 d24,d18,#50 - vsli.64 d25,d18,#46 - vmov d29,d18 - vsli.64 d26,d18,#23 + vld1.64 {d28},[r3,:64]! @ K[i++] + vsli.64 d24,d18,#50 + vsli.64 d25,d18,#46 + vmov d29,d18 + vsli.64 d26,d18,#23 #if 26<16 && defined(__ARMEL__) vrev64.8 , #endif - veor d25,d24 - vbsl d29,d19,d20 @ Ch(e,f,g) + veor d25,d24 + vbsl d29,d19,d20 @ Ch(e,f,g) vshr.u64 d24,d22,#28 - veor d26,d25 @ Sigma1(e) + veor d26,d25 @ Sigma1(e) vadd.i64 d27,d29,d21 vshr.u64 d25,d22,#34 - vsli.64 d24,d22,#36 + vsli.64 d24,d22,#36 vadd.i64 d27,d26 vshr.u64 d26,d22,#39 vadd.i64 d28,d10 - vsli.64 d25,d22,#30 - veor d30,d22,d23 - vsli.64 d26,d22,#25 - veor d21,d24,d25 + vsli.64 d25,d22,#30 + veor d30,d22,d23 + vsli.64 d26,d22,#25 + veor d21,d24,d25 vadd.i64 d27,d28 - vbsl d30,d16,d23 @ Maj(a,b,c) - veor d21,d26 @ Sigma0(a) + vbsl d30,d16,d23 @ Maj(a,b,c) + veor d21,d26 @ Sigma0(a) vadd.i64 d17,d27 vadd.i64 d30,d27 @ vadd.i64 d21,d30 vshr.u64 d24,d17,#14 @ 27 #if 27<16 - vld1.64 {d11},[r1]! @ handles unaligned + vld1.64 {d11},[r1]! @ handles unaligned #endif vshr.u64 d25,d17,#18 #if 27>0 - vadd.i64 d21,d30 @ h+=Maj from the past + vadd.i64 d21,d30 @ h+=Maj from the past #endif vshr.u64 d26,d17,#41 - vld1.64 {d28},[r3,:64]! @ K[i++] - vsli.64 d24,d17,#50 - vsli.64 d25,d17,#46 - vmov d29,d17 - vsli.64 d26,d17,#23 + vld1.64 {d28},[r3,:64]! @ K[i++] + vsli.64 d24,d17,#50 + vsli.64 d25,d17,#46 + vmov d29,d17 + vsli.64 d26,d17,#23 #if 27<16 && defined(__ARMEL__) vrev64.8 , #endif - veor d25,d24 - vbsl d29,d18,d19 @ Ch(e,f,g) + veor d25,d24 + vbsl d29,d18,d19 @ Ch(e,f,g) vshr.u64 d24,d21,#28 - veor d26,d25 @ Sigma1(e) + veor d26,d25 @ Sigma1(e) vadd.i64 d27,d29,d20 vshr.u64 d25,d21,#34 - vsli.64 d24,d21,#36 + vsli.64 d24,d21,#36 vadd.i64 d27,d26 vshr.u64 d26,d21,#39 vadd.i64 d28,d11 - vsli.64 d25,d21,#30 - veor d30,d21,d22 - vsli.64 d26,d21,#25 - veor d20,d24,d25 + vsli.64 d25,d21,#30 + veor d30,d21,d22 + vsli.64 d26,d21,#25 + veor d20,d24,d25 vadd.i64 d27,d28 - vbsl d30,d23,d22 @ Maj(a,b,c) - veor d20,d26 @ Sigma0(a) + vbsl d30,d23,d22 @ Maj(a,b,c) + veor d20,d26 @ Sigma0(a) vadd.i64 d16,d27 vadd.i64 d30,d27 @ vadd.i64 d20,d30 vshr.u64 q12,q5,#19 vshr.u64 q13,q5,#61 - vadd.i64 d20,d30 @ h+=Maj from the past + vadd.i64 d20,d30 @ h+=Maj from the past vshr.u64 q15,q5,#6 - vsli.64 q12,q5,#45 - vext.8 q14,q6,q7,#8 @ X[i+1] - vsli.64 q13,q5,#3 - veor q15,q12 + vsli.64 q12,q5,#45 + vext.8 q14,q6,q7,#8 @ X[i+1] + vsli.64 q13,q5,#3 + veor q15,q12 vshr.u64 q12,q14,#1 - veor q15,q13 @ sigma1(X[i+14]) + veor q15,q13 @ sigma1(X[i+14]) vshr.u64 q13,q14,#8 vadd.i64 q6,q15 vshr.u64 q15,q14,#7 - vsli.64 q12,q14,#63 - vsli.64 q13,q14,#56 - vext.8 q14,q2,q3,#8 @ X[i+9] - veor q15,q12 + vsli.64 q12,q14,#63 + vsli.64 q13,q14,#56 + vext.8 q14,q2,q3,#8 @ X[i+9] + veor q15,q12 vshr.u64 d24,d16,#14 @ from NEON_00_15 vadd.i64 q6,q14 vshr.u64 d25,d16,#18 @ from NEON_00_15 - veor q15,q13 @ sigma0(X[i+1]) + veor q15,q13 @ sigma0(X[i+1]) vshr.u64 d26,d16,#41 @ from NEON_00_15 vadd.i64 q6,q15 - vld1.64 {d28},[r3,:64]! @ K[i++] - vsli.64 d24,d16,#50 - vsli.64 d25,d16,#46 - vmov d29,d16 - vsli.64 d26,d16,#23 + vld1.64 {d28},[r3,:64]! @ K[i++] + vsli.64 d24,d16,#50 + vsli.64 d25,d16,#46 + vmov d29,d16 + vsli.64 d26,d16,#23 #if 28<16 && defined(__ARMEL__) vrev64.8 , #endif - veor d25,d24 - vbsl d29,d17,d18 @ Ch(e,f,g) + veor d25,d24 + vbsl d29,d17,d18 @ Ch(e,f,g) vshr.u64 d24,d20,#28 - veor d26,d25 @ Sigma1(e) + veor d26,d25 @ Sigma1(e) vadd.i64 d27,d29,d19 vshr.u64 d25,d20,#34 - vsli.64 d24,d20,#36 + vsli.64 d24,d20,#36 vadd.i64 d27,d26 vshr.u64 d26,d20,#39 vadd.i64 d28,d12 - vsli.64 d25,d20,#30 - veor d30,d20,d21 - vsli.64 d26,d20,#25 - veor d19,d24,d25 + vsli.64 d25,d20,#30 + veor d30,d20,d21 + vsli.64 d26,d20,#25 + veor d19,d24,d25 vadd.i64 d27,d28 - vbsl d30,d22,d21 @ Maj(a,b,c) - veor d19,d26 @ Sigma0(a) + vbsl d30,d22,d21 @ Maj(a,b,c) + veor d19,d26 @ Sigma0(a) vadd.i64 d23,d27 vadd.i64 d30,d27 @ vadd.i64 d19,d30 vshr.u64 d24,d23,#14 @ 29 #if 29<16 - vld1.64 {d13},[r1]! @ handles unaligned + vld1.64 {d13},[r1]! @ handles unaligned #endif vshr.u64 d25,d23,#18 #if 29>0 - vadd.i64 d19,d30 @ h+=Maj from the past + vadd.i64 d19,d30 @ h+=Maj from the past #endif vshr.u64 d26,d23,#41 - vld1.64 {d28},[r3,:64]! @ K[i++] - vsli.64 d24,d23,#50 - vsli.64 d25,d23,#46 - vmov d29,d23 - vsli.64 d26,d23,#23 + vld1.64 {d28},[r3,:64]! @ K[i++] + vsli.64 d24,d23,#50 + vsli.64 d25,d23,#46 + vmov d29,d23 + vsli.64 d26,d23,#23 #if 29<16 && defined(__ARMEL__) vrev64.8 , #endif - veor d25,d24 - vbsl d29,d16,d17 @ Ch(e,f,g) + veor d25,d24 + vbsl d29,d16,d17 @ Ch(e,f,g) vshr.u64 d24,d19,#28 - veor d26,d25 @ Sigma1(e) + veor d26,d25 @ Sigma1(e) vadd.i64 d27,d29,d18 vshr.u64 d25,d19,#34 - vsli.64 d24,d19,#36 + vsli.64 d24,d19,#36 vadd.i64 d27,d26 vshr.u64 d26,d19,#39 vadd.i64 d28,d13 - vsli.64 d25,d19,#30 - veor d30,d19,d20 - vsli.64 d26,d19,#25 - veor d18,d24,d25 + vsli.64 d25,d19,#30 + veor d30,d19,d20 + vsli.64 d26,d19,#25 + veor d18,d24,d25 vadd.i64 d27,d28 - vbsl d30,d21,d20 @ Maj(a,b,c) - veor d18,d26 @ Sigma0(a) + vbsl d30,d21,d20 @ Maj(a,b,c) + veor d18,d26 @ Sigma0(a) vadd.i64 d22,d27 vadd.i64 d30,d27 @ vadd.i64 d18,d30 vshr.u64 q12,q6,#19 vshr.u64 q13,q6,#61 - vadd.i64 d18,d30 @ h+=Maj from the past + vadd.i64 d18,d30 @ h+=Maj from the past vshr.u64 q15,q6,#6 - vsli.64 q12,q6,#45 - vext.8 q14,q7,q0,#8 @ X[i+1] - vsli.64 q13,q6,#3 - veor q15,q12 + vsli.64 q12,q6,#45 + vext.8 q14,q7,q0,#8 @ X[i+1] + vsli.64 q13,q6,#3 + veor q15,q12 vshr.u64 q12,q14,#1 - veor q15,q13 @ sigma1(X[i+14]) + veor q15,q13 @ sigma1(X[i+14]) vshr.u64 q13,q14,#8 vadd.i64 q7,q15 vshr.u64 q15,q14,#7 - vsli.64 q12,q14,#63 - vsli.64 q13,q14,#56 - vext.8 q14,q3,q4,#8 @ X[i+9] - veor q15,q12 + vsli.64 q12,q14,#63 + vsli.64 q13,q14,#56 + vext.8 q14,q3,q4,#8 @ X[i+9] + veor q15,q12 vshr.u64 d24,d22,#14 @ from NEON_00_15 vadd.i64 q7,q14 vshr.u64 d25,d22,#18 @ from NEON_00_15 - veor q15,q13 @ sigma0(X[i+1]) + veor q15,q13 @ sigma0(X[i+1]) vshr.u64 d26,d22,#41 @ from NEON_00_15 vadd.i64 q7,q15 - vld1.64 {d28},[r3,:64]! @ K[i++] - vsli.64 d24,d22,#50 - vsli.64 d25,d22,#46 - vmov d29,d22 - vsli.64 d26,d22,#23 + vld1.64 {d28},[r3,:64]! @ K[i++] + vsli.64 d24,d22,#50 + vsli.64 d25,d22,#46 + vmov d29,d22 + vsli.64 d26,d22,#23 #if 30<16 && defined(__ARMEL__) vrev64.8 , #endif - veor d25,d24 - vbsl d29,d23,d16 @ Ch(e,f,g) + veor d25,d24 + vbsl d29,d23,d16 @ Ch(e,f,g) vshr.u64 d24,d18,#28 - veor d26,d25 @ Sigma1(e) + veor d26,d25 @ Sigma1(e) vadd.i64 d27,d29,d17 vshr.u64 d25,d18,#34 - vsli.64 d24,d18,#36 + vsli.64 d24,d18,#36 vadd.i64 d27,d26 vshr.u64 d26,d18,#39 vadd.i64 d28,d14 - vsli.64 d25,d18,#30 - veor d30,d18,d19 - vsli.64 d26,d18,#25 - veor d17,d24,d25 + vsli.64 d25,d18,#30 + veor d30,d18,d19 + vsli.64 d26,d18,#25 + veor d17,d24,d25 vadd.i64 d27,d28 - vbsl d30,d20,d19 @ Maj(a,b,c) - veor d17,d26 @ Sigma0(a) + vbsl d30,d20,d19 @ Maj(a,b,c) + veor d17,d26 @ Sigma0(a) vadd.i64 d21,d27 vadd.i64 d30,d27 @ vadd.i64 d17,d30 vshr.u64 d24,d21,#14 @ 31 #if 31<16 - vld1.64 {d15},[r1]! @ handles unaligned + vld1.64 {d15},[r1]! @ handles unaligned #endif vshr.u64 d25,d21,#18 #if 31>0 - vadd.i64 d17,d30 @ h+=Maj from the past + vadd.i64 d17,d30 @ h+=Maj from the past #endif vshr.u64 d26,d21,#41 - vld1.64 {d28},[r3,:64]! @ K[i++] - vsli.64 d24,d21,#50 - vsli.64 d25,d21,#46 - vmov d29,d21 - vsli.64 d26,d21,#23 + vld1.64 {d28},[r3,:64]! @ K[i++] + vsli.64 d24,d21,#50 + vsli.64 d25,d21,#46 + vmov d29,d21 + vsli.64 d26,d21,#23 #if 31<16 && defined(__ARMEL__) vrev64.8 , #endif - veor d25,d24 - vbsl d29,d22,d23 @ Ch(e,f,g) + veor d25,d24 + vbsl d29,d22,d23 @ Ch(e,f,g) vshr.u64 d24,d17,#28 - veor d26,d25 @ Sigma1(e) + veor d26,d25 @ Sigma1(e) vadd.i64 d27,d29,d16 vshr.u64 d25,d17,#34 - vsli.64 d24,d17,#36 + vsli.64 d24,d17,#36 vadd.i64 d27,d26 vshr.u64 d26,d17,#39 vadd.i64 d28,d15 - vsli.64 d25,d17,#30 - veor d30,d17,d18 - vsli.64 d26,d17,#25 - veor d16,d24,d25 + vsli.64 d25,d17,#30 + veor d30,d17,d18 + vsli.64 d26,d17,#25 + veor d16,d24,d25 vadd.i64 d27,d28 - vbsl d30,d19,d18 @ Maj(a,b,c) - veor d16,d26 @ Sigma0(a) + vbsl d30,d19,d18 @ Maj(a,b,c) + veor d16,d26 @ Sigma0(a) vadd.i64 d20,d27 vadd.i64 d30,d27 @ vadd.i64 d16,d30 - bne .L16_79_neon + bne .L16_79_neon - vadd.i64 d16,d30 @ h+=Maj from the past - vldmia r0,{d24-d31} @ load context to temp + vadd.i64 d16,d30 @ h+=Maj from the past + vldmia r0,{d24,d25,d26,d27,d28,d29,d30,d31} @ load context to temp vadd.i64 q8,q12 @ vectorized accumulate vadd.i64 q9,q13 vadd.i64 q10,q14 vadd.i64 q11,q15 - vstmia r0,{d16-d23} @ save context - teq r1,r2 - sub r3,#640 @ rewind K512 - bne .Loop_neon + vstmia r0,{d16,d17,d18,d19,d20,d21,d22,d23} @ save context + teq r1,r2 + sub r3,#640 @ rewind K512 + bne .Loop_neon - vldmia sp!,{d8-d15} @ epilogue + VFP_ABI_POP bx lr @ .word 0xe12fff1e +.size sha512_block_data_order_neon,.-sha512_block_data_order_neon #endif -.size sha512_block_data_order,.-sha512_block_data_order -.asciz "SHA512 block transform for ARMv4/NEON, CRYPTOGAMS by " +.byte 83,72,65,53,49,50,32,98,108,111,99,107,32,116,114,97,110,115,102,111,114,109,32,102,111,114,32,65,82,77,118,52,47,78,69,79,78,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0 .align 2 -#if __ARM_MAX_ARCH__>=7 +.align 2 +#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) .comm OPENSSL_armcap_P,4,4 .hidden OPENSSL_armcap_P #endif +#endif \ No newline at end of file diff --git a/third_party/boringssl/linux-x86/crypto/aes/aesni-x86.S b/third_party/boringssl/linux-x86/crypto/aes/aesni-x86.S index 5aee116e84353..aec110d4b11ee 100644 --- a/third_party/boringssl/linux-x86/crypto/aes/aesni-x86.S +++ b/third_party/boringssl/linux-x86/crypto/aes/aesni-x86.S @@ -23,7 +23,10 @@ aesni_encrypt: leal 16(%edx),%edx jnz .L000enc1_loop_1 .byte 102,15,56,221,209 + pxor %xmm0,%xmm0 + pxor %xmm1,%xmm1 movups %xmm2,(%eax) + pxor %xmm2,%xmm2 ret .size aesni_encrypt,.-.L_aesni_encrypt_begin .globl aesni_decrypt @@ -48,7 +51,10 @@ aesni_decrypt: leal 16(%edx),%edx jnz .L001dec1_loop_2 .byte 102,15,56,223,209 + pxor %xmm0,%xmm0 + pxor %xmm1,%xmm1 movups %xmm2,(%eax) + pxor %xmm2,%xmm2 ret .size aesni_decrypt,.-.L_aesni_decrypt_begin .hidden _aesni_encrypt2 @@ -269,17 +275,15 @@ _aesni_encrypt6: negl %ecx .byte 102,15,56,220,225 pxor %xmm0,%xmm7 + movups (%edx,%ecx,1),%xmm0 addl $16,%ecx -.byte 102,15,56,220,233 -.byte 102,15,56,220,241 -.byte 102,15,56,220,249 - movups -16(%edx,%ecx,1),%xmm0 - jmp .L_aesni_encrypt6_enter + jmp .L008_aesni_encrypt6_inner .align 16 -.L008enc6_loop: +.L009enc6_loop: .byte 102,15,56,220,209 .byte 102,15,56,220,217 .byte 102,15,56,220,225 +.L008_aesni_encrypt6_inner: .byte 102,15,56,220,233 .byte 102,15,56,220,241 .byte 102,15,56,220,249 @@ -293,7 +297,7 @@ _aesni_encrypt6: .byte 102,15,56,220,240 .byte 102,15,56,220,248 movups -16(%edx,%ecx,1),%xmm0 - jnz .L008enc6_loop + jnz .L009enc6_loop .byte 102,15,56,220,209 .byte 102,15,56,220,217 .byte 102,15,56,220,225 @@ -326,17 +330,15 @@ _aesni_decrypt6: negl %ecx .byte 102,15,56,222,225 pxor %xmm0,%xmm7 + movups (%edx,%ecx,1),%xmm0 addl $16,%ecx -.byte 102,15,56,222,233 -.byte 102,15,56,222,241 -.byte 102,15,56,222,249 - movups -16(%edx,%ecx,1),%xmm0 - jmp .L_aesni_decrypt6_enter + jmp .L010_aesni_decrypt6_inner .align 16 -.L009dec6_loop: +.L011dec6_loop: .byte 102,15,56,222,209 .byte 102,15,56,222,217 .byte 102,15,56,222,225 +.L010_aesni_decrypt6_inner: .byte 102,15,56,222,233 .byte 102,15,56,222,241 .byte 102,15,56,222,249 @@ -350,7 +352,7 @@ _aesni_decrypt6: .byte 102,15,56,222,240 .byte 102,15,56,222,248 movups -16(%edx,%ecx,1),%xmm0 - jnz .L009dec6_loop + jnz .L011dec6_loop .byte 102,15,56,222,209 .byte 102,15,56,222,217 .byte 102,15,56,222,225 @@ -381,14 +383,14 @@ aesni_ecb_encrypt: movl 32(%esp),%edx movl 36(%esp),%ebx andl $-16,%eax - jz .L010ecb_ret + jz .L012ecb_ret movl 240(%edx),%ecx testl %ebx,%ebx - jz .L011ecb_decrypt + jz .L013ecb_decrypt movl %edx,%ebp movl %ecx,%ebx cmpl $96,%eax - jb .L012ecb_enc_tail + jb .L014ecb_enc_tail movdqu (%esi),%xmm2 movdqu 16(%esi),%xmm3 movdqu 32(%esi),%xmm4 @@ -397,9 +399,9 @@ aesni_ecb_encrypt: movdqu 80(%esi),%xmm7 leal 96(%esi),%esi subl $96,%eax - jmp .L013ecb_enc_loop6_enter + jmp .L015ecb_enc_loop6_enter .align 16 -.L014ecb_enc_loop6: +.L016ecb_enc_loop6: movups %xmm2,(%edi) movdqu (%esi),%xmm2 movups %xmm3,16(%edi) @@ -414,12 +416,12 @@ aesni_ecb_encrypt: leal 96(%edi),%edi movdqu 80(%esi),%xmm7 leal 96(%esi),%esi -.L013ecb_enc_loop6_enter: +.L015ecb_enc_loop6_enter: call _aesni_encrypt6 movl %ebp,%edx movl %ebx,%ecx subl $96,%eax - jnc .L014ecb_enc_loop6 + jnc .L016ecb_enc_loop6 movups %xmm2,(%edi) movups %xmm3,16(%edi) movups %xmm4,32(%edi) @@ -428,18 +430,18 @@ aesni_ecb_encrypt: movups %xmm7,80(%edi) leal 96(%edi),%edi addl $96,%eax - jz .L010ecb_ret -.L012ecb_enc_tail: + jz .L012ecb_ret +.L014ecb_enc_tail: movups (%esi),%xmm2 cmpl $32,%eax - jb .L015ecb_enc_one + jb .L017ecb_enc_one movups 16(%esi),%xmm3 - je .L016ecb_enc_two + je .L018ecb_enc_two movups 32(%esi),%xmm4 cmpl $64,%eax - jb .L017ecb_enc_three + jb .L019ecb_enc_three movups 48(%esi),%xmm5 - je .L018ecb_enc_four + je .L020ecb_enc_four movups 64(%esi),%xmm6 xorps %xmm7,%xmm7 call _aesni_encrypt6 @@ -448,49 +450,49 @@ aesni_ecb_encrypt: movups %xmm4,32(%edi) movups %xmm5,48(%edi) movups %xmm6,64(%edi) - jmp .L010ecb_ret + jmp .L012ecb_ret .align 16 -.L015ecb_enc_one: +.L017ecb_enc_one: movups (%edx),%xmm0 movups 16(%edx),%xmm1 leal 32(%edx),%edx xorps %xmm0,%xmm2 -.L019enc1_loop_3: +.L021enc1_loop_3: .byte 102,15,56,220,209 decl %ecx movups (%edx),%xmm1 leal 16(%edx),%edx - jnz .L019enc1_loop_3 + jnz .L021enc1_loop_3 .byte 102,15,56,221,209 movups %xmm2,(%edi) - jmp .L010ecb_ret + jmp .L012ecb_ret .align 16 -.L016ecb_enc_two: +.L018ecb_enc_two: call _aesni_encrypt2 movups %xmm2,(%edi) movups %xmm3,16(%edi) - jmp .L010ecb_ret + jmp .L012ecb_ret .align 16 -.L017ecb_enc_three: +.L019ecb_enc_three: call _aesni_encrypt3 movups %xmm2,(%edi) movups %xmm3,16(%edi) movups %xmm4,32(%edi) - jmp .L010ecb_ret + jmp .L012ecb_ret .align 16 -.L018ecb_enc_four: +.L020ecb_enc_four: call _aesni_encrypt4 movups %xmm2,(%edi) movups %xmm3,16(%edi) movups %xmm4,32(%edi) movups %xmm5,48(%edi) - jmp .L010ecb_ret + jmp .L012ecb_ret .align 16 -.L011ecb_decrypt: +.L013ecb_decrypt: movl %edx,%ebp movl %ecx,%ebx cmpl $96,%eax - jb .L020ecb_dec_tail + jb .L022ecb_dec_tail movdqu (%esi),%xmm2 movdqu 16(%esi),%xmm3 movdqu 32(%esi),%xmm4 @@ -499,9 +501,9 @@ aesni_ecb_encrypt: movdqu 80(%esi),%xmm7 leal 96(%esi),%esi subl $96,%eax - jmp .L021ecb_dec_loop6_enter + jmp .L023ecb_dec_loop6_enter .align 16 -.L022ecb_dec_loop6: +.L024ecb_dec_loop6: movups %xmm2,(%edi) movdqu (%esi),%xmm2 movups %xmm3,16(%edi) @@ -516,12 +518,12 @@ aesni_ecb_encrypt: leal 96(%edi),%edi movdqu 80(%esi),%xmm7 leal 96(%esi),%esi -.L021ecb_dec_loop6_enter: +.L023ecb_dec_loop6_enter: call _aesni_decrypt6 movl %ebp,%edx movl %ebx,%ecx subl $96,%eax - jnc .L022ecb_dec_loop6 + jnc .L024ecb_dec_loop6 movups %xmm2,(%edi) movups %xmm3,16(%edi) movups %xmm4,32(%edi) @@ -530,18 +532,18 @@ aesni_ecb_encrypt: movups %xmm7,80(%edi) leal 96(%edi),%edi addl $96,%eax - jz .L010ecb_ret -.L020ecb_dec_tail: + jz .L012ecb_ret +.L022ecb_dec_tail: movups (%esi),%xmm2 cmpl $32,%eax - jb .L023ecb_dec_one + jb .L025ecb_dec_one movups 16(%esi),%xmm3 - je .L024ecb_dec_two + je .L026ecb_dec_two movups 32(%esi),%xmm4 cmpl $64,%eax - jb .L025ecb_dec_three + jb .L027ecb_dec_three movups 48(%esi),%xmm5 - je .L026ecb_dec_four + je .L028ecb_dec_four movups 64(%esi),%xmm6 xorps %xmm7,%xmm7 call _aesni_decrypt6 @@ -550,43 +552,51 @@ aesni_ecb_encrypt: movups %xmm4,32(%edi) movups %xmm5,48(%edi) movups %xmm6,64(%edi) - jmp .L010ecb_ret + jmp .L012ecb_ret .align 16 -.L023ecb_dec_one: +.L025ecb_dec_one: movups (%edx),%xmm0 movups 16(%edx),%xmm1 leal 32(%edx),%edx xorps %xmm0,%xmm2 -.L027dec1_loop_4: +.L029dec1_loop_4: .byte 102,15,56,222,209 decl %ecx movups (%edx),%xmm1 leal 16(%edx),%edx - jnz .L027dec1_loop_4 + jnz .L029dec1_loop_4 .byte 102,15,56,223,209 movups %xmm2,(%edi) - jmp .L010ecb_ret + jmp .L012ecb_ret .align 16 -.L024ecb_dec_two: +.L026ecb_dec_two: call _aesni_decrypt2 movups %xmm2,(%edi) movups %xmm3,16(%edi) - jmp .L010ecb_ret + jmp .L012ecb_ret .align 16 -.L025ecb_dec_three: +.L027ecb_dec_three: call _aesni_decrypt3 movups %xmm2,(%edi) movups %xmm3,16(%edi) movups %xmm4,32(%edi) - jmp .L010ecb_ret + jmp .L012ecb_ret .align 16 -.L026ecb_dec_four: +.L028ecb_dec_four: call _aesni_decrypt4 movups %xmm2,(%edi) movups %xmm3,16(%edi) movups %xmm4,32(%edi) movups %xmm5,48(%edi) -.L010ecb_ret: +.L012ecb_ret: + pxor %xmm0,%xmm0 + pxor %xmm1,%xmm1 + pxor %xmm2,%xmm2 + pxor %xmm3,%xmm3 + pxor %xmm4,%xmm4 + pxor %xmm5,%xmm5 + pxor %xmm6,%xmm6 + pxor %xmm7,%xmm7 popl %edi popl %esi popl %ebx @@ -634,7 +644,7 @@ aesni_ccm64_encrypt_blocks: leal 32(%edx,%ecx,1),%edx subl %ecx,%ebx .byte 102,15,56,0,253 -.L028ccm64_enc_outer: +.L030ccm64_enc_outer: movups (%ebp),%xmm0 movl %ebx,%ecx movups (%esi),%xmm6 @@ -643,7 +653,7 @@ aesni_ccm64_encrypt_blocks: xorps %xmm6,%xmm0 xorps %xmm0,%xmm3 movups 32(%ebp),%xmm0 -.L029ccm64_enc2_loop: +.L031ccm64_enc2_loop: .byte 102,15,56,220,209 .byte 102,15,56,220,217 movups (%edx,%ecx,1),%xmm1 @@ -651,7 +661,7 @@ aesni_ccm64_encrypt_blocks: .byte 102,15,56,220,208 .byte 102,15,56,220,216 movups -16(%edx,%ecx,1),%xmm0 - jnz .L029ccm64_enc2_loop + jnz .L031ccm64_enc2_loop .byte 102,15,56,220,209 .byte 102,15,56,220,217 paddq 16(%esp),%xmm7 @@ -664,10 +674,18 @@ aesni_ccm64_encrypt_blocks: movups %xmm6,(%edi) .byte 102,15,56,0,213 leal 16(%edi),%edi - jnz .L028ccm64_enc_outer + jnz .L030ccm64_enc_outer movl 48(%esp),%esp movl 40(%esp),%edi movups %xmm3,(%edi) + pxor %xmm0,%xmm0 + pxor %xmm1,%xmm1 + pxor %xmm2,%xmm2 + pxor %xmm3,%xmm3 + pxor %xmm4,%xmm4 + pxor %xmm5,%xmm5 + pxor %xmm6,%xmm6 + pxor %xmm7,%xmm7 popl %edi popl %esi popl %ebx @@ -716,12 +734,12 @@ aesni_ccm64_decrypt_blocks: movups 16(%edx),%xmm1 leal 32(%edx),%edx xorps %xmm0,%xmm2 -.L030enc1_loop_5: +.L032enc1_loop_5: .byte 102,15,56,220,209 decl %ecx movups (%edx),%xmm1 leal 16(%edx),%edx - jnz .L030enc1_loop_5 + jnz .L032enc1_loop_5 .byte 102,15,56,221,209 shll $4,%ebx movl $16,%ecx @@ -731,16 +749,16 @@ aesni_ccm64_decrypt_blocks: subl %ebx,%ecx leal 32(%ebp,%ebx,1),%edx movl %ecx,%ebx - jmp .L031ccm64_dec_outer + jmp .L033ccm64_dec_outer .align 16 -.L031ccm64_dec_outer: +.L033ccm64_dec_outer: xorps %xmm2,%xmm6 movdqa %xmm7,%xmm2 movups %xmm6,(%edi) leal 16(%edi),%edi .byte 102,15,56,0,213 subl $1,%eax - jz .L032ccm64_dec_break + jz .L034ccm64_dec_break movups (%ebp),%xmm0 movl %ebx,%ecx movups 16(%ebp),%xmm1 @@ -748,7 +766,7 @@ aesni_ccm64_decrypt_blocks: xorps %xmm0,%xmm2 xorps %xmm6,%xmm3 movups 32(%ebp),%xmm0 -.L033ccm64_dec2_loop: +.L035ccm64_dec2_loop: .byte 102,15,56,220,209 .byte 102,15,56,220,217 movups (%edx,%ecx,1),%xmm1 @@ -756,7 +774,7 @@ aesni_ccm64_decrypt_blocks: .byte 102,15,56,220,208 .byte 102,15,56,220,216 movups -16(%edx,%ecx,1),%xmm0 - jnz .L033ccm64_dec2_loop + jnz .L035ccm64_dec2_loop movups (%esi),%xmm6 paddq 16(%esp),%xmm7 .byte 102,15,56,220,209 @@ -764,9 +782,9 @@ aesni_ccm64_decrypt_blocks: .byte 102,15,56,221,208 .byte 102,15,56,221,216 leal 16(%esi),%esi - jmp .L031ccm64_dec_outer + jmp .L033ccm64_dec_outer .align 16 -.L032ccm64_dec_break: +.L034ccm64_dec_break: movl 240(%ebp),%ecx movl %ebp,%edx movups (%edx),%xmm0 @@ -774,16 +792,24 @@ aesni_ccm64_decrypt_blocks: xorps %xmm0,%xmm6 leal 32(%edx),%edx xorps %xmm6,%xmm3 -.L034enc1_loop_6: +.L036enc1_loop_6: .byte 102,15,56,220,217 decl %ecx movups (%edx),%xmm1 leal 16(%edx),%edx - jnz .L034enc1_loop_6 + jnz .L036enc1_loop_6 .byte 102,15,56,221,217 movl 48(%esp),%esp movl 40(%esp),%edi movups %xmm3,(%edi) + pxor %xmm0,%xmm0 + pxor %xmm1,%xmm1 + pxor %xmm2,%xmm2 + pxor %xmm3,%xmm3 + pxor %xmm4,%xmm4 + pxor %xmm5,%xmm5 + pxor %xmm6,%xmm6 + pxor %xmm7,%xmm7 popl %edi popl %esi popl %ebx @@ -810,7 +836,7 @@ aesni_ctr32_encrypt_blocks: andl $-16,%esp movl %ebp,80(%esp) cmpl $1,%eax - je .L035ctr32_one_shortcut + je .L037ctr32_one_shortcut movdqu (%ebx),%xmm7 movl $202182159,(%esp) movl $134810123,4(%esp) @@ -848,7 +874,7 @@ aesni_ctr32_encrypt_blocks: pshufd $192,%xmm0,%xmm2 pshufd $128,%xmm0,%xmm3 cmpl $6,%eax - jb .L036ctr32_tail + jb .L038ctr32_tail pxor %xmm6,%xmm7 shll $4,%ecx movl $16,%ebx @@ -857,9 +883,9 @@ aesni_ctr32_encrypt_blocks: subl %ecx,%ebx leal 32(%edx,%ecx,1),%edx subl $6,%eax - jmp .L037ctr32_loop6 + jmp .L039ctr32_loop6 .align 16 -.L037ctr32_loop6: +.L039ctr32_loop6: pshufd $64,%xmm0,%xmm4 movdqa 32(%esp),%xmm0 pshufd $192,%xmm1,%xmm5 @@ -913,27 +939,27 @@ aesni_ctr32_encrypt_blocks: leal 96(%edi),%edi pshufd $128,%xmm0,%xmm3 subl $6,%eax - jnc .L037ctr32_loop6 + jnc .L039ctr32_loop6 addl $6,%eax - jz .L038ctr32_ret + jz .L040ctr32_ret movdqu (%ebp),%xmm7 movl %ebp,%edx pxor 32(%esp),%xmm7 movl 240(%ebp),%ecx -.L036ctr32_tail: +.L038ctr32_tail: por %xmm7,%xmm2 cmpl $2,%eax - jb .L039ctr32_one + jb .L041ctr32_one pshufd $64,%xmm0,%xmm4 por %xmm7,%xmm3 - je .L040ctr32_two + je .L042ctr32_two pshufd $192,%xmm1,%xmm5 por %xmm7,%xmm4 cmpl $4,%eax - jb .L041ctr32_three + jb .L043ctr32_three pshufd $128,%xmm1,%xmm6 por %xmm7,%xmm5 - je .L042ctr32_four + je .L044ctr32_four por %xmm7,%xmm6 call _aesni_encrypt6 movups (%esi),%xmm1 @@ -951,29 +977,29 @@ aesni_ctr32_encrypt_blocks: movups %xmm4,32(%edi) movups %xmm5,48(%edi) movups %xmm6,64(%edi) - jmp .L038ctr32_ret + jmp .L040ctr32_ret .align 16 -.L035ctr32_one_shortcut: +.L037ctr32_one_shortcut: movups (%ebx),%xmm2 movl 240(%edx),%ecx -.L039ctr32_one: +.L041ctr32_one: movups (%edx),%xmm0 movups 16(%edx),%xmm1 leal 32(%edx),%edx xorps %xmm0,%xmm2 -.L043enc1_loop_7: +.L045enc1_loop_7: .byte 102,15,56,220,209 decl %ecx movups (%edx),%xmm1 leal 16(%edx),%edx - jnz .L043enc1_loop_7 + jnz .L045enc1_loop_7 .byte 102,15,56,221,209 movups (%esi),%xmm6 xorps %xmm2,%xmm6 movups %xmm6,(%edi) - jmp .L038ctr32_ret + jmp .L040ctr32_ret .align 16 -.L040ctr32_two: +.L042ctr32_two: call _aesni_encrypt2 movups (%esi),%xmm5 movups 16(%esi),%xmm6 @@ -981,9 +1007,9 @@ aesni_ctr32_encrypt_blocks: xorps %xmm6,%xmm3 movups %xmm2,(%edi) movups %xmm3,16(%edi) - jmp .L038ctr32_ret + jmp .L040ctr32_ret .align 16 -.L041ctr32_three: +.L043ctr32_three: call _aesni_encrypt3 movups (%esi),%xmm5 movups 16(%esi),%xmm6 @@ -994,9 +1020,9 @@ aesni_ctr32_encrypt_blocks: xorps %xmm7,%xmm4 movups %xmm3,16(%edi) movups %xmm4,32(%edi) - jmp .L038ctr32_ret + jmp .L040ctr32_ret .align 16 -.L042ctr32_four: +.L044ctr32_four: call _aesni_encrypt4 movups (%esi),%xmm6 movups 16(%esi),%xmm7 @@ -1010,7 +1036,18 @@ aesni_ctr32_encrypt_blocks: xorps %xmm0,%xmm5 movups %xmm4,32(%edi) movups %xmm5,48(%edi) -.L038ctr32_ret: +.L040ctr32_ret: + pxor %xmm0,%xmm0 + pxor %xmm1,%xmm1 + pxor %xmm2,%xmm2 + pxor %xmm3,%xmm3 + pxor %xmm4,%xmm4 + movdqa %xmm0,32(%esp) + pxor %xmm5,%xmm5 + movdqa %xmm0,48(%esp) + pxor %xmm6,%xmm6 + movdqa %xmm0,64(%esp) + pxor %xmm7,%xmm7 movl 80(%esp),%esp popl %edi popl %esi @@ -1036,12 +1073,12 @@ aesni_xts_encrypt: movups 16(%edx),%xmm1 leal 32(%edx),%edx xorps %xmm0,%xmm2 -.L044enc1_loop_8: +.L046enc1_loop_8: .byte 102,15,56,220,209 decl %ecx movups (%edx),%xmm1 leal 16(%edx),%edx - jnz .L044enc1_loop_8 + jnz .L046enc1_loop_8 .byte 102,15,56,221,209 movl 20(%esp),%esi movl 24(%esp),%edi @@ -1065,14 +1102,14 @@ aesni_xts_encrypt: movl %edx,%ebp movl %ecx,%ebx subl $96,%eax - jc .L045xts_enc_short + jc .L047xts_enc_short shll $4,%ecx movl $16,%ebx subl %ecx,%ebx leal 32(%edx,%ecx,1),%edx - jmp .L046xts_enc_loop6 + jmp .L048xts_enc_loop6 .align 16 -.L046xts_enc_loop6: +.L048xts_enc_loop6: pshufd $19,%xmm0,%xmm2 pxor %xmm0,%xmm0 movdqa %xmm1,(%esp) @@ -1161,23 +1198,23 @@ aesni_xts_encrypt: pcmpgtd %xmm1,%xmm0 pxor %xmm2,%xmm1 subl $96,%eax - jnc .L046xts_enc_loop6 + jnc .L048xts_enc_loop6 movl 240(%ebp),%ecx movl %ebp,%edx movl %ecx,%ebx -.L045xts_enc_short: +.L047xts_enc_short: addl $96,%eax - jz .L047xts_enc_done6x + jz .L049xts_enc_done6x movdqa %xmm1,%xmm5 cmpl $32,%eax - jb .L048xts_enc_one + jb .L050xts_enc_one pshufd $19,%xmm0,%xmm2 pxor %xmm0,%xmm0 paddq %xmm1,%xmm1 pand %xmm3,%xmm2 pcmpgtd %xmm1,%xmm0 pxor %xmm2,%xmm1 - je .L049xts_enc_two + je .L051xts_enc_two pshufd $19,%xmm0,%xmm2 pxor %xmm0,%xmm0 movdqa %xmm1,%xmm6 @@ -1186,7 +1223,7 @@ aesni_xts_encrypt: pcmpgtd %xmm1,%xmm0 pxor %xmm2,%xmm1 cmpl $64,%eax - jb .L050xts_enc_three + jb .L052xts_enc_three pshufd $19,%xmm0,%xmm2 pxor %xmm0,%xmm0 movdqa %xmm1,%xmm7 @@ -1196,7 +1233,7 @@ aesni_xts_encrypt: pxor %xmm2,%xmm1 movdqa %xmm5,(%esp) movdqa %xmm6,16(%esp) - je .L051xts_enc_four + je .L053xts_enc_four movdqa %xmm7,32(%esp) pshufd $19,%xmm0,%xmm7 movdqa %xmm1,48(%esp) @@ -1228,9 +1265,9 @@ aesni_xts_encrypt: movups %xmm5,48(%edi) movups %xmm6,64(%edi) leal 80(%edi),%edi - jmp .L052xts_enc_done + jmp .L054xts_enc_done .align 16 -.L048xts_enc_one: +.L050xts_enc_one: movups (%esi),%xmm2 leal 16(%esi),%esi xorps %xmm5,%xmm2 @@ -1238,20 +1275,20 @@ aesni_xts_encrypt: movups 16(%edx),%xmm1 leal 32(%edx),%edx xorps %xmm0,%xmm2 -.L053enc1_loop_9: +.L055enc1_loop_9: .byte 102,15,56,220,209 decl %ecx movups (%edx),%xmm1 leal 16(%edx),%edx - jnz .L053enc1_loop_9 + jnz .L055enc1_loop_9 .byte 102,15,56,221,209 xorps %xmm5,%xmm2 movups %xmm2,(%edi) leal 16(%edi),%edi movdqa %xmm5,%xmm1 - jmp .L052xts_enc_done + jmp .L054xts_enc_done .align 16 -.L049xts_enc_two: +.L051xts_enc_two: movaps %xmm1,%xmm6 movups (%esi),%xmm2 movups 16(%esi),%xmm3 @@ -1265,9 +1302,9 @@ aesni_xts_encrypt: movups %xmm3,16(%edi) leal 32(%edi),%edi movdqa %xmm6,%xmm1 - jmp .L052xts_enc_done + jmp .L054xts_enc_done .align 16 -.L050xts_enc_three: +.L052xts_enc_three: movaps %xmm1,%xmm7 movups (%esi),%xmm2 movups 16(%esi),%xmm3 @@ -1285,9 +1322,9 @@ aesni_xts_encrypt: movups %xmm4,32(%edi) leal 48(%edi),%edi movdqa %xmm7,%xmm1 - jmp .L052xts_enc_done + jmp .L054xts_enc_done .align 16 -.L051xts_enc_four: +.L053xts_enc_four: movaps %xmm1,%xmm6 movups (%esi),%xmm2 movups 16(%esi),%xmm3 @@ -1309,28 +1346,28 @@ aesni_xts_encrypt: movups %xmm5,48(%edi) leal 64(%edi),%edi movdqa %xmm6,%xmm1 - jmp .L052xts_enc_done + jmp .L054xts_enc_done .align 16 -.L047xts_enc_done6x: +.L049xts_enc_done6x: movl 112(%esp),%eax andl $15,%eax - jz .L054xts_enc_ret + jz .L056xts_enc_ret movdqa %xmm1,%xmm5 movl %eax,112(%esp) - jmp .L055xts_enc_steal + jmp .L057xts_enc_steal .align 16 -.L052xts_enc_done: +.L054xts_enc_done: movl 112(%esp),%eax pxor %xmm0,%xmm0 andl $15,%eax - jz .L054xts_enc_ret + jz .L056xts_enc_ret pcmpgtd %xmm1,%xmm0 movl %eax,112(%esp) pshufd $19,%xmm0,%xmm5 paddq %xmm1,%xmm1 pand 96(%esp),%xmm5 pxor %xmm1,%xmm5 -.L055xts_enc_steal: +.L057xts_enc_steal: movzbl (%esi),%ecx movzbl -16(%edi),%edx leal 1(%esi),%esi @@ -1338,7 +1375,7 @@ aesni_xts_encrypt: movb %dl,(%edi) leal 1(%edi),%edi subl $1,%eax - jnz .L055xts_enc_steal + jnz .L057xts_enc_steal subl 112(%esp),%edi movl %ebp,%edx movl %ebx,%ecx @@ -1348,16 +1385,30 @@ aesni_xts_encrypt: movups 16(%edx),%xmm1 leal 32(%edx),%edx xorps %xmm0,%xmm2 -.L056enc1_loop_10: +.L058enc1_loop_10: .byte 102,15,56,220,209 decl %ecx movups (%edx),%xmm1 leal 16(%edx),%edx - jnz .L056enc1_loop_10 + jnz .L058enc1_loop_10 .byte 102,15,56,221,209 xorps %xmm5,%xmm2 movups %xmm2,-16(%edi) -.L054xts_enc_ret: +.L056xts_enc_ret: + pxor %xmm0,%xmm0 + pxor %xmm1,%xmm1 + pxor %xmm2,%xmm2 + movdqa %xmm0,(%esp) + pxor %xmm3,%xmm3 + movdqa %xmm0,16(%esp) + pxor %xmm4,%xmm4 + movdqa %xmm0,32(%esp) + pxor %xmm5,%xmm5 + movdqa %xmm0,48(%esp) + pxor %xmm6,%xmm6 + movdqa %xmm0,64(%esp) + pxor %xmm7,%xmm7 + movdqa %xmm0,80(%esp) movl 116(%esp),%esp popl %edi popl %esi @@ -1383,12 +1434,12 @@ aesni_xts_decrypt: movups 16(%edx),%xmm1 leal 32(%edx),%edx xorps %xmm0,%xmm2 -.L057enc1_loop_11: +.L059enc1_loop_11: .byte 102,15,56,220,209 decl %ecx movups (%edx),%xmm1 leal 16(%edx),%edx - jnz .L057enc1_loop_11 + jnz .L059enc1_loop_11 .byte 102,15,56,221,209 movl 20(%esp),%esi movl 24(%esp),%edi @@ -1417,14 +1468,14 @@ aesni_xts_decrypt: pcmpgtd %xmm1,%xmm0 andl $-16,%eax subl $96,%eax - jc .L058xts_dec_short + jc .L060xts_dec_short shll $4,%ecx movl $16,%ebx subl %ecx,%ebx leal 32(%edx,%ecx,1),%edx - jmp .L059xts_dec_loop6 + jmp .L061xts_dec_loop6 .align 16 -.L059xts_dec_loop6: +.L061xts_dec_loop6: pshufd $19,%xmm0,%xmm2 pxor %xmm0,%xmm0 movdqa %xmm1,(%esp) @@ -1513,23 +1564,23 @@ aesni_xts_decrypt: pcmpgtd %xmm1,%xmm0 pxor %xmm2,%xmm1 subl $96,%eax - jnc .L059xts_dec_loop6 + jnc .L061xts_dec_loop6 movl 240(%ebp),%ecx movl %ebp,%edx movl %ecx,%ebx -.L058xts_dec_short: +.L060xts_dec_short: addl $96,%eax - jz .L060xts_dec_done6x + jz .L062xts_dec_done6x movdqa %xmm1,%xmm5 cmpl $32,%eax - jb .L061xts_dec_one + jb .L063xts_dec_one pshufd $19,%xmm0,%xmm2 pxor %xmm0,%xmm0 paddq %xmm1,%xmm1 pand %xmm3,%xmm2 pcmpgtd %xmm1,%xmm0 pxor %xmm2,%xmm1 - je .L062xts_dec_two + je .L064xts_dec_two pshufd $19,%xmm0,%xmm2 pxor %xmm0,%xmm0 movdqa %xmm1,%xmm6 @@ -1538,7 +1589,7 @@ aesni_xts_decrypt: pcmpgtd %xmm1,%xmm0 pxor %xmm2,%xmm1 cmpl $64,%eax - jb .L063xts_dec_three + jb .L065xts_dec_three pshufd $19,%xmm0,%xmm2 pxor %xmm0,%xmm0 movdqa %xmm1,%xmm7 @@ -1548,7 +1599,7 @@ aesni_xts_decrypt: pxor %xmm2,%xmm1 movdqa %xmm5,(%esp) movdqa %xmm6,16(%esp) - je .L064xts_dec_four + je .L066xts_dec_four movdqa %xmm7,32(%esp) pshufd $19,%xmm0,%xmm7 movdqa %xmm1,48(%esp) @@ -1580,9 +1631,9 @@ aesni_xts_decrypt: movups %xmm5,48(%edi) movups %xmm6,64(%edi) leal 80(%edi),%edi - jmp .L065xts_dec_done + jmp .L067xts_dec_done .align 16 -.L061xts_dec_one: +.L063xts_dec_one: movups (%esi),%xmm2 leal 16(%esi),%esi xorps %xmm5,%xmm2 @@ -1590,20 +1641,20 @@ aesni_xts_decrypt: movups 16(%edx),%xmm1 leal 32(%edx),%edx xorps %xmm0,%xmm2 -.L066dec1_loop_12: +.L068dec1_loop_12: .byte 102,15,56,222,209 decl %ecx movups (%edx),%xmm1 leal 16(%edx),%edx - jnz .L066dec1_loop_12 + jnz .L068dec1_loop_12 .byte 102,15,56,223,209 xorps %xmm5,%xmm2 movups %xmm2,(%edi) leal 16(%edi),%edi movdqa %xmm5,%xmm1 - jmp .L065xts_dec_done + jmp .L067xts_dec_done .align 16 -.L062xts_dec_two: +.L064xts_dec_two: movaps %xmm1,%xmm6 movups (%esi),%xmm2 movups 16(%esi),%xmm3 @@ -1617,9 +1668,9 @@ aesni_xts_decrypt: movups %xmm3,16(%edi) leal 32(%edi),%edi movdqa %xmm6,%xmm1 - jmp .L065xts_dec_done + jmp .L067xts_dec_done .align 16 -.L063xts_dec_three: +.L065xts_dec_three: movaps %xmm1,%xmm7 movups (%esi),%xmm2 movups 16(%esi),%xmm3 @@ -1637,9 +1688,9 @@ aesni_xts_decrypt: movups %xmm4,32(%edi) leal 48(%edi),%edi movdqa %xmm7,%xmm1 - jmp .L065xts_dec_done + jmp .L067xts_dec_done .align 16 -.L064xts_dec_four: +.L066xts_dec_four: movaps %xmm1,%xmm6 movups (%esi),%xmm2 movups 16(%esi),%xmm3 @@ -1661,20 +1712,20 @@ aesni_xts_decrypt: movups %xmm5,48(%edi) leal 64(%edi),%edi movdqa %xmm6,%xmm1 - jmp .L065xts_dec_done + jmp .L067xts_dec_done .align 16 -.L060xts_dec_done6x: +.L062xts_dec_done6x: movl 112(%esp),%eax andl $15,%eax - jz .L067xts_dec_ret + jz .L069xts_dec_ret movl %eax,112(%esp) - jmp .L068xts_dec_only_one_more + jmp .L070xts_dec_only_one_more .align 16 -.L065xts_dec_done: +.L067xts_dec_done: movl 112(%esp),%eax pxor %xmm0,%xmm0 andl $15,%eax - jz .L067xts_dec_ret + jz .L069xts_dec_ret pcmpgtd %xmm1,%xmm0 movl %eax,112(%esp) pshufd $19,%xmm0,%xmm2 @@ -1684,7 +1735,7 @@ aesni_xts_decrypt: pand %xmm3,%xmm2 pcmpgtd %xmm1,%xmm0 pxor %xmm2,%xmm1 -.L068xts_dec_only_one_more: +.L070xts_dec_only_one_more: pshufd $19,%xmm0,%xmm5 movdqa %xmm1,%xmm6 paddq %xmm1,%xmm1 @@ -1698,16 +1749,16 @@ aesni_xts_decrypt: movups 16(%edx),%xmm1 leal 32(%edx),%edx xorps %xmm0,%xmm2 -.L069dec1_loop_13: +.L071dec1_loop_13: .byte 102,15,56,222,209 decl %ecx movups (%edx),%xmm1 leal 16(%edx),%edx - jnz .L069dec1_loop_13 + jnz .L071dec1_loop_13 .byte 102,15,56,223,209 xorps %xmm5,%xmm2 movups %xmm2,(%edi) -.L070xts_dec_steal: +.L072xts_dec_steal: movzbl 16(%esi),%ecx movzbl (%edi),%edx leal 1(%esi),%esi @@ -1715,7 +1766,7 @@ aesni_xts_decrypt: movb %dl,16(%edi) leal 1(%edi),%edi subl $1,%eax - jnz .L070xts_dec_steal + jnz .L072xts_dec_steal subl 112(%esp),%edi movl %ebp,%edx movl %ebx,%ecx @@ -1725,16 +1776,30 @@ aesni_xts_decrypt: movups 16(%edx),%xmm1 leal 32(%edx),%edx xorps %xmm0,%xmm2 -.L071dec1_loop_14: +.L073dec1_loop_14: .byte 102,15,56,222,209 decl %ecx movups (%edx),%xmm1 leal 16(%edx),%edx - jnz .L071dec1_loop_14 + jnz .L073dec1_loop_14 .byte 102,15,56,223,209 xorps %xmm6,%xmm2 movups %xmm2,(%edi) -.L067xts_dec_ret: +.L069xts_dec_ret: + pxor %xmm0,%xmm0 + pxor %xmm1,%xmm1 + pxor %xmm2,%xmm2 + movdqa %xmm0,(%esp) + pxor %xmm3,%xmm3 + movdqa %xmm0,16(%esp) + pxor %xmm4,%xmm4 + movdqa %xmm0,32(%esp) + pxor %xmm5,%xmm5 + movdqa %xmm0,48(%esp) + pxor %xmm6,%xmm6 + movdqa %xmm0,64(%esp) + pxor %xmm7,%xmm7 + movdqa %xmm0,80(%esp) movl 116(%esp),%esp popl %edi popl %esi @@ -1761,7 +1826,7 @@ aesni_cbc_encrypt: movl 32(%esp),%edx movl 36(%esp),%ebp testl %eax,%eax - jz .L072cbc_abort + jz .L074cbc_abort cmpl $0,40(%esp) xchgl %esp,%ebx movups (%ebp),%xmm7 @@ -1769,14 +1834,14 @@ aesni_cbc_encrypt: movl %edx,%ebp movl %ebx,16(%esp) movl %ecx,%ebx - je .L073cbc_decrypt + je .L075cbc_decrypt movaps %xmm7,%xmm2 cmpl $16,%eax - jb .L074cbc_enc_tail + jb .L076cbc_enc_tail subl $16,%eax - jmp .L075cbc_enc_loop + jmp .L077cbc_enc_loop .align 16 -.L075cbc_enc_loop: +.L077cbc_enc_loop: movups (%esi),%xmm7 leal 16(%esi),%esi movups (%edx),%xmm0 @@ -1784,24 +1849,25 @@ aesni_cbc_encrypt: xorps %xmm0,%xmm7 leal 32(%edx),%edx xorps %xmm7,%xmm2 -.L076enc1_loop_15: +.L078enc1_loop_15: .byte 102,15,56,220,209 decl %ecx movups (%edx),%xmm1 leal 16(%edx),%edx - jnz .L076enc1_loop_15 + jnz .L078enc1_loop_15 .byte 102,15,56,221,209 movl %ebx,%ecx movl %ebp,%edx movups %xmm2,(%edi) leal 16(%edi),%edi subl $16,%eax - jnc .L075cbc_enc_loop + jnc .L077cbc_enc_loop addl $16,%eax - jnz .L074cbc_enc_tail + jnz .L076cbc_enc_tail movaps %xmm2,%xmm7 - jmp .L077cbc_ret -.L074cbc_enc_tail: + pxor %xmm2,%xmm2 + jmp .L079cbc_ret +.L076cbc_enc_tail: movl %eax,%ecx .long 2767451785 movl $16,%ecx @@ -1812,20 +1878,20 @@ aesni_cbc_encrypt: movl %ebx,%ecx movl %edi,%esi movl %ebp,%edx - jmp .L075cbc_enc_loop + jmp .L077cbc_enc_loop .align 16 -.L073cbc_decrypt: +.L075cbc_decrypt: cmpl $80,%eax - jbe .L078cbc_dec_tail + jbe .L080cbc_dec_tail movaps %xmm7,(%esp) subl $80,%eax - jmp .L079cbc_dec_loop6_enter + jmp .L081cbc_dec_loop6_enter .align 16 -.L080cbc_dec_loop6: +.L082cbc_dec_loop6: movaps %xmm0,(%esp) movups %xmm7,(%edi) leal 16(%edi),%edi -.L079cbc_dec_loop6_enter: +.L081cbc_dec_loop6_enter: movdqu (%esi),%xmm2 movdqu 16(%esi),%xmm3 movdqu 32(%esi),%xmm4 @@ -1855,28 +1921,28 @@ aesni_cbc_encrypt: movups %xmm6,64(%edi) leal 80(%edi),%edi subl $96,%eax - ja .L080cbc_dec_loop6 + ja .L082cbc_dec_loop6 movaps %xmm7,%xmm2 movaps %xmm0,%xmm7 addl $80,%eax - jle .L081cbc_dec_tail_collected + jle .L083cbc_dec_clear_tail_collected movups %xmm2,(%edi) leal 16(%edi),%edi -.L078cbc_dec_tail: +.L080cbc_dec_tail: movups (%esi),%xmm2 movaps %xmm2,%xmm6 cmpl $16,%eax - jbe .L082cbc_dec_one + jbe .L084cbc_dec_one movups 16(%esi),%xmm3 movaps %xmm3,%xmm5 cmpl $32,%eax - jbe .L083cbc_dec_two + jbe .L085cbc_dec_two movups 32(%esi),%xmm4 cmpl $48,%eax - jbe .L084cbc_dec_three + jbe .L086cbc_dec_three movups 48(%esi),%xmm5 cmpl $64,%eax - jbe .L085cbc_dec_four + jbe .L087cbc_dec_four movups 64(%esi),%xmm6 movaps %xmm7,(%esp) movups (%esi),%xmm2 @@ -1894,55 +1960,62 @@ aesni_cbc_encrypt: xorps %xmm0,%xmm6 movups %xmm2,(%edi) movups %xmm3,16(%edi) + pxor %xmm3,%xmm3 movups %xmm4,32(%edi) + pxor %xmm4,%xmm4 movups %xmm5,48(%edi) + pxor %xmm5,%xmm5 leal 64(%edi),%edi movaps %xmm6,%xmm2 + pxor %xmm6,%xmm6 subl $80,%eax - jmp .L081cbc_dec_tail_collected + jmp .L088cbc_dec_tail_collected .align 16 -.L082cbc_dec_one: +.L084cbc_dec_one: movups (%edx),%xmm0 movups 16(%edx),%xmm1 leal 32(%edx),%edx xorps %xmm0,%xmm2 -.L086dec1_loop_16: +.L089dec1_loop_16: .byte 102,15,56,222,209 decl %ecx movups (%edx),%xmm1 leal 16(%edx),%edx - jnz .L086dec1_loop_16 + jnz .L089dec1_loop_16 .byte 102,15,56,223,209 xorps %xmm7,%xmm2 movaps %xmm6,%xmm7 subl $16,%eax - jmp .L081cbc_dec_tail_collected + jmp .L088cbc_dec_tail_collected .align 16 -.L083cbc_dec_two: +.L085cbc_dec_two: call _aesni_decrypt2 xorps %xmm7,%xmm2 xorps %xmm6,%xmm3 movups %xmm2,(%edi) movaps %xmm3,%xmm2 + pxor %xmm3,%xmm3 leal 16(%edi),%edi movaps %xmm5,%xmm7 subl $32,%eax - jmp .L081cbc_dec_tail_collected + jmp .L088cbc_dec_tail_collected .align 16 -.L084cbc_dec_three: +.L086cbc_dec_three: call _aesni_decrypt3 xorps %xmm7,%xmm2 xorps %xmm6,%xmm3 xorps %xmm5,%xmm4 movups %xmm2,(%edi) movaps %xmm4,%xmm2 + pxor %xmm4,%xmm4 movups %xmm3,16(%edi) + pxor %xmm3,%xmm3 leal 32(%edi),%edi movups 32(%esi),%xmm7 subl $48,%eax - jmp .L081cbc_dec_tail_collected + jmp .L088cbc_dec_tail_collected .align 16 -.L085cbc_dec_four: +.L087cbc_dec_four: call _aesni_decrypt4 movups 16(%esi),%xmm1 movups 32(%esi),%xmm0 @@ -1952,28 +2025,44 @@ aesni_cbc_encrypt: movups %xmm2,(%edi) xorps %xmm1,%xmm4 movups %xmm3,16(%edi) + pxor %xmm3,%xmm3 xorps %xmm0,%xmm5 movups %xmm4,32(%edi) + pxor %xmm4,%xmm4 leal 48(%edi),%edi movaps %xmm5,%xmm2 + pxor %xmm5,%xmm5 subl $64,%eax -.L081cbc_dec_tail_collected: + jmp .L088cbc_dec_tail_collected +.align 16 +.L083cbc_dec_clear_tail_collected: + pxor %xmm3,%xmm3 + pxor %xmm4,%xmm4 + pxor %xmm5,%xmm5 + pxor %xmm6,%xmm6 +.L088cbc_dec_tail_collected: andl $15,%eax - jnz .L087cbc_dec_tail_partial + jnz .L090cbc_dec_tail_partial movups %xmm2,(%edi) - jmp .L077cbc_ret + pxor %xmm0,%xmm0 + jmp .L079cbc_ret .align 16 -.L087cbc_dec_tail_partial: +.L090cbc_dec_tail_partial: movaps %xmm2,(%esp) + pxor %xmm0,%xmm0 movl $16,%ecx movl %esp,%esi subl %eax,%ecx .long 2767451785 -.L077cbc_ret: + movdqa %xmm2,(%esp) +.L079cbc_ret: movl 16(%esp),%esp movl 36(%esp),%ebp + pxor %xmm2,%xmm2 + pxor %xmm1,%xmm1 movups %xmm7,(%ebp) -.L072cbc_abort: + pxor %xmm7,%xmm7 +.L074cbc_abort: popl %edi popl %esi popl %ebx @@ -1984,52 +2073,62 @@ aesni_cbc_encrypt: .type _aesni_set_encrypt_key,@function .align 16 _aesni_set_encrypt_key: + pushl %ebp + pushl %ebx testl %eax,%eax - jz .L088bad_pointer + jz .L091bad_pointer testl %edx,%edx - jz .L088bad_pointer + jz .L091bad_pointer + call .L092pic +.L092pic: + popl %ebx + leal .Lkey_const-.L092pic(%ebx),%ebx + leal OPENSSL_ia32cap_P-.Lkey_const(%ebx),%ebp movups (%eax),%xmm0 xorps %xmm4,%xmm4 + movl 4(%ebp),%ebp leal 16(%edx),%edx + andl $268437504,%ebp cmpl $256,%ecx - je .L08914rounds + je .L09314rounds cmpl $192,%ecx - je .L09012rounds + je .L09412rounds cmpl $128,%ecx - jne .L091bad_keybits + jne .L095bad_keybits .align 16 -.L09210rounds: +.L09610rounds: + cmpl $268435456,%ebp + je .L09710rounds_alt movl $9,%ecx movups %xmm0,-16(%edx) .byte 102,15,58,223,200,1 - call .L093key_128_cold + call .L098key_128_cold .byte 102,15,58,223,200,2 - call .L094key_128 + call .L099key_128 .byte 102,15,58,223,200,4 - call .L094key_128 + call .L099key_128 .byte 102,15,58,223,200,8 - call .L094key_128 + call .L099key_128 .byte 102,15,58,223,200,16 - call .L094key_128 + call .L099key_128 .byte 102,15,58,223,200,32 - call .L094key_128 + call .L099key_128 .byte 102,15,58,223,200,64 - call .L094key_128 + call .L099key_128 .byte 102,15,58,223,200,128 - call .L094key_128 + call .L099key_128 .byte 102,15,58,223,200,27 - call .L094key_128 + call .L099key_128 .byte 102,15,58,223,200,54 - call .L094key_128 + call .L099key_128 movups %xmm0,(%edx) movl %ecx,80(%edx) - xorl %eax,%eax - ret + jmp .L100good_key .align 16 -.L094key_128: +.L099key_128: movups %xmm0,(%edx) leal 16(%edx),%edx -.L093key_128_cold: +.L098key_128_cold: shufps $16,%xmm0,%xmm4 xorps %xmm4,%xmm0 shufps $140,%xmm0,%xmm4 @@ -2038,38 +2137,91 @@ _aesni_set_encrypt_key: xorps %xmm1,%xmm0 ret .align 16 -.L09012rounds: +.L09710rounds_alt: + movdqa (%ebx),%xmm5 + movl $8,%ecx + movdqa 32(%ebx),%xmm4 + movdqa %xmm0,%xmm2 + movdqu %xmm0,-16(%edx) +.L101loop_key128: +.byte 102,15,56,0,197 +.byte 102,15,56,221,196 + pslld $1,%xmm4 + leal 16(%edx),%edx + movdqa %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm3,%xmm2 + pxor %xmm2,%xmm0 + movdqu %xmm0,-16(%edx) + movdqa %xmm0,%xmm2 + decl %ecx + jnz .L101loop_key128 + movdqa 48(%ebx),%xmm4 +.byte 102,15,56,0,197 +.byte 102,15,56,221,196 + pslld $1,%xmm4 + movdqa %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm3,%xmm2 + pxor %xmm2,%xmm0 + movdqu %xmm0,(%edx) + movdqa %xmm0,%xmm2 +.byte 102,15,56,0,197 +.byte 102,15,56,221,196 + movdqa %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm3,%xmm2 + pxor %xmm2,%xmm0 + movdqu %xmm0,16(%edx) + movl $9,%ecx + movl %ecx,96(%edx) + jmp .L100good_key +.align 16 +.L09412rounds: movq 16(%eax),%xmm2 + cmpl $268435456,%ebp + je .L10212rounds_alt movl $11,%ecx movups %xmm0,-16(%edx) .byte 102,15,58,223,202,1 - call .L095key_192a_cold + call .L103key_192a_cold .byte 102,15,58,223,202,2 - call .L096key_192b + call .L104key_192b .byte 102,15,58,223,202,4 - call .L097key_192a + call .L105key_192a .byte 102,15,58,223,202,8 - call .L096key_192b + call .L104key_192b .byte 102,15,58,223,202,16 - call .L097key_192a + call .L105key_192a .byte 102,15,58,223,202,32 - call .L096key_192b + call .L104key_192b .byte 102,15,58,223,202,64 - call .L097key_192a + call .L105key_192a .byte 102,15,58,223,202,128 - call .L096key_192b + call .L104key_192b movups %xmm0,(%edx) movl %ecx,48(%edx) - xorl %eax,%eax - ret + jmp .L100good_key .align 16 -.L097key_192a: +.L105key_192a: movups %xmm0,(%edx) leal 16(%edx),%edx .align 16 -.L095key_192a_cold: +.L103key_192a_cold: movaps %xmm2,%xmm5 -.L098key_192b_warm: +.L106key_192b_warm: shufps $16,%xmm0,%xmm4 movdqa %xmm2,%xmm3 xorps %xmm4,%xmm0 @@ -2083,56 +2235,90 @@ _aesni_set_encrypt_key: pxor %xmm3,%xmm2 ret .align 16 -.L096key_192b: +.L104key_192b: movaps %xmm0,%xmm3 shufps $68,%xmm0,%xmm5 movups %xmm5,(%edx) shufps $78,%xmm2,%xmm3 movups %xmm3,16(%edx) leal 32(%edx),%edx - jmp .L098key_192b_warm + jmp .L106key_192b_warm +.align 16 +.L10212rounds_alt: + movdqa 16(%ebx),%xmm5 + movdqa 32(%ebx),%xmm4 + movl $8,%ecx + movdqu %xmm0,-16(%edx) +.L107loop_key192: + movq %xmm2,(%edx) + movdqa %xmm2,%xmm1 +.byte 102,15,56,0,213 +.byte 102,15,56,221,212 + pslld $1,%xmm4 + leal 24(%edx),%edx + movdqa %xmm0,%xmm3 + pslldq $4,%xmm0 + pxor %xmm0,%xmm3 + pslldq $4,%xmm0 + pxor %xmm0,%xmm3 + pslldq $4,%xmm0 + pxor %xmm3,%xmm0 + pshufd $255,%xmm0,%xmm3 + pxor %xmm1,%xmm3 + pslldq $4,%xmm1 + pxor %xmm1,%xmm3 + pxor %xmm2,%xmm0 + pxor %xmm3,%xmm2 + movdqu %xmm0,-16(%edx) + decl %ecx + jnz .L107loop_key192 + movl $11,%ecx + movl %ecx,32(%edx) + jmp .L100good_key .align 16 -.L08914rounds: +.L09314rounds: movups 16(%eax),%xmm2 - movl $13,%ecx leal 16(%edx),%edx + cmpl $268435456,%ebp + je .L10814rounds_alt + movl $13,%ecx movups %xmm0,-32(%edx) movups %xmm2,-16(%edx) .byte 102,15,58,223,202,1 - call .L099key_256a_cold + call .L109key_256a_cold .byte 102,15,58,223,200,1 - call .L100key_256b + call .L110key_256b .byte 102,15,58,223,202,2 - call .L101key_256a + call .L111key_256a .byte 102,15,58,223,200,2 - call .L100key_256b + call .L110key_256b .byte 102,15,58,223,202,4 - call .L101key_256a + call .L111key_256a .byte 102,15,58,223,200,4 - call .L100key_256b + call .L110key_256b .byte 102,15,58,223,202,8 - call .L101key_256a + call .L111key_256a .byte 102,15,58,223,200,8 - call .L100key_256b + call .L110key_256b .byte 102,15,58,223,202,16 - call .L101key_256a + call .L111key_256a .byte 102,15,58,223,200,16 - call .L100key_256b + call .L110key_256b .byte 102,15,58,223,202,32 - call .L101key_256a + call .L111key_256a .byte 102,15,58,223,200,32 - call .L100key_256b + call .L110key_256b .byte 102,15,58,223,202,64 - call .L101key_256a + call .L111key_256a movups %xmm0,(%edx) movl %ecx,16(%edx) xorl %eax,%eax - ret + jmp .L100good_key .align 16 -.L101key_256a: +.L111key_256a: movups %xmm2,(%edx) leal 16(%edx),%edx -.L099key_256a_cold: +.L109key_256a_cold: shufps $16,%xmm0,%xmm4 xorps %xmm4,%xmm0 shufps $140,%xmm0,%xmm4 @@ -2141,7 +2327,7 @@ _aesni_set_encrypt_key: xorps %xmm1,%xmm0 ret .align 16 -.L100key_256b: +.L110key_256b: movups %xmm0,(%edx) leal 16(%edx),%edx shufps $16,%xmm2,%xmm4 @@ -2151,13 +2337,70 @@ _aesni_set_encrypt_key: shufps $170,%xmm1,%xmm1 xorps %xmm1,%xmm2 ret +.align 16 +.L10814rounds_alt: + movdqa (%ebx),%xmm5 + movdqa 32(%ebx),%xmm4 + movl $7,%ecx + movdqu %xmm0,-32(%edx) + movdqa %xmm2,%xmm1 + movdqu %xmm2,-16(%edx) +.L112loop_key256: +.byte 102,15,56,0,213 +.byte 102,15,56,221,212 + movdqa %xmm0,%xmm3 + pslldq $4,%xmm0 + pxor %xmm0,%xmm3 + pslldq $4,%xmm0 + pxor %xmm0,%xmm3 + pslldq $4,%xmm0 + pxor %xmm3,%xmm0 + pslld $1,%xmm4 + pxor %xmm2,%xmm0 + movdqu %xmm0,(%edx) + decl %ecx + jz .L113done_key256 + pshufd $255,%xmm0,%xmm2 + pxor %xmm3,%xmm3 +.byte 102,15,56,221,211 + movdqa %xmm1,%xmm3 + pslldq $4,%xmm1 + pxor %xmm1,%xmm3 + pslldq $4,%xmm1 + pxor %xmm1,%xmm3 + pslldq $4,%xmm1 + pxor %xmm3,%xmm1 + pxor %xmm1,%xmm2 + movdqu %xmm2,16(%edx) + leal 32(%edx),%edx + movdqa %xmm2,%xmm1 + jmp .L112loop_key256 +.L113done_key256: + movl $13,%ecx + movl %ecx,16(%edx) +.L100good_key: + pxor %xmm0,%xmm0 + pxor %xmm1,%xmm1 + pxor %xmm2,%xmm2 + pxor %xmm3,%xmm3 + pxor %xmm4,%xmm4 + pxor %xmm5,%xmm5 + xorl %eax,%eax + popl %ebx + popl %ebp + ret .align 4 -.L088bad_pointer: +.L091bad_pointer: movl $-1,%eax + popl %ebx + popl %ebp ret .align 4 -.L091bad_keybits: +.L095bad_keybits: + pxor %xmm0,%xmm0 movl $-2,%eax + popl %ebx + popl %ebp ret .size _aesni_set_encrypt_key,.-_aesni_set_encrypt_key .globl aesni_set_encrypt_key @@ -2185,7 +2428,7 @@ aesni_set_decrypt_key: movl 12(%esp),%edx shll $4,%ecx testl %eax,%eax - jnz .L102dec_key_ret + jnz .L114dec_key_ret leal 16(%edx,%ecx,1),%eax movups (%edx),%xmm0 movups (%eax),%xmm1 @@ -2193,7 +2436,7 @@ aesni_set_decrypt_key: movups %xmm1,(%edx) leal 16(%edx),%edx leal -16(%eax),%eax -.L103dec_key_inverse: +.L115dec_key_inverse: movups (%edx),%xmm0 movups (%eax),%xmm1 .byte 102,15,56,219,192 @@ -2203,14 +2446,22 @@ aesni_set_decrypt_key: movups %xmm0,16(%eax) movups %xmm1,-16(%edx) cmpl %edx,%eax - ja .L103dec_key_inverse + ja .L115dec_key_inverse movups (%edx),%xmm0 .byte 102,15,56,219,192 movups %xmm0,(%edx) + pxor %xmm0,%xmm0 + pxor %xmm1,%xmm1 xorl %eax,%eax -.L102dec_key_ret: +.L114dec_key_ret: ret .size aesni_set_decrypt_key,.-.L_aesni_set_decrypt_key_begin +.align 64 +.Lkey_const: +.long 202313229,202313229,202313229,202313229 +.long 67569157,67569157,67569157,67569157 +.long 1,1,1,1 +.long 27,27,27,27 .byte 65,69,83,32,102,111,114,32,73,110,116,101,108,32,65,69 .byte 83,45,78,73,44,32,67,82,89,80,84,79,71,65,77,83 .byte 32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115 diff --git a/third_party/boringssl/linux-x86/crypto/bn/bn-586.S b/third_party/boringssl/linux-x86/crypto/bn/bn-586.S index b9533934bef00..773beff9c11f2 100644 --- a/third_party/boringssl/linux-x86/crypto/bn/bn-586.S +++ b/third_party/boringssl/linux-x86/crypto/bn/bn-586.S @@ -7,6 +7,102 @@ .align 16 bn_mul_add_words: .L_bn_mul_add_words_begin: + call .L000PIC_me_up +.L000PIC_me_up: + popl %eax + leal OPENSSL_ia32cap_P-.L000PIC_me_up(%eax),%eax + btl $26,(%eax) + jnc .L001maw_non_sse2 + movl 4(%esp),%eax + movl 8(%esp),%edx + movl 12(%esp),%ecx + movd 16(%esp),%mm0 + pxor %mm1,%mm1 + jmp .L002maw_sse2_entry +.align 16 +.L003maw_sse2_unrolled: + movd (%eax),%mm3 + paddq %mm3,%mm1 + movd (%edx),%mm2 + pmuludq %mm0,%mm2 + movd 4(%edx),%mm4 + pmuludq %mm0,%mm4 + movd 8(%edx),%mm6 + pmuludq %mm0,%mm6 + movd 12(%edx),%mm7 + pmuludq %mm0,%mm7 + paddq %mm2,%mm1 + movd 4(%eax),%mm3 + paddq %mm4,%mm3 + movd 8(%eax),%mm5 + paddq %mm6,%mm5 + movd 12(%eax),%mm4 + paddq %mm4,%mm7 + movd %mm1,(%eax) + movd 16(%edx),%mm2 + pmuludq %mm0,%mm2 + psrlq $32,%mm1 + movd 20(%edx),%mm4 + pmuludq %mm0,%mm4 + paddq %mm3,%mm1 + movd 24(%edx),%mm6 + pmuludq %mm0,%mm6 + movd %mm1,4(%eax) + psrlq $32,%mm1 + movd 28(%edx),%mm3 + addl $32,%edx + pmuludq %mm0,%mm3 + paddq %mm5,%mm1 + movd 16(%eax),%mm5 + paddq %mm5,%mm2 + movd %mm1,8(%eax) + psrlq $32,%mm1 + paddq %mm7,%mm1 + movd 20(%eax),%mm5 + paddq %mm5,%mm4 + movd %mm1,12(%eax) + psrlq $32,%mm1 + paddq %mm2,%mm1 + movd 24(%eax),%mm5 + paddq %mm5,%mm6 + movd %mm1,16(%eax) + psrlq $32,%mm1 + paddq %mm4,%mm1 + movd 28(%eax),%mm5 + paddq %mm5,%mm3 + movd %mm1,20(%eax) + psrlq $32,%mm1 + paddq %mm6,%mm1 + movd %mm1,24(%eax) + psrlq $32,%mm1 + paddq %mm3,%mm1 + movd %mm1,28(%eax) + leal 32(%eax),%eax + psrlq $32,%mm1 + subl $8,%ecx + jz .L004maw_sse2_exit +.L002maw_sse2_entry: + testl $4294967288,%ecx + jnz .L003maw_sse2_unrolled +.align 4 +.L005maw_sse2_loop: + movd (%edx),%mm2 + movd (%eax),%mm3 + pmuludq %mm0,%mm2 + leal 4(%edx),%edx + paddq %mm3,%mm1 + paddq %mm2,%mm1 + movd %mm1,(%eax) + subl $1,%ecx + psrlq $32,%mm1 + leal 4(%eax),%eax + jnz .L005maw_sse2_loop +.L004maw_sse2_exit: + movd %mm1,%eax + emms + ret +.align 16 +.L001maw_non_sse2: pushl %ebp pushl %ebx pushl %esi @@ -19,9 +115,9 @@ bn_mul_add_words: andl $4294967288,%ecx movl 32(%esp),%ebp pushl %ecx - jz .L000maw_finish + jz .L006maw_finish .align 16 -.L001maw_loop: +.L007maw_loop: movl (%ebx),%eax mull %ebp @@ -98,13 +194,13 @@ bn_mul_add_words: subl $8,%ecx leal 32(%ebx),%ebx leal 32(%edi),%edi - jnz .L001maw_loop -.L000maw_finish: + jnz .L007maw_loop +.L006maw_finish: movl 32(%esp),%ecx andl $7,%ecx - jnz .L002maw_finish2 - jmp .L003maw_end -.L002maw_finish2: + jnz .L008maw_finish2 + jmp .L009maw_end +.L008maw_finish2: movl (%ebx),%eax mull %ebp @@ -115,7 +211,7 @@ bn_mul_add_words: decl %ecx movl %eax,(%edi) movl %edx,%esi - jz .L003maw_end + jz .L009maw_end movl 4(%ebx),%eax mull %ebp @@ -126,7 +222,7 @@ bn_mul_add_words: decl %ecx movl %eax,4(%edi) movl %edx,%esi - jz .L003maw_end + jz .L009maw_end movl 8(%ebx),%eax mull %ebp @@ -137,7 +233,7 @@ bn_mul_add_words: decl %ecx movl %eax,8(%edi) movl %edx,%esi - jz .L003maw_end + jz .L009maw_end movl 12(%ebx),%eax mull %ebp @@ -148,7 +244,7 @@ bn_mul_add_words: decl %ecx movl %eax,12(%edi) movl %edx,%esi - jz .L003maw_end + jz .L009maw_end movl 16(%ebx),%eax mull %ebp @@ -159,7 +255,7 @@ bn_mul_add_words: decl %ecx movl %eax,16(%edi) movl %edx,%esi - jz .L003maw_end + jz .L009maw_end movl 20(%ebx),%eax mull %ebp @@ -170,7 +266,7 @@ bn_mul_add_words: decl %ecx movl %eax,20(%edi) movl %edx,%esi - jz .L003maw_end + jz .L009maw_end movl 24(%ebx),%eax mull %ebp @@ -180,7 +276,7 @@ bn_mul_add_words: adcl $0,%edx movl %eax,24(%edi) movl %edx,%esi -.L003maw_end: +.L009maw_end: movl %esi,%eax popl %ecx popl %edi @@ -195,6 +291,33 @@ bn_mul_add_words: .align 16 bn_mul_words: .L_bn_mul_words_begin: + call .L010PIC_me_up +.L010PIC_me_up: + popl %eax + leal OPENSSL_ia32cap_P-.L010PIC_me_up(%eax),%eax + btl $26,(%eax) + jnc .L011mw_non_sse2 + movl 4(%esp),%eax + movl 8(%esp),%edx + movl 12(%esp),%ecx + movd 16(%esp),%mm0 + pxor %mm1,%mm1 +.align 16 +.L012mw_sse2_loop: + movd (%edx),%mm2 + pmuludq %mm0,%mm2 + leal 4(%edx),%edx + paddq %mm2,%mm1 + movd %mm1,(%eax) + subl $1,%ecx + psrlq $32,%mm1 + leal 4(%eax),%eax + jnz .L012mw_sse2_loop + movd %mm1,%eax + emms + ret +.align 16 +.L011mw_non_sse2: pushl %ebp pushl %ebx pushl %esi @@ -206,8 +329,8 @@ bn_mul_words: movl 28(%esp),%ebp movl 32(%esp),%ecx andl $4294967288,%ebp - jz .L004mw_finish -.L005mw_loop: + jz .L013mw_finish +.L014mw_loop: movl (%ebx),%eax mull %ecx @@ -268,14 +391,14 @@ bn_mul_words: addl $32,%ebx addl $32,%edi subl $8,%ebp - jz .L004mw_finish - jmp .L005mw_loop -.L004mw_finish: + jz .L013mw_finish + jmp .L014mw_loop +.L013mw_finish: movl 28(%esp),%ebp andl $7,%ebp - jnz .L006mw_finish2 - jmp .L007mw_end -.L006mw_finish2: + jnz .L015mw_finish2 + jmp .L016mw_end +.L015mw_finish2: movl (%ebx),%eax mull %ecx @@ -284,7 +407,7 @@ bn_mul_words: movl %eax,(%edi) movl %edx,%esi decl %ebp - jz .L007mw_end + jz .L016mw_end movl 4(%ebx),%eax mull %ecx @@ -293,7 +416,7 @@ bn_mul_words: movl %eax,4(%edi) movl %edx,%esi decl %ebp - jz .L007mw_end + jz .L016mw_end movl 8(%ebx),%eax mull %ecx @@ -302,7 +425,7 @@ bn_mul_words: movl %eax,8(%edi) movl %edx,%esi decl %ebp - jz .L007mw_end + jz .L016mw_end movl 12(%ebx),%eax mull %ecx @@ -311,7 +434,7 @@ bn_mul_words: movl %eax,12(%edi) movl %edx,%esi decl %ebp - jz .L007mw_end + jz .L016mw_end movl 16(%ebx),%eax mull %ecx @@ -320,7 +443,7 @@ bn_mul_words: movl %eax,16(%edi) movl %edx,%esi decl %ebp - jz .L007mw_end + jz .L016mw_end movl 20(%ebx),%eax mull %ecx @@ -329,7 +452,7 @@ bn_mul_words: movl %eax,20(%edi) movl %edx,%esi decl %ebp - jz .L007mw_end + jz .L016mw_end movl 24(%ebx),%eax mull %ecx @@ -337,7 +460,7 @@ bn_mul_words: adcl $0,%edx movl %eax,24(%edi) movl %edx,%esi -.L007mw_end: +.L016mw_end: movl %esi,%eax popl %edi popl %esi @@ -351,6 +474,28 @@ bn_mul_words: .align 16 bn_sqr_words: .L_bn_sqr_words_begin: + call .L017PIC_me_up +.L017PIC_me_up: + popl %eax + leal OPENSSL_ia32cap_P-.L017PIC_me_up(%eax),%eax + btl $26,(%eax) + jnc .L018sqr_non_sse2 + movl 4(%esp),%eax + movl 8(%esp),%edx + movl 12(%esp),%ecx +.align 16 +.L019sqr_sse2_loop: + movd (%edx),%mm0 + pmuludq %mm0,%mm0 + leal 4(%edx),%edx + movq %mm0,(%eax) + subl $1,%ecx + leal 8(%eax),%eax + jnz .L019sqr_sse2_loop + emms + ret +.align 16 +.L018sqr_non_sse2: pushl %ebp pushl %ebx pushl %esi @@ -360,8 +505,8 @@ bn_sqr_words: movl 24(%esp),%edi movl 28(%esp),%ebx andl $4294967288,%ebx - jz .L008sw_finish -.L009sw_loop: + jz .L020sw_finish +.L021sw_loop: movl (%edi),%eax mull %eax @@ -406,59 +551,59 @@ bn_sqr_words: addl $32,%edi addl $64,%esi subl $8,%ebx - jnz .L009sw_loop -.L008sw_finish: + jnz .L021sw_loop +.L020sw_finish: movl 28(%esp),%ebx andl $7,%ebx - jz .L010sw_end + jz .L022sw_end movl (%edi),%eax mull %eax movl %eax,(%esi) decl %ebx movl %edx,4(%esi) - jz .L010sw_end + jz .L022sw_end movl 4(%edi),%eax mull %eax movl %eax,8(%esi) decl %ebx movl %edx,12(%esi) - jz .L010sw_end + jz .L022sw_end movl 8(%edi),%eax mull %eax movl %eax,16(%esi) decl %ebx movl %edx,20(%esi) - jz .L010sw_end + jz .L022sw_end movl 12(%edi),%eax mull %eax movl %eax,24(%esi) decl %ebx movl %edx,28(%esi) - jz .L010sw_end + jz .L022sw_end movl 16(%edi),%eax mull %eax movl %eax,32(%esi) decl %ebx movl %edx,36(%esi) - jz .L010sw_end + jz .L022sw_end movl 20(%edi),%eax mull %eax movl %eax,40(%esi) decl %ebx movl %edx,44(%esi) - jz .L010sw_end + jz .L022sw_end movl 24(%edi),%eax mull %eax movl %eax,48(%esi) movl %edx,52(%esi) -.L010sw_end: +.L022sw_end: popl %edi popl %esi popl %ebx @@ -494,8 +639,8 @@ bn_add_words: movl 32(%esp),%ebp xorl %eax,%eax andl $4294967288,%ebp - jz .L011aw_finish -.L012aw_loop: + jz .L023aw_finish +.L024aw_loop: movl (%esi),%ecx movl (%edi),%edx @@ -573,11 +718,11 @@ bn_add_words: addl $32,%edi addl $32,%ebx subl $8,%ebp - jnz .L012aw_loop -.L011aw_finish: + jnz .L024aw_loop +.L023aw_finish: movl 32(%esp),%ebp andl $7,%ebp - jz .L013aw_end + jz .L025aw_end movl (%esi),%ecx movl (%edi),%edx @@ -588,7 +733,7 @@ bn_add_words: adcl $0,%eax decl %ebp movl %ecx,(%ebx) - jz .L013aw_end + jz .L025aw_end movl 4(%esi),%ecx movl 4(%edi),%edx @@ -599,7 +744,7 @@ bn_add_words: adcl $0,%eax decl %ebp movl %ecx,4(%ebx) - jz .L013aw_end + jz .L025aw_end movl 8(%esi),%ecx movl 8(%edi),%edx @@ -610,7 +755,7 @@ bn_add_words: adcl $0,%eax decl %ebp movl %ecx,8(%ebx) - jz .L013aw_end + jz .L025aw_end movl 12(%esi),%ecx movl 12(%edi),%edx @@ -621,7 +766,7 @@ bn_add_words: adcl $0,%eax decl %ebp movl %ecx,12(%ebx) - jz .L013aw_end + jz .L025aw_end movl 16(%esi),%ecx movl 16(%edi),%edx @@ -632,7 +777,7 @@ bn_add_words: adcl $0,%eax decl %ebp movl %ecx,16(%ebx) - jz .L013aw_end + jz .L025aw_end movl 20(%esi),%ecx movl 20(%edi),%edx @@ -643,7 +788,7 @@ bn_add_words: adcl $0,%eax decl %ebp movl %ecx,20(%ebx) - jz .L013aw_end + jz .L025aw_end movl 24(%esi),%ecx movl 24(%edi),%edx @@ -653,7 +798,7 @@ bn_add_words: addl %edx,%ecx adcl $0,%eax movl %ecx,24(%ebx) -.L013aw_end: +.L025aw_end: popl %edi popl %esi popl %ebx @@ -677,8 +822,8 @@ bn_sub_words: movl 32(%esp),%ebp xorl %eax,%eax andl $4294967288,%ebp - jz .L014aw_finish -.L015aw_loop: + jz .L026aw_finish +.L027aw_loop: movl (%esi),%ecx movl (%edi),%edx @@ -756,11 +901,11 @@ bn_sub_words: addl $32,%edi addl $32,%ebx subl $8,%ebp - jnz .L015aw_loop -.L014aw_finish: + jnz .L027aw_loop +.L026aw_finish: movl 32(%esp),%ebp andl $7,%ebp - jz .L016aw_end + jz .L028aw_end movl (%esi),%ecx movl (%edi),%edx @@ -771,7 +916,7 @@ bn_sub_words: adcl $0,%eax decl %ebp movl %ecx,(%ebx) - jz .L016aw_end + jz .L028aw_end movl 4(%esi),%ecx movl 4(%edi),%edx @@ -782,7 +927,7 @@ bn_sub_words: adcl $0,%eax decl %ebp movl %ecx,4(%ebx) - jz .L016aw_end + jz .L028aw_end movl 8(%esi),%ecx movl 8(%edi),%edx @@ -793,7 +938,7 @@ bn_sub_words: adcl $0,%eax decl %ebp movl %ecx,8(%ebx) - jz .L016aw_end + jz .L028aw_end movl 12(%esi),%ecx movl 12(%edi),%edx @@ -804,7 +949,7 @@ bn_sub_words: adcl $0,%eax decl %ebp movl %ecx,12(%ebx) - jz .L016aw_end + jz .L028aw_end movl 16(%esi),%ecx movl 16(%edi),%edx @@ -815,7 +960,7 @@ bn_sub_words: adcl $0,%eax decl %ebp movl %ecx,16(%ebx) - jz .L016aw_end + jz .L028aw_end movl 20(%esi),%ecx movl 20(%edi),%edx @@ -826,7 +971,7 @@ bn_sub_words: adcl $0,%eax decl %ebp movl %ecx,20(%ebx) - jz .L016aw_end + jz .L028aw_end movl 24(%esi),%ecx movl 24(%edi),%edx @@ -836,7 +981,7 @@ bn_sub_words: subl %edx,%ecx adcl $0,%eax movl %ecx,24(%ebx) -.L016aw_end: +.L028aw_end: popl %edi popl %esi popl %ebx @@ -860,8 +1005,8 @@ bn_sub_part_words: movl 32(%esp),%ebp xorl %eax,%eax andl $4294967288,%ebp - jz .L017aw_finish -.L018aw_loop: + jz .L029aw_finish +.L030aw_loop: movl (%esi),%ecx movl (%edi),%edx @@ -939,11 +1084,11 @@ bn_sub_part_words: addl $32,%edi addl $32,%ebx subl $8,%ebp - jnz .L018aw_loop -.L017aw_finish: + jnz .L030aw_loop +.L029aw_finish: movl 32(%esp),%ebp andl $7,%ebp - jz .L019aw_end + jz .L031aw_end movl (%esi),%ecx movl (%edi),%edx @@ -957,7 +1102,7 @@ bn_sub_part_words: addl $4,%edi addl $4,%ebx decl %ebp - jz .L019aw_end + jz .L031aw_end movl (%esi),%ecx movl (%edi),%edx @@ -971,7 +1116,7 @@ bn_sub_part_words: addl $4,%edi addl $4,%ebx decl %ebp - jz .L019aw_end + jz .L031aw_end movl (%esi),%ecx movl (%edi),%edx @@ -985,7 +1130,7 @@ bn_sub_part_words: addl $4,%edi addl $4,%ebx decl %ebp - jz .L019aw_end + jz .L031aw_end movl (%esi),%ecx movl (%edi),%edx @@ -999,7 +1144,7 @@ bn_sub_part_words: addl $4,%edi addl $4,%ebx decl %ebp - jz .L019aw_end + jz .L031aw_end movl (%esi),%ecx movl (%edi),%edx @@ -1013,7 +1158,7 @@ bn_sub_part_words: addl $4,%edi addl $4,%ebx decl %ebp - jz .L019aw_end + jz .L031aw_end movl (%esi),%ecx movl (%edi),%edx @@ -1027,7 +1172,7 @@ bn_sub_part_words: addl $4,%edi addl $4,%ebx decl %ebp - jz .L019aw_end + jz .L031aw_end movl (%esi),%ecx movl (%edi),%edx @@ -1040,20 +1185,20 @@ bn_sub_part_words: addl $4,%esi addl $4,%edi addl $4,%ebx -.L019aw_end: +.L031aw_end: cmpl $0,36(%esp) - je .L020pw_end + je .L032pw_end movl 36(%esp),%ebp cmpl $0,%ebp - je .L020pw_end - jge .L021pw_pos + je .L032pw_end + jge .L033pw_pos movl $0,%edx subl %ebp,%edx movl %edx,%ebp andl $4294967288,%ebp - jz .L022pw_neg_finish -.L023pw_neg_loop: + jz .L034pw_neg_finish +.L035pw_neg_loop: movl $0,%ecx movl (%edi),%edx @@ -1130,13 +1275,13 @@ bn_sub_part_words: addl $32,%edi addl $32,%ebx subl $8,%ebp - jnz .L023pw_neg_loop -.L022pw_neg_finish: + jnz .L035pw_neg_loop +.L034pw_neg_finish: movl 36(%esp),%edx movl $0,%ebp subl %edx,%ebp andl $7,%ebp - jz .L020pw_end + jz .L032pw_end movl $0,%ecx movl (%edi),%edx @@ -1147,7 +1292,7 @@ bn_sub_part_words: adcl $0,%eax decl %ebp movl %ecx,(%ebx) - jz .L020pw_end + jz .L032pw_end movl $0,%ecx movl 4(%edi),%edx @@ -1158,7 +1303,7 @@ bn_sub_part_words: adcl $0,%eax decl %ebp movl %ecx,4(%ebx) - jz .L020pw_end + jz .L032pw_end movl $0,%ecx movl 8(%edi),%edx @@ -1169,7 +1314,7 @@ bn_sub_part_words: adcl $0,%eax decl %ebp movl %ecx,8(%ebx) - jz .L020pw_end + jz .L032pw_end movl $0,%ecx movl 12(%edi),%edx @@ -1180,7 +1325,7 @@ bn_sub_part_words: adcl $0,%eax decl %ebp movl %ecx,12(%ebx) - jz .L020pw_end + jz .L032pw_end movl $0,%ecx movl 16(%edi),%edx @@ -1191,7 +1336,7 @@ bn_sub_part_words: adcl $0,%eax decl %ebp movl %ecx,16(%ebx) - jz .L020pw_end + jz .L032pw_end movl $0,%ecx movl 20(%edi),%edx @@ -1202,7 +1347,7 @@ bn_sub_part_words: adcl $0,%eax decl %ebp movl %ecx,20(%ebx) - jz .L020pw_end + jz .L032pw_end movl $0,%ecx movl 24(%edi),%edx @@ -1212,178 +1357,178 @@ bn_sub_part_words: subl %edx,%ecx adcl $0,%eax movl %ecx,24(%ebx) - jmp .L020pw_end -.L021pw_pos: + jmp .L032pw_end +.L033pw_pos: andl $4294967288,%ebp - jz .L024pw_pos_finish -.L025pw_pos_loop: + jz .L036pw_pos_finish +.L037pw_pos_loop: movl (%esi),%ecx subl %eax,%ecx movl %ecx,(%ebx) - jnc .L026pw_nc0 + jnc .L038pw_nc0 movl 4(%esi),%ecx subl %eax,%ecx movl %ecx,4(%ebx) - jnc .L027pw_nc1 + jnc .L039pw_nc1 movl 8(%esi),%ecx subl %eax,%ecx movl %ecx,8(%ebx) - jnc .L028pw_nc2 + jnc .L040pw_nc2 movl 12(%esi),%ecx subl %eax,%ecx movl %ecx,12(%ebx) - jnc .L029pw_nc3 + jnc .L041pw_nc3 movl 16(%esi),%ecx subl %eax,%ecx movl %ecx,16(%ebx) - jnc .L030pw_nc4 + jnc .L042pw_nc4 movl 20(%esi),%ecx subl %eax,%ecx movl %ecx,20(%ebx) - jnc .L031pw_nc5 + jnc .L043pw_nc5 movl 24(%esi),%ecx subl %eax,%ecx movl %ecx,24(%ebx) - jnc .L032pw_nc6 + jnc .L044pw_nc6 movl 28(%esi),%ecx subl %eax,%ecx movl %ecx,28(%ebx) - jnc .L033pw_nc7 + jnc .L045pw_nc7 addl $32,%esi addl $32,%ebx subl $8,%ebp - jnz .L025pw_pos_loop -.L024pw_pos_finish: + jnz .L037pw_pos_loop +.L036pw_pos_finish: movl 36(%esp),%ebp andl $7,%ebp - jz .L020pw_end + jz .L032pw_end movl (%esi),%ecx subl %eax,%ecx movl %ecx,(%ebx) - jnc .L034pw_tail_nc0 + jnc .L046pw_tail_nc0 decl %ebp - jz .L020pw_end + jz .L032pw_end movl 4(%esi),%ecx subl %eax,%ecx movl %ecx,4(%ebx) - jnc .L035pw_tail_nc1 + jnc .L047pw_tail_nc1 decl %ebp - jz .L020pw_end + jz .L032pw_end movl 8(%esi),%ecx subl %eax,%ecx movl %ecx,8(%ebx) - jnc .L036pw_tail_nc2 + jnc .L048pw_tail_nc2 decl %ebp - jz .L020pw_end + jz .L032pw_end movl 12(%esi),%ecx subl %eax,%ecx movl %ecx,12(%ebx) - jnc .L037pw_tail_nc3 + jnc .L049pw_tail_nc3 decl %ebp - jz .L020pw_end + jz .L032pw_end movl 16(%esi),%ecx subl %eax,%ecx movl %ecx,16(%ebx) - jnc .L038pw_tail_nc4 + jnc .L050pw_tail_nc4 decl %ebp - jz .L020pw_end + jz .L032pw_end movl 20(%esi),%ecx subl %eax,%ecx movl %ecx,20(%ebx) - jnc .L039pw_tail_nc5 + jnc .L051pw_tail_nc5 decl %ebp - jz .L020pw_end + jz .L032pw_end movl 24(%esi),%ecx subl %eax,%ecx movl %ecx,24(%ebx) - jnc .L040pw_tail_nc6 + jnc .L052pw_tail_nc6 movl $1,%eax - jmp .L020pw_end -.L041pw_nc_loop: + jmp .L032pw_end +.L053pw_nc_loop: movl (%esi),%ecx movl %ecx,(%ebx) -.L026pw_nc0: +.L038pw_nc0: movl 4(%esi),%ecx movl %ecx,4(%ebx) -.L027pw_nc1: +.L039pw_nc1: movl 8(%esi),%ecx movl %ecx,8(%ebx) -.L028pw_nc2: +.L040pw_nc2: movl 12(%esi),%ecx movl %ecx,12(%ebx) -.L029pw_nc3: +.L041pw_nc3: movl 16(%esi),%ecx movl %ecx,16(%ebx) -.L030pw_nc4: +.L042pw_nc4: movl 20(%esi),%ecx movl %ecx,20(%ebx) -.L031pw_nc5: +.L043pw_nc5: movl 24(%esi),%ecx movl %ecx,24(%ebx) -.L032pw_nc6: +.L044pw_nc6: movl 28(%esi),%ecx movl %ecx,28(%ebx) -.L033pw_nc7: +.L045pw_nc7: addl $32,%esi addl $32,%ebx subl $8,%ebp - jnz .L041pw_nc_loop + jnz .L053pw_nc_loop movl 36(%esp),%ebp andl $7,%ebp - jz .L042pw_nc_end + jz .L054pw_nc_end movl (%esi),%ecx movl %ecx,(%ebx) -.L034pw_tail_nc0: +.L046pw_tail_nc0: decl %ebp - jz .L042pw_nc_end + jz .L054pw_nc_end movl 4(%esi),%ecx movl %ecx,4(%ebx) -.L035pw_tail_nc1: +.L047pw_tail_nc1: decl %ebp - jz .L042pw_nc_end + jz .L054pw_nc_end movl 8(%esi),%ecx movl %ecx,8(%ebx) -.L036pw_tail_nc2: +.L048pw_tail_nc2: decl %ebp - jz .L042pw_nc_end + jz .L054pw_nc_end movl 12(%esi),%ecx movl %ecx,12(%ebx) -.L037pw_tail_nc3: +.L049pw_tail_nc3: decl %ebp - jz .L042pw_nc_end + jz .L054pw_nc_end movl 16(%esi),%ecx movl %ecx,16(%ebx) -.L038pw_tail_nc4: +.L050pw_tail_nc4: decl %ebp - jz .L042pw_nc_end + jz .L054pw_nc_end movl 20(%esi),%ecx movl %ecx,20(%ebx) -.L039pw_tail_nc5: +.L051pw_tail_nc5: decl %ebp - jz .L042pw_nc_end + jz .L054pw_nc_end movl 24(%esi),%ecx movl %ecx,24(%ebx) -.L040pw_tail_nc6: -.L042pw_nc_end: +.L052pw_tail_nc6: +.L054pw_nc_end: movl $0,%eax -.L020pw_end: +.L032pw_end: popl %edi popl %esi popl %ebx diff --git a/third_party/boringssl/linux-x86/crypto/bn/x86-mont.S b/third_party/boringssl/linux-x86/crypto/bn/x86-mont.S index e2d23b32dd664..1569b2cff1738 100644 --- a/third_party/boringssl/linux-x86/crypto/bn/x86-mont.S +++ b/third_party/boringssl/linux-x86/crypto/bn/x86-mont.S @@ -44,6 +44,126 @@ bn_mul_mont: movl %esi,20(%esp) leal -3(%edi),%ebx movl %ebp,24(%esp) + call .L001PIC_me_up +.L001PIC_me_up: + popl %eax + leal OPENSSL_ia32cap_P-.L001PIC_me_up(%eax),%eax + btl $26,(%eax) + jnc .L002non_sse2 + movl $-1,%eax + movd %eax,%mm7 + movl 8(%esp),%esi + movl 12(%esp),%edi + movl 16(%esp),%ebp + xorl %edx,%edx + xorl %ecx,%ecx + movd (%edi),%mm4 + movd (%esi),%mm5 + movd (%ebp),%mm3 + pmuludq %mm4,%mm5 + movq %mm5,%mm2 + movq %mm5,%mm0 + pand %mm7,%mm0 + pmuludq 20(%esp),%mm5 + pmuludq %mm5,%mm3 + paddq %mm0,%mm3 + movd 4(%ebp),%mm1 + movd 4(%esi),%mm0 + psrlq $32,%mm2 + psrlq $32,%mm3 + incl %ecx +.align 16 +.L0031st: + pmuludq %mm4,%mm0 + pmuludq %mm5,%mm1 + paddq %mm0,%mm2 + paddq %mm1,%mm3 + movq %mm2,%mm0 + pand %mm7,%mm0 + movd 4(%ebp,%ecx,4),%mm1 + paddq %mm0,%mm3 + movd 4(%esi,%ecx,4),%mm0 + psrlq $32,%mm2 + movd %mm3,28(%esp,%ecx,4) + psrlq $32,%mm3 + leal 1(%ecx),%ecx + cmpl %ebx,%ecx + jl .L0031st + pmuludq %mm4,%mm0 + pmuludq %mm5,%mm1 + paddq %mm0,%mm2 + paddq %mm1,%mm3 + movq %mm2,%mm0 + pand %mm7,%mm0 + paddq %mm0,%mm3 + movd %mm3,28(%esp,%ecx,4) + psrlq $32,%mm2 + psrlq $32,%mm3 + paddq %mm2,%mm3 + movq %mm3,32(%esp,%ebx,4) + incl %edx +.L004outer: + xorl %ecx,%ecx + movd (%edi,%edx,4),%mm4 + movd (%esi),%mm5 + movd 32(%esp),%mm6 + movd (%ebp),%mm3 + pmuludq %mm4,%mm5 + paddq %mm6,%mm5 + movq %mm5,%mm0 + movq %mm5,%mm2 + pand %mm7,%mm0 + pmuludq 20(%esp),%mm5 + pmuludq %mm5,%mm3 + paddq %mm0,%mm3 + movd 36(%esp),%mm6 + movd 4(%ebp),%mm1 + movd 4(%esi),%mm0 + psrlq $32,%mm2 + psrlq $32,%mm3 + paddq %mm6,%mm2 + incl %ecx + decl %ebx +.L005inner: + pmuludq %mm4,%mm0 + pmuludq %mm5,%mm1 + paddq %mm0,%mm2 + paddq %mm1,%mm3 + movq %mm2,%mm0 + movd 36(%esp,%ecx,4),%mm6 + pand %mm7,%mm0 + movd 4(%ebp,%ecx,4),%mm1 + paddq %mm0,%mm3 + movd 4(%esi,%ecx,4),%mm0 + psrlq $32,%mm2 + movd %mm3,28(%esp,%ecx,4) + psrlq $32,%mm3 + paddq %mm6,%mm2 + decl %ebx + leal 1(%ecx),%ecx + jnz .L005inner + movl %ecx,%ebx + pmuludq %mm4,%mm0 + pmuludq %mm5,%mm1 + paddq %mm0,%mm2 + paddq %mm1,%mm3 + movq %mm2,%mm0 + pand %mm7,%mm0 + paddq %mm0,%mm3 + movd %mm3,28(%esp,%ecx,4) + psrlq $32,%mm2 + psrlq $32,%mm3 + movd 36(%esp,%ebx,4),%mm6 + paddq %mm2,%mm3 + paddq %mm6,%mm3 + movq %mm3,32(%esp,%ebx,4) + leal 1(%edx),%edx + cmpl %ebx,%edx + jle .L004outer + emms + jmp .L006common_tail +.align 16 +.L002non_sse2: movl 8(%esp),%esi leal 1(%ebx),%ebp movl 12(%esp),%edi @@ -54,12 +174,12 @@ bn_mul_mont: leal 4(%edi,%ebx,4),%eax orl %edx,%ebp movl (%edi),%edi - jz .L001bn_sqr_mont + jz .L007bn_sqr_mont movl %eax,28(%esp) movl (%esi),%eax xorl %edx,%edx .align 16 -.L002mull: +.L008mull: movl %edx,%ebp mull %edi addl %eax,%ebp @@ -68,7 +188,7 @@ bn_mul_mont: movl (%esi,%ecx,4),%eax cmpl %ebx,%ecx movl %ebp,28(%esp,%ecx,4) - jl .L002mull + jl .L008mull movl %edx,%ebp mull %edi movl 20(%esp),%edi @@ -86,9 +206,9 @@ bn_mul_mont: movl 4(%esi),%eax adcl $0,%edx incl %ecx - jmp .L0032ndmadd + jmp .L0092ndmadd .align 16 -.L0041stmadd: +.L0101stmadd: movl %edx,%ebp mull %edi addl 32(%esp,%ecx,4),%ebp @@ -99,7 +219,7 @@ bn_mul_mont: adcl $0,%edx cmpl %ebx,%ecx movl %ebp,28(%esp,%ecx,4) - jl .L0041stmadd + jl .L0101stmadd movl %edx,%ebp mull %edi addl 32(%esp,%ebx,4),%eax @@ -122,7 +242,7 @@ bn_mul_mont: adcl $0,%edx movl $1,%ecx .align 16 -.L0032ndmadd: +.L0092ndmadd: movl %edx,%ebp mull %edi addl 32(%esp,%ecx,4),%ebp @@ -133,7 +253,7 @@ bn_mul_mont: adcl $0,%edx cmpl %ebx,%ecx movl %ebp,24(%esp,%ecx,4) - jl .L0032ndmadd + jl .L0092ndmadd movl %edx,%ebp mull %edi addl 32(%esp,%ebx,4),%ebp @@ -149,16 +269,16 @@ bn_mul_mont: movl %edx,32(%esp,%ebx,4) cmpl 28(%esp),%ecx movl %eax,36(%esp,%ebx,4) - je .L005common_tail + je .L006common_tail movl (%ecx),%edi movl 8(%esp),%esi movl %ecx,12(%esp) xorl %ecx,%ecx xorl %edx,%edx movl (%esi),%eax - jmp .L0041stmadd + jmp .L0101stmadd .align 16 -.L001bn_sqr_mont: +.L007bn_sqr_mont: movl %ebx,(%esp) movl %ecx,12(%esp) movl %edi,%eax @@ -169,7 +289,7 @@ bn_mul_mont: andl $1,%ebx incl %ecx .align 16 -.L006sqr: +.L011sqr: movl (%esi,%ecx,4),%eax movl %edx,%ebp mull %edi @@ -181,7 +301,7 @@ bn_mul_mont: cmpl (%esp),%ecx movl %eax,%ebx movl %ebp,28(%esp,%ecx,4) - jl .L006sqr + jl .L011sqr movl (%esi,%ecx,4),%eax movl %edx,%ebp mull %edi @@ -205,7 +325,7 @@ bn_mul_mont: movl 4(%esi),%eax movl $1,%ecx .align 16 -.L0073rdmadd: +.L0123rdmadd: movl %edx,%ebp mull %edi addl 32(%esp,%ecx,4),%ebp @@ -224,7 +344,7 @@ bn_mul_mont: adcl $0,%edx cmpl %ebx,%ecx movl %ebp,24(%esp,%ecx,4) - jl .L0073rdmadd + jl .L0123rdmadd movl %edx,%ebp mull %edi addl 32(%esp,%ebx,4),%ebp @@ -240,7 +360,7 @@ bn_mul_mont: movl %edx,32(%esp,%ebx,4) cmpl %ebx,%ecx movl %eax,36(%esp,%ebx,4) - je .L005common_tail + je .L006common_tail movl 4(%esi,%ecx,4),%edi leal 1(%ecx),%ecx movl %edi,%eax @@ -252,12 +372,12 @@ bn_mul_mont: xorl %ebp,%ebp cmpl %ebx,%ecx leal 1(%ecx),%ecx - je .L008sqrlast + je .L013sqrlast movl %edx,%ebx shrl $1,%edx andl $1,%ebx .align 16 -.L009sqradd: +.L014sqradd: movl (%esi,%ecx,4),%eax movl %edx,%ebp mull %edi @@ -273,13 +393,13 @@ bn_mul_mont: cmpl (%esp),%ecx movl %ebp,28(%esp,%ecx,4) movl %eax,%ebx - jle .L009sqradd + jle .L014sqradd movl %edx,%ebp addl %edx,%edx shrl $31,%ebp addl %ebx,%edx adcl $0,%ebp -.L008sqrlast: +.L013sqrlast: movl 20(%esp),%edi movl 16(%esp),%esi imull 32(%esp),%edi @@ -294,9 +414,9 @@ bn_mul_mont: adcl $0,%edx movl $1,%ecx movl 4(%esi),%eax - jmp .L0073rdmadd + jmp .L0123rdmadd .align 16 -.L005common_tail: +.L006common_tail: movl 16(%esp),%ebp movl 4(%esp),%edi leal 32(%esp),%esi @@ -304,16 +424,16 @@ bn_mul_mont: movl %ebx,%ecx xorl %edx,%edx .align 16 -.L010sub: +.L015sub: sbbl (%ebp,%edx,4),%eax movl %eax,(%edi,%edx,4) decl %ecx movl 4(%esi,%edx,4),%eax leal 1(%edx),%edx - jge .L010sub + jge .L015sub sbbl $0,%eax .align 16 -.L011copy: +.L016copy: movl (%esi,%ebx,4),%edx movl (%edi,%ebx,4),%ebp xorl %ebp,%edx @@ -322,7 +442,7 @@ bn_mul_mont: movl %ecx,(%esi,%ebx,4) movl %edx,(%edi,%ebx,4) decl %ebx - jge .L011copy + jge .L016copy movl 24(%esp),%esp movl $1,%eax .L000just_leave: diff --git a/third_party/boringssl/linux-x86/crypto/cpu-x86-asm.S b/third_party/boringssl/linux-x86/crypto/cpu-x86-asm.S index 2e52a2c723df5..24a8dd4d4247f 100644 --- a/third_party/boringssl/linux-x86/crypto/cpu-x86-asm.S +++ b/third_party/boringssl/linux-x86/crypto/cpu-x86-asm.S @@ -237,6 +237,18 @@ OPENSSL_wipe_cpu: movl (%ecx),%ecx btl $1,(%ecx) jnc .L016no_x87 + andl $83886080,%ecx + cmpl $83886080,%ecx + jne .L017no_sse2 + pxor %xmm0,%xmm0 + pxor %xmm1,%xmm1 + pxor %xmm2,%xmm2 + pxor %xmm3,%xmm3 + pxor %xmm4,%xmm4 + pxor %xmm5,%xmm5 + pxor %xmm6,%xmm6 + pxor %xmm7,%xmm7 +.L017no_sse2: .long 4007259865,4007259865,4007259865,4007259865,2430851995 .L016no_x87: leal 4(%esp),%eax @@ -253,11 +265,11 @@ OPENSSL_atomic_add: pushl %ebx nop movl (%edx),%eax -.L017spin: +.L018spin: leal (%eax,%ecx,1),%ebx nop .long 447811568 - jne .L017spin + jne .L018spin movl %ebx,%eax popl %ebx ret @@ -297,11 +309,11 @@ OPENSSL_indirect_call: OPENSSL_ia32_rdrand: .L_OPENSSL_ia32_rdrand_begin: movl $8,%ecx -.L018loop: +.L019loop: .byte 15,199,240 - jc .L019break - loop .L018loop -.L019break: + jc .L020break + loop .L019loop +.L020break: cmpl $0,%eax cmovel %ecx,%eax ret diff --git a/third_party/boringssl/linux-x86/crypto/sha/sha1-586.S b/third_party/boringssl/linux-x86/crypto/sha/sha1-586.S index 71ae5b351daa4..808ccac5178f7 100644 --- a/third_party/boringssl/linux-x86/crypto/sha/sha1-586.S +++ b/third_party/boringssl/linux-x86/crypto/sha/sha1-586.S @@ -11,6 +11,23 @@ sha1_block_data_order: pushl %ebx pushl %esi pushl %edi + call .L000pic_point +.L000pic_point: + popl %ebp + leal OPENSSL_ia32cap_P-.L000pic_point(%ebp),%esi + leal .LK_XX_XX-.L000pic_point(%ebp),%ebp + movl (%esi),%eax + movl 4(%esi),%edx + testl $512,%edx + jz .L001x86 + movl 8(%esi),%ecx + testl $16777216,%eax + jz .L001x86 + testl $536870912,%ecx + jnz .Lshaext_shortcut + jmp .Lssse3_shortcut +.align 16 +.L001x86: movl 20(%esp),%ebp movl 24(%esp),%esi movl 28(%esp),%eax @@ -19,9 +36,9 @@ sha1_block_data_order: addl %esi,%eax movl %eax,104(%esp) movl 16(%ebp),%edi - jmp .L000loop + jmp .L002loop .align 16 -.L000loop: +.L002loop: movl (%esi),%eax movl 4(%esi),%ebx movl 8(%esi),%ecx @@ -1368,7 +1385,7 @@ sha1_block_data_order: movl %ebx,12(%ebp) movl %edx,%esi movl %ecx,16(%ebp) - jb .L000loop + jb .L002loop addl $76,%esp popl %edi popl %esi @@ -1376,6 +1393,1405 @@ sha1_block_data_order: popl %ebp ret .size sha1_block_data_order,.-.L_sha1_block_data_order_begin +.hidden _sha1_block_data_order_shaext +.type _sha1_block_data_order_shaext,@function +.align 16 +_sha1_block_data_order_shaext: + pushl %ebp + pushl %ebx + pushl %esi + pushl %edi + call .L003pic_point +.L003pic_point: + popl %ebp + leal .LK_XX_XX-.L003pic_point(%ebp),%ebp +.Lshaext_shortcut: + movl 20(%esp),%edi + movl %esp,%ebx + movl 24(%esp),%esi + movl 28(%esp),%ecx + subl $32,%esp + movdqu (%edi),%xmm0 + movd 16(%edi),%xmm1 + andl $-32,%esp + movdqa 80(%ebp),%xmm3 + movdqu (%esi),%xmm4 + pshufd $27,%xmm0,%xmm0 + movdqu 16(%esi),%xmm5 + pshufd $27,%xmm1,%xmm1 + movdqu 32(%esi),%xmm6 +.byte 102,15,56,0,227 + movdqu 48(%esi),%xmm7 +.byte 102,15,56,0,235 +.byte 102,15,56,0,243 +.byte 102,15,56,0,251 + jmp .L004loop_shaext +.align 16 +.L004loop_shaext: + decl %ecx + leal 64(%esi),%eax + movdqa %xmm1,(%esp) + paddd %xmm4,%xmm1 + cmovnel %eax,%esi + movdqa %xmm0,16(%esp) +.byte 15,56,201,229 + movdqa %xmm0,%xmm2 +.byte 15,58,204,193,0 +.byte 15,56,200,213 + pxor %xmm6,%xmm4 +.byte 15,56,201,238 +.byte 15,56,202,231 + movdqa %xmm0,%xmm1 +.byte 15,58,204,194,0 +.byte 15,56,200,206 + pxor %xmm7,%xmm5 +.byte 15,56,202,236 +.byte 15,56,201,247 + movdqa %xmm0,%xmm2 +.byte 15,58,204,193,0 +.byte 15,56,200,215 + pxor %xmm4,%xmm6 +.byte 15,56,201,252 +.byte 15,56,202,245 + movdqa %xmm0,%xmm1 +.byte 15,58,204,194,0 +.byte 15,56,200,204 + pxor %xmm5,%xmm7 +.byte 15,56,202,254 +.byte 15,56,201,229 + movdqa %xmm0,%xmm2 +.byte 15,58,204,193,0 +.byte 15,56,200,213 + pxor %xmm6,%xmm4 +.byte 15,56,201,238 +.byte 15,56,202,231 + movdqa %xmm0,%xmm1 +.byte 15,58,204,194,1 +.byte 15,56,200,206 + pxor %xmm7,%xmm5 +.byte 15,56,202,236 +.byte 15,56,201,247 + movdqa %xmm0,%xmm2 +.byte 15,58,204,193,1 +.byte 15,56,200,215 + pxor %xmm4,%xmm6 +.byte 15,56,201,252 +.byte 15,56,202,245 + movdqa %xmm0,%xmm1 +.byte 15,58,204,194,1 +.byte 15,56,200,204 + pxor %xmm5,%xmm7 +.byte 15,56,202,254 +.byte 15,56,201,229 + movdqa %xmm0,%xmm2 +.byte 15,58,204,193,1 +.byte 15,56,200,213 + pxor %xmm6,%xmm4 +.byte 15,56,201,238 +.byte 15,56,202,231 + movdqa %xmm0,%xmm1 +.byte 15,58,204,194,1 +.byte 15,56,200,206 + pxor %xmm7,%xmm5 +.byte 15,56,202,236 +.byte 15,56,201,247 + movdqa %xmm0,%xmm2 +.byte 15,58,204,193,2 +.byte 15,56,200,215 + pxor %xmm4,%xmm6 +.byte 15,56,201,252 +.byte 15,56,202,245 + movdqa %xmm0,%xmm1 +.byte 15,58,204,194,2 +.byte 15,56,200,204 + pxor %xmm5,%xmm7 +.byte 15,56,202,254 +.byte 15,56,201,229 + movdqa %xmm0,%xmm2 +.byte 15,58,204,193,2 +.byte 15,56,200,213 + pxor %xmm6,%xmm4 +.byte 15,56,201,238 +.byte 15,56,202,231 + movdqa %xmm0,%xmm1 +.byte 15,58,204,194,2 +.byte 15,56,200,206 + pxor %xmm7,%xmm5 +.byte 15,56,202,236 +.byte 15,56,201,247 + movdqa %xmm0,%xmm2 +.byte 15,58,204,193,2 +.byte 15,56,200,215 + pxor %xmm4,%xmm6 +.byte 15,56,201,252 +.byte 15,56,202,245 + movdqa %xmm0,%xmm1 +.byte 15,58,204,194,3 +.byte 15,56,200,204 + pxor %xmm5,%xmm7 +.byte 15,56,202,254 + movdqu (%esi),%xmm4 + movdqa %xmm0,%xmm2 +.byte 15,58,204,193,3 +.byte 15,56,200,213 + movdqu 16(%esi),%xmm5 +.byte 102,15,56,0,227 + movdqa %xmm0,%xmm1 +.byte 15,58,204,194,3 +.byte 15,56,200,206 + movdqu 32(%esi),%xmm6 +.byte 102,15,56,0,235 + movdqa %xmm0,%xmm2 +.byte 15,58,204,193,3 +.byte 15,56,200,215 + movdqu 48(%esi),%xmm7 +.byte 102,15,56,0,243 + movdqa %xmm0,%xmm1 +.byte 15,58,204,194,3 + movdqa (%esp),%xmm2 +.byte 102,15,56,0,251 +.byte 15,56,200,202 + paddd 16(%esp),%xmm0 + jnz .L004loop_shaext + pshufd $27,%xmm0,%xmm0 + pshufd $27,%xmm1,%xmm1 + movdqu %xmm0,(%edi) + movd %xmm1,16(%edi) + movl %ebx,%esp + popl %edi + popl %esi + popl %ebx + popl %ebp + ret +.size _sha1_block_data_order_shaext,.-_sha1_block_data_order_shaext +.hidden _sha1_block_data_order_ssse3 +.type _sha1_block_data_order_ssse3,@function +.align 16 +_sha1_block_data_order_ssse3: + pushl %ebp + pushl %ebx + pushl %esi + pushl %edi + call .L005pic_point +.L005pic_point: + popl %ebp + leal .LK_XX_XX-.L005pic_point(%ebp),%ebp +.Lssse3_shortcut: + movdqa (%ebp),%xmm7 + movdqa 16(%ebp),%xmm0 + movdqa 32(%ebp),%xmm1 + movdqa 48(%ebp),%xmm2 + movdqa 64(%ebp),%xmm6 + movl 20(%esp),%edi + movl 24(%esp),%ebp + movl 28(%esp),%edx + movl %esp,%esi + subl $208,%esp + andl $-64,%esp + movdqa %xmm0,112(%esp) + movdqa %xmm1,128(%esp) + movdqa %xmm2,144(%esp) + shll $6,%edx + movdqa %xmm7,160(%esp) + addl %ebp,%edx + movdqa %xmm6,176(%esp) + addl $64,%ebp + movl %edi,192(%esp) + movl %ebp,196(%esp) + movl %edx,200(%esp) + movl %esi,204(%esp) + movl (%edi),%eax + movl 4(%edi),%ebx + movl 8(%edi),%ecx + movl 12(%edi),%edx + movl 16(%edi),%edi + movl %ebx,%esi + movdqu -64(%ebp),%xmm0 + movdqu -48(%ebp),%xmm1 + movdqu -32(%ebp),%xmm2 + movdqu -16(%ebp),%xmm3 +.byte 102,15,56,0,198 +.byte 102,15,56,0,206 +.byte 102,15,56,0,214 + movdqa %xmm7,96(%esp) +.byte 102,15,56,0,222 + paddd %xmm7,%xmm0 + paddd %xmm7,%xmm1 + paddd %xmm7,%xmm2 + movdqa %xmm0,(%esp) + psubd %xmm7,%xmm0 + movdqa %xmm1,16(%esp) + psubd %xmm7,%xmm1 + movdqa %xmm2,32(%esp) + movl %ecx,%ebp + psubd %xmm7,%xmm2 + xorl %edx,%ebp + pshufd $238,%xmm0,%xmm4 + andl %ebp,%esi + jmp .L006loop +.align 16 +.L006loop: + rorl $2,%ebx + xorl %edx,%esi + movl %eax,%ebp + punpcklqdq %xmm1,%xmm4 + movdqa %xmm3,%xmm6 + addl (%esp),%edi + xorl %ecx,%ebx + paddd %xmm3,%xmm7 + movdqa %xmm0,64(%esp) + roll $5,%eax + addl %esi,%edi + psrldq $4,%xmm6 + andl %ebx,%ebp + xorl %ecx,%ebx + pxor %xmm0,%xmm4 + addl %eax,%edi + rorl $7,%eax + pxor %xmm2,%xmm6 + xorl %ecx,%ebp + movl %edi,%esi + addl 4(%esp),%edx + pxor %xmm6,%xmm4 + xorl %ebx,%eax + roll $5,%edi + movdqa %xmm7,48(%esp) + addl %ebp,%edx + andl %eax,%esi + movdqa %xmm4,%xmm0 + xorl %ebx,%eax + addl %edi,%edx + rorl $7,%edi + movdqa %xmm4,%xmm6 + xorl %ebx,%esi + pslldq $12,%xmm0 + paddd %xmm4,%xmm4 + movl %edx,%ebp + addl 8(%esp),%ecx + psrld $31,%xmm6 + xorl %eax,%edi + roll $5,%edx + movdqa %xmm0,%xmm7 + addl %esi,%ecx + andl %edi,%ebp + xorl %eax,%edi + psrld $30,%xmm0 + addl %edx,%ecx + rorl $7,%edx + por %xmm6,%xmm4 + xorl %eax,%ebp + movl %ecx,%esi + addl 12(%esp),%ebx + pslld $2,%xmm7 + xorl %edi,%edx + roll $5,%ecx + pxor %xmm0,%xmm4 + movdqa 96(%esp),%xmm0 + addl %ebp,%ebx + andl %edx,%esi + pxor %xmm7,%xmm4 + pshufd $238,%xmm1,%xmm5 + xorl %edi,%edx + addl %ecx,%ebx + rorl $7,%ecx + xorl %edi,%esi + movl %ebx,%ebp + punpcklqdq %xmm2,%xmm5 + movdqa %xmm4,%xmm7 + addl 16(%esp),%eax + xorl %edx,%ecx + paddd %xmm4,%xmm0 + movdqa %xmm1,80(%esp) + roll $5,%ebx + addl %esi,%eax + psrldq $4,%xmm7 + andl %ecx,%ebp + xorl %edx,%ecx + pxor %xmm1,%xmm5 + addl %ebx,%eax + rorl $7,%ebx + pxor %xmm3,%xmm7 + xorl %edx,%ebp + movl %eax,%esi + addl 20(%esp),%edi + pxor %xmm7,%xmm5 + xorl %ecx,%ebx + roll $5,%eax + movdqa %xmm0,(%esp) + addl %ebp,%edi + andl %ebx,%esi + movdqa %xmm5,%xmm1 + xorl %ecx,%ebx + addl %eax,%edi + rorl $7,%eax + movdqa %xmm5,%xmm7 + xorl %ecx,%esi + pslldq $12,%xmm1 + paddd %xmm5,%xmm5 + movl %edi,%ebp + addl 24(%esp),%edx + psrld $31,%xmm7 + xorl %ebx,%eax + roll $5,%edi + movdqa %xmm1,%xmm0 + addl %esi,%edx + andl %eax,%ebp + xorl %ebx,%eax + psrld $30,%xmm1 + addl %edi,%edx + rorl $7,%edi + por %xmm7,%xmm5 + xorl %ebx,%ebp + movl %edx,%esi + addl 28(%esp),%ecx + pslld $2,%xmm0 + xorl %eax,%edi + roll $5,%edx + pxor %xmm1,%xmm5 + movdqa 112(%esp),%xmm1 + addl %ebp,%ecx + andl %edi,%esi + pxor %xmm0,%xmm5 + pshufd $238,%xmm2,%xmm6 + xorl %eax,%edi + addl %edx,%ecx + rorl $7,%edx + xorl %eax,%esi + movl %ecx,%ebp + punpcklqdq %xmm3,%xmm6 + movdqa %xmm5,%xmm0 + addl 32(%esp),%ebx + xorl %edi,%edx + paddd %xmm5,%xmm1 + movdqa %xmm2,96(%esp) + roll $5,%ecx + addl %esi,%ebx + psrldq $4,%xmm0 + andl %edx,%ebp + xorl %edi,%edx + pxor %xmm2,%xmm6 + addl %ecx,%ebx + rorl $7,%ecx + pxor %xmm4,%xmm0 + xorl %edi,%ebp + movl %ebx,%esi + addl 36(%esp),%eax + pxor %xmm0,%xmm6 + xorl %edx,%ecx + roll $5,%ebx + movdqa %xmm1,16(%esp) + addl %ebp,%eax + andl %ecx,%esi + movdqa %xmm6,%xmm2 + xorl %edx,%ecx + addl %ebx,%eax + rorl $7,%ebx + movdqa %xmm6,%xmm0 + xorl %edx,%esi + pslldq $12,%xmm2 + paddd %xmm6,%xmm6 + movl %eax,%ebp + addl 40(%esp),%edi + psrld $31,%xmm0 + xorl %ecx,%ebx + roll $5,%eax + movdqa %xmm2,%xmm1 + addl %esi,%edi + andl %ebx,%ebp + xorl %ecx,%ebx + psrld $30,%xmm2 + addl %eax,%edi + rorl $7,%eax + por %xmm0,%xmm6 + xorl %ecx,%ebp + movdqa 64(%esp),%xmm0 + movl %edi,%esi + addl 44(%esp),%edx + pslld $2,%xmm1 + xorl %ebx,%eax + roll $5,%edi + pxor %xmm2,%xmm6 + movdqa 112(%esp),%xmm2 + addl %ebp,%edx + andl %eax,%esi + pxor %xmm1,%xmm6 + pshufd $238,%xmm3,%xmm7 + xorl %ebx,%eax + addl %edi,%edx + rorl $7,%edi + xorl %ebx,%esi + movl %edx,%ebp + punpcklqdq %xmm4,%xmm7 + movdqa %xmm6,%xmm1 + addl 48(%esp),%ecx + xorl %eax,%edi + paddd %xmm6,%xmm2 + movdqa %xmm3,64(%esp) + roll $5,%edx + addl %esi,%ecx + psrldq $4,%xmm1 + andl %edi,%ebp + xorl %eax,%edi + pxor %xmm3,%xmm7 + addl %edx,%ecx + rorl $7,%edx + pxor %xmm5,%xmm1 + xorl %eax,%ebp + movl %ecx,%esi + addl 52(%esp),%ebx + pxor %xmm1,%xmm7 + xorl %edi,%edx + roll $5,%ecx + movdqa %xmm2,32(%esp) + addl %ebp,%ebx + andl %edx,%esi + movdqa %xmm7,%xmm3 + xorl %edi,%edx + addl %ecx,%ebx + rorl $7,%ecx + movdqa %xmm7,%xmm1 + xorl %edi,%esi + pslldq $12,%xmm3 + paddd %xmm7,%xmm7 + movl %ebx,%ebp + addl 56(%esp),%eax + psrld $31,%xmm1 + xorl %edx,%ecx + roll $5,%ebx + movdqa %xmm3,%xmm2 + addl %esi,%eax + andl %ecx,%ebp + xorl %edx,%ecx + psrld $30,%xmm3 + addl %ebx,%eax + rorl $7,%ebx + por %xmm1,%xmm7 + xorl %edx,%ebp + movdqa 80(%esp),%xmm1 + movl %eax,%esi + addl 60(%esp),%edi + pslld $2,%xmm2 + xorl %ecx,%ebx + roll $5,%eax + pxor %xmm3,%xmm7 + movdqa 112(%esp),%xmm3 + addl %ebp,%edi + andl %ebx,%esi + pxor %xmm2,%xmm7 + pshufd $238,%xmm6,%xmm2 + xorl %ecx,%ebx + addl %eax,%edi + rorl $7,%eax + pxor %xmm4,%xmm0 + punpcklqdq %xmm7,%xmm2 + xorl %ecx,%esi + movl %edi,%ebp + addl (%esp),%edx + pxor %xmm1,%xmm0 + movdqa %xmm4,80(%esp) + xorl %ebx,%eax + roll $5,%edi + movdqa %xmm3,%xmm4 + addl %esi,%edx + paddd %xmm7,%xmm3 + andl %eax,%ebp + pxor %xmm2,%xmm0 + xorl %ebx,%eax + addl %edi,%edx + rorl $7,%edi + xorl %ebx,%ebp + movdqa %xmm0,%xmm2 + movdqa %xmm3,48(%esp) + movl %edx,%esi + addl 4(%esp),%ecx + xorl %eax,%edi + roll $5,%edx + pslld $2,%xmm0 + addl %ebp,%ecx + andl %edi,%esi + psrld $30,%xmm2 + xorl %eax,%edi + addl %edx,%ecx + rorl $7,%edx + xorl %eax,%esi + movl %ecx,%ebp + addl 8(%esp),%ebx + xorl %edi,%edx + roll $5,%ecx + por %xmm2,%xmm0 + addl %esi,%ebx + andl %edx,%ebp + movdqa 96(%esp),%xmm2 + xorl %edi,%edx + addl %ecx,%ebx + addl 12(%esp),%eax + xorl %edi,%ebp + movl %ebx,%esi + pshufd $238,%xmm7,%xmm3 + roll $5,%ebx + addl %ebp,%eax + xorl %edx,%esi + rorl $7,%ecx + addl %ebx,%eax + addl 16(%esp),%edi + pxor %xmm5,%xmm1 + punpcklqdq %xmm0,%xmm3 + xorl %ecx,%esi + movl %eax,%ebp + roll $5,%eax + pxor %xmm2,%xmm1 + movdqa %xmm5,96(%esp) + addl %esi,%edi + xorl %ecx,%ebp + movdqa %xmm4,%xmm5 + rorl $7,%ebx + paddd %xmm0,%xmm4 + addl %eax,%edi + pxor %xmm3,%xmm1 + addl 20(%esp),%edx + xorl %ebx,%ebp + movl %edi,%esi + roll $5,%edi + movdqa %xmm1,%xmm3 + movdqa %xmm4,(%esp) + addl %ebp,%edx + xorl %ebx,%esi + rorl $7,%eax + addl %edi,%edx + pslld $2,%xmm1 + addl 24(%esp),%ecx + xorl %eax,%esi + psrld $30,%xmm3 + movl %edx,%ebp + roll $5,%edx + addl %esi,%ecx + xorl %eax,%ebp + rorl $7,%edi + addl %edx,%ecx + por %xmm3,%xmm1 + addl 28(%esp),%ebx + xorl %edi,%ebp + movdqa 64(%esp),%xmm3 + movl %ecx,%esi + roll $5,%ecx + addl %ebp,%ebx + xorl %edi,%esi + rorl $7,%edx + pshufd $238,%xmm0,%xmm4 + addl %ecx,%ebx + addl 32(%esp),%eax + pxor %xmm6,%xmm2 + punpcklqdq %xmm1,%xmm4 + xorl %edx,%esi + movl %ebx,%ebp + roll $5,%ebx + pxor %xmm3,%xmm2 + movdqa %xmm6,64(%esp) + addl %esi,%eax + xorl %edx,%ebp + movdqa 128(%esp),%xmm6 + rorl $7,%ecx + paddd %xmm1,%xmm5 + addl %ebx,%eax + pxor %xmm4,%xmm2 + addl 36(%esp),%edi + xorl %ecx,%ebp + movl %eax,%esi + roll $5,%eax + movdqa %xmm2,%xmm4 + movdqa %xmm5,16(%esp) + addl %ebp,%edi + xorl %ecx,%esi + rorl $7,%ebx + addl %eax,%edi + pslld $2,%xmm2 + addl 40(%esp),%edx + xorl %ebx,%esi + psrld $30,%xmm4 + movl %edi,%ebp + roll $5,%edi + addl %esi,%edx + xorl %ebx,%ebp + rorl $7,%eax + addl %edi,%edx + por %xmm4,%xmm2 + addl 44(%esp),%ecx + xorl %eax,%ebp + movdqa 80(%esp),%xmm4 + movl %edx,%esi + roll $5,%edx + addl %ebp,%ecx + xorl %eax,%esi + rorl $7,%edi + pshufd $238,%xmm1,%xmm5 + addl %edx,%ecx + addl 48(%esp),%ebx + pxor %xmm7,%xmm3 + punpcklqdq %xmm2,%xmm5 + xorl %edi,%esi + movl %ecx,%ebp + roll $5,%ecx + pxor %xmm4,%xmm3 + movdqa %xmm7,80(%esp) + addl %esi,%ebx + xorl %edi,%ebp + movdqa %xmm6,%xmm7 + rorl $7,%edx + paddd %xmm2,%xmm6 + addl %ecx,%ebx + pxor %xmm5,%xmm3 + addl 52(%esp),%eax + xorl %edx,%ebp + movl %ebx,%esi + roll $5,%ebx + movdqa %xmm3,%xmm5 + movdqa %xmm6,32(%esp) + addl %ebp,%eax + xorl %edx,%esi + rorl $7,%ecx + addl %ebx,%eax + pslld $2,%xmm3 + addl 56(%esp),%edi + xorl %ecx,%esi + psrld $30,%xmm5 + movl %eax,%ebp + roll $5,%eax + addl %esi,%edi + xorl %ecx,%ebp + rorl $7,%ebx + addl %eax,%edi + por %xmm5,%xmm3 + addl 60(%esp),%edx + xorl %ebx,%ebp + movdqa 96(%esp),%xmm5 + movl %edi,%esi + roll $5,%edi + addl %ebp,%edx + xorl %ebx,%esi + rorl $7,%eax + pshufd $238,%xmm2,%xmm6 + addl %edi,%edx + addl (%esp),%ecx + pxor %xmm0,%xmm4 + punpcklqdq %xmm3,%xmm6 + xorl %eax,%esi + movl %edx,%ebp + roll $5,%edx + pxor %xmm5,%xmm4 + movdqa %xmm0,96(%esp) + addl %esi,%ecx + xorl %eax,%ebp + movdqa %xmm7,%xmm0 + rorl $7,%edi + paddd %xmm3,%xmm7 + addl %edx,%ecx + pxor %xmm6,%xmm4 + addl 4(%esp),%ebx + xorl %edi,%ebp + movl %ecx,%esi + roll $5,%ecx + movdqa %xmm4,%xmm6 + movdqa %xmm7,48(%esp) + addl %ebp,%ebx + xorl %edi,%esi + rorl $7,%edx + addl %ecx,%ebx + pslld $2,%xmm4 + addl 8(%esp),%eax + xorl %edx,%esi + psrld $30,%xmm6 + movl %ebx,%ebp + roll $5,%ebx + addl %esi,%eax + xorl %edx,%ebp + rorl $7,%ecx + addl %ebx,%eax + por %xmm6,%xmm4 + addl 12(%esp),%edi + xorl %ecx,%ebp + movdqa 64(%esp),%xmm6 + movl %eax,%esi + roll $5,%eax + addl %ebp,%edi + xorl %ecx,%esi + rorl $7,%ebx + pshufd $238,%xmm3,%xmm7 + addl %eax,%edi + addl 16(%esp),%edx + pxor %xmm1,%xmm5 + punpcklqdq %xmm4,%xmm7 + xorl %ebx,%esi + movl %edi,%ebp + roll $5,%edi + pxor %xmm6,%xmm5 + movdqa %xmm1,64(%esp) + addl %esi,%edx + xorl %ebx,%ebp + movdqa %xmm0,%xmm1 + rorl $7,%eax + paddd %xmm4,%xmm0 + addl %edi,%edx + pxor %xmm7,%xmm5 + addl 20(%esp),%ecx + xorl %eax,%ebp + movl %edx,%esi + roll $5,%edx + movdqa %xmm5,%xmm7 + movdqa %xmm0,(%esp) + addl %ebp,%ecx + xorl %eax,%esi + rorl $7,%edi + addl %edx,%ecx + pslld $2,%xmm5 + addl 24(%esp),%ebx + xorl %edi,%esi + psrld $30,%xmm7 + movl %ecx,%ebp + roll $5,%ecx + addl %esi,%ebx + xorl %edi,%ebp + rorl $7,%edx + addl %ecx,%ebx + por %xmm7,%xmm5 + addl 28(%esp),%eax + movdqa 80(%esp),%xmm7 + rorl $7,%ecx + movl %ebx,%esi + xorl %edx,%ebp + roll $5,%ebx + pshufd $238,%xmm4,%xmm0 + addl %ebp,%eax + xorl %ecx,%esi + xorl %edx,%ecx + addl %ebx,%eax + addl 32(%esp),%edi + pxor %xmm2,%xmm6 + punpcklqdq %xmm5,%xmm0 + andl %ecx,%esi + xorl %edx,%ecx + rorl $7,%ebx + pxor %xmm7,%xmm6 + movdqa %xmm2,80(%esp) + movl %eax,%ebp + xorl %ecx,%esi + roll $5,%eax + movdqa %xmm1,%xmm2 + addl %esi,%edi + paddd %xmm5,%xmm1 + xorl %ebx,%ebp + pxor %xmm0,%xmm6 + xorl %ecx,%ebx + addl %eax,%edi + addl 36(%esp),%edx + andl %ebx,%ebp + movdqa %xmm6,%xmm0 + movdqa %xmm1,16(%esp) + xorl %ecx,%ebx + rorl $7,%eax + movl %edi,%esi + xorl %ebx,%ebp + roll $5,%edi + pslld $2,%xmm6 + addl %ebp,%edx + xorl %eax,%esi + psrld $30,%xmm0 + xorl %ebx,%eax + addl %edi,%edx + addl 40(%esp),%ecx + andl %eax,%esi + xorl %ebx,%eax + rorl $7,%edi + por %xmm0,%xmm6 + movl %edx,%ebp + xorl %eax,%esi + movdqa 96(%esp),%xmm0 + roll $5,%edx + addl %esi,%ecx + xorl %edi,%ebp + xorl %eax,%edi + addl %edx,%ecx + pshufd $238,%xmm5,%xmm1 + addl 44(%esp),%ebx + andl %edi,%ebp + xorl %eax,%edi + rorl $7,%edx + movl %ecx,%esi + xorl %edi,%ebp + roll $5,%ecx + addl %ebp,%ebx + xorl %edx,%esi + xorl %edi,%edx + addl %ecx,%ebx + addl 48(%esp),%eax + pxor %xmm3,%xmm7 + punpcklqdq %xmm6,%xmm1 + andl %edx,%esi + xorl %edi,%edx + rorl $7,%ecx + pxor %xmm0,%xmm7 + movdqa %xmm3,96(%esp) + movl %ebx,%ebp + xorl %edx,%esi + roll $5,%ebx + movdqa 144(%esp),%xmm3 + addl %esi,%eax + paddd %xmm6,%xmm2 + xorl %ecx,%ebp + pxor %xmm1,%xmm7 + xorl %edx,%ecx + addl %ebx,%eax + addl 52(%esp),%edi + andl %ecx,%ebp + movdqa %xmm7,%xmm1 + movdqa %xmm2,32(%esp) + xorl %edx,%ecx + rorl $7,%ebx + movl %eax,%esi + xorl %ecx,%ebp + roll $5,%eax + pslld $2,%xmm7 + addl %ebp,%edi + xorl %ebx,%esi + psrld $30,%xmm1 + xorl %ecx,%ebx + addl %eax,%edi + addl 56(%esp),%edx + andl %ebx,%esi + xorl %ecx,%ebx + rorl $7,%eax + por %xmm1,%xmm7 + movl %edi,%ebp + xorl %ebx,%esi + movdqa 64(%esp),%xmm1 + roll $5,%edi + addl %esi,%edx + xorl %eax,%ebp + xorl %ebx,%eax + addl %edi,%edx + pshufd $238,%xmm6,%xmm2 + addl 60(%esp),%ecx + andl %eax,%ebp + xorl %ebx,%eax + rorl $7,%edi + movl %edx,%esi + xorl %eax,%ebp + roll $5,%edx + addl %ebp,%ecx + xorl %edi,%esi + xorl %eax,%edi + addl %edx,%ecx + addl (%esp),%ebx + pxor %xmm4,%xmm0 + punpcklqdq %xmm7,%xmm2 + andl %edi,%esi + xorl %eax,%edi + rorl $7,%edx + pxor %xmm1,%xmm0 + movdqa %xmm4,64(%esp) + movl %ecx,%ebp + xorl %edi,%esi + roll $5,%ecx + movdqa %xmm3,%xmm4 + addl %esi,%ebx + paddd %xmm7,%xmm3 + xorl %edx,%ebp + pxor %xmm2,%xmm0 + xorl %edi,%edx + addl %ecx,%ebx + addl 4(%esp),%eax + andl %edx,%ebp + movdqa %xmm0,%xmm2 + movdqa %xmm3,48(%esp) + xorl %edi,%edx + rorl $7,%ecx + movl %ebx,%esi + xorl %edx,%ebp + roll $5,%ebx + pslld $2,%xmm0 + addl %ebp,%eax + xorl %ecx,%esi + psrld $30,%xmm2 + xorl %edx,%ecx + addl %ebx,%eax + addl 8(%esp),%edi + andl %ecx,%esi + xorl %edx,%ecx + rorl $7,%ebx + por %xmm2,%xmm0 + movl %eax,%ebp + xorl %ecx,%esi + movdqa 80(%esp),%xmm2 + roll $5,%eax + addl %esi,%edi + xorl %ebx,%ebp + xorl %ecx,%ebx + addl %eax,%edi + pshufd $238,%xmm7,%xmm3 + addl 12(%esp),%edx + andl %ebx,%ebp + xorl %ecx,%ebx + rorl $7,%eax + movl %edi,%esi + xorl %ebx,%ebp + roll $5,%edi + addl %ebp,%edx + xorl %eax,%esi + xorl %ebx,%eax + addl %edi,%edx + addl 16(%esp),%ecx + pxor %xmm5,%xmm1 + punpcklqdq %xmm0,%xmm3 + andl %eax,%esi + xorl %ebx,%eax + rorl $7,%edi + pxor %xmm2,%xmm1 + movdqa %xmm5,80(%esp) + movl %edx,%ebp + xorl %eax,%esi + roll $5,%edx + movdqa %xmm4,%xmm5 + addl %esi,%ecx + paddd %xmm0,%xmm4 + xorl %edi,%ebp + pxor %xmm3,%xmm1 + xorl %eax,%edi + addl %edx,%ecx + addl 20(%esp),%ebx + andl %edi,%ebp + movdqa %xmm1,%xmm3 + movdqa %xmm4,(%esp) + xorl %eax,%edi + rorl $7,%edx + movl %ecx,%esi + xorl %edi,%ebp + roll $5,%ecx + pslld $2,%xmm1 + addl %ebp,%ebx + xorl %edx,%esi + psrld $30,%xmm3 + xorl %edi,%edx + addl %ecx,%ebx + addl 24(%esp),%eax + andl %edx,%esi + xorl %edi,%edx + rorl $7,%ecx + por %xmm3,%xmm1 + movl %ebx,%ebp + xorl %edx,%esi + movdqa 96(%esp),%xmm3 + roll $5,%ebx + addl %esi,%eax + xorl %ecx,%ebp + xorl %edx,%ecx + addl %ebx,%eax + pshufd $238,%xmm0,%xmm4 + addl 28(%esp),%edi + andl %ecx,%ebp + xorl %edx,%ecx + rorl $7,%ebx + movl %eax,%esi + xorl %ecx,%ebp + roll $5,%eax + addl %ebp,%edi + xorl %ebx,%esi + xorl %ecx,%ebx + addl %eax,%edi + addl 32(%esp),%edx + pxor %xmm6,%xmm2 + punpcklqdq %xmm1,%xmm4 + andl %ebx,%esi + xorl %ecx,%ebx + rorl $7,%eax + pxor %xmm3,%xmm2 + movdqa %xmm6,96(%esp) + movl %edi,%ebp + xorl %ebx,%esi + roll $5,%edi + movdqa %xmm5,%xmm6 + addl %esi,%edx + paddd %xmm1,%xmm5 + xorl %eax,%ebp + pxor %xmm4,%xmm2 + xorl %ebx,%eax + addl %edi,%edx + addl 36(%esp),%ecx + andl %eax,%ebp + movdqa %xmm2,%xmm4 + movdqa %xmm5,16(%esp) + xorl %ebx,%eax + rorl $7,%edi + movl %edx,%esi + xorl %eax,%ebp + roll $5,%edx + pslld $2,%xmm2 + addl %ebp,%ecx + xorl %edi,%esi + psrld $30,%xmm4 + xorl %eax,%edi + addl %edx,%ecx + addl 40(%esp),%ebx + andl %edi,%esi + xorl %eax,%edi + rorl $7,%edx + por %xmm4,%xmm2 + movl %ecx,%ebp + xorl %edi,%esi + movdqa 64(%esp),%xmm4 + roll $5,%ecx + addl %esi,%ebx + xorl %edx,%ebp + xorl %edi,%edx + addl %ecx,%ebx + pshufd $238,%xmm1,%xmm5 + addl 44(%esp),%eax + andl %edx,%ebp + xorl %edi,%edx + rorl $7,%ecx + movl %ebx,%esi + xorl %edx,%ebp + roll $5,%ebx + addl %ebp,%eax + xorl %edx,%esi + addl %ebx,%eax + addl 48(%esp),%edi + pxor %xmm7,%xmm3 + punpcklqdq %xmm2,%xmm5 + xorl %ecx,%esi + movl %eax,%ebp + roll $5,%eax + pxor %xmm4,%xmm3 + movdqa %xmm7,64(%esp) + addl %esi,%edi + xorl %ecx,%ebp + movdqa %xmm6,%xmm7 + rorl $7,%ebx + paddd %xmm2,%xmm6 + addl %eax,%edi + pxor %xmm5,%xmm3 + addl 52(%esp),%edx + xorl %ebx,%ebp + movl %edi,%esi + roll $5,%edi + movdqa %xmm3,%xmm5 + movdqa %xmm6,32(%esp) + addl %ebp,%edx + xorl %ebx,%esi + rorl $7,%eax + addl %edi,%edx + pslld $2,%xmm3 + addl 56(%esp),%ecx + xorl %eax,%esi + psrld $30,%xmm5 + movl %edx,%ebp + roll $5,%edx + addl %esi,%ecx + xorl %eax,%ebp + rorl $7,%edi + addl %edx,%ecx + por %xmm5,%xmm3 + addl 60(%esp),%ebx + xorl %edi,%ebp + movl %ecx,%esi + roll $5,%ecx + addl %ebp,%ebx + xorl %edi,%esi + rorl $7,%edx + addl %ecx,%ebx + addl (%esp),%eax + xorl %edx,%esi + movl %ebx,%ebp + roll $5,%ebx + addl %esi,%eax + xorl %edx,%ebp + rorl $7,%ecx + paddd %xmm3,%xmm7 + addl %ebx,%eax + addl 4(%esp),%edi + xorl %ecx,%ebp + movl %eax,%esi + movdqa %xmm7,48(%esp) + roll $5,%eax + addl %ebp,%edi + xorl %ecx,%esi + rorl $7,%ebx + addl %eax,%edi + addl 8(%esp),%edx + xorl %ebx,%esi + movl %edi,%ebp + roll $5,%edi + addl %esi,%edx + xorl %ebx,%ebp + rorl $7,%eax + addl %edi,%edx + addl 12(%esp),%ecx + xorl %eax,%ebp + movl %edx,%esi + roll $5,%edx + addl %ebp,%ecx + xorl %eax,%esi + rorl $7,%edi + addl %edx,%ecx + movl 196(%esp),%ebp + cmpl 200(%esp),%ebp + je .L007done + movdqa 160(%esp),%xmm7 + movdqa 176(%esp),%xmm6 + movdqu (%ebp),%xmm0 + movdqu 16(%ebp),%xmm1 + movdqu 32(%ebp),%xmm2 + movdqu 48(%ebp),%xmm3 + addl $64,%ebp +.byte 102,15,56,0,198 + movl %ebp,196(%esp) + movdqa %xmm7,96(%esp) + addl 16(%esp),%ebx + xorl %edi,%esi + movl %ecx,%ebp + roll $5,%ecx + addl %esi,%ebx + xorl %edi,%ebp + rorl $7,%edx +.byte 102,15,56,0,206 + addl %ecx,%ebx + addl 20(%esp),%eax + xorl %edx,%ebp + movl %ebx,%esi + paddd %xmm7,%xmm0 + roll $5,%ebx + addl %ebp,%eax + xorl %edx,%esi + rorl $7,%ecx + movdqa %xmm0,(%esp) + addl %ebx,%eax + addl 24(%esp),%edi + xorl %ecx,%esi + movl %eax,%ebp + psubd %xmm7,%xmm0 + roll $5,%eax + addl %esi,%edi + xorl %ecx,%ebp + rorl $7,%ebx + addl %eax,%edi + addl 28(%esp),%edx + xorl %ebx,%ebp + movl %edi,%esi + roll $5,%edi + addl %ebp,%edx + xorl %ebx,%esi + rorl $7,%eax + addl %edi,%edx + addl 32(%esp),%ecx + xorl %eax,%esi + movl %edx,%ebp + roll $5,%edx + addl %esi,%ecx + xorl %eax,%ebp + rorl $7,%edi +.byte 102,15,56,0,214 + addl %edx,%ecx + addl 36(%esp),%ebx + xorl %edi,%ebp + movl %ecx,%esi + paddd %xmm7,%xmm1 + roll $5,%ecx + addl %ebp,%ebx + xorl %edi,%esi + rorl $7,%edx + movdqa %xmm1,16(%esp) + addl %ecx,%ebx + addl 40(%esp),%eax + xorl %edx,%esi + movl %ebx,%ebp + psubd %xmm7,%xmm1 + roll $5,%ebx + addl %esi,%eax + xorl %edx,%ebp + rorl $7,%ecx + addl %ebx,%eax + addl 44(%esp),%edi + xorl %ecx,%ebp + movl %eax,%esi + roll $5,%eax + addl %ebp,%edi + xorl %ecx,%esi + rorl $7,%ebx + addl %eax,%edi + addl 48(%esp),%edx + xorl %ebx,%esi + movl %edi,%ebp + roll $5,%edi + addl %esi,%edx + xorl %ebx,%ebp + rorl $7,%eax +.byte 102,15,56,0,222 + addl %edi,%edx + addl 52(%esp),%ecx + xorl %eax,%ebp + movl %edx,%esi + paddd %xmm7,%xmm2 + roll $5,%edx + addl %ebp,%ecx + xorl %eax,%esi + rorl $7,%edi + movdqa %xmm2,32(%esp) + addl %edx,%ecx + addl 56(%esp),%ebx + xorl %edi,%esi + movl %ecx,%ebp + psubd %xmm7,%xmm2 + roll $5,%ecx + addl %esi,%ebx + xorl %edi,%ebp + rorl $7,%edx + addl %ecx,%ebx + addl 60(%esp),%eax + xorl %edx,%ebp + movl %ebx,%esi + roll $5,%ebx + addl %ebp,%eax + rorl $7,%ecx + addl %ebx,%eax + movl 192(%esp),%ebp + addl (%ebp),%eax + addl 4(%ebp),%esi + addl 8(%ebp),%ecx + movl %eax,(%ebp) + addl 12(%ebp),%edx + movl %esi,4(%ebp) + addl 16(%ebp),%edi + movl %ecx,8(%ebp) + movl %ecx,%ebx + movl %edx,12(%ebp) + xorl %edx,%ebx + movl %edi,16(%ebp) + movl %esi,%ebp + pshufd $238,%xmm0,%xmm4 + andl %ebx,%esi + movl %ebp,%ebx + jmp .L006loop +.align 16 +.L007done: + addl 16(%esp),%ebx + xorl %edi,%esi + movl %ecx,%ebp + roll $5,%ecx + addl %esi,%ebx + xorl %edi,%ebp + rorl $7,%edx + addl %ecx,%ebx + addl 20(%esp),%eax + xorl %edx,%ebp + movl %ebx,%esi + roll $5,%ebx + addl %ebp,%eax + xorl %edx,%esi + rorl $7,%ecx + addl %ebx,%eax + addl 24(%esp),%edi + xorl %ecx,%esi + movl %eax,%ebp + roll $5,%eax + addl %esi,%edi + xorl %ecx,%ebp + rorl $7,%ebx + addl %eax,%edi + addl 28(%esp),%edx + xorl %ebx,%ebp + movl %edi,%esi + roll $5,%edi + addl %ebp,%edx + xorl %ebx,%esi + rorl $7,%eax + addl %edi,%edx + addl 32(%esp),%ecx + xorl %eax,%esi + movl %edx,%ebp + roll $5,%edx + addl %esi,%ecx + xorl %eax,%ebp + rorl $7,%edi + addl %edx,%ecx + addl 36(%esp),%ebx + xorl %edi,%ebp + movl %ecx,%esi + roll $5,%ecx + addl %ebp,%ebx + xorl %edi,%esi + rorl $7,%edx + addl %ecx,%ebx + addl 40(%esp),%eax + xorl %edx,%esi + movl %ebx,%ebp + roll $5,%ebx + addl %esi,%eax + xorl %edx,%ebp + rorl $7,%ecx + addl %ebx,%eax + addl 44(%esp),%edi + xorl %ecx,%ebp + movl %eax,%esi + roll $5,%eax + addl %ebp,%edi + xorl %ecx,%esi + rorl $7,%ebx + addl %eax,%edi + addl 48(%esp),%edx + xorl %ebx,%esi + movl %edi,%ebp + roll $5,%edi + addl %esi,%edx + xorl %ebx,%ebp + rorl $7,%eax + addl %edi,%edx + addl 52(%esp),%ecx + xorl %eax,%ebp + movl %edx,%esi + roll $5,%edx + addl %ebp,%ecx + xorl %eax,%esi + rorl $7,%edi + addl %edx,%ecx + addl 56(%esp),%ebx + xorl %edi,%esi + movl %ecx,%ebp + roll $5,%ecx + addl %esi,%ebx + xorl %edi,%ebp + rorl $7,%edx + addl %ecx,%ebx + addl 60(%esp),%eax + xorl %edx,%ebp + movl %ebx,%esi + roll $5,%ebx + addl %ebp,%eax + rorl $7,%ecx + addl %ebx,%eax + movl 192(%esp),%ebp + addl (%ebp),%eax + movl 204(%esp),%esp + addl 4(%ebp),%esi + addl 8(%ebp),%ecx + movl %eax,(%ebp) + addl 12(%ebp),%edx + movl %esi,4(%ebp) + addl 16(%ebp),%edi + movl %ecx,8(%ebp) + movl %edx,12(%ebp) + movl %edi,16(%ebp) + popl %edi + popl %esi + popl %ebx + popl %ebp + ret +.size _sha1_block_data_order_ssse3,.-_sha1_block_data_order_ssse3 +.align 64 +.LK_XX_XX: +.long 1518500249,1518500249,1518500249,1518500249 +.long 1859775393,1859775393,1859775393,1859775393 +.long 2400959708,2400959708,2400959708,2400959708 +.long 3395469782,3395469782,3395469782,3395469782 +.long 66051,67438087,134810123,202182159 +.byte 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 .byte 83,72,65,49,32,98,108,111,99,107,32,116,114,97,110,115 .byte 102,111,114,109,32,102,111,114,32,120,56,54,44,32,67,82 .byte 89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112 diff --git a/third_party/boringssl/linux-x86/crypto/sha/sha256-586.S b/third_party/boringssl/linux-x86/crypto/sha/sha256-586.S index fe41afcafa10c..08d948432bc22 100644 --- a/third_party/boringssl/linux-x86/crypto/sha/sha256-586.S +++ b/third_party/boringssl/linux-x86/crypto/sha/sha256-586.S @@ -27,6 +27,27 @@ sha256_block_data_order: movl %edi,4(%esp) movl %eax,8(%esp) movl %ebx,12(%esp) + leal OPENSSL_ia32cap_P-.L001K256(%ebp),%edx + movl (%edx),%ecx + movl 4(%edx),%ebx + testl $1048576,%ecx + jnz .L002loop + movl 8(%edx),%edx + testl $16777216,%ecx + jz .L003no_xmm + andl $1073741824,%ecx + andl $268435968,%ebx + testl $536870912,%edx + jnz .L004shaext + orl %ebx,%ecx + andl $1342177280,%ecx + cmpl $1342177280,%ecx + testl $512,%ebx + jnz .L005SSSE3 +.L003no_xmm: + subl %edi,%eax + cmpl $256,%eax + jae .L006unrolled jmp .L002loop .align 16 .L002loop: @@ -98,7 +119,7 @@ sha256_block_data_order: movl %ecx,28(%esp) movl %edi,32(%esp) .align 16 -.L00300_15: +.L00700_15: movl %edx,%ecx movl 24(%esp),%esi rorl $14,%ecx @@ -136,11 +157,11 @@ sha256_block_data_order: addl $4,%ebp addl %ebx,%eax cmpl $3248222580,%esi - jne .L00300_15 + jne .L00700_15 movl 156(%esp),%ecx - jmp .L00416_63 + jmp .L00816_63 .align 16 -.L00416_63: +.L00816_63: movl %ecx,%ebx movl 104(%esp),%esi rorl $11,%ecx @@ -195,7 +216,7 @@ sha256_block_data_order: addl $4,%ebp addl %ebx,%eax cmpl $3329325298,%esi - jne .L00416_63 + jne .L00816_63 movl 356(%esp),%esi movl 8(%esp),%ebx movl 16(%esp),%ecx @@ -229,207 +250,6 @@ sha256_block_data_order: popl %ebx popl %ebp ret -.align 32 -.L005loop_shrd: - movl (%edi),%eax - movl 4(%edi),%ebx - movl 8(%edi),%ecx - bswap %eax - movl 12(%edi),%edx - bswap %ebx - pushl %eax - bswap %ecx - pushl %ebx - bswap %edx - pushl %ecx - pushl %edx - movl 16(%edi),%eax - movl 20(%edi),%ebx - movl 24(%edi),%ecx - bswap %eax - movl 28(%edi),%edx - bswap %ebx - pushl %eax - bswap %ecx - pushl %ebx - bswap %edx - pushl %ecx - pushl %edx - movl 32(%edi),%eax - movl 36(%edi),%ebx - movl 40(%edi),%ecx - bswap %eax - movl 44(%edi),%edx - bswap %ebx - pushl %eax - bswap %ecx - pushl %ebx - bswap %edx - pushl %ecx - pushl %edx - movl 48(%edi),%eax - movl 52(%edi),%ebx - movl 56(%edi),%ecx - bswap %eax - movl 60(%edi),%edx - bswap %ebx - pushl %eax - bswap %ecx - pushl %ebx - bswap %edx - pushl %ecx - pushl %edx - addl $64,%edi - leal -36(%esp),%esp - movl %edi,104(%esp) - movl (%esi),%eax - movl 4(%esi),%ebx - movl 8(%esi),%ecx - movl 12(%esi),%edi - movl %ebx,8(%esp) - xorl %ecx,%ebx - movl %ecx,12(%esp) - movl %edi,16(%esp) - movl %ebx,(%esp) - movl 16(%esi),%edx - movl 20(%esi),%ebx - movl 24(%esi),%ecx - movl 28(%esi),%edi - movl %ebx,24(%esp) - movl %ecx,28(%esp) - movl %edi,32(%esp) -.align 16 -.L00600_15_shrd: - movl %edx,%ecx - movl 24(%esp),%esi - shrdl $14,%ecx,%ecx - movl 28(%esp),%edi - xorl %edx,%ecx - xorl %edi,%esi - movl 96(%esp),%ebx - shrdl $5,%ecx,%ecx - andl %edx,%esi - movl %edx,20(%esp) - xorl %ecx,%edx - addl 32(%esp),%ebx - xorl %edi,%esi - shrdl $6,%edx,%edx - movl %eax,%ecx - addl %esi,%ebx - shrdl $9,%ecx,%ecx - addl %edx,%ebx - movl 8(%esp),%edi - xorl %eax,%ecx - movl %eax,4(%esp) - leal -4(%esp),%esp - shrdl $11,%ecx,%ecx - movl (%ebp),%esi - xorl %eax,%ecx - movl 20(%esp),%edx - xorl %edi,%eax - shrdl $2,%ecx,%ecx - addl %esi,%ebx - movl %eax,(%esp) - addl %ebx,%edx - andl 4(%esp),%eax - addl %ecx,%ebx - xorl %edi,%eax - addl $4,%ebp - addl %ebx,%eax - cmpl $3248222580,%esi - jne .L00600_15_shrd - movl 156(%esp),%ecx - jmp .L00716_63_shrd -.align 16 -.L00716_63_shrd: - movl %ecx,%ebx - movl 104(%esp),%esi - shrdl $11,%ecx,%ecx - movl %esi,%edi - shrdl $2,%esi,%esi - xorl %ebx,%ecx - shrl $3,%ebx - shrdl $7,%ecx,%ecx - xorl %edi,%esi - xorl %ecx,%ebx - shrdl $17,%esi,%esi - addl 160(%esp),%ebx - shrl $10,%edi - addl 124(%esp),%ebx - movl %edx,%ecx - xorl %esi,%edi - movl 24(%esp),%esi - shrdl $14,%ecx,%ecx - addl %edi,%ebx - movl 28(%esp),%edi - xorl %edx,%ecx - xorl %edi,%esi - movl %ebx,96(%esp) - shrdl $5,%ecx,%ecx - andl %edx,%esi - movl %edx,20(%esp) - xorl %ecx,%edx - addl 32(%esp),%ebx - xorl %edi,%esi - shrdl $6,%edx,%edx - movl %eax,%ecx - addl %esi,%ebx - shrdl $9,%ecx,%ecx - addl %edx,%ebx - movl 8(%esp),%edi - xorl %eax,%ecx - movl %eax,4(%esp) - leal -4(%esp),%esp - shrdl $11,%ecx,%ecx - movl (%ebp),%esi - xorl %eax,%ecx - movl 20(%esp),%edx - xorl %edi,%eax - shrdl $2,%ecx,%ecx - addl %esi,%ebx - movl %eax,(%esp) - addl %ebx,%edx - andl 4(%esp),%eax - addl %ecx,%ebx - xorl %edi,%eax - movl 156(%esp),%ecx - addl $4,%ebp - addl %ebx,%eax - cmpl $3329325298,%esi - jne .L00716_63_shrd - movl 356(%esp),%esi - movl 8(%esp),%ebx - movl 16(%esp),%ecx - addl (%esi),%eax - addl 4(%esi),%ebx - addl 8(%esi),%edi - addl 12(%esi),%ecx - movl %eax,(%esi) - movl %ebx,4(%esi) - movl %edi,8(%esi) - movl %ecx,12(%esi) - movl 24(%esp),%eax - movl 28(%esp),%ebx - movl 32(%esp),%ecx - movl 360(%esp),%edi - addl 16(%esi),%edx - addl 20(%esi),%eax - addl 24(%esi),%ebx - addl 28(%esi),%ecx - movl %edx,16(%esi) - movl %eax,20(%esi) - movl %ebx,24(%esi) - movl %ecx,28(%esi) - leal 356(%esp),%esp - subl $256,%ebp - cmpl 8(%esp),%edi - jb .L005loop_shrd - movl 12(%esp),%esp - popl %edi - popl %esi - popl %ebx - popl %ebp - ret .align 64 .L001K256: .long 1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298 @@ -440,7 +260,7 @@ sha256_block_data_order: .byte 112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103 .byte 62,0 .align 16 -.L008unrolled: +.L006unrolled: leal -96(%esp),%esp movl (%esi),%eax movl 4(%esi),%ebp @@ -3346,5 +3166,1414 @@ sha256_block_data_order: popl %ebx popl %ebp ret +.align 32 +.L004shaext: + subl $32,%esp + movdqu (%esi),%xmm1 + leal 128(%ebp),%ebp + movdqu 16(%esi),%xmm2 + movdqa 128(%ebp),%xmm7 + pshufd $27,%xmm1,%xmm0 + pshufd $177,%xmm1,%xmm1 + pshufd $27,%xmm2,%xmm2 +.byte 102,15,58,15,202,8 + punpcklqdq %xmm0,%xmm2 + jmp .L010loop_shaext +.align 16 +.L010loop_shaext: + movdqu (%edi),%xmm3 + movdqu 16(%edi),%xmm4 + movdqu 32(%edi),%xmm5 +.byte 102,15,56,0,223 + movdqu 48(%edi),%xmm6 + movdqa %xmm2,16(%esp) + movdqa -128(%ebp),%xmm0 + paddd %xmm3,%xmm0 +.byte 102,15,56,0,231 +.byte 15,56,203,209 + pshufd $14,%xmm0,%xmm0 + nop + movdqa %xmm1,(%esp) +.byte 15,56,203,202 + movdqa -112(%ebp),%xmm0 + paddd %xmm4,%xmm0 +.byte 102,15,56,0,239 +.byte 15,56,203,209 + pshufd $14,%xmm0,%xmm0 + leal 64(%edi),%edi +.byte 15,56,204,220 +.byte 15,56,203,202 + movdqa -96(%ebp),%xmm0 + paddd %xmm5,%xmm0 +.byte 102,15,56,0,247 +.byte 15,56,203,209 + pshufd $14,%xmm0,%xmm0 + movdqa %xmm6,%xmm7 +.byte 102,15,58,15,253,4 + nop + paddd %xmm7,%xmm3 +.byte 15,56,204,229 +.byte 15,56,203,202 + movdqa -80(%ebp),%xmm0 + paddd %xmm6,%xmm0 +.byte 15,56,205,222 +.byte 15,56,203,209 + pshufd $14,%xmm0,%xmm0 + movdqa %xmm3,%xmm7 +.byte 102,15,58,15,254,4 + nop + paddd %xmm7,%xmm4 +.byte 15,56,204,238 +.byte 15,56,203,202 + movdqa -64(%ebp),%xmm0 + paddd %xmm3,%xmm0 +.byte 15,56,205,227 +.byte 15,56,203,209 + pshufd $14,%xmm0,%xmm0 + movdqa %xmm4,%xmm7 +.byte 102,15,58,15,251,4 + nop + paddd %xmm7,%xmm5 +.byte 15,56,204,243 +.byte 15,56,203,202 + movdqa -48(%ebp),%xmm0 + paddd %xmm4,%xmm0 +.byte 15,56,205,236 +.byte 15,56,203,209 + pshufd $14,%xmm0,%xmm0 + movdqa %xmm5,%xmm7 +.byte 102,15,58,15,252,4 + nop + paddd %xmm7,%xmm6 +.byte 15,56,204,220 +.byte 15,56,203,202 + movdqa -32(%ebp),%xmm0 + paddd %xmm5,%xmm0 +.byte 15,56,205,245 +.byte 15,56,203,209 + pshufd $14,%xmm0,%xmm0 + movdqa %xmm6,%xmm7 +.byte 102,15,58,15,253,4 + nop + paddd %xmm7,%xmm3 +.byte 15,56,204,229 +.byte 15,56,203,202 + movdqa -16(%ebp),%xmm0 + paddd %xmm6,%xmm0 +.byte 15,56,205,222 +.byte 15,56,203,209 + pshufd $14,%xmm0,%xmm0 + movdqa %xmm3,%xmm7 +.byte 102,15,58,15,254,4 + nop + paddd %xmm7,%xmm4 +.byte 15,56,204,238 +.byte 15,56,203,202 + movdqa (%ebp),%xmm0 + paddd %xmm3,%xmm0 +.byte 15,56,205,227 +.byte 15,56,203,209 + pshufd $14,%xmm0,%xmm0 + movdqa %xmm4,%xmm7 +.byte 102,15,58,15,251,4 + nop + paddd %xmm7,%xmm5 +.byte 15,56,204,243 +.byte 15,56,203,202 + movdqa 16(%ebp),%xmm0 + paddd %xmm4,%xmm0 +.byte 15,56,205,236 +.byte 15,56,203,209 + pshufd $14,%xmm0,%xmm0 + movdqa %xmm5,%xmm7 +.byte 102,15,58,15,252,4 + nop + paddd %xmm7,%xmm6 +.byte 15,56,204,220 +.byte 15,56,203,202 + movdqa 32(%ebp),%xmm0 + paddd %xmm5,%xmm0 +.byte 15,56,205,245 +.byte 15,56,203,209 + pshufd $14,%xmm0,%xmm0 + movdqa %xmm6,%xmm7 +.byte 102,15,58,15,253,4 + nop + paddd %xmm7,%xmm3 +.byte 15,56,204,229 +.byte 15,56,203,202 + movdqa 48(%ebp),%xmm0 + paddd %xmm6,%xmm0 +.byte 15,56,205,222 +.byte 15,56,203,209 + pshufd $14,%xmm0,%xmm0 + movdqa %xmm3,%xmm7 +.byte 102,15,58,15,254,4 + nop + paddd %xmm7,%xmm4 +.byte 15,56,204,238 +.byte 15,56,203,202 + movdqa 64(%ebp),%xmm0 + paddd %xmm3,%xmm0 +.byte 15,56,205,227 +.byte 15,56,203,209 + pshufd $14,%xmm0,%xmm0 + movdqa %xmm4,%xmm7 +.byte 102,15,58,15,251,4 + nop + paddd %xmm7,%xmm5 +.byte 15,56,204,243 +.byte 15,56,203,202 + movdqa 80(%ebp),%xmm0 + paddd %xmm4,%xmm0 +.byte 15,56,205,236 +.byte 15,56,203,209 + pshufd $14,%xmm0,%xmm0 + movdqa %xmm5,%xmm7 +.byte 102,15,58,15,252,4 +.byte 15,56,203,202 + paddd %xmm7,%xmm6 + movdqa 96(%ebp),%xmm0 + paddd %xmm5,%xmm0 +.byte 15,56,203,209 + pshufd $14,%xmm0,%xmm0 +.byte 15,56,205,245 + movdqa 128(%ebp),%xmm7 +.byte 15,56,203,202 + movdqa 112(%ebp),%xmm0 + paddd %xmm6,%xmm0 + nop +.byte 15,56,203,209 + pshufd $14,%xmm0,%xmm0 + cmpl %edi,%eax + nop +.byte 15,56,203,202 + paddd 16(%esp),%xmm2 + paddd (%esp),%xmm1 + jnz .L010loop_shaext + pshufd $177,%xmm2,%xmm2 + pshufd $27,%xmm1,%xmm7 + pshufd $177,%xmm1,%xmm1 + punpckhqdq %xmm2,%xmm1 +.byte 102,15,58,15,215,8 + movl 44(%esp),%esp + movdqu %xmm1,(%esi) + movdqu %xmm2,16(%esi) + popl %edi + popl %esi + popl %ebx + popl %ebp + ret +.align 32 +.L005SSSE3: + leal -96(%esp),%esp + movl (%esi),%eax + movl 4(%esi),%ebx + movl 8(%esi),%ecx + movl 12(%esi),%edi + movl %ebx,4(%esp) + xorl %ecx,%ebx + movl %ecx,8(%esp) + movl %edi,12(%esp) + movl 16(%esi),%edx + movl 20(%esi),%edi + movl 24(%esi),%ecx + movl 28(%esi),%esi + movl %edi,20(%esp) + movl 100(%esp),%edi + movl %ecx,24(%esp) + movl %esi,28(%esp) + movdqa 256(%ebp),%xmm7 + jmp .L011grand_ssse3 +.align 16 +.L011grand_ssse3: + movdqu (%edi),%xmm0 + movdqu 16(%edi),%xmm1 + movdqu 32(%edi),%xmm2 + movdqu 48(%edi),%xmm3 + addl $64,%edi +.byte 102,15,56,0,199 + movl %edi,100(%esp) +.byte 102,15,56,0,207 + movdqa (%ebp),%xmm4 +.byte 102,15,56,0,215 + movdqa 16(%ebp),%xmm5 + paddd %xmm0,%xmm4 +.byte 102,15,56,0,223 + movdqa 32(%ebp),%xmm6 + paddd %xmm1,%xmm5 + movdqa 48(%ebp),%xmm7 + movdqa %xmm4,32(%esp) + paddd %xmm2,%xmm6 + movdqa %xmm5,48(%esp) + paddd %xmm3,%xmm7 + movdqa %xmm6,64(%esp) + movdqa %xmm7,80(%esp) + jmp .L012ssse3_00_47 +.align 16 +.L012ssse3_00_47: + addl $64,%ebp + movl %edx,%ecx + movdqa %xmm1,%xmm4 + rorl $14,%edx + movl 20(%esp),%esi + movdqa %xmm3,%xmm7 + xorl %ecx,%edx + movl 24(%esp),%edi +.byte 102,15,58,15,224,4 + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi +.byte 102,15,58,15,250,4 + movl %ecx,16(%esp) + xorl %ecx,%edx + xorl %esi,%edi + movdqa %xmm4,%xmm5 + rorl $6,%edx + movl %eax,%ecx + movdqa %xmm4,%xmm6 + addl %edi,%edx + movl 4(%esp),%edi + psrld $3,%xmm4 + movl %eax,%esi + rorl $9,%ecx + paddd %xmm7,%xmm0 + movl %eax,(%esp) + xorl %eax,%ecx + psrld $7,%xmm6 + xorl %edi,%eax + addl 28(%esp),%edx + rorl $11,%ecx + andl %eax,%ebx + pshufd $250,%xmm3,%xmm7 + xorl %esi,%ecx + addl 32(%esp),%edx + pslld $14,%xmm5 + xorl %edi,%ebx + rorl $2,%ecx + pxor %xmm6,%xmm4 + addl %edx,%ebx + addl 12(%esp),%edx + psrld $11,%xmm6 + addl %ecx,%ebx + movl %edx,%ecx + rorl $14,%edx + pxor %xmm5,%xmm4 + movl 16(%esp),%esi + xorl %ecx,%edx + pslld $11,%xmm5 + movl 20(%esp),%edi + xorl %edi,%esi + rorl $5,%edx + pxor %xmm6,%xmm4 + andl %ecx,%esi + movl %ecx,12(%esp) + movdqa %xmm7,%xmm6 + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + pxor %xmm5,%xmm4 + movl %ebx,%ecx + addl %edi,%edx + psrld $10,%xmm7 + movl (%esp),%edi + movl %ebx,%esi + rorl $9,%ecx + paddd %xmm4,%xmm0 + movl %ebx,28(%esp) + xorl %ebx,%ecx + psrlq $17,%xmm6 + xorl %edi,%ebx + addl 24(%esp),%edx + rorl $11,%ecx + pxor %xmm6,%xmm7 + andl %ebx,%eax + xorl %esi,%ecx + psrlq $2,%xmm6 + addl 36(%esp),%edx + xorl %edi,%eax + rorl $2,%ecx + pxor %xmm6,%xmm7 + addl %edx,%eax + addl 8(%esp),%edx + pshufd $128,%xmm7,%xmm7 + addl %ecx,%eax + movl %edx,%ecx + rorl $14,%edx + movl 12(%esp),%esi + xorl %ecx,%edx + movl 16(%esp),%edi + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi + psrldq $8,%xmm7 + movl %ecx,8(%esp) + xorl %ecx,%edx + xorl %esi,%edi + paddd %xmm7,%xmm0 + rorl $6,%edx + movl %eax,%ecx + addl %edi,%edx + movl 28(%esp),%edi + movl %eax,%esi + rorl $9,%ecx + movl %eax,24(%esp) + pshufd $80,%xmm0,%xmm7 + xorl %eax,%ecx + xorl %edi,%eax + addl 20(%esp),%edx + movdqa %xmm7,%xmm6 + rorl $11,%ecx + psrld $10,%xmm7 + andl %eax,%ebx + psrlq $17,%xmm6 + xorl %esi,%ecx + addl 40(%esp),%edx + xorl %edi,%ebx + rorl $2,%ecx + pxor %xmm6,%xmm7 + addl %edx,%ebx + addl 4(%esp),%edx + psrlq $2,%xmm6 + addl %ecx,%ebx + movl %edx,%ecx + rorl $14,%edx + pxor %xmm6,%xmm7 + movl 8(%esp),%esi + xorl %ecx,%edx + movl 12(%esp),%edi + pshufd $8,%xmm7,%xmm7 + xorl %edi,%esi + rorl $5,%edx + movdqa (%ebp),%xmm6 + andl %ecx,%esi + movl %ecx,4(%esp) + pslldq $8,%xmm7 + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + movl %ebx,%ecx + addl %edi,%edx + movl 24(%esp),%edi + movl %ebx,%esi + rorl $9,%ecx + paddd %xmm7,%xmm0 + movl %ebx,20(%esp) + xorl %ebx,%ecx + xorl %edi,%ebx + addl 16(%esp),%edx + paddd %xmm0,%xmm6 + rorl $11,%ecx + andl %ebx,%eax + xorl %esi,%ecx + addl 44(%esp),%edx + xorl %edi,%eax + rorl $2,%ecx + addl %edx,%eax + addl (%esp),%edx + addl %ecx,%eax + movdqa %xmm6,32(%esp) + movl %edx,%ecx + movdqa %xmm2,%xmm4 + rorl $14,%edx + movl 4(%esp),%esi + movdqa %xmm0,%xmm7 + xorl %ecx,%edx + movl 8(%esp),%edi +.byte 102,15,58,15,225,4 + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi +.byte 102,15,58,15,251,4 + movl %ecx,(%esp) + xorl %ecx,%edx + xorl %esi,%edi + movdqa %xmm4,%xmm5 + rorl $6,%edx + movl %eax,%ecx + movdqa %xmm4,%xmm6 + addl %edi,%edx + movl 20(%esp),%edi + psrld $3,%xmm4 + movl %eax,%esi + rorl $9,%ecx + paddd %xmm7,%xmm1 + movl %eax,16(%esp) + xorl %eax,%ecx + psrld $7,%xmm6 + xorl %edi,%eax + addl 12(%esp),%edx + rorl $11,%ecx + andl %eax,%ebx + pshufd $250,%xmm0,%xmm7 + xorl %esi,%ecx + addl 48(%esp),%edx + pslld $14,%xmm5 + xorl %edi,%ebx + rorl $2,%ecx + pxor %xmm6,%xmm4 + addl %edx,%ebx + addl 28(%esp),%edx + psrld $11,%xmm6 + addl %ecx,%ebx + movl %edx,%ecx + rorl $14,%edx + pxor %xmm5,%xmm4 + movl (%esp),%esi + xorl %ecx,%edx + pslld $11,%xmm5 + movl 4(%esp),%edi + xorl %edi,%esi + rorl $5,%edx + pxor %xmm6,%xmm4 + andl %ecx,%esi + movl %ecx,28(%esp) + movdqa %xmm7,%xmm6 + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + pxor %xmm5,%xmm4 + movl %ebx,%ecx + addl %edi,%edx + psrld $10,%xmm7 + movl 16(%esp),%edi + movl %ebx,%esi + rorl $9,%ecx + paddd %xmm4,%xmm1 + movl %ebx,12(%esp) + xorl %ebx,%ecx + psrlq $17,%xmm6 + xorl %edi,%ebx + addl 8(%esp),%edx + rorl $11,%ecx + pxor %xmm6,%xmm7 + andl %ebx,%eax + xorl %esi,%ecx + psrlq $2,%xmm6 + addl 52(%esp),%edx + xorl %edi,%eax + rorl $2,%ecx + pxor %xmm6,%xmm7 + addl %edx,%eax + addl 24(%esp),%edx + pshufd $128,%xmm7,%xmm7 + addl %ecx,%eax + movl %edx,%ecx + rorl $14,%edx + movl 28(%esp),%esi + xorl %ecx,%edx + movl (%esp),%edi + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi + psrldq $8,%xmm7 + movl %ecx,24(%esp) + xorl %ecx,%edx + xorl %esi,%edi + paddd %xmm7,%xmm1 + rorl $6,%edx + movl %eax,%ecx + addl %edi,%edx + movl 12(%esp),%edi + movl %eax,%esi + rorl $9,%ecx + movl %eax,8(%esp) + pshufd $80,%xmm1,%xmm7 + xorl %eax,%ecx + xorl %edi,%eax + addl 4(%esp),%edx + movdqa %xmm7,%xmm6 + rorl $11,%ecx + psrld $10,%xmm7 + andl %eax,%ebx + psrlq $17,%xmm6 + xorl %esi,%ecx + addl 56(%esp),%edx + xorl %edi,%ebx + rorl $2,%ecx + pxor %xmm6,%xmm7 + addl %edx,%ebx + addl 20(%esp),%edx + psrlq $2,%xmm6 + addl %ecx,%ebx + movl %edx,%ecx + rorl $14,%edx + pxor %xmm6,%xmm7 + movl 24(%esp),%esi + xorl %ecx,%edx + movl 28(%esp),%edi + pshufd $8,%xmm7,%xmm7 + xorl %edi,%esi + rorl $5,%edx + movdqa 16(%ebp),%xmm6 + andl %ecx,%esi + movl %ecx,20(%esp) + pslldq $8,%xmm7 + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + movl %ebx,%ecx + addl %edi,%edx + movl 8(%esp),%edi + movl %ebx,%esi + rorl $9,%ecx + paddd %xmm7,%xmm1 + movl %ebx,4(%esp) + xorl %ebx,%ecx + xorl %edi,%ebx + addl (%esp),%edx + paddd %xmm1,%xmm6 + rorl $11,%ecx + andl %ebx,%eax + xorl %esi,%ecx + addl 60(%esp),%edx + xorl %edi,%eax + rorl $2,%ecx + addl %edx,%eax + addl 16(%esp),%edx + addl %ecx,%eax + movdqa %xmm6,48(%esp) + movl %edx,%ecx + movdqa %xmm3,%xmm4 + rorl $14,%edx + movl 20(%esp),%esi + movdqa %xmm1,%xmm7 + xorl %ecx,%edx + movl 24(%esp),%edi +.byte 102,15,58,15,226,4 + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi +.byte 102,15,58,15,248,4 + movl %ecx,16(%esp) + xorl %ecx,%edx + xorl %esi,%edi + movdqa %xmm4,%xmm5 + rorl $6,%edx + movl %eax,%ecx + movdqa %xmm4,%xmm6 + addl %edi,%edx + movl 4(%esp),%edi + psrld $3,%xmm4 + movl %eax,%esi + rorl $9,%ecx + paddd %xmm7,%xmm2 + movl %eax,(%esp) + xorl %eax,%ecx + psrld $7,%xmm6 + xorl %edi,%eax + addl 28(%esp),%edx + rorl $11,%ecx + andl %eax,%ebx + pshufd $250,%xmm1,%xmm7 + xorl %esi,%ecx + addl 64(%esp),%edx + pslld $14,%xmm5 + xorl %edi,%ebx + rorl $2,%ecx + pxor %xmm6,%xmm4 + addl %edx,%ebx + addl 12(%esp),%edx + psrld $11,%xmm6 + addl %ecx,%ebx + movl %edx,%ecx + rorl $14,%edx + pxor %xmm5,%xmm4 + movl 16(%esp),%esi + xorl %ecx,%edx + pslld $11,%xmm5 + movl 20(%esp),%edi + xorl %edi,%esi + rorl $5,%edx + pxor %xmm6,%xmm4 + andl %ecx,%esi + movl %ecx,12(%esp) + movdqa %xmm7,%xmm6 + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + pxor %xmm5,%xmm4 + movl %ebx,%ecx + addl %edi,%edx + psrld $10,%xmm7 + movl (%esp),%edi + movl %ebx,%esi + rorl $9,%ecx + paddd %xmm4,%xmm2 + movl %ebx,28(%esp) + xorl %ebx,%ecx + psrlq $17,%xmm6 + xorl %edi,%ebx + addl 24(%esp),%edx + rorl $11,%ecx + pxor %xmm6,%xmm7 + andl %ebx,%eax + xorl %esi,%ecx + psrlq $2,%xmm6 + addl 68(%esp),%edx + xorl %edi,%eax + rorl $2,%ecx + pxor %xmm6,%xmm7 + addl %edx,%eax + addl 8(%esp),%edx + pshufd $128,%xmm7,%xmm7 + addl %ecx,%eax + movl %edx,%ecx + rorl $14,%edx + movl 12(%esp),%esi + xorl %ecx,%edx + movl 16(%esp),%edi + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi + psrldq $8,%xmm7 + movl %ecx,8(%esp) + xorl %ecx,%edx + xorl %esi,%edi + paddd %xmm7,%xmm2 + rorl $6,%edx + movl %eax,%ecx + addl %edi,%edx + movl 28(%esp),%edi + movl %eax,%esi + rorl $9,%ecx + movl %eax,24(%esp) + pshufd $80,%xmm2,%xmm7 + xorl %eax,%ecx + xorl %edi,%eax + addl 20(%esp),%edx + movdqa %xmm7,%xmm6 + rorl $11,%ecx + psrld $10,%xmm7 + andl %eax,%ebx + psrlq $17,%xmm6 + xorl %esi,%ecx + addl 72(%esp),%edx + xorl %edi,%ebx + rorl $2,%ecx + pxor %xmm6,%xmm7 + addl %edx,%ebx + addl 4(%esp),%edx + psrlq $2,%xmm6 + addl %ecx,%ebx + movl %edx,%ecx + rorl $14,%edx + pxor %xmm6,%xmm7 + movl 8(%esp),%esi + xorl %ecx,%edx + movl 12(%esp),%edi + pshufd $8,%xmm7,%xmm7 + xorl %edi,%esi + rorl $5,%edx + movdqa 32(%ebp),%xmm6 + andl %ecx,%esi + movl %ecx,4(%esp) + pslldq $8,%xmm7 + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + movl %ebx,%ecx + addl %edi,%edx + movl 24(%esp),%edi + movl %ebx,%esi + rorl $9,%ecx + paddd %xmm7,%xmm2 + movl %ebx,20(%esp) + xorl %ebx,%ecx + xorl %edi,%ebx + addl 16(%esp),%edx + paddd %xmm2,%xmm6 + rorl $11,%ecx + andl %ebx,%eax + xorl %esi,%ecx + addl 76(%esp),%edx + xorl %edi,%eax + rorl $2,%ecx + addl %edx,%eax + addl (%esp),%edx + addl %ecx,%eax + movdqa %xmm6,64(%esp) + movl %edx,%ecx + movdqa %xmm0,%xmm4 + rorl $14,%edx + movl 4(%esp),%esi + movdqa %xmm2,%xmm7 + xorl %ecx,%edx + movl 8(%esp),%edi +.byte 102,15,58,15,227,4 + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi +.byte 102,15,58,15,249,4 + movl %ecx,(%esp) + xorl %ecx,%edx + xorl %esi,%edi + movdqa %xmm4,%xmm5 + rorl $6,%edx + movl %eax,%ecx + movdqa %xmm4,%xmm6 + addl %edi,%edx + movl 20(%esp),%edi + psrld $3,%xmm4 + movl %eax,%esi + rorl $9,%ecx + paddd %xmm7,%xmm3 + movl %eax,16(%esp) + xorl %eax,%ecx + psrld $7,%xmm6 + xorl %edi,%eax + addl 12(%esp),%edx + rorl $11,%ecx + andl %eax,%ebx + pshufd $250,%xmm2,%xmm7 + xorl %esi,%ecx + addl 80(%esp),%edx + pslld $14,%xmm5 + xorl %edi,%ebx + rorl $2,%ecx + pxor %xmm6,%xmm4 + addl %edx,%ebx + addl 28(%esp),%edx + psrld $11,%xmm6 + addl %ecx,%ebx + movl %edx,%ecx + rorl $14,%edx + pxor %xmm5,%xmm4 + movl (%esp),%esi + xorl %ecx,%edx + pslld $11,%xmm5 + movl 4(%esp),%edi + xorl %edi,%esi + rorl $5,%edx + pxor %xmm6,%xmm4 + andl %ecx,%esi + movl %ecx,28(%esp) + movdqa %xmm7,%xmm6 + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + pxor %xmm5,%xmm4 + movl %ebx,%ecx + addl %edi,%edx + psrld $10,%xmm7 + movl 16(%esp),%edi + movl %ebx,%esi + rorl $9,%ecx + paddd %xmm4,%xmm3 + movl %ebx,12(%esp) + xorl %ebx,%ecx + psrlq $17,%xmm6 + xorl %edi,%ebx + addl 8(%esp),%edx + rorl $11,%ecx + pxor %xmm6,%xmm7 + andl %ebx,%eax + xorl %esi,%ecx + psrlq $2,%xmm6 + addl 84(%esp),%edx + xorl %edi,%eax + rorl $2,%ecx + pxor %xmm6,%xmm7 + addl %edx,%eax + addl 24(%esp),%edx + pshufd $128,%xmm7,%xmm7 + addl %ecx,%eax + movl %edx,%ecx + rorl $14,%edx + movl 28(%esp),%esi + xorl %ecx,%edx + movl (%esp),%edi + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi + psrldq $8,%xmm7 + movl %ecx,24(%esp) + xorl %ecx,%edx + xorl %esi,%edi + paddd %xmm7,%xmm3 + rorl $6,%edx + movl %eax,%ecx + addl %edi,%edx + movl 12(%esp),%edi + movl %eax,%esi + rorl $9,%ecx + movl %eax,8(%esp) + pshufd $80,%xmm3,%xmm7 + xorl %eax,%ecx + xorl %edi,%eax + addl 4(%esp),%edx + movdqa %xmm7,%xmm6 + rorl $11,%ecx + psrld $10,%xmm7 + andl %eax,%ebx + psrlq $17,%xmm6 + xorl %esi,%ecx + addl 88(%esp),%edx + xorl %edi,%ebx + rorl $2,%ecx + pxor %xmm6,%xmm7 + addl %edx,%ebx + addl 20(%esp),%edx + psrlq $2,%xmm6 + addl %ecx,%ebx + movl %edx,%ecx + rorl $14,%edx + pxor %xmm6,%xmm7 + movl 24(%esp),%esi + xorl %ecx,%edx + movl 28(%esp),%edi + pshufd $8,%xmm7,%xmm7 + xorl %edi,%esi + rorl $5,%edx + movdqa 48(%ebp),%xmm6 + andl %ecx,%esi + movl %ecx,20(%esp) + pslldq $8,%xmm7 + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + movl %ebx,%ecx + addl %edi,%edx + movl 8(%esp),%edi + movl %ebx,%esi + rorl $9,%ecx + paddd %xmm7,%xmm3 + movl %ebx,4(%esp) + xorl %ebx,%ecx + xorl %edi,%ebx + addl (%esp),%edx + paddd %xmm3,%xmm6 + rorl $11,%ecx + andl %ebx,%eax + xorl %esi,%ecx + addl 92(%esp),%edx + xorl %edi,%eax + rorl $2,%ecx + addl %edx,%eax + addl 16(%esp),%edx + addl %ecx,%eax + movdqa %xmm6,80(%esp) + cmpl $66051,64(%ebp) + jne .L012ssse3_00_47 + movl %edx,%ecx + rorl $14,%edx + movl 20(%esp),%esi + xorl %ecx,%edx + movl 24(%esp),%edi + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi + movl %ecx,16(%esp) + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + movl %eax,%ecx + addl %edi,%edx + movl 4(%esp),%edi + movl %eax,%esi + rorl $9,%ecx + movl %eax,(%esp) + xorl %eax,%ecx + xorl %edi,%eax + addl 28(%esp),%edx + rorl $11,%ecx + andl %eax,%ebx + xorl %esi,%ecx + addl 32(%esp),%edx + xorl %edi,%ebx + rorl $2,%ecx + addl %edx,%ebx + addl 12(%esp),%edx + addl %ecx,%ebx + movl %edx,%ecx + rorl $14,%edx + movl 16(%esp),%esi + xorl %ecx,%edx + movl 20(%esp),%edi + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi + movl %ecx,12(%esp) + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + movl %ebx,%ecx + addl %edi,%edx + movl (%esp),%edi + movl %ebx,%esi + rorl $9,%ecx + movl %ebx,28(%esp) + xorl %ebx,%ecx + xorl %edi,%ebx + addl 24(%esp),%edx + rorl $11,%ecx + andl %ebx,%eax + xorl %esi,%ecx + addl 36(%esp),%edx + xorl %edi,%eax + rorl $2,%ecx + addl %edx,%eax + addl 8(%esp),%edx + addl %ecx,%eax + movl %edx,%ecx + rorl $14,%edx + movl 12(%esp),%esi + xorl %ecx,%edx + movl 16(%esp),%edi + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi + movl %ecx,8(%esp) + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + movl %eax,%ecx + addl %edi,%edx + movl 28(%esp),%edi + movl %eax,%esi + rorl $9,%ecx + movl %eax,24(%esp) + xorl %eax,%ecx + xorl %edi,%eax + addl 20(%esp),%edx + rorl $11,%ecx + andl %eax,%ebx + xorl %esi,%ecx + addl 40(%esp),%edx + xorl %edi,%ebx + rorl $2,%ecx + addl %edx,%ebx + addl 4(%esp),%edx + addl %ecx,%ebx + movl %edx,%ecx + rorl $14,%edx + movl 8(%esp),%esi + xorl %ecx,%edx + movl 12(%esp),%edi + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi + movl %ecx,4(%esp) + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + movl %ebx,%ecx + addl %edi,%edx + movl 24(%esp),%edi + movl %ebx,%esi + rorl $9,%ecx + movl %ebx,20(%esp) + xorl %ebx,%ecx + xorl %edi,%ebx + addl 16(%esp),%edx + rorl $11,%ecx + andl %ebx,%eax + xorl %esi,%ecx + addl 44(%esp),%edx + xorl %edi,%eax + rorl $2,%ecx + addl %edx,%eax + addl (%esp),%edx + addl %ecx,%eax + movl %edx,%ecx + rorl $14,%edx + movl 4(%esp),%esi + xorl %ecx,%edx + movl 8(%esp),%edi + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi + movl %ecx,(%esp) + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + movl %eax,%ecx + addl %edi,%edx + movl 20(%esp),%edi + movl %eax,%esi + rorl $9,%ecx + movl %eax,16(%esp) + xorl %eax,%ecx + xorl %edi,%eax + addl 12(%esp),%edx + rorl $11,%ecx + andl %eax,%ebx + xorl %esi,%ecx + addl 48(%esp),%edx + xorl %edi,%ebx + rorl $2,%ecx + addl %edx,%ebx + addl 28(%esp),%edx + addl %ecx,%ebx + movl %edx,%ecx + rorl $14,%edx + movl (%esp),%esi + xorl %ecx,%edx + movl 4(%esp),%edi + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi + movl %ecx,28(%esp) + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + movl %ebx,%ecx + addl %edi,%edx + movl 16(%esp),%edi + movl %ebx,%esi + rorl $9,%ecx + movl %ebx,12(%esp) + xorl %ebx,%ecx + xorl %edi,%ebx + addl 8(%esp),%edx + rorl $11,%ecx + andl %ebx,%eax + xorl %esi,%ecx + addl 52(%esp),%edx + xorl %edi,%eax + rorl $2,%ecx + addl %edx,%eax + addl 24(%esp),%edx + addl %ecx,%eax + movl %edx,%ecx + rorl $14,%edx + movl 28(%esp),%esi + xorl %ecx,%edx + movl (%esp),%edi + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi + movl %ecx,24(%esp) + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + movl %eax,%ecx + addl %edi,%edx + movl 12(%esp),%edi + movl %eax,%esi + rorl $9,%ecx + movl %eax,8(%esp) + xorl %eax,%ecx + xorl %edi,%eax + addl 4(%esp),%edx + rorl $11,%ecx + andl %eax,%ebx + xorl %esi,%ecx + addl 56(%esp),%edx + xorl %edi,%ebx + rorl $2,%ecx + addl %edx,%ebx + addl 20(%esp),%edx + addl %ecx,%ebx + movl %edx,%ecx + rorl $14,%edx + movl 24(%esp),%esi + xorl %ecx,%edx + movl 28(%esp),%edi + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi + movl %ecx,20(%esp) + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + movl %ebx,%ecx + addl %edi,%edx + movl 8(%esp),%edi + movl %ebx,%esi + rorl $9,%ecx + movl %ebx,4(%esp) + xorl %ebx,%ecx + xorl %edi,%ebx + addl (%esp),%edx + rorl $11,%ecx + andl %ebx,%eax + xorl %esi,%ecx + addl 60(%esp),%edx + xorl %edi,%eax + rorl $2,%ecx + addl %edx,%eax + addl 16(%esp),%edx + addl %ecx,%eax + movl %edx,%ecx + rorl $14,%edx + movl 20(%esp),%esi + xorl %ecx,%edx + movl 24(%esp),%edi + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi + movl %ecx,16(%esp) + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + movl %eax,%ecx + addl %edi,%edx + movl 4(%esp),%edi + movl %eax,%esi + rorl $9,%ecx + movl %eax,(%esp) + xorl %eax,%ecx + xorl %edi,%eax + addl 28(%esp),%edx + rorl $11,%ecx + andl %eax,%ebx + xorl %esi,%ecx + addl 64(%esp),%edx + xorl %edi,%ebx + rorl $2,%ecx + addl %edx,%ebx + addl 12(%esp),%edx + addl %ecx,%ebx + movl %edx,%ecx + rorl $14,%edx + movl 16(%esp),%esi + xorl %ecx,%edx + movl 20(%esp),%edi + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi + movl %ecx,12(%esp) + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + movl %ebx,%ecx + addl %edi,%edx + movl (%esp),%edi + movl %ebx,%esi + rorl $9,%ecx + movl %ebx,28(%esp) + xorl %ebx,%ecx + xorl %edi,%ebx + addl 24(%esp),%edx + rorl $11,%ecx + andl %ebx,%eax + xorl %esi,%ecx + addl 68(%esp),%edx + xorl %edi,%eax + rorl $2,%ecx + addl %edx,%eax + addl 8(%esp),%edx + addl %ecx,%eax + movl %edx,%ecx + rorl $14,%edx + movl 12(%esp),%esi + xorl %ecx,%edx + movl 16(%esp),%edi + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi + movl %ecx,8(%esp) + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + movl %eax,%ecx + addl %edi,%edx + movl 28(%esp),%edi + movl %eax,%esi + rorl $9,%ecx + movl %eax,24(%esp) + xorl %eax,%ecx + xorl %edi,%eax + addl 20(%esp),%edx + rorl $11,%ecx + andl %eax,%ebx + xorl %esi,%ecx + addl 72(%esp),%edx + xorl %edi,%ebx + rorl $2,%ecx + addl %edx,%ebx + addl 4(%esp),%edx + addl %ecx,%ebx + movl %edx,%ecx + rorl $14,%edx + movl 8(%esp),%esi + xorl %ecx,%edx + movl 12(%esp),%edi + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi + movl %ecx,4(%esp) + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + movl %ebx,%ecx + addl %edi,%edx + movl 24(%esp),%edi + movl %ebx,%esi + rorl $9,%ecx + movl %ebx,20(%esp) + xorl %ebx,%ecx + xorl %edi,%ebx + addl 16(%esp),%edx + rorl $11,%ecx + andl %ebx,%eax + xorl %esi,%ecx + addl 76(%esp),%edx + xorl %edi,%eax + rorl $2,%ecx + addl %edx,%eax + addl (%esp),%edx + addl %ecx,%eax + movl %edx,%ecx + rorl $14,%edx + movl 4(%esp),%esi + xorl %ecx,%edx + movl 8(%esp),%edi + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi + movl %ecx,(%esp) + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + movl %eax,%ecx + addl %edi,%edx + movl 20(%esp),%edi + movl %eax,%esi + rorl $9,%ecx + movl %eax,16(%esp) + xorl %eax,%ecx + xorl %edi,%eax + addl 12(%esp),%edx + rorl $11,%ecx + andl %eax,%ebx + xorl %esi,%ecx + addl 80(%esp),%edx + xorl %edi,%ebx + rorl $2,%ecx + addl %edx,%ebx + addl 28(%esp),%edx + addl %ecx,%ebx + movl %edx,%ecx + rorl $14,%edx + movl (%esp),%esi + xorl %ecx,%edx + movl 4(%esp),%edi + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi + movl %ecx,28(%esp) + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + movl %ebx,%ecx + addl %edi,%edx + movl 16(%esp),%edi + movl %ebx,%esi + rorl $9,%ecx + movl %ebx,12(%esp) + xorl %ebx,%ecx + xorl %edi,%ebx + addl 8(%esp),%edx + rorl $11,%ecx + andl %ebx,%eax + xorl %esi,%ecx + addl 84(%esp),%edx + xorl %edi,%eax + rorl $2,%ecx + addl %edx,%eax + addl 24(%esp),%edx + addl %ecx,%eax + movl %edx,%ecx + rorl $14,%edx + movl 28(%esp),%esi + xorl %ecx,%edx + movl (%esp),%edi + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi + movl %ecx,24(%esp) + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + movl %eax,%ecx + addl %edi,%edx + movl 12(%esp),%edi + movl %eax,%esi + rorl $9,%ecx + movl %eax,8(%esp) + xorl %eax,%ecx + xorl %edi,%eax + addl 4(%esp),%edx + rorl $11,%ecx + andl %eax,%ebx + xorl %esi,%ecx + addl 88(%esp),%edx + xorl %edi,%ebx + rorl $2,%ecx + addl %edx,%ebx + addl 20(%esp),%edx + addl %ecx,%ebx + movl %edx,%ecx + rorl $14,%edx + movl 24(%esp),%esi + xorl %ecx,%edx + movl 28(%esp),%edi + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi + movl %ecx,20(%esp) + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + movl %ebx,%ecx + addl %edi,%edx + movl 8(%esp),%edi + movl %ebx,%esi + rorl $9,%ecx + movl %ebx,4(%esp) + xorl %ebx,%ecx + xorl %edi,%ebx + addl (%esp),%edx + rorl $11,%ecx + andl %ebx,%eax + xorl %esi,%ecx + addl 92(%esp),%edx + xorl %edi,%eax + rorl $2,%ecx + addl %edx,%eax + addl 16(%esp),%edx + addl %ecx,%eax + movl 96(%esp),%esi + xorl %edi,%ebx + movl 12(%esp),%ecx + addl (%esi),%eax + addl 4(%esi),%ebx + addl 8(%esi),%edi + addl 12(%esi),%ecx + movl %eax,(%esi) + movl %ebx,4(%esi) + movl %edi,8(%esi) + movl %ecx,12(%esi) + movl %ebx,4(%esp) + xorl %edi,%ebx + movl %edi,8(%esp) + movl %ecx,12(%esp) + movl 20(%esp),%edi + movl 24(%esp),%ecx + addl 16(%esi),%edx + addl 20(%esi),%edi + addl 24(%esi),%ecx + movl %edx,16(%esi) + movl %edi,20(%esi) + movl %edi,20(%esp) + movl 28(%esp),%edi + movl %ecx,24(%esi) + addl 28(%esi),%edi + movl %ecx,24(%esp) + movl %edi,28(%esi) + movl %edi,28(%esp) + movl 100(%esp),%edi + movdqa 64(%ebp),%xmm7 + subl $192,%ebp + cmpl 104(%esp),%edi + jb .L011grand_ssse3 + movl 108(%esp),%esp + popl %edi + popl %esi + popl %ebx + popl %ebp + ret .size sha256_block_data_order,.-.L_sha256_block_data_order_begin #endif diff --git a/third_party/boringssl/linux-x86/crypto/sha/sha512-586.S b/third_party/boringssl/linux-x86/crypto/sha/sha512-586.S index 17f794536daef..a9284000b35a0 100644 --- a/third_party/boringssl/linux-x86/crypto/sha/sha512-586.S +++ b/third_party/boringssl/linux-x86/crypto/sha/sha512-586.S @@ -27,6 +27,2269 @@ sha512_block_data_order: movl %edi,4(%esp) movl %eax,8(%esp) movl %ebx,12(%esp) + leal OPENSSL_ia32cap_P-.L001K512(%ebp),%edx + movl (%edx),%ecx + testl $67108864,%ecx + jz .L002loop_x86 + movl 4(%edx),%edx + movq (%esi),%mm0 + andl $16777216,%ecx + movq 8(%esi),%mm1 + andl $512,%edx + movq 16(%esi),%mm2 + orl %edx,%ecx + movq 24(%esi),%mm3 + movq 32(%esi),%mm4 + movq 40(%esi),%mm5 + movq 48(%esi),%mm6 + movq 56(%esi),%mm7 + cmpl $16777728,%ecx + je .L003SSSE3 + subl $80,%esp + jmp .L004loop_sse2 +.align 16 +.L004loop_sse2: + movq %mm1,8(%esp) + movq %mm2,16(%esp) + movq %mm3,24(%esp) + movq %mm5,40(%esp) + movq %mm6,48(%esp) + pxor %mm1,%mm2 + movq %mm7,56(%esp) + movq %mm0,%mm3 + movl (%edi),%eax + movl 4(%edi),%ebx + addl $8,%edi + movl $15,%edx + bswap %eax + bswap %ebx + jmp .L00500_14_sse2 +.align 16 +.L00500_14_sse2: + movd %eax,%mm1 + movl (%edi),%eax + movd %ebx,%mm7 + movl 4(%edi),%ebx + addl $8,%edi + bswap %eax + bswap %ebx + punpckldq %mm1,%mm7 + movq %mm4,%mm1 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,32(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + movq %mm3,%mm0 + movq %mm7,72(%esp) + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm0,(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 56(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + paddq (%ebp),%mm7 + pxor %mm4,%mm3 + movq 24(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm0,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm0,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 8(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + subl $8,%esp + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm0,%mm2 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + pxor %mm7,%mm6 + movq 40(%esp),%mm5 + paddq %mm2,%mm3 + movq %mm0,%mm2 + addl $8,%ebp + paddq %mm6,%mm3 + movq 48(%esp),%mm6 + decl %edx + jnz .L00500_14_sse2 + movd %eax,%mm1 + movd %ebx,%mm7 + punpckldq %mm1,%mm7 + movq %mm4,%mm1 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,32(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + movq %mm3,%mm0 + movq %mm7,72(%esp) + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm0,(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 56(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + paddq (%ebp),%mm7 + pxor %mm4,%mm3 + movq 24(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm0,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm0,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 8(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + subl $8,%esp + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm0,%mm2 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + pxor %mm7,%mm6 + movq 192(%esp),%mm7 + paddq %mm2,%mm3 + movq %mm0,%mm2 + addl $8,%ebp + paddq %mm6,%mm3 + pxor %mm0,%mm0 + movl $32,%edx + jmp .L00616_79_sse2 +.align 16 +.L00616_79_sse2: + movq 88(%esp),%mm5 + movq %mm7,%mm1 + psrlq $1,%mm7 + movq %mm5,%mm6 + psrlq $6,%mm5 + psllq $56,%mm1 + paddq %mm3,%mm0 + movq %mm7,%mm3 + psrlq $6,%mm7 + pxor %mm1,%mm3 + psllq $7,%mm1 + pxor %mm7,%mm3 + psrlq $1,%mm7 + pxor %mm1,%mm3 + movq %mm5,%mm1 + psrlq $13,%mm5 + pxor %mm3,%mm7 + psllq $3,%mm6 + pxor %mm5,%mm1 + paddq 200(%esp),%mm7 + pxor %mm6,%mm1 + psrlq $42,%mm5 + paddq 128(%esp),%mm7 + pxor %mm5,%mm1 + psllq $42,%mm6 + movq 40(%esp),%mm5 + pxor %mm6,%mm1 + movq 48(%esp),%mm6 + paddq %mm1,%mm7 + movq %mm4,%mm1 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,32(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + movq %mm7,72(%esp) + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm0,(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 56(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + paddq (%ebp),%mm7 + pxor %mm4,%mm3 + movq 24(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm0,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm0,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 8(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + subl $8,%esp + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm0,%mm2 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + pxor %mm7,%mm6 + movq 192(%esp),%mm7 + paddq %mm6,%mm2 + addl $8,%ebp + movq 88(%esp),%mm5 + movq %mm7,%mm1 + psrlq $1,%mm7 + movq %mm5,%mm6 + psrlq $6,%mm5 + psllq $56,%mm1 + paddq %mm3,%mm2 + movq %mm7,%mm3 + psrlq $6,%mm7 + pxor %mm1,%mm3 + psllq $7,%mm1 + pxor %mm7,%mm3 + psrlq $1,%mm7 + pxor %mm1,%mm3 + movq %mm5,%mm1 + psrlq $13,%mm5 + pxor %mm3,%mm7 + psllq $3,%mm6 + pxor %mm5,%mm1 + paddq 200(%esp),%mm7 + pxor %mm6,%mm1 + psrlq $42,%mm5 + paddq 128(%esp),%mm7 + pxor %mm5,%mm1 + psllq $42,%mm6 + movq 40(%esp),%mm5 + pxor %mm6,%mm1 + movq 48(%esp),%mm6 + paddq %mm1,%mm7 + movq %mm4,%mm1 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,32(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + movq %mm7,72(%esp) + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm2,(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 56(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + paddq (%ebp),%mm7 + pxor %mm4,%mm3 + movq 24(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm2,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm2,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 8(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + subl $8,%esp + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm2,%mm0 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + pxor %mm7,%mm6 + movq 192(%esp),%mm7 + paddq %mm6,%mm0 + addl $8,%ebp + decl %edx + jnz .L00616_79_sse2 + paddq %mm3,%mm0 + movq 8(%esp),%mm1 + movq 24(%esp),%mm3 + movq 40(%esp),%mm5 + movq 48(%esp),%mm6 + movq 56(%esp),%mm7 + pxor %mm1,%mm2 + paddq (%esi),%mm0 + paddq 8(%esi),%mm1 + paddq 16(%esi),%mm2 + paddq 24(%esi),%mm3 + paddq 32(%esi),%mm4 + paddq 40(%esi),%mm5 + paddq 48(%esi),%mm6 + paddq 56(%esi),%mm7 + movl $640,%eax + movq %mm0,(%esi) + movq %mm1,8(%esi) + movq %mm2,16(%esi) + movq %mm3,24(%esi) + movq %mm4,32(%esi) + movq %mm5,40(%esi) + movq %mm6,48(%esi) + movq %mm7,56(%esi) + leal (%esp,%eax,1),%esp + subl %eax,%ebp + cmpl 88(%esp),%edi + jb .L004loop_sse2 + movl 92(%esp),%esp + emms + popl %edi + popl %esi + popl %ebx + popl %ebp + ret +.align 32 +.L003SSSE3: + leal -64(%esp),%edx + subl $256,%esp + movdqa 640(%ebp),%xmm1 + movdqu (%edi),%xmm0 +.byte 102,15,56,0,193 + movdqa (%ebp),%xmm3 + movdqa %xmm1,%xmm2 + movdqu 16(%edi),%xmm1 + paddq %xmm0,%xmm3 +.byte 102,15,56,0,202 + movdqa %xmm3,-128(%edx) + movdqa 16(%ebp),%xmm4 + movdqa %xmm2,%xmm3 + movdqu 32(%edi),%xmm2 + paddq %xmm1,%xmm4 +.byte 102,15,56,0,211 + movdqa %xmm4,-112(%edx) + movdqa 32(%ebp),%xmm5 + movdqa %xmm3,%xmm4 + movdqu 48(%edi),%xmm3 + paddq %xmm2,%xmm5 +.byte 102,15,56,0,220 + movdqa %xmm5,-96(%edx) + movdqa 48(%ebp),%xmm6 + movdqa %xmm4,%xmm5 + movdqu 64(%edi),%xmm4 + paddq %xmm3,%xmm6 +.byte 102,15,56,0,229 + movdqa %xmm6,-80(%edx) + movdqa 64(%ebp),%xmm7 + movdqa %xmm5,%xmm6 + movdqu 80(%edi),%xmm5 + paddq %xmm4,%xmm7 +.byte 102,15,56,0,238 + movdqa %xmm7,-64(%edx) + movdqa %xmm0,(%edx) + movdqa 80(%ebp),%xmm0 + movdqa %xmm6,%xmm7 + movdqu 96(%edi),%xmm6 + paddq %xmm5,%xmm0 +.byte 102,15,56,0,247 + movdqa %xmm0,-48(%edx) + movdqa %xmm1,16(%edx) + movdqa 96(%ebp),%xmm1 + movdqa %xmm7,%xmm0 + movdqu 112(%edi),%xmm7 + paddq %xmm6,%xmm1 +.byte 102,15,56,0,248 + movdqa %xmm1,-32(%edx) + movdqa %xmm2,32(%edx) + movdqa 112(%ebp),%xmm2 + movdqa (%edx),%xmm0 + paddq %xmm7,%xmm2 + movdqa %xmm2,-16(%edx) + nop +.align 32 +.L007loop_ssse3: + movdqa 16(%edx),%xmm2 + movdqa %xmm3,48(%edx) + leal 128(%ebp),%ebp + movq %mm1,8(%esp) + movl %edi,%ebx + movq %mm2,16(%esp) + leal 128(%edi),%edi + movq %mm3,24(%esp) + cmpl %eax,%edi + movq %mm5,40(%esp) + cmovbl %edi,%ebx + movq %mm6,48(%esp) + movl $4,%ecx + pxor %mm1,%mm2 + movq %mm7,56(%esp) + pxor %mm3,%mm3 + jmp .L00800_47_ssse3 +.align 32 +.L00800_47_ssse3: + movdqa %xmm5,%xmm3 + movdqa %xmm2,%xmm1 +.byte 102,15,58,15,208,8 + movdqa %xmm4,(%edx) +.byte 102,15,58,15,220,8 + movdqa %xmm2,%xmm4 + psrlq $7,%xmm2 + paddq %xmm3,%xmm0 + movdqa %xmm4,%xmm3 + psrlq $1,%xmm4 + psllq $56,%xmm3 + pxor %xmm4,%xmm2 + psrlq $7,%xmm4 + pxor %xmm3,%xmm2 + psllq $7,%xmm3 + pxor %xmm4,%xmm2 + movdqa %xmm7,%xmm4 + pxor %xmm3,%xmm2 + movdqa %xmm7,%xmm3 + psrlq $6,%xmm4 + paddq %xmm2,%xmm0 + movdqa %xmm7,%xmm2 + psrlq $19,%xmm3 + psllq $3,%xmm2 + pxor %xmm3,%xmm4 + psrlq $42,%xmm3 + pxor %xmm2,%xmm4 + psllq $42,%xmm2 + pxor %xmm3,%xmm4 + movdqa 32(%edx),%xmm3 + pxor %xmm2,%xmm4 + movdqa (%ebp),%xmm2 + movq %mm4,%mm1 + paddq %xmm4,%xmm0 + movq -128(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,32(%esp) + paddq %xmm0,%xmm2 + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm0 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm0,(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 56(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 24(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm0,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm0,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 8(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm0,%mm2 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + pxor %mm7,%mm6 + movq 32(%esp),%mm5 + paddq %mm6,%mm2 + movq 40(%esp),%mm6 + movq %mm4,%mm1 + movq -120(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,24(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm2 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm2,56(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 48(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 16(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm2,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm2,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq (%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm2,%mm0 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + pxor %mm7,%mm6 + movq 24(%esp),%mm5 + paddq %mm6,%mm0 + movq 32(%esp),%mm6 + movdqa %xmm2,-128(%edx) + movdqa %xmm6,%xmm4 + movdqa %xmm3,%xmm2 +.byte 102,15,58,15,217,8 + movdqa %xmm5,16(%edx) +.byte 102,15,58,15,229,8 + movdqa %xmm3,%xmm5 + psrlq $7,%xmm3 + paddq %xmm4,%xmm1 + movdqa %xmm5,%xmm4 + psrlq $1,%xmm5 + psllq $56,%xmm4 + pxor %xmm5,%xmm3 + psrlq $7,%xmm5 + pxor %xmm4,%xmm3 + psllq $7,%xmm4 + pxor %xmm5,%xmm3 + movdqa %xmm0,%xmm5 + pxor %xmm4,%xmm3 + movdqa %xmm0,%xmm4 + psrlq $6,%xmm5 + paddq %xmm3,%xmm1 + movdqa %xmm0,%xmm3 + psrlq $19,%xmm4 + psllq $3,%xmm3 + pxor %xmm4,%xmm5 + psrlq $42,%xmm4 + pxor %xmm3,%xmm5 + psllq $42,%xmm3 + pxor %xmm4,%xmm5 + movdqa 48(%edx),%xmm4 + pxor %xmm3,%xmm5 + movdqa 16(%ebp),%xmm3 + movq %mm4,%mm1 + paddq %xmm5,%xmm1 + movq -112(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,16(%esp) + paddq %xmm1,%xmm3 + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm0 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm0,48(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 40(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 8(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm0,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm0,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 56(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm0,%mm2 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + pxor %mm7,%mm6 + movq 16(%esp),%mm5 + paddq %mm6,%mm2 + movq 24(%esp),%mm6 + movq %mm4,%mm1 + movq -104(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,8(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm2 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm2,40(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 32(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq (%esp),%mm4 + paddq %mm7,%mm3 + movq %mm2,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm2,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 48(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm2,%mm0 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + pxor %mm7,%mm6 + movq 8(%esp),%mm5 + paddq %mm6,%mm0 + movq 16(%esp),%mm6 + movdqa %xmm3,-112(%edx) + movdqa %xmm7,%xmm5 + movdqa %xmm4,%xmm3 +.byte 102,15,58,15,226,8 + movdqa %xmm6,32(%edx) +.byte 102,15,58,15,238,8 + movdqa %xmm4,%xmm6 + psrlq $7,%xmm4 + paddq %xmm5,%xmm2 + movdqa %xmm6,%xmm5 + psrlq $1,%xmm6 + psllq $56,%xmm5 + pxor %xmm6,%xmm4 + psrlq $7,%xmm6 + pxor %xmm5,%xmm4 + psllq $7,%xmm5 + pxor %xmm6,%xmm4 + movdqa %xmm1,%xmm6 + pxor %xmm5,%xmm4 + movdqa %xmm1,%xmm5 + psrlq $6,%xmm6 + paddq %xmm4,%xmm2 + movdqa %xmm1,%xmm4 + psrlq $19,%xmm5 + psllq $3,%xmm4 + pxor %xmm5,%xmm6 + psrlq $42,%xmm5 + pxor %xmm4,%xmm6 + psllq $42,%xmm4 + pxor %xmm5,%xmm6 + movdqa (%edx),%xmm5 + pxor %xmm4,%xmm6 + movdqa 32(%ebp),%xmm4 + movq %mm4,%mm1 + paddq %xmm6,%xmm2 + movq -96(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,(%esp) + paddq %xmm2,%xmm4 + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm0 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm0,32(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 24(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 56(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm0,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm0,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 40(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm0,%mm2 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + pxor %mm7,%mm6 + movq (%esp),%mm5 + paddq %mm6,%mm2 + movq 8(%esp),%mm6 + movq %mm4,%mm1 + movq -88(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,56(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm2 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm2,24(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 16(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 48(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm2,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm2,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 32(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm2,%mm0 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + pxor %mm7,%mm6 + movq 56(%esp),%mm5 + paddq %mm6,%mm0 + movq (%esp),%mm6 + movdqa %xmm4,-96(%edx) + movdqa %xmm0,%xmm6 + movdqa %xmm5,%xmm4 +.byte 102,15,58,15,235,8 + movdqa %xmm7,48(%edx) +.byte 102,15,58,15,247,8 + movdqa %xmm5,%xmm7 + psrlq $7,%xmm5 + paddq %xmm6,%xmm3 + movdqa %xmm7,%xmm6 + psrlq $1,%xmm7 + psllq $56,%xmm6 + pxor %xmm7,%xmm5 + psrlq $7,%xmm7 + pxor %xmm6,%xmm5 + psllq $7,%xmm6 + pxor %xmm7,%xmm5 + movdqa %xmm2,%xmm7 + pxor %xmm6,%xmm5 + movdqa %xmm2,%xmm6 + psrlq $6,%xmm7 + paddq %xmm5,%xmm3 + movdqa %xmm2,%xmm5 + psrlq $19,%xmm6 + psllq $3,%xmm5 + pxor %xmm6,%xmm7 + psrlq $42,%xmm6 + pxor %xmm5,%xmm7 + psllq $42,%xmm5 + pxor %xmm6,%xmm7 + movdqa 16(%edx),%xmm6 + pxor %xmm5,%xmm7 + movdqa 48(%ebp),%xmm5 + movq %mm4,%mm1 + paddq %xmm7,%xmm3 + movq -80(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,48(%esp) + paddq %xmm3,%xmm5 + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm0 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm0,16(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 8(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 40(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm0,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm0,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 24(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm0,%mm2 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + pxor %mm7,%mm6 + movq 48(%esp),%mm5 + paddq %mm6,%mm2 + movq 56(%esp),%mm6 + movq %mm4,%mm1 + movq -72(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,40(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm2 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm2,8(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq (%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 32(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm2,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm2,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 16(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm2,%mm0 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + pxor %mm7,%mm6 + movq 40(%esp),%mm5 + paddq %mm6,%mm0 + movq 48(%esp),%mm6 + movdqa %xmm5,-80(%edx) + movdqa %xmm1,%xmm7 + movdqa %xmm6,%xmm5 +.byte 102,15,58,15,244,8 + movdqa %xmm0,(%edx) +.byte 102,15,58,15,248,8 + movdqa %xmm6,%xmm0 + psrlq $7,%xmm6 + paddq %xmm7,%xmm4 + movdqa %xmm0,%xmm7 + psrlq $1,%xmm0 + psllq $56,%xmm7 + pxor %xmm0,%xmm6 + psrlq $7,%xmm0 + pxor %xmm7,%xmm6 + psllq $7,%xmm7 + pxor %xmm0,%xmm6 + movdqa %xmm3,%xmm0 + pxor %xmm7,%xmm6 + movdqa %xmm3,%xmm7 + psrlq $6,%xmm0 + paddq %xmm6,%xmm4 + movdqa %xmm3,%xmm6 + psrlq $19,%xmm7 + psllq $3,%xmm6 + pxor %xmm7,%xmm0 + psrlq $42,%xmm7 + pxor %xmm6,%xmm0 + psllq $42,%xmm6 + pxor %xmm7,%xmm0 + movdqa 32(%edx),%xmm7 + pxor %xmm6,%xmm0 + movdqa 64(%ebp),%xmm6 + movq %mm4,%mm1 + paddq %xmm0,%xmm4 + movq -64(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,32(%esp) + paddq %xmm4,%xmm6 + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm0 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm0,(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 56(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 24(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm0,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm0,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 8(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm0,%mm2 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + pxor %mm7,%mm6 + movq 32(%esp),%mm5 + paddq %mm6,%mm2 + movq 40(%esp),%mm6 + movq %mm4,%mm1 + movq -56(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,24(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm2 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm2,56(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 48(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 16(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm2,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm2,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq (%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm2,%mm0 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + pxor %mm7,%mm6 + movq 24(%esp),%mm5 + paddq %mm6,%mm0 + movq 32(%esp),%mm6 + movdqa %xmm6,-64(%edx) + movdqa %xmm2,%xmm0 + movdqa %xmm7,%xmm6 +.byte 102,15,58,15,253,8 + movdqa %xmm1,16(%edx) +.byte 102,15,58,15,193,8 + movdqa %xmm7,%xmm1 + psrlq $7,%xmm7 + paddq %xmm0,%xmm5 + movdqa %xmm1,%xmm0 + psrlq $1,%xmm1 + psllq $56,%xmm0 + pxor %xmm1,%xmm7 + psrlq $7,%xmm1 + pxor %xmm0,%xmm7 + psllq $7,%xmm0 + pxor %xmm1,%xmm7 + movdqa %xmm4,%xmm1 + pxor %xmm0,%xmm7 + movdqa %xmm4,%xmm0 + psrlq $6,%xmm1 + paddq %xmm7,%xmm5 + movdqa %xmm4,%xmm7 + psrlq $19,%xmm0 + psllq $3,%xmm7 + pxor %xmm0,%xmm1 + psrlq $42,%xmm0 + pxor %xmm7,%xmm1 + psllq $42,%xmm7 + pxor %xmm0,%xmm1 + movdqa 48(%edx),%xmm0 + pxor %xmm7,%xmm1 + movdqa 80(%ebp),%xmm7 + movq %mm4,%mm1 + paddq %xmm1,%xmm5 + movq -48(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,16(%esp) + paddq %xmm5,%xmm7 + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm0 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm0,48(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 40(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 8(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm0,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm0,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 56(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm0,%mm2 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + pxor %mm7,%mm6 + movq 16(%esp),%mm5 + paddq %mm6,%mm2 + movq 24(%esp),%mm6 + movq %mm4,%mm1 + movq -40(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,8(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm2 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm2,40(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 32(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq (%esp),%mm4 + paddq %mm7,%mm3 + movq %mm2,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm2,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 48(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm2,%mm0 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + pxor %mm7,%mm6 + movq 8(%esp),%mm5 + paddq %mm6,%mm0 + movq 16(%esp),%mm6 + movdqa %xmm7,-48(%edx) + movdqa %xmm3,%xmm1 + movdqa %xmm0,%xmm7 +.byte 102,15,58,15,198,8 + movdqa %xmm2,32(%edx) +.byte 102,15,58,15,202,8 + movdqa %xmm0,%xmm2 + psrlq $7,%xmm0 + paddq %xmm1,%xmm6 + movdqa %xmm2,%xmm1 + psrlq $1,%xmm2 + psllq $56,%xmm1 + pxor %xmm2,%xmm0 + psrlq $7,%xmm2 + pxor %xmm1,%xmm0 + psllq $7,%xmm1 + pxor %xmm2,%xmm0 + movdqa %xmm5,%xmm2 + pxor %xmm1,%xmm0 + movdqa %xmm5,%xmm1 + psrlq $6,%xmm2 + paddq %xmm0,%xmm6 + movdqa %xmm5,%xmm0 + psrlq $19,%xmm1 + psllq $3,%xmm0 + pxor %xmm1,%xmm2 + psrlq $42,%xmm1 + pxor %xmm0,%xmm2 + psllq $42,%xmm0 + pxor %xmm1,%xmm2 + movdqa (%edx),%xmm1 + pxor %xmm0,%xmm2 + movdqa 96(%ebp),%xmm0 + movq %mm4,%mm1 + paddq %xmm2,%xmm6 + movq -32(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,(%esp) + paddq %xmm6,%xmm0 + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm0 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm0,32(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 24(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 56(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm0,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm0,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 40(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm0,%mm2 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + pxor %mm7,%mm6 + movq (%esp),%mm5 + paddq %mm6,%mm2 + movq 8(%esp),%mm6 + movq %mm4,%mm1 + movq -24(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,56(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm2 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm2,24(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 16(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 48(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm2,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm2,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 32(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm2,%mm0 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + pxor %mm7,%mm6 + movq 56(%esp),%mm5 + paddq %mm6,%mm0 + movq (%esp),%mm6 + movdqa %xmm0,-32(%edx) + movdqa %xmm4,%xmm2 + movdqa %xmm1,%xmm0 +.byte 102,15,58,15,207,8 + movdqa %xmm3,48(%edx) +.byte 102,15,58,15,211,8 + movdqa %xmm1,%xmm3 + psrlq $7,%xmm1 + paddq %xmm2,%xmm7 + movdqa %xmm3,%xmm2 + psrlq $1,%xmm3 + psllq $56,%xmm2 + pxor %xmm3,%xmm1 + psrlq $7,%xmm3 + pxor %xmm2,%xmm1 + psllq $7,%xmm2 + pxor %xmm3,%xmm1 + movdqa %xmm6,%xmm3 + pxor %xmm2,%xmm1 + movdqa %xmm6,%xmm2 + psrlq $6,%xmm3 + paddq %xmm1,%xmm7 + movdqa %xmm6,%xmm1 + psrlq $19,%xmm2 + psllq $3,%xmm1 + pxor %xmm2,%xmm3 + psrlq $42,%xmm2 + pxor %xmm1,%xmm3 + psllq $42,%xmm1 + pxor %xmm2,%xmm3 + movdqa 16(%edx),%xmm2 + pxor %xmm1,%xmm3 + movdqa 112(%ebp),%xmm1 + movq %mm4,%mm1 + paddq %xmm3,%xmm7 + movq -16(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,48(%esp) + paddq %xmm7,%xmm1 + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm0 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm0,16(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 8(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 40(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm0,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm0,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 24(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm0,%mm2 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + pxor %mm7,%mm6 + movq 48(%esp),%mm5 + paddq %mm6,%mm2 + movq 56(%esp),%mm6 + movq %mm4,%mm1 + movq -8(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,40(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm2 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm2,8(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq (%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 32(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm2,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm2,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 16(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm2,%mm0 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + pxor %mm7,%mm6 + movq 40(%esp),%mm5 + paddq %mm6,%mm0 + movq 48(%esp),%mm6 + movdqa %xmm1,-16(%edx) + leal 128(%ebp),%ebp + decl %ecx + jnz .L00800_47_ssse3 + movdqa (%ebp),%xmm1 + leal -640(%ebp),%ebp + movdqu (%ebx),%xmm0 +.byte 102,15,56,0,193 + movdqa (%ebp),%xmm3 + movdqa %xmm1,%xmm2 + movdqu 16(%ebx),%xmm1 + paddq %xmm0,%xmm3 +.byte 102,15,56,0,202 + movq %mm4,%mm1 + movq -128(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,32(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm0 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm0,(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 56(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 24(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm0,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm0,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 8(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm0,%mm2 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + pxor %mm7,%mm6 + movq 32(%esp),%mm5 + paddq %mm6,%mm2 + movq 40(%esp),%mm6 + movq %mm4,%mm1 + movq -120(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,24(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm2 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm2,56(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 48(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 16(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm2,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm2,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq (%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm2,%mm0 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + pxor %mm7,%mm6 + movq 24(%esp),%mm5 + paddq %mm6,%mm0 + movq 32(%esp),%mm6 + movdqa %xmm3,-128(%edx) + movdqa 16(%ebp),%xmm4 + movdqa %xmm2,%xmm3 + movdqu 32(%ebx),%xmm2 + paddq %xmm1,%xmm4 +.byte 102,15,56,0,211 + movq %mm4,%mm1 + movq -112(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,16(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm0 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm0,48(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 40(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 8(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm0,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm0,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 56(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm0,%mm2 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + pxor %mm7,%mm6 + movq 16(%esp),%mm5 + paddq %mm6,%mm2 + movq 24(%esp),%mm6 + movq %mm4,%mm1 + movq -104(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,8(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm2 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm2,40(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 32(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq (%esp),%mm4 + paddq %mm7,%mm3 + movq %mm2,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm2,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 48(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm2,%mm0 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + pxor %mm7,%mm6 + movq 8(%esp),%mm5 + paddq %mm6,%mm0 + movq 16(%esp),%mm6 + movdqa %xmm4,-112(%edx) + movdqa 32(%ebp),%xmm5 + movdqa %xmm3,%xmm4 + movdqu 48(%ebx),%xmm3 + paddq %xmm2,%xmm5 +.byte 102,15,56,0,220 + movq %mm4,%mm1 + movq -96(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm0 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm0,32(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 24(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 56(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm0,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm0,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 40(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm0,%mm2 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + pxor %mm7,%mm6 + movq (%esp),%mm5 + paddq %mm6,%mm2 + movq 8(%esp),%mm6 + movq %mm4,%mm1 + movq -88(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,56(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm2 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm2,24(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 16(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 48(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm2,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm2,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 32(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm2,%mm0 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + pxor %mm7,%mm6 + movq 56(%esp),%mm5 + paddq %mm6,%mm0 + movq (%esp),%mm6 + movdqa %xmm5,-96(%edx) + movdqa 48(%ebp),%xmm6 + movdqa %xmm4,%xmm5 + movdqu 64(%ebx),%xmm4 + paddq %xmm3,%xmm6 +.byte 102,15,56,0,229 + movq %mm4,%mm1 + movq -80(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,48(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm0 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm0,16(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 8(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 40(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm0,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm0,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 24(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm0,%mm2 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + pxor %mm7,%mm6 + movq 48(%esp),%mm5 + paddq %mm6,%mm2 + movq 56(%esp),%mm6 + movq %mm4,%mm1 + movq -72(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,40(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm2 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm2,8(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq (%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 32(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm2,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm2,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 16(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm2,%mm0 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + pxor %mm7,%mm6 + movq 40(%esp),%mm5 + paddq %mm6,%mm0 + movq 48(%esp),%mm6 + movdqa %xmm6,-80(%edx) + movdqa 64(%ebp),%xmm7 + movdqa %xmm5,%xmm6 + movdqu 80(%ebx),%xmm5 + paddq %xmm4,%xmm7 +.byte 102,15,56,0,238 + movq %mm4,%mm1 + movq -64(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,32(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm0 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm0,(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 56(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 24(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm0,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm0,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 8(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm0,%mm2 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + pxor %mm7,%mm6 + movq 32(%esp),%mm5 + paddq %mm6,%mm2 + movq 40(%esp),%mm6 + movq %mm4,%mm1 + movq -56(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,24(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm2 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm2,56(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 48(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 16(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm2,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm2,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq (%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm2,%mm0 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + pxor %mm7,%mm6 + movq 24(%esp),%mm5 + paddq %mm6,%mm0 + movq 32(%esp),%mm6 + movdqa %xmm7,-64(%edx) + movdqa %xmm0,(%edx) + movdqa 80(%ebp),%xmm0 + movdqa %xmm6,%xmm7 + movdqu 96(%ebx),%xmm6 + paddq %xmm5,%xmm0 +.byte 102,15,56,0,247 + movq %mm4,%mm1 + movq -48(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,16(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm0 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm0,48(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 40(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 8(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm0,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm0,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 56(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm0,%mm2 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + pxor %mm7,%mm6 + movq 16(%esp),%mm5 + paddq %mm6,%mm2 + movq 24(%esp),%mm6 + movq %mm4,%mm1 + movq -40(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,8(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm2 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm2,40(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 32(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq (%esp),%mm4 + paddq %mm7,%mm3 + movq %mm2,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm2,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 48(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm2,%mm0 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + pxor %mm7,%mm6 + movq 8(%esp),%mm5 + paddq %mm6,%mm0 + movq 16(%esp),%mm6 + movdqa %xmm0,-48(%edx) + movdqa %xmm1,16(%edx) + movdqa 96(%ebp),%xmm1 + movdqa %xmm7,%xmm0 + movdqu 112(%ebx),%xmm7 + paddq %xmm6,%xmm1 +.byte 102,15,56,0,248 + movq %mm4,%mm1 + movq -32(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm0 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm0,32(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 24(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 56(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm0,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm0,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 40(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm0,%mm2 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + pxor %mm7,%mm6 + movq (%esp),%mm5 + paddq %mm6,%mm2 + movq 8(%esp),%mm6 + movq %mm4,%mm1 + movq -24(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,56(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm2 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm2,24(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 16(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 48(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm2,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm2,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 32(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm2,%mm0 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + pxor %mm7,%mm6 + movq 56(%esp),%mm5 + paddq %mm6,%mm0 + movq (%esp),%mm6 + movdqa %xmm1,-32(%edx) + movdqa %xmm2,32(%edx) + movdqa 112(%ebp),%xmm2 + movdqa (%edx),%xmm0 + paddq %xmm7,%xmm2 + movq %mm4,%mm1 + movq -16(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,48(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm0 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm0,16(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 8(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 40(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm0,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm0,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 24(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm0,%mm2 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + pxor %mm7,%mm6 + movq 48(%esp),%mm5 + paddq %mm6,%mm2 + movq 56(%esp),%mm6 + movq %mm4,%mm1 + movq -8(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,40(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm2 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm2,8(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq (%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 32(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm2,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm2,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 16(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm2,%mm0 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + pxor %mm7,%mm6 + movq 40(%esp),%mm5 + paddq %mm6,%mm0 + movq 48(%esp),%mm6 + movdqa %xmm2,-16(%edx) + movq 8(%esp),%mm1 + paddq %mm3,%mm0 + movq 24(%esp),%mm3 + movq 56(%esp),%mm7 + pxor %mm1,%mm2 + paddq (%esi),%mm0 + paddq 8(%esi),%mm1 + paddq 16(%esi),%mm2 + paddq 24(%esi),%mm3 + paddq 32(%esi),%mm4 + paddq 40(%esi),%mm5 + paddq 48(%esi),%mm6 + paddq 56(%esi),%mm7 + movq %mm0,(%esi) + movq %mm1,8(%esi) + movq %mm2,16(%esi) + movq %mm3,24(%esi) + movq %mm4,32(%esi) + movq %mm5,40(%esi) + movq %mm6,48(%esi) + movq %mm7,56(%esi) + cmpl %eax,%edi + jb .L007loop_ssse3 + movl 76(%edx),%esp + emms + popl %edi + popl %esi + popl %ebx + popl %ebp + ret .align 16 .L002loop_x86: movl (%edi),%eax @@ -132,7 +2395,7 @@ sha512_block_data_order: movl $16,%ecx .long 2784229001 .align 16 -.L00300_15_x86: +.L00900_15_x86: movl 40(%esp),%ecx movl 44(%esp),%edx movl %ecx,%esi @@ -239,9 +2502,9 @@ sha512_block_data_order: subl $8,%esp leal 8(%ebp),%ebp cmpb $148,%dl - jne .L00300_15_x86 + jne .L00900_15_x86 .align 16 -.L00416_79_x86: +.L01016_79_x86: movl 312(%esp),%ecx movl 316(%esp),%edx movl %ecx,%esi @@ -414,7 +2677,7 @@ sha512_block_data_order: subl $8,%esp leal 8(%ebp),%ebp cmpb $23,%dl - jne .L00416_79_x86 + jne .L01016_79_x86 movl 840(%esp),%esi movl 844(%esp),%edi movl (%esi),%eax diff --git a/third_party/boringssl/linux-x86_64/crypto/aes/aesni-x86_64.S b/third_party/boringssl/linux-x86_64/crypto/aes/aesni-x86_64.S index ecefbe59f10a8..1d51d5b50efda 100644 --- a/third_party/boringssl/linux-x86_64/crypto/aes/aesni-x86_64.S +++ b/third_party/boringssl/linux-x86_64/crypto/aes/aesni-x86_64.S @@ -20,7 +20,10 @@ aesni_encrypt: leaq 16(%rdx),%rdx jnz .Loop_enc1_1 .byte 102,15,56,221,209 + pxor %xmm0,%xmm0 + pxor %xmm1,%xmm1 movups %xmm2,(%rsi) + pxor %xmm2,%xmm2 .byte 0xf3,0xc3 .size aesni_encrypt,.-aesni_encrypt @@ -42,7 +45,10 @@ aesni_decrypt: leaq 16(%rdx),%rdx jnz .Loop_dec1_2 .byte 102,15,56,223,209 + pxor %xmm0,%xmm0 + pxor %xmm1,%xmm1 movups %xmm2,(%rsi) + pxor %xmm2,%xmm2 .byte 0xf3,0xc3 .size aesni_decrypt, .-aesni_decrypt .type _aesni_encrypt2,@function @@ -268,21 +274,18 @@ _aesni_encrypt6: pxor %xmm0,%xmm6 .byte 102,15,56,220,225 pxor %xmm0,%xmm7 + movups (%rcx,%rax,1),%xmm0 addq $16,%rax -.byte 102,15,56,220,233 -.byte 102,15,56,220,241 -.byte 102,15,56,220,249 - movups -16(%rcx,%rax,1),%xmm0 jmp .Lenc_loop6_enter .align 16 .Lenc_loop6: .byte 102,15,56,220,209 .byte 102,15,56,220,217 .byte 102,15,56,220,225 +.Lenc_loop6_enter: .byte 102,15,56,220,233 .byte 102,15,56,220,241 .byte 102,15,56,220,249 -.Lenc_loop6_enter: movups (%rcx,%rax,1),%xmm1 addq $32,%rax .byte 102,15,56,220,208 @@ -325,21 +328,18 @@ _aesni_decrypt6: pxor %xmm0,%xmm6 .byte 102,15,56,222,225 pxor %xmm0,%xmm7 + movups (%rcx,%rax,1),%xmm0 addq $16,%rax -.byte 102,15,56,222,233 -.byte 102,15,56,222,241 -.byte 102,15,56,222,249 - movups -16(%rcx,%rax,1),%xmm0 jmp .Ldec_loop6_enter .align 16 .Ldec_loop6: .byte 102,15,56,222,209 .byte 102,15,56,222,217 .byte 102,15,56,222,225 +.Ldec_loop6_enter: .byte 102,15,56,222,233 .byte 102,15,56,222,241 .byte 102,15,56,222,249 -.Ldec_loop6_enter: movups (%rcx,%rax,1),%xmm1 addq $32,%rax .byte 102,15,56,222,208 @@ -379,23 +379,18 @@ _aesni_encrypt8: leaq 32(%rcx,%rax,1),%rcx negq %rax .byte 102,15,56,220,209 - addq $16,%rax pxor %xmm0,%xmm7 -.byte 102,15,56,220,217 pxor %xmm0,%xmm8 +.byte 102,15,56,220,217 pxor %xmm0,%xmm9 -.byte 102,15,56,220,225 -.byte 102,15,56,220,233 -.byte 102,15,56,220,241 -.byte 102,15,56,220,249 -.byte 102,68,15,56,220,193 -.byte 102,68,15,56,220,201 - movups -16(%rcx,%rax,1),%xmm0 - jmp .Lenc_loop8_enter + movups (%rcx,%rax,1),%xmm0 + addq $16,%rax + jmp .Lenc_loop8_inner .align 16 .Lenc_loop8: .byte 102,15,56,220,209 .byte 102,15,56,220,217 +.Lenc_loop8_inner: .byte 102,15,56,220,225 .byte 102,15,56,220,233 .byte 102,15,56,220,241 @@ -448,23 +443,18 @@ _aesni_decrypt8: leaq 32(%rcx,%rax,1),%rcx negq %rax .byte 102,15,56,222,209 - addq $16,%rax pxor %xmm0,%xmm7 -.byte 102,15,56,222,217 pxor %xmm0,%xmm8 +.byte 102,15,56,222,217 pxor %xmm0,%xmm9 -.byte 102,15,56,222,225 -.byte 102,15,56,222,233 -.byte 102,15,56,222,241 -.byte 102,15,56,222,249 -.byte 102,68,15,56,222,193 -.byte 102,68,15,56,222,201 - movups -16(%rcx,%rax,1),%xmm0 - jmp .Ldec_loop8_enter + movups (%rcx,%rax,1),%xmm0 + addq $16,%rax + jmp .Ldec_loop8_inner .align 16 .Ldec_loop8: .byte 102,15,56,222,209 .byte 102,15,56,222,217 +.Ldec_loop8_inner: .byte 102,15,56,222,225 .byte 102,15,56,222,233 .byte 102,15,56,222,241 @@ -592,6 +582,7 @@ aesni_ecb_encrypt: movups 80(%rdi),%xmm7 je .Lecb_enc_six movdqu 96(%rdi),%xmm8 + xorps %xmm9,%xmm9 call _aesni_encrypt8 movups %xmm2,(%rsi) movups %xmm3,16(%rsi) @@ -705,15 +696,23 @@ aesni_ecb_encrypt: jnc .Lecb_dec_loop8 movups %xmm2,(%rsi) + pxor %xmm2,%xmm2 movq %r11,%rcx movups %xmm3,16(%rsi) + pxor %xmm3,%xmm3 movl %r10d,%eax movups %xmm4,32(%rsi) + pxor %xmm4,%xmm4 movups %xmm5,48(%rsi) + pxor %xmm5,%xmm5 movups %xmm6,64(%rsi) + pxor %xmm6,%xmm6 movups %xmm7,80(%rsi) + pxor %xmm7,%xmm7 movups %xmm8,96(%rsi) + pxor %xmm8,%xmm8 movups %xmm9,112(%rsi) + pxor %xmm9,%xmm9 leaq 128(%rsi),%rsi addq $128,%rdx jz .Lecb_ret @@ -736,14 +735,23 @@ aesni_ecb_encrypt: je .Lecb_dec_six movups 96(%rdi),%xmm8 movups (%rcx),%xmm0 + xorps %xmm9,%xmm9 call _aesni_decrypt8 movups %xmm2,(%rsi) + pxor %xmm2,%xmm2 movups %xmm3,16(%rsi) + pxor %xmm3,%xmm3 movups %xmm4,32(%rsi) + pxor %xmm4,%xmm4 movups %xmm5,48(%rsi) + pxor %xmm5,%xmm5 movups %xmm6,64(%rsi) + pxor %xmm6,%xmm6 movups %xmm7,80(%rsi) + pxor %xmm7,%xmm7 movups %xmm8,96(%rsi) + pxor %xmm8,%xmm8 + pxor %xmm9,%xmm9 jmp .Lecb_ret .align 16 .Lecb_dec_one: @@ -759,49 +767,73 @@ aesni_ecb_encrypt: jnz .Loop_dec1_4 .byte 102,15,56,223,209 movups %xmm2,(%rsi) + pxor %xmm2,%xmm2 jmp .Lecb_ret .align 16 .Lecb_dec_two: call _aesni_decrypt2 movups %xmm2,(%rsi) + pxor %xmm2,%xmm2 movups %xmm3,16(%rsi) + pxor %xmm3,%xmm3 jmp .Lecb_ret .align 16 .Lecb_dec_three: call _aesni_decrypt3 movups %xmm2,(%rsi) + pxor %xmm2,%xmm2 movups %xmm3,16(%rsi) + pxor %xmm3,%xmm3 movups %xmm4,32(%rsi) + pxor %xmm4,%xmm4 jmp .Lecb_ret .align 16 .Lecb_dec_four: call _aesni_decrypt4 movups %xmm2,(%rsi) + pxor %xmm2,%xmm2 movups %xmm3,16(%rsi) + pxor %xmm3,%xmm3 movups %xmm4,32(%rsi) + pxor %xmm4,%xmm4 movups %xmm5,48(%rsi) + pxor %xmm5,%xmm5 jmp .Lecb_ret .align 16 .Lecb_dec_five: xorps %xmm7,%xmm7 call _aesni_decrypt6 movups %xmm2,(%rsi) + pxor %xmm2,%xmm2 movups %xmm3,16(%rsi) + pxor %xmm3,%xmm3 movups %xmm4,32(%rsi) + pxor %xmm4,%xmm4 movups %xmm5,48(%rsi) + pxor %xmm5,%xmm5 movups %xmm6,64(%rsi) + pxor %xmm6,%xmm6 + pxor %xmm7,%xmm7 jmp .Lecb_ret .align 16 .Lecb_dec_six: call _aesni_decrypt6 movups %xmm2,(%rsi) + pxor %xmm2,%xmm2 movups %xmm3,16(%rsi) + pxor %xmm3,%xmm3 movups %xmm4,32(%rsi) + pxor %xmm4,%xmm4 movups %xmm5,48(%rsi) + pxor %xmm5,%xmm5 movups %xmm6,64(%rsi) + pxor %xmm6,%xmm6 movups %xmm7,80(%rsi) + pxor %xmm7,%xmm7 .Lecb_ret: + xorps %xmm0,%xmm0 + pxor %xmm1,%xmm1 .byte 0xf3,0xc3 .size aesni_ecb_encrypt,.-aesni_ecb_encrypt .globl aesni_ccm64_encrypt_blocks @@ -859,7 +891,13 @@ aesni_ccm64_encrypt_blocks: leaq 16(%rsi),%rsi jnz .Lccm64_enc_outer + pxor %xmm0,%xmm0 + pxor %xmm1,%xmm1 + pxor %xmm2,%xmm2 movups %xmm3,(%r9) + pxor %xmm3,%xmm3 + pxor %xmm8,%xmm8 + pxor %xmm6,%xmm6 .byte 0xf3,0xc3 .size aesni_ccm64_encrypt_blocks,.-aesni_ccm64_encrypt_blocks .globl aesni_ccm64_decrypt_blocks @@ -951,7 +989,13 @@ aesni_ccm64_decrypt_blocks: leaq 16(%r11),%r11 jnz .Loop_enc1_6 .byte 102,15,56,221,217 + pxor %xmm0,%xmm0 + pxor %xmm1,%xmm1 + pxor %xmm2,%xmm2 movups %xmm3,(%r9) + pxor %xmm3,%xmm3 + pxor %xmm8,%xmm8 + pxor %xmm6,%xmm6 .byte 0xf3,0xc3 .size aesni_ccm64_decrypt_blocks,.-aesni_ccm64_decrypt_blocks .globl aesni_ctr32_encrypt_blocks @@ -959,14 +1003,43 @@ aesni_ccm64_decrypt_blocks: .type aesni_ctr32_encrypt_blocks,@function .align 16 aesni_ctr32_encrypt_blocks: + cmpq $1,%rdx + jne .Lctr32_bulk + + + + movups (%r8),%xmm2 + movups (%rdi),%xmm3 + movl 240(%rcx),%edx + movups (%rcx),%xmm0 + movups 16(%rcx),%xmm1 + leaq 32(%rcx),%rcx + xorps %xmm0,%xmm2 +.Loop_enc1_7: +.byte 102,15,56,220,209 + decl %edx + movups (%rcx),%xmm1 + leaq 16(%rcx),%rcx + jnz .Loop_enc1_7 +.byte 102,15,56,221,209 + pxor %xmm0,%xmm0 + pxor %xmm1,%xmm1 + xorps %xmm3,%xmm2 + pxor %xmm3,%xmm3 + movups %xmm2,(%rsi) + xorps %xmm2,%xmm2 + jmp .Lctr32_epilogue + +.align 16 +.Lctr32_bulk: leaq (%rsp),%rax pushq %rbp subq $128,%rsp andq $-16,%rsp leaq -8(%rax),%rbp - cmpq $1,%rdx - je .Lctr32_one_shortcut + + movdqu (%r8),%xmm2 movdqu (%rcx),%xmm0 @@ -1357,11 +1430,14 @@ aesni_ctr32_encrypt_blocks: leaq -128(%rcx),%rcx .Lctr32_tail: + + leaq 16(%rcx),%rcx cmpq $4,%rdx jb .Lctr32_loop3 je .Lctr32_loop4 + shll $4,%eax movdqa 96(%rsp),%xmm8 pxor %xmm9,%xmm9 @@ -1464,30 +1540,33 @@ aesni_ctr32_encrypt_blocks: movups 32(%rdi),%xmm12 xorps %xmm12,%xmm4 movups %xmm4,32(%rsi) - jmp .Lctr32_done -.align 16 -.Lctr32_one_shortcut: - movups (%r8),%xmm2 - movups (%rdi),%xmm10 - movl 240(%rcx),%eax - movups (%rcx),%xmm0 - movups 16(%rcx),%xmm1 - leaq 32(%rcx),%rcx - xorps %xmm0,%xmm2 -.Loop_enc1_7: -.byte 102,15,56,220,209 - decl %eax - movups (%rcx),%xmm1 - leaq 16(%rcx),%rcx - jnz .Loop_enc1_7 -.byte 102,15,56,221,209 - xorps %xmm10,%xmm2 - movups %xmm2,(%rsi) - jmp .Lctr32_done - -.align 16 .Lctr32_done: + xorps %xmm0,%xmm0 + xorl %r11d,%r11d + pxor %xmm1,%xmm1 + pxor %xmm2,%xmm2 + pxor %xmm3,%xmm3 + pxor %xmm4,%xmm4 + pxor %xmm5,%xmm5 + pxor %xmm6,%xmm6 + pxor %xmm7,%xmm7 + movaps %xmm0,0(%rsp) + pxor %xmm8,%xmm8 + movaps %xmm0,16(%rsp) + pxor %xmm9,%xmm9 + movaps %xmm0,32(%rsp) + pxor %xmm10,%xmm10 + movaps %xmm0,48(%rsp) + pxor %xmm11,%xmm11 + movaps %xmm0,64(%rsp) + pxor %xmm12,%xmm12 + movaps %xmm0,80(%rsp) + pxor %xmm13,%xmm13 + movaps %xmm0,96(%rsp) + pxor %xmm14,%xmm14 + movaps %xmm0,112(%rsp) + pxor %xmm15,%xmm15 leaq (%rbp),%rsp popq %rbp .Lctr32_epilogue: @@ -1759,6 +1838,7 @@ aesni_xts_encrypt: shrl $4,%eax .Lxts_enc_short: + movl %eax,%r10d pxor %xmm0,%xmm10 addq $96,%rdx @@ -1787,6 +1867,7 @@ aesni_xts_encrypt: pxor %xmm12,%xmm4 pxor %xmm13,%xmm5 pxor %xmm14,%xmm6 + pxor %xmm7,%xmm7 call _aesni_encrypt6 @@ -1929,6 +2010,29 @@ aesni_xts_encrypt: movups %xmm2,-16(%rsi) .Lxts_enc_ret: + xorps %xmm0,%xmm0 + pxor %xmm1,%xmm1 + pxor %xmm2,%xmm2 + pxor %xmm3,%xmm3 + pxor %xmm4,%xmm4 + pxor %xmm5,%xmm5 + pxor %xmm6,%xmm6 + pxor %xmm7,%xmm7 + movaps %xmm0,0(%rsp) + pxor %xmm8,%xmm8 + movaps %xmm0,16(%rsp) + pxor %xmm9,%xmm9 + movaps %xmm0,32(%rsp) + pxor %xmm10,%xmm10 + movaps %xmm0,48(%rsp) + pxor %xmm11,%xmm11 + movaps %xmm0,64(%rsp) + pxor %xmm12,%xmm12 + movaps %xmm0,80(%rsp) + pxor %xmm13,%xmm13 + movaps %xmm0,96(%rsp) + pxor %xmm14,%xmm14 + pxor %xmm15,%xmm15 leaq (%rbp),%rsp popq %rbp .Lxts_enc_epilogue: @@ -2206,6 +2310,7 @@ aesni_xts_decrypt: shrl $4,%eax .Lxts_dec_short: + movl %eax,%r10d pxor %xmm0,%xmm10 pxor %xmm0,%xmm11 @@ -2408,6 +2513,29 @@ aesni_xts_decrypt: movups %xmm2,(%rsi) .Lxts_dec_ret: + xorps %xmm0,%xmm0 + pxor %xmm1,%xmm1 + pxor %xmm2,%xmm2 + pxor %xmm3,%xmm3 + pxor %xmm4,%xmm4 + pxor %xmm5,%xmm5 + pxor %xmm6,%xmm6 + pxor %xmm7,%xmm7 + movaps %xmm0,0(%rsp) + pxor %xmm8,%xmm8 + movaps %xmm0,16(%rsp) + pxor %xmm9,%xmm9 + movaps %xmm0,32(%rsp) + pxor %xmm10,%xmm10 + movaps %xmm0,48(%rsp) + pxor %xmm11,%xmm11 + movaps %xmm0,64(%rsp) + pxor %xmm12,%xmm12 + movaps %xmm0,80(%rsp) + pxor %xmm13,%xmm13 + movaps %xmm0,96(%rsp) + pxor %xmm14,%xmm14 + pxor %xmm15,%xmm15 leaq (%rbp),%rsp popq %rbp .Lxts_dec_epilogue: @@ -2457,7 +2585,11 @@ aesni_cbc_encrypt: jnc .Lcbc_enc_loop addq $16,%rdx jnz .Lcbc_enc_tail + pxor %xmm0,%xmm0 + pxor %xmm1,%xmm1 movups %xmm2,(%r8) + pxor %xmm2,%xmm2 + pxor %xmm3,%xmm3 jmp .Lcbc_ret .Lcbc_enc_tail: @@ -2477,6 +2609,35 @@ aesni_cbc_encrypt: .align 16 .Lcbc_decrypt: + cmpq $16,%rdx + jne .Lcbc_decrypt_bulk + + + + movdqu (%rdi),%xmm2 + movdqu (%r8),%xmm3 + movdqa %xmm2,%xmm4 + movups (%rcx),%xmm0 + movups 16(%rcx),%xmm1 + leaq 32(%rcx),%rcx + xorps %xmm0,%xmm2 +.Loop_dec1_16: +.byte 102,15,56,222,209 + decl %r10d + movups (%rcx),%xmm1 + leaq 16(%rcx),%rcx + jnz .Loop_dec1_16 +.byte 102,15,56,223,209 + pxor %xmm0,%xmm0 + pxor %xmm1,%xmm1 + movdqu %xmm4,(%r8) + xorps %xmm3,%xmm2 + pxor %xmm3,%xmm3 + movups %xmm2,(%rsi) + pxor %xmm2,%xmm2 + jmp .Lcbc_ret +.align 16 +.Lcbc_decrypt_bulk: leaq (%rsp),%rax pushq %rbp subq $16,%rsp @@ -2713,7 +2874,7 @@ aesni_cbc_encrypt: movaps %xmm9,%xmm2 leaq -112(%rcx),%rcx addq $112,%rdx - jle .Lcbc_dec_tail_collected + jle .Lcbc_dec_clear_tail_collected movups %xmm9,(%rsi) leaq 16(%rsi),%rsi cmpq $80,%rdx @@ -2732,14 +2893,19 @@ aesni_cbc_encrypt: movdqu %xmm2,(%rsi) pxor %xmm12,%xmm4 movdqu %xmm3,16(%rsi) + pxor %xmm3,%xmm3 pxor %xmm13,%xmm5 movdqu %xmm4,32(%rsi) + pxor %xmm4,%xmm4 pxor %xmm14,%xmm6 movdqu %xmm5,48(%rsi) + pxor %xmm5,%xmm5 pxor %xmm15,%xmm7 movdqu %xmm6,64(%rsi) + pxor %xmm6,%xmm6 leaq 80(%rsi),%rsi movdqa %xmm7,%xmm2 + pxor %xmm7,%xmm7 jmp .Lcbc_dec_tail_collected .align 16 @@ -2754,16 +2920,23 @@ aesni_cbc_encrypt: movdqu %xmm2,(%rsi) pxor %xmm12,%xmm4 movdqu %xmm3,16(%rsi) + pxor %xmm3,%xmm3 pxor %xmm13,%xmm5 movdqu %xmm4,32(%rsi) + pxor %xmm4,%xmm4 pxor %xmm14,%xmm6 movdqu %xmm5,48(%rsi) + pxor %xmm5,%xmm5 pxor %xmm15,%xmm7 movdqu %xmm6,64(%rsi) + pxor %xmm6,%xmm6 pxor %xmm9,%xmm8 movdqu %xmm7,80(%rsi) + pxor %xmm7,%xmm7 leaq 96(%rsi),%rsi movdqa %xmm8,%xmm2 + pxor %xmm8,%xmm8 + pxor %xmm9,%xmm9 jmp .Lcbc_dec_tail_collected .align 16 @@ -2807,7 +2980,7 @@ aesni_cbc_encrypt: movdqa %xmm7,%xmm2 addq $80,%rdx - jle .Lcbc_dec_tail_collected + jle .Lcbc_dec_clear_tail_collected movups %xmm7,(%rsi) leaq 16(%rsi),%rsi @@ -2842,12 +3015,17 @@ aesni_cbc_encrypt: movdqu %xmm2,(%rsi) pxor %xmm12,%xmm4 movdqu %xmm3,16(%rsi) + pxor %xmm3,%xmm3 pxor %xmm13,%xmm5 movdqu %xmm4,32(%rsi) + pxor %xmm4,%xmm4 pxor %xmm14,%xmm6 movdqu %xmm5,48(%rsi) + pxor %xmm5,%xmm5 leaq 64(%rsi),%rsi movdqa %xmm6,%xmm2 + pxor %xmm6,%xmm6 + pxor %xmm7,%xmm7 subq $16,%rdx jmp .Lcbc_dec_tail_collected @@ -2858,12 +3036,12 @@ aesni_cbc_encrypt: movups 16(%rcx),%xmm1 leaq 32(%rcx),%rcx xorps %xmm0,%xmm2 -.Loop_dec1_16: +.Loop_dec1_17: .byte 102,15,56,222,209 decl %eax movups (%rcx),%xmm1 leaq 16(%rcx),%rcx - jnz .Loop_dec1_16 + jnz .Loop_dec1_17 .byte 102,15,56,223,209 xorps %xmm10,%xmm2 movaps %xmm11,%xmm10 @@ -2877,6 +3055,7 @@ aesni_cbc_encrypt: pxor %xmm11,%xmm3 movdqu %xmm2,(%rsi) movdqa %xmm3,%xmm2 + pxor %xmm3,%xmm3 leaq 16(%rsi),%rsi jmp .Lcbc_dec_tail_collected .align 16 @@ -2889,7 +3068,9 @@ aesni_cbc_encrypt: movdqu %xmm2,(%rsi) pxor %xmm12,%xmm4 movdqu %xmm3,16(%rsi) + pxor %xmm3,%xmm3 movdqa %xmm4,%xmm2 + pxor %xmm4,%xmm4 leaq 32(%rsi),%rsi jmp .Lcbc_dec_tail_collected .align 16 @@ -2902,29 +3083,45 @@ aesni_cbc_encrypt: movdqu %xmm2,(%rsi) pxor %xmm12,%xmm4 movdqu %xmm3,16(%rsi) + pxor %xmm3,%xmm3 pxor %xmm13,%xmm5 movdqu %xmm4,32(%rsi) + pxor %xmm4,%xmm4 movdqa %xmm5,%xmm2 + pxor %xmm5,%xmm5 leaq 48(%rsi),%rsi jmp .Lcbc_dec_tail_collected .align 16 +.Lcbc_dec_clear_tail_collected: + pxor %xmm3,%xmm3 + pxor %xmm4,%xmm4 + pxor %xmm5,%xmm5 + pxor %xmm6,%xmm6 + pxor %xmm7,%xmm7 + pxor %xmm8,%xmm8 + pxor %xmm9,%xmm9 .Lcbc_dec_tail_collected: movups %xmm10,(%r8) andq $15,%rdx jnz .Lcbc_dec_tail_partial movups %xmm2,(%rsi) + pxor %xmm2,%xmm2 jmp .Lcbc_dec_ret .align 16 .Lcbc_dec_tail_partial: movaps %xmm2,(%rsp) + pxor %xmm2,%xmm2 movq $16,%rcx movq %rsi,%rdi subq %rdx,%rcx leaq (%rsp),%rsi .long 0x9066A4F3 + movdqa %xmm2,(%rsp) .Lcbc_dec_ret: + xorps %xmm0,%xmm0 + pxor %xmm1,%xmm1 leaq (%rbp),%rsp popq %rbp .Lcbc_ret: @@ -2963,7 +3160,9 @@ aesni_set_decrypt_key: movups (%rdx),%xmm0 .byte 102,15,56,219,192 + pxor %xmm1,%xmm1 movups %xmm0,(%rdi) + pxor %xmm0,%xmm0 .Ldec_key_ret: addq $8,%rsp .byte 0xf3,0xc3 @@ -2982,8 +3181,10 @@ __aesni_set_encrypt_key: testq %rdx,%rdx jz .Lenc_key_ret + movl $268437504,%r10d movups (%rdi),%xmm0 xorps %xmm4,%xmm4 + andl OPENSSL_ia32cap_P+4(%rip),%r10d leaq 16(%rdx),%rax cmpl $256,%esi je .L14rounds @@ -2994,6 +3195,9 @@ __aesni_set_encrypt_key: .L10rounds: movl $9,%esi + cmpl $268435456,%r10d + je .L10rounds_alt + movups %xmm0,(%rdx) .byte 102,15,58,223,200,1 call .Lkey_expansion_128_cold @@ -3020,10 +3224,80 @@ __aesni_set_encrypt_key: xorl %eax,%eax jmp .Lenc_key_ret +.align 16 +.L10rounds_alt: + movdqa .Lkey_rotate(%rip),%xmm5 + movl $8,%r10d + movdqa .Lkey_rcon1(%rip),%xmm4 + movdqa %xmm0,%xmm2 + movdqu %xmm0,(%rdx) + jmp .Loop_key128 + +.align 16 +.Loop_key128: +.byte 102,15,56,0,197 +.byte 102,15,56,221,196 + pslld $1,%xmm4 + leaq 16(%rax),%rax + + movdqa %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm3,%xmm2 + + pxor %xmm2,%xmm0 + movdqu %xmm0,-16(%rax) + movdqa %xmm0,%xmm2 + + decl %r10d + jnz .Loop_key128 + + movdqa .Lkey_rcon1b(%rip),%xmm4 + +.byte 102,15,56,0,197 +.byte 102,15,56,221,196 + pslld $1,%xmm4 + + movdqa %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm3,%xmm2 + + pxor %xmm2,%xmm0 + movdqu %xmm0,(%rax) + + movdqa %xmm0,%xmm2 +.byte 102,15,56,0,197 +.byte 102,15,56,221,196 + + movdqa %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm3,%xmm2 + + pxor %xmm2,%xmm0 + movdqu %xmm0,16(%rax) + + movl %esi,96(%rax) + xorl %eax,%eax + jmp .Lenc_key_ret + .align 16 .L12rounds: movq 16(%rdi),%xmm2 movl $11,%esi + cmpl $268435456,%r10d + je .L12rounds_alt + movups %xmm0,(%rdx) .byte 102,15,58,223,202,1 call .Lkey_expansion_192a_cold @@ -3046,11 +3320,55 @@ __aesni_set_encrypt_key: xorq %rax,%rax jmp .Lenc_key_ret +.align 16 +.L12rounds_alt: + movdqa .Lkey_rotate192(%rip),%xmm5 + movdqa .Lkey_rcon1(%rip),%xmm4 + movl $8,%r10d + movdqu %xmm0,(%rdx) + jmp .Loop_key192 + +.align 16 +.Loop_key192: + movq %xmm2,0(%rax) + movdqa %xmm2,%xmm1 +.byte 102,15,56,0,213 +.byte 102,15,56,221,212 + pslld $1,%xmm4 + leaq 24(%rax),%rax + + movdqa %xmm0,%xmm3 + pslldq $4,%xmm0 + pxor %xmm0,%xmm3 + pslldq $4,%xmm0 + pxor %xmm0,%xmm3 + pslldq $4,%xmm0 + pxor %xmm3,%xmm0 + + pshufd $255,%xmm0,%xmm3 + pxor %xmm1,%xmm3 + pslldq $4,%xmm1 + pxor %xmm1,%xmm3 + + pxor %xmm2,%xmm0 + pxor %xmm3,%xmm2 + movdqu %xmm0,-16(%rax) + + decl %r10d + jnz .Loop_key192 + + movl %esi,32(%rax) + xorl %eax,%eax + jmp .Lenc_key_ret + .align 16 .L14rounds: movups 16(%rdi),%xmm2 movl $13,%esi leaq 16(%rax),%rax + cmpl $268435456,%r10d + je .L14rounds_alt + movups %xmm0,(%rdx) movups %xmm2,16(%rdx) .byte 102,15,58,223,202,1 @@ -3084,10 +3402,70 @@ __aesni_set_encrypt_key: xorq %rax,%rax jmp .Lenc_key_ret +.align 16 +.L14rounds_alt: + movdqa .Lkey_rotate(%rip),%xmm5 + movdqa .Lkey_rcon1(%rip),%xmm4 + movl $7,%r10d + movdqu %xmm0,0(%rdx) + movdqa %xmm2,%xmm1 + movdqu %xmm2,16(%rdx) + jmp .Loop_key256 + +.align 16 +.Loop_key256: +.byte 102,15,56,0,213 +.byte 102,15,56,221,212 + + movdqa %xmm0,%xmm3 + pslldq $4,%xmm0 + pxor %xmm0,%xmm3 + pslldq $4,%xmm0 + pxor %xmm0,%xmm3 + pslldq $4,%xmm0 + pxor %xmm3,%xmm0 + pslld $1,%xmm4 + + pxor %xmm2,%xmm0 + movdqu %xmm0,(%rax) + + decl %r10d + jz .Ldone_key256 + + pshufd $255,%xmm0,%xmm2 + pxor %xmm3,%xmm3 +.byte 102,15,56,221,211 + + movdqa %xmm1,%xmm3 + pslldq $4,%xmm1 + pxor %xmm1,%xmm3 + pslldq $4,%xmm1 + pxor %xmm1,%xmm3 + pslldq $4,%xmm1 + pxor %xmm3,%xmm1 + + pxor %xmm1,%xmm2 + movdqu %xmm2,16(%rax) + leaq 32(%rax),%rax + movdqa %xmm2,%xmm1 + + jmp .Loop_key256 + +.Ldone_key256: + movl %esi,16(%rax) + xorl %eax,%eax + jmp .Lenc_key_ret + .align 16 .Lbad_keybits: movq $-2,%rax .Lenc_key_ret: + pxor %xmm0,%xmm0 + pxor %xmm1,%xmm1 + pxor %xmm2,%xmm2 + pxor %xmm3,%xmm3 + pxor %xmm4,%xmm4 + pxor %xmm5,%xmm5 addq $8,%rsp .byte 0xf3,0xc3 .LSEH_end_set_encrypt_key: @@ -3173,6 +3551,14 @@ __aesni_set_encrypt_key: .long 0x87,0,1,0 .Lincrement1: .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 +.Lkey_rotate: +.long 0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d +.Lkey_rotate192: +.long 0x04070605,0x04070605,0x04070605,0x04070605 +.Lkey_rcon1: +.long 1,1,1,1 +.Lkey_rcon1b: +.long 0x1b,0x1b,0x1b,0x1b .byte 65,69,83,32,102,111,114,32,73,110,116,101,108,32,65,69,83,45,78,73,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0 .align 64 diff --git a/third_party/boringssl/linux-x86_64/crypto/rand/rdrand-x86_64.S b/third_party/boringssl/linux-x86_64/crypto/rand/rdrand-x86_64.S new file mode 100644 index 0000000000000..94aab9c19b7ef --- /dev/null +++ b/third_party/boringssl/linux-x86_64/crypto/rand/rdrand-x86_64.S @@ -0,0 +1,48 @@ +#if defined(__x86_64__) +.text + + + + +.globl CRYPTO_rdrand +.hidden CRYPTO_rdrand +.type CRYPTO_rdrand,@function +.align 16 +CRYPTO_rdrand: + xorq %rax,%rax + + +.byte 0x48, 0x0f, 0xc7, 0xf1 + + adcq %rax,%rax + movq %rcx,0(%rdi) + .byte 0xf3,0xc3 + + + + + +.globl CRYPTO_rdrand_multiple8_buf +.hidden CRYPTO_rdrand_multiple8_buf +.type CRYPTO_rdrand_multiple8_buf,@function +.align 16 +CRYPTO_rdrand_multiple8_buf: + testq %rsi,%rsi + jz .Lout + movq $8,%rdx +.Lloop: + + +.byte 0x48, 0x0f, 0xc7, 0xf1 + jnc .Lerr + movq %rcx,0(%rdi) + addq %rdx,%rdi + subq %rdx,%rsi + jnz .Lloop +.Lout: + movq $1,%rax + .byte 0xf3,0xc3 +.Lerr: + xorq %rax,%rax + .byte 0xf3,0xc3 +#endif diff --git a/third_party/boringssl/mac-x86/crypto/aes/aesni-x86.S b/third_party/boringssl/mac-x86/crypto/aes/aesni-x86.S index 9000478d20e1a..07719ba7ae8f6 100644 --- a/third_party/boringssl/mac-x86/crypto/aes/aesni-x86.S +++ b/third_party/boringssl/mac-x86/crypto/aes/aesni-x86.S @@ -22,7 +22,10 @@ L000enc1_loop_1: leal 16(%edx),%edx jnz L000enc1_loop_1 .byte 102,15,56,221,209 + pxor %xmm0,%xmm0 + pxor %xmm1,%xmm1 movups %xmm2,(%eax) + pxor %xmm2,%xmm2 ret .globl _aesni_decrypt .private_extern _aesni_decrypt @@ -45,7 +48,10 @@ L001dec1_loop_2: leal 16(%edx),%edx jnz L001dec1_loop_2 .byte 102,15,56,223,209 + pxor %xmm0,%xmm0 + pxor %xmm1,%xmm1 movups %xmm2,(%eax) + pxor %xmm2,%xmm2 ret .private_extern __aesni_encrypt2 .align 4 @@ -252,17 +258,15 @@ __aesni_encrypt6: negl %ecx .byte 102,15,56,220,225 pxor %xmm0,%xmm7 + movups (%edx,%ecx,1),%xmm0 addl $16,%ecx -.byte 102,15,56,220,233 -.byte 102,15,56,220,241 -.byte 102,15,56,220,249 - movups -16(%edx,%ecx,1),%xmm0 - jmp L_aesni_encrypt6_enter + jmp L008_aesni_encrypt6_inner .align 4,0x90 -L008enc6_loop: +L009enc6_loop: .byte 102,15,56,220,209 .byte 102,15,56,220,217 .byte 102,15,56,220,225 +L008_aesni_encrypt6_inner: .byte 102,15,56,220,233 .byte 102,15,56,220,241 .byte 102,15,56,220,249 @@ -276,7 +280,7 @@ L_aesni_encrypt6_enter: .byte 102,15,56,220,240 .byte 102,15,56,220,248 movups -16(%edx,%ecx,1),%xmm0 - jnz L008enc6_loop + jnz L009enc6_loop .byte 102,15,56,220,209 .byte 102,15,56,220,217 .byte 102,15,56,220,225 @@ -307,17 +311,15 @@ __aesni_decrypt6: negl %ecx .byte 102,15,56,222,225 pxor %xmm0,%xmm7 + movups (%edx,%ecx,1),%xmm0 addl $16,%ecx -.byte 102,15,56,222,233 -.byte 102,15,56,222,241 -.byte 102,15,56,222,249 - movups -16(%edx,%ecx,1),%xmm0 - jmp L_aesni_decrypt6_enter + jmp L010_aesni_decrypt6_inner .align 4,0x90 -L009dec6_loop: +L011dec6_loop: .byte 102,15,56,222,209 .byte 102,15,56,222,217 .byte 102,15,56,222,225 +L010_aesni_decrypt6_inner: .byte 102,15,56,222,233 .byte 102,15,56,222,241 .byte 102,15,56,222,249 @@ -331,7 +333,7 @@ L_aesni_decrypt6_enter: .byte 102,15,56,222,240 .byte 102,15,56,222,248 movups -16(%edx,%ecx,1),%xmm0 - jnz L009dec6_loop + jnz L011dec6_loop .byte 102,15,56,222,209 .byte 102,15,56,222,217 .byte 102,15,56,222,225 @@ -360,14 +362,14 @@ L_aesni_ecb_encrypt_begin: movl 32(%esp),%edx movl 36(%esp),%ebx andl $-16,%eax - jz L010ecb_ret + jz L012ecb_ret movl 240(%edx),%ecx testl %ebx,%ebx - jz L011ecb_decrypt + jz L013ecb_decrypt movl %edx,%ebp movl %ecx,%ebx cmpl $96,%eax - jb L012ecb_enc_tail + jb L014ecb_enc_tail movdqu (%esi),%xmm2 movdqu 16(%esi),%xmm3 movdqu 32(%esi),%xmm4 @@ -376,9 +378,9 @@ L_aesni_ecb_encrypt_begin: movdqu 80(%esi),%xmm7 leal 96(%esi),%esi subl $96,%eax - jmp L013ecb_enc_loop6_enter + jmp L015ecb_enc_loop6_enter .align 4,0x90 -L014ecb_enc_loop6: +L016ecb_enc_loop6: movups %xmm2,(%edi) movdqu (%esi),%xmm2 movups %xmm3,16(%edi) @@ -393,12 +395,12 @@ L014ecb_enc_loop6: leal 96(%edi),%edi movdqu 80(%esi),%xmm7 leal 96(%esi),%esi -L013ecb_enc_loop6_enter: +L015ecb_enc_loop6_enter: call __aesni_encrypt6 movl %ebp,%edx movl %ebx,%ecx subl $96,%eax - jnc L014ecb_enc_loop6 + jnc L016ecb_enc_loop6 movups %xmm2,(%edi) movups %xmm3,16(%edi) movups %xmm4,32(%edi) @@ -407,18 +409,18 @@ L013ecb_enc_loop6_enter: movups %xmm7,80(%edi) leal 96(%edi),%edi addl $96,%eax - jz L010ecb_ret -L012ecb_enc_tail: + jz L012ecb_ret +L014ecb_enc_tail: movups (%esi),%xmm2 cmpl $32,%eax - jb L015ecb_enc_one + jb L017ecb_enc_one movups 16(%esi),%xmm3 - je L016ecb_enc_two + je L018ecb_enc_two movups 32(%esi),%xmm4 cmpl $64,%eax - jb L017ecb_enc_three + jb L019ecb_enc_three movups 48(%esi),%xmm5 - je L018ecb_enc_four + je L020ecb_enc_four movups 64(%esi),%xmm6 xorps %xmm7,%xmm7 call __aesni_encrypt6 @@ -427,49 +429,49 @@ L012ecb_enc_tail: movups %xmm4,32(%edi) movups %xmm5,48(%edi) movups %xmm6,64(%edi) - jmp L010ecb_ret + jmp L012ecb_ret .align 4,0x90 -L015ecb_enc_one: +L017ecb_enc_one: movups (%edx),%xmm0 movups 16(%edx),%xmm1 leal 32(%edx),%edx xorps %xmm0,%xmm2 -L019enc1_loop_3: +L021enc1_loop_3: .byte 102,15,56,220,209 decl %ecx movups (%edx),%xmm1 leal 16(%edx),%edx - jnz L019enc1_loop_3 + jnz L021enc1_loop_3 .byte 102,15,56,221,209 movups %xmm2,(%edi) - jmp L010ecb_ret + jmp L012ecb_ret .align 4,0x90 -L016ecb_enc_two: +L018ecb_enc_two: call __aesni_encrypt2 movups %xmm2,(%edi) movups %xmm3,16(%edi) - jmp L010ecb_ret + jmp L012ecb_ret .align 4,0x90 -L017ecb_enc_three: +L019ecb_enc_three: call __aesni_encrypt3 movups %xmm2,(%edi) movups %xmm3,16(%edi) movups %xmm4,32(%edi) - jmp L010ecb_ret + jmp L012ecb_ret .align 4,0x90 -L018ecb_enc_four: +L020ecb_enc_four: call __aesni_encrypt4 movups %xmm2,(%edi) movups %xmm3,16(%edi) movups %xmm4,32(%edi) movups %xmm5,48(%edi) - jmp L010ecb_ret + jmp L012ecb_ret .align 4,0x90 -L011ecb_decrypt: +L013ecb_decrypt: movl %edx,%ebp movl %ecx,%ebx cmpl $96,%eax - jb L020ecb_dec_tail + jb L022ecb_dec_tail movdqu (%esi),%xmm2 movdqu 16(%esi),%xmm3 movdqu 32(%esi),%xmm4 @@ -478,9 +480,9 @@ L011ecb_decrypt: movdqu 80(%esi),%xmm7 leal 96(%esi),%esi subl $96,%eax - jmp L021ecb_dec_loop6_enter + jmp L023ecb_dec_loop6_enter .align 4,0x90 -L022ecb_dec_loop6: +L024ecb_dec_loop6: movups %xmm2,(%edi) movdqu (%esi),%xmm2 movups %xmm3,16(%edi) @@ -495,12 +497,12 @@ L022ecb_dec_loop6: leal 96(%edi),%edi movdqu 80(%esi),%xmm7 leal 96(%esi),%esi -L021ecb_dec_loop6_enter: +L023ecb_dec_loop6_enter: call __aesni_decrypt6 movl %ebp,%edx movl %ebx,%ecx subl $96,%eax - jnc L022ecb_dec_loop6 + jnc L024ecb_dec_loop6 movups %xmm2,(%edi) movups %xmm3,16(%edi) movups %xmm4,32(%edi) @@ -509,18 +511,18 @@ L021ecb_dec_loop6_enter: movups %xmm7,80(%edi) leal 96(%edi),%edi addl $96,%eax - jz L010ecb_ret -L020ecb_dec_tail: + jz L012ecb_ret +L022ecb_dec_tail: movups (%esi),%xmm2 cmpl $32,%eax - jb L023ecb_dec_one + jb L025ecb_dec_one movups 16(%esi),%xmm3 - je L024ecb_dec_two + je L026ecb_dec_two movups 32(%esi),%xmm4 cmpl $64,%eax - jb L025ecb_dec_three + jb L027ecb_dec_three movups 48(%esi),%xmm5 - je L026ecb_dec_four + je L028ecb_dec_four movups 64(%esi),%xmm6 xorps %xmm7,%xmm7 call __aesni_decrypt6 @@ -529,43 +531,51 @@ L020ecb_dec_tail: movups %xmm4,32(%edi) movups %xmm5,48(%edi) movups %xmm6,64(%edi) - jmp L010ecb_ret + jmp L012ecb_ret .align 4,0x90 -L023ecb_dec_one: +L025ecb_dec_one: movups (%edx),%xmm0 movups 16(%edx),%xmm1 leal 32(%edx),%edx xorps %xmm0,%xmm2 -L027dec1_loop_4: +L029dec1_loop_4: .byte 102,15,56,222,209 decl %ecx movups (%edx),%xmm1 leal 16(%edx),%edx - jnz L027dec1_loop_4 + jnz L029dec1_loop_4 .byte 102,15,56,223,209 movups %xmm2,(%edi) - jmp L010ecb_ret + jmp L012ecb_ret .align 4,0x90 -L024ecb_dec_two: +L026ecb_dec_two: call __aesni_decrypt2 movups %xmm2,(%edi) movups %xmm3,16(%edi) - jmp L010ecb_ret + jmp L012ecb_ret .align 4,0x90 -L025ecb_dec_three: +L027ecb_dec_three: call __aesni_decrypt3 movups %xmm2,(%edi) movups %xmm3,16(%edi) movups %xmm4,32(%edi) - jmp L010ecb_ret + jmp L012ecb_ret .align 4,0x90 -L026ecb_dec_four: +L028ecb_dec_four: call __aesni_decrypt4 movups %xmm2,(%edi) movups %xmm3,16(%edi) movups %xmm4,32(%edi) movups %xmm5,48(%edi) -L010ecb_ret: +L012ecb_ret: + pxor %xmm0,%xmm0 + pxor %xmm1,%xmm1 + pxor %xmm2,%xmm2 + pxor %xmm3,%xmm3 + pxor %xmm4,%xmm4 + pxor %xmm5,%xmm5 + pxor %xmm6,%xmm6 + pxor %xmm7,%xmm7 popl %edi popl %esi popl %ebx @@ -611,7 +621,7 @@ L_aesni_ccm64_encrypt_blocks_begin: leal 32(%edx,%ecx,1),%edx subl %ecx,%ebx .byte 102,15,56,0,253 -L028ccm64_enc_outer: +L030ccm64_enc_outer: movups (%ebp),%xmm0 movl %ebx,%ecx movups (%esi),%xmm6 @@ -620,7 +630,7 @@ L028ccm64_enc_outer: xorps %xmm6,%xmm0 xorps %xmm0,%xmm3 movups 32(%ebp),%xmm0 -L029ccm64_enc2_loop: +L031ccm64_enc2_loop: .byte 102,15,56,220,209 .byte 102,15,56,220,217 movups (%edx,%ecx,1),%xmm1 @@ -628,7 +638,7 @@ L029ccm64_enc2_loop: .byte 102,15,56,220,208 .byte 102,15,56,220,216 movups -16(%edx,%ecx,1),%xmm0 - jnz L029ccm64_enc2_loop + jnz L031ccm64_enc2_loop .byte 102,15,56,220,209 .byte 102,15,56,220,217 paddq 16(%esp),%xmm7 @@ -641,10 +651,18 @@ L029ccm64_enc2_loop: movups %xmm6,(%edi) .byte 102,15,56,0,213 leal 16(%edi),%edi - jnz L028ccm64_enc_outer + jnz L030ccm64_enc_outer movl 48(%esp),%esp movl 40(%esp),%edi movups %xmm3,(%edi) + pxor %xmm0,%xmm0 + pxor %xmm1,%xmm1 + pxor %xmm2,%xmm2 + pxor %xmm3,%xmm3 + pxor %xmm4,%xmm4 + pxor %xmm5,%xmm5 + pxor %xmm6,%xmm6 + pxor %xmm7,%xmm7 popl %edi popl %esi popl %ebx @@ -691,12 +709,12 @@ L_aesni_ccm64_decrypt_blocks_begin: movups 16(%edx),%xmm1 leal 32(%edx),%edx xorps %xmm0,%xmm2 -L030enc1_loop_5: +L032enc1_loop_5: .byte 102,15,56,220,209 decl %ecx movups (%edx),%xmm1 leal 16(%edx),%edx - jnz L030enc1_loop_5 + jnz L032enc1_loop_5 .byte 102,15,56,221,209 shll $4,%ebx movl $16,%ecx @@ -706,16 +724,16 @@ L030enc1_loop_5: subl %ebx,%ecx leal 32(%ebp,%ebx,1),%edx movl %ecx,%ebx - jmp L031ccm64_dec_outer + jmp L033ccm64_dec_outer .align 4,0x90 -L031ccm64_dec_outer: +L033ccm64_dec_outer: xorps %xmm2,%xmm6 movdqa %xmm7,%xmm2 movups %xmm6,(%edi) leal 16(%edi),%edi .byte 102,15,56,0,213 subl $1,%eax - jz L032ccm64_dec_break + jz L034ccm64_dec_break movups (%ebp),%xmm0 movl %ebx,%ecx movups 16(%ebp),%xmm1 @@ -723,7 +741,7 @@ L031ccm64_dec_outer: xorps %xmm0,%xmm2 xorps %xmm6,%xmm3 movups 32(%ebp),%xmm0 -L033ccm64_dec2_loop: +L035ccm64_dec2_loop: .byte 102,15,56,220,209 .byte 102,15,56,220,217 movups (%edx,%ecx,1),%xmm1 @@ -731,7 +749,7 @@ L033ccm64_dec2_loop: .byte 102,15,56,220,208 .byte 102,15,56,220,216 movups -16(%edx,%ecx,1),%xmm0 - jnz L033ccm64_dec2_loop + jnz L035ccm64_dec2_loop movups (%esi),%xmm6 paddq 16(%esp),%xmm7 .byte 102,15,56,220,209 @@ -739,9 +757,9 @@ L033ccm64_dec2_loop: .byte 102,15,56,221,208 .byte 102,15,56,221,216 leal 16(%esi),%esi - jmp L031ccm64_dec_outer + jmp L033ccm64_dec_outer .align 4,0x90 -L032ccm64_dec_break: +L034ccm64_dec_break: movl 240(%ebp),%ecx movl %ebp,%edx movups (%edx),%xmm0 @@ -749,16 +767,24 @@ L032ccm64_dec_break: xorps %xmm0,%xmm6 leal 32(%edx),%edx xorps %xmm6,%xmm3 -L034enc1_loop_6: +L036enc1_loop_6: .byte 102,15,56,220,217 decl %ecx movups (%edx),%xmm1 leal 16(%edx),%edx - jnz L034enc1_loop_6 + jnz L036enc1_loop_6 .byte 102,15,56,221,217 movl 48(%esp),%esp movl 40(%esp),%edi movups %xmm3,(%edi) + pxor %xmm0,%xmm0 + pxor %xmm1,%xmm1 + pxor %xmm2,%xmm2 + pxor %xmm3,%xmm3 + pxor %xmm4,%xmm4 + pxor %xmm5,%xmm5 + pxor %xmm6,%xmm6 + pxor %xmm7,%xmm7 popl %edi popl %esi popl %ebx @@ -783,7 +809,7 @@ L_aesni_ctr32_encrypt_blocks_begin: andl $-16,%esp movl %ebp,80(%esp) cmpl $1,%eax - je L035ctr32_one_shortcut + je L037ctr32_one_shortcut movdqu (%ebx),%xmm7 movl $202182159,(%esp) movl $134810123,4(%esp) @@ -821,7 +847,7 @@ L_aesni_ctr32_encrypt_blocks_begin: pshufd $192,%xmm0,%xmm2 pshufd $128,%xmm0,%xmm3 cmpl $6,%eax - jb L036ctr32_tail + jb L038ctr32_tail pxor %xmm6,%xmm7 shll $4,%ecx movl $16,%ebx @@ -830,9 +856,9 @@ L_aesni_ctr32_encrypt_blocks_begin: subl %ecx,%ebx leal 32(%edx,%ecx,1),%edx subl $6,%eax - jmp L037ctr32_loop6 + jmp L039ctr32_loop6 .align 4,0x90 -L037ctr32_loop6: +L039ctr32_loop6: pshufd $64,%xmm0,%xmm4 movdqa 32(%esp),%xmm0 pshufd $192,%xmm1,%xmm5 @@ -886,27 +912,27 @@ L037ctr32_loop6: leal 96(%edi),%edi pshufd $128,%xmm0,%xmm3 subl $6,%eax - jnc L037ctr32_loop6 + jnc L039ctr32_loop6 addl $6,%eax - jz L038ctr32_ret + jz L040ctr32_ret movdqu (%ebp),%xmm7 movl %ebp,%edx pxor 32(%esp),%xmm7 movl 240(%ebp),%ecx -L036ctr32_tail: +L038ctr32_tail: por %xmm7,%xmm2 cmpl $2,%eax - jb L039ctr32_one + jb L041ctr32_one pshufd $64,%xmm0,%xmm4 por %xmm7,%xmm3 - je L040ctr32_two + je L042ctr32_two pshufd $192,%xmm1,%xmm5 por %xmm7,%xmm4 cmpl $4,%eax - jb L041ctr32_three + jb L043ctr32_three pshufd $128,%xmm1,%xmm6 por %xmm7,%xmm5 - je L042ctr32_four + je L044ctr32_four por %xmm7,%xmm6 call __aesni_encrypt6 movups (%esi),%xmm1 @@ -924,29 +950,29 @@ L036ctr32_tail: movups %xmm4,32(%edi) movups %xmm5,48(%edi) movups %xmm6,64(%edi) - jmp L038ctr32_ret + jmp L040ctr32_ret .align 4,0x90 -L035ctr32_one_shortcut: +L037ctr32_one_shortcut: movups (%ebx),%xmm2 movl 240(%edx),%ecx -L039ctr32_one: +L041ctr32_one: movups (%edx),%xmm0 movups 16(%edx),%xmm1 leal 32(%edx),%edx xorps %xmm0,%xmm2 -L043enc1_loop_7: +L045enc1_loop_7: .byte 102,15,56,220,209 decl %ecx movups (%edx),%xmm1 leal 16(%edx),%edx - jnz L043enc1_loop_7 + jnz L045enc1_loop_7 .byte 102,15,56,221,209 movups (%esi),%xmm6 xorps %xmm2,%xmm6 movups %xmm6,(%edi) - jmp L038ctr32_ret + jmp L040ctr32_ret .align 4,0x90 -L040ctr32_two: +L042ctr32_two: call __aesni_encrypt2 movups (%esi),%xmm5 movups 16(%esi),%xmm6 @@ -954,9 +980,9 @@ L040ctr32_two: xorps %xmm6,%xmm3 movups %xmm2,(%edi) movups %xmm3,16(%edi) - jmp L038ctr32_ret + jmp L040ctr32_ret .align 4,0x90 -L041ctr32_three: +L043ctr32_three: call __aesni_encrypt3 movups (%esi),%xmm5 movups 16(%esi),%xmm6 @@ -967,9 +993,9 @@ L041ctr32_three: xorps %xmm7,%xmm4 movups %xmm3,16(%edi) movups %xmm4,32(%edi) - jmp L038ctr32_ret + jmp L040ctr32_ret .align 4,0x90 -L042ctr32_four: +L044ctr32_four: call __aesni_encrypt4 movups (%esi),%xmm6 movups 16(%esi),%xmm7 @@ -983,7 +1009,18 @@ L042ctr32_four: xorps %xmm0,%xmm5 movups %xmm4,32(%edi) movups %xmm5,48(%edi) -L038ctr32_ret: +L040ctr32_ret: + pxor %xmm0,%xmm0 + pxor %xmm1,%xmm1 + pxor %xmm2,%xmm2 + pxor %xmm3,%xmm3 + pxor %xmm4,%xmm4 + movdqa %xmm0,32(%esp) + pxor %xmm5,%xmm5 + movdqa %xmm0,48(%esp) + pxor %xmm6,%xmm6 + movdqa %xmm0,64(%esp) + pxor %xmm7,%xmm7 movl 80(%esp),%esp popl %edi popl %esi @@ -1007,12 +1044,12 @@ L_aesni_xts_encrypt_begin: movups 16(%edx),%xmm1 leal 32(%edx),%edx xorps %xmm0,%xmm2 -L044enc1_loop_8: +L046enc1_loop_8: .byte 102,15,56,220,209 decl %ecx movups (%edx),%xmm1 leal 16(%edx),%edx - jnz L044enc1_loop_8 + jnz L046enc1_loop_8 .byte 102,15,56,221,209 movl 20(%esp),%esi movl 24(%esp),%edi @@ -1036,14 +1073,14 @@ L044enc1_loop_8: movl %edx,%ebp movl %ecx,%ebx subl $96,%eax - jc L045xts_enc_short + jc L047xts_enc_short shll $4,%ecx movl $16,%ebx subl %ecx,%ebx leal 32(%edx,%ecx,1),%edx - jmp L046xts_enc_loop6 + jmp L048xts_enc_loop6 .align 4,0x90 -L046xts_enc_loop6: +L048xts_enc_loop6: pshufd $19,%xmm0,%xmm2 pxor %xmm0,%xmm0 movdqa %xmm1,(%esp) @@ -1132,23 +1169,23 @@ L046xts_enc_loop6: pcmpgtd %xmm1,%xmm0 pxor %xmm2,%xmm1 subl $96,%eax - jnc L046xts_enc_loop6 + jnc L048xts_enc_loop6 movl 240(%ebp),%ecx movl %ebp,%edx movl %ecx,%ebx -L045xts_enc_short: +L047xts_enc_short: addl $96,%eax - jz L047xts_enc_done6x + jz L049xts_enc_done6x movdqa %xmm1,%xmm5 cmpl $32,%eax - jb L048xts_enc_one + jb L050xts_enc_one pshufd $19,%xmm0,%xmm2 pxor %xmm0,%xmm0 paddq %xmm1,%xmm1 pand %xmm3,%xmm2 pcmpgtd %xmm1,%xmm0 pxor %xmm2,%xmm1 - je L049xts_enc_two + je L051xts_enc_two pshufd $19,%xmm0,%xmm2 pxor %xmm0,%xmm0 movdqa %xmm1,%xmm6 @@ -1157,7 +1194,7 @@ L045xts_enc_short: pcmpgtd %xmm1,%xmm0 pxor %xmm2,%xmm1 cmpl $64,%eax - jb L050xts_enc_three + jb L052xts_enc_three pshufd $19,%xmm0,%xmm2 pxor %xmm0,%xmm0 movdqa %xmm1,%xmm7 @@ -1167,7 +1204,7 @@ L045xts_enc_short: pxor %xmm2,%xmm1 movdqa %xmm5,(%esp) movdqa %xmm6,16(%esp) - je L051xts_enc_four + je L053xts_enc_four movdqa %xmm7,32(%esp) pshufd $19,%xmm0,%xmm7 movdqa %xmm1,48(%esp) @@ -1199,9 +1236,9 @@ L045xts_enc_short: movups %xmm5,48(%edi) movups %xmm6,64(%edi) leal 80(%edi),%edi - jmp L052xts_enc_done + jmp L054xts_enc_done .align 4,0x90 -L048xts_enc_one: +L050xts_enc_one: movups (%esi),%xmm2 leal 16(%esi),%esi xorps %xmm5,%xmm2 @@ -1209,20 +1246,20 @@ L048xts_enc_one: movups 16(%edx),%xmm1 leal 32(%edx),%edx xorps %xmm0,%xmm2 -L053enc1_loop_9: +L055enc1_loop_9: .byte 102,15,56,220,209 decl %ecx movups (%edx),%xmm1 leal 16(%edx),%edx - jnz L053enc1_loop_9 + jnz L055enc1_loop_9 .byte 102,15,56,221,209 xorps %xmm5,%xmm2 movups %xmm2,(%edi) leal 16(%edi),%edi movdqa %xmm5,%xmm1 - jmp L052xts_enc_done + jmp L054xts_enc_done .align 4,0x90 -L049xts_enc_two: +L051xts_enc_two: movaps %xmm1,%xmm6 movups (%esi),%xmm2 movups 16(%esi),%xmm3 @@ -1236,9 +1273,9 @@ L049xts_enc_two: movups %xmm3,16(%edi) leal 32(%edi),%edi movdqa %xmm6,%xmm1 - jmp L052xts_enc_done + jmp L054xts_enc_done .align 4,0x90 -L050xts_enc_three: +L052xts_enc_three: movaps %xmm1,%xmm7 movups (%esi),%xmm2 movups 16(%esi),%xmm3 @@ -1256,9 +1293,9 @@ L050xts_enc_three: movups %xmm4,32(%edi) leal 48(%edi),%edi movdqa %xmm7,%xmm1 - jmp L052xts_enc_done + jmp L054xts_enc_done .align 4,0x90 -L051xts_enc_four: +L053xts_enc_four: movaps %xmm1,%xmm6 movups (%esi),%xmm2 movups 16(%esi),%xmm3 @@ -1280,28 +1317,28 @@ L051xts_enc_four: movups %xmm5,48(%edi) leal 64(%edi),%edi movdqa %xmm6,%xmm1 - jmp L052xts_enc_done + jmp L054xts_enc_done .align 4,0x90 -L047xts_enc_done6x: +L049xts_enc_done6x: movl 112(%esp),%eax andl $15,%eax - jz L054xts_enc_ret + jz L056xts_enc_ret movdqa %xmm1,%xmm5 movl %eax,112(%esp) - jmp L055xts_enc_steal + jmp L057xts_enc_steal .align 4,0x90 -L052xts_enc_done: +L054xts_enc_done: movl 112(%esp),%eax pxor %xmm0,%xmm0 andl $15,%eax - jz L054xts_enc_ret + jz L056xts_enc_ret pcmpgtd %xmm1,%xmm0 movl %eax,112(%esp) pshufd $19,%xmm0,%xmm5 paddq %xmm1,%xmm1 pand 96(%esp),%xmm5 pxor %xmm1,%xmm5 -L055xts_enc_steal: +L057xts_enc_steal: movzbl (%esi),%ecx movzbl -16(%edi),%edx leal 1(%esi),%esi @@ -1309,7 +1346,7 @@ L055xts_enc_steal: movb %dl,(%edi) leal 1(%edi),%edi subl $1,%eax - jnz L055xts_enc_steal + jnz L057xts_enc_steal subl 112(%esp),%edi movl %ebp,%edx movl %ebx,%ecx @@ -1319,16 +1356,30 @@ L055xts_enc_steal: movups 16(%edx),%xmm1 leal 32(%edx),%edx xorps %xmm0,%xmm2 -L056enc1_loop_10: +L058enc1_loop_10: .byte 102,15,56,220,209 decl %ecx movups (%edx),%xmm1 leal 16(%edx),%edx - jnz L056enc1_loop_10 + jnz L058enc1_loop_10 .byte 102,15,56,221,209 xorps %xmm5,%xmm2 movups %xmm2,-16(%edi) -L054xts_enc_ret: +L056xts_enc_ret: + pxor %xmm0,%xmm0 + pxor %xmm1,%xmm1 + pxor %xmm2,%xmm2 + movdqa %xmm0,(%esp) + pxor %xmm3,%xmm3 + movdqa %xmm0,16(%esp) + pxor %xmm4,%xmm4 + movdqa %xmm0,32(%esp) + pxor %xmm5,%xmm5 + movdqa %xmm0,48(%esp) + pxor %xmm6,%xmm6 + movdqa %xmm0,64(%esp) + pxor %xmm7,%xmm7 + movdqa %xmm0,80(%esp) movl 116(%esp),%esp popl %edi popl %esi @@ -1352,12 +1403,12 @@ L_aesni_xts_decrypt_begin: movups 16(%edx),%xmm1 leal 32(%edx),%edx xorps %xmm0,%xmm2 -L057enc1_loop_11: +L059enc1_loop_11: .byte 102,15,56,220,209 decl %ecx movups (%edx),%xmm1 leal 16(%edx),%edx - jnz L057enc1_loop_11 + jnz L059enc1_loop_11 .byte 102,15,56,221,209 movl 20(%esp),%esi movl 24(%esp),%edi @@ -1386,14 +1437,14 @@ L057enc1_loop_11: pcmpgtd %xmm1,%xmm0 andl $-16,%eax subl $96,%eax - jc L058xts_dec_short + jc L060xts_dec_short shll $4,%ecx movl $16,%ebx subl %ecx,%ebx leal 32(%edx,%ecx,1),%edx - jmp L059xts_dec_loop6 + jmp L061xts_dec_loop6 .align 4,0x90 -L059xts_dec_loop6: +L061xts_dec_loop6: pshufd $19,%xmm0,%xmm2 pxor %xmm0,%xmm0 movdqa %xmm1,(%esp) @@ -1482,23 +1533,23 @@ L059xts_dec_loop6: pcmpgtd %xmm1,%xmm0 pxor %xmm2,%xmm1 subl $96,%eax - jnc L059xts_dec_loop6 + jnc L061xts_dec_loop6 movl 240(%ebp),%ecx movl %ebp,%edx movl %ecx,%ebx -L058xts_dec_short: +L060xts_dec_short: addl $96,%eax - jz L060xts_dec_done6x + jz L062xts_dec_done6x movdqa %xmm1,%xmm5 cmpl $32,%eax - jb L061xts_dec_one + jb L063xts_dec_one pshufd $19,%xmm0,%xmm2 pxor %xmm0,%xmm0 paddq %xmm1,%xmm1 pand %xmm3,%xmm2 pcmpgtd %xmm1,%xmm0 pxor %xmm2,%xmm1 - je L062xts_dec_two + je L064xts_dec_two pshufd $19,%xmm0,%xmm2 pxor %xmm0,%xmm0 movdqa %xmm1,%xmm6 @@ -1507,7 +1558,7 @@ L058xts_dec_short: pcmpgtd %xmm1,%xmm0 pxor %xmm2,%xmm1 cmpl $64,%eax - jb L063xts_dec_three + jb L065xts_dec_three pshufd $19,%xmm0,%xmm2 pxor %xmm0,%xmm0 movdqa %xmm1,%xmm7 @@ -1517,7 +1568,7 @@ L058xts_dec_short: pxor %xmm2,%xmm1 movdqa %xmm5,(%esp) movdqa %xmm6,16(%esp) - je L064xts_dec_four + je L066xts_dec_four movdqa %xmm7,32(%esp) pshufd $19,%xmm0,%xmm7 movdqa %xmm1,48(%esp) @@ -1549,9 +1600,9 @@ L058xts_dec_short: movups %xmm5,48(%edi) movups %xmm6,64(%edi) leal 80(%edi),%edi - jmp L065xts_dec_done + jmp L067xts_dec_done .align 4,0x90 -L061xts_dec_one: +L063xts_dec_one: movups (%esi),%xmm2 leal 16(%esi),%esi xorps %xmm5,%xmm2 @@ -1559,20 +1610,20 @@ L061xts_dec_one: movups 16(%edx),%xmm1 leal 32(%edx),%edx xorps %xmm0,%xmm2 -L066dec1_loop_12: +L068dec1_loop_12: .byte 102,15,56,222,209 decl %ecx movups (%edx),%xmm1 leal 16(%edx),%edx - jnz L066dec1_loop_12 + jnz L068dec1_loop_12 .byte 102,15,56,223,209 xorps %xmm5,%xmm2 movups %xmm2,(%edi) leal 16(%edi),%edi movdqa %xmm5,%xmm1 - jmp L065xts_dec_done + jmp L067xts_dec_done .align 4,0x90 -L062xts_dec_two: +L064xts_dec_two: movaps %xmm1,%xmm6 movups (%esi),%xmm2 movups 16(%esi),%xmm3 @@ -1586,9 +1637,9 @@ L062xts_dec_two: movups %xmm3,16(%edi) leal 32(%edi),%edi movdqa %xmm6,%xmm1 - jmp L065xts_dec_done + jmp L067xts_dec_done .align 4,0x90 -L063xts_dec_three: +L065xts_dec_three: movaps %xmm1,%xmm7 movups (%esi),%xmm2 movups 16(%esi),%xmm3 @@ -1606,9 +1657,9 @@ L063xts_dec_three: movups %xmm4,32(%edi) leal 48(%edi),%edi movdqa %xmm7,%xmm1 - jmp L065xts_dec_done + jmp L067xts_dec_done .align 4,0x90 -L064xts_dec_four: +L066xts_dec_four: movaps %xmm1,%xmm6 movups (%esi),%xmm2 movups 16(%esi),%xmm3 @@ -1630,20 +1681,20 @@ L064xts_dec_four: movups %xmm5,48(%edi) leal 64(%edi),%edi movdqa %xmm6,%xmm1 - jmp L065xts_dec_done + jmp L067xts_dec_done .align 4,0x90 -L060xts_dec_done6x: +L062xts_dec_done6x: movl 112(%esp),%eax andl $15,%eax - jz L067xts_dec_ret + jz L069xts_dec_ret movl %eax,112(%esp) - jmp L068xts_dec_only_one_more + jmp L070xts_dec_only_one_more .align 4,0x90 -L065xts_dec_done: +L067xts_dec_done: movl 112(%esp),%eax pxor %xmm0,%xmm0 andl $15,%eax - jz L067xts_dec_ret + jz L069xts_dec_ret pcmpgtd %xmm1,%xmm0 movl %eax,112(%esp) pshufd $19,%xmm0,%xmm2 @@ -1653,7 +1704,7 @@ L065xts_dec_done: pand %xmm3,%xmm2 pcmpgtd %xmm1,%xmm0 pxor %xmm2,%xmm1 -L068xts_dec_only_one_more: +L070xts_dec_only_one_more: pshufd $19,%xmm0,%xmm5 movdqa %xmm1,%xmm6 paddq %xmm1,%xmm1 @@ -1667,16 +1718,16 @@ L068xts_dec_only_one_more: movups 16(%edx),%xmm1 leal 32(%edx),%edx xorps %xmm0,%xmm2 -L069dec1_loop_13: +L071dec1_loop_13: .byte 102,15,56,222,209 decl %ecx movups (%edx),%xmm1 leal 16(%edx),%edx - jnz L069dec1_loop_13 + jnz L071dec1_loop_13 .byte 102,15,56,223,209 xorps %xmm5,%xmm2 movups %xmm2,(%edi) -L070xts_dec_steal: +L072xts_dec_steal: movzbl 16(%esi),%ecx movzbl (%edi),%edx leal 1(%esi),%esi @@ -1684,7 +1735,7 @@ L070xts_dec_steal: movb %dl,16(%edi) leal 1(%edi),%edi subl $1,%eax - jnz L070xts_dec_steal + jnz L072xts_dec_steal subl 112(%esp),%edi movl %ebp,%edx movl %ebx,%ecx @@ -1694,16 +1745,30 @@ L070xts_dec_steal: movups 16(%edx),%xmm1 leal 32(%edx),%edx xorps %xmm0,%xmm2 -L071dec1_loop_14: +L073dec1_loop_14: .byte 102,15,56,222,209 decl %ecx movups (%edx),%xmm1 leal 16(%edx),%edx - jnz L071dec1_loop_14 + jnz L073dec1_loop_14 .byte 102,15,56,223,209 xorps %xmm6,%xmm2 movups %xmm2,(%edi) -L067xts_dec_ret: +L069xts_dec_ret: + pxor %xmm0,%xmm0 + pxor %xmm1,%xmm1 + pxor %xmm2,%xmm2 + movdqa %xmm0,(%esp) + pxor %xmm3,%xmm3 + movdqa %xmm0,16(%esp) + pxor %xmm4,%xmm4 + movdqa %xmm0,32(%esp) + pxor %xmm5,%xmm5 + movdqa %xmm0,48(%esp) + pxor %xmm6,%xmm6 + movdqa %xmm0,64(%esp) + pxor %xmm7,%xmm7 + movdqa %xmm0,80(%esp) movl 116(%esp),%esp popl %edi popl %esi @@ -1728,7 +1793,7 @@ L_aesni_cbc_encrypt_begin: movl 32(%esp),%edx movl 36(%esp),%ebp testl %eax,%eax - jz L072cbc_abort + jz L074cbc_abort cmpl $0,40(%esp) xchgl %esp,%ebx movups (%ebp),%xmm7 @@ -1736,14 +1801,14 @@ L_aesni_cbc_encrypt_begin: movl %edx,%ebp movl %ebx,16(%esp) movl %ecx,%ebx - je L073cbc_decrypt + je L075cbc_decrypt movaps %xmm7,%xmm2 cmpl $16,%eax - jb L074cbc_enc_tail + jb L076cbc_enc_tail subl $16,%eax - jmp L075cbc_enc_loop + jmp L077cbc_enc_loop .align 4,0x90 -L075cbc_enc_loop: +L077cbc_enc_loop: movups (%esi),%xmm7 leal 16(%esi),%esi movups (%edx),%xmm0 @@ -1751,24 +1816,25 @@ L075cbc_enc_loop: xorps %xmm0,%xmm7 leal 32(%edx),%edx xorps %xmm7,%xmm2 -L076enc1_loop_15: +L078enc1_loop_15: .byte 102,15,56,220,209 decl %ecx movups (%edx),%xmm1 leal 16(%edx),%edx - jnz L076enc1_loop_15 + jnz L078enc1_loop_15 .byte 102,15,56,221,209 movl %ebx,%ecx movl %ebp,%edx movups %xmm2,(%edi) leal 16(%edi),%edi subl $16,%eax - jnc L075cbc_enc_loop + jnc L077cbc_enc_loop addl $16,%eax - jnz L074cbc_enc_tail + jnz L076cbc_enc_tail movaps %xmm2,%xmm7 - jmp L077cbc_ret -L074cbc_enc_tail: + pxor %xmm2,%xmm2 + jmp L079cbc_ret +L076cbc_enc_tail: movl %eax,%ecx .long 2767451785 movl $16,%ecx @@ -1779,20 +1845,20 @@ L074cbc_enc_tail: movl %ebx,%ecx movl %edi,%esi movl %ebp,%edx - jmp L075cbc_enc_loop + jmp L077cbc_enc_loop .align 4,0x90 -L073cbc_decrypt: +L075cbc_decrypt: cmpl $80,%eax - jbe L078cbc_dec_tail + jbe L080cbc_dec_tail movaps %xmm7,(%esp) subl $80,%eax - jmp L079cbc_dec_loop6_enter + jmp L081cbc_dec_loop6_enter .align 4,0x90 -L080cbc_dec_loop6: +L082cbc_dec_loop6: movaps %xmm0,(%esp) movups %xmm7,(%edi) leal 16(%edi),%edi -L079cbc_dec_loop6_enter: +L081cbc_dec_loop6_enter: movdqu (%esi),%xmm2 movdqu 16(%esi),%xmm3 movdqu 32(%esi),%xmm4 @@ -1822,28 +1888,28 @@ L079cbc_dec_loop6_enter: movups %xmm6,64(%edi) leal 80(%edi),%edi subl $96,%eax - ja L080cbc_dec_loop6 + ja L082cbc_dec_loop6 movaps %xmm7,%xmm2 movaps %xmm0,%xmm7 addl $80,%eax - jle L081cbc_dec_tail_collected + jle L083cbc_dec_clear_tail_collected movups %xmm2,(%edi) leal 16(%edi),%edi -L078cbc_dec_tail: +L080cbc_dec_tail: movups (%esi),%xmm2 movaps %xmm2,%xmm6 cmpl $16,%eax - jbe L082cbc_dec_one + jbe L084cbc_dec_one movups 16(%esi),%xmm3 movaps %xmm3,%xmm5 cmpl $32,%eax - jbe L083cbc_dec_two + jbe L085cbc_dec_two movups 32(%esi),%xmm4 cmpl $48,%eax - jbe L084cbc_dec_three + jbe L086cbc_dec_three movups 48(%esi),%xmm5 cmpl $64,%eax - jbe L085cbc_dec_four + jbe L087cbc_dec_four movups 64(%esi),%xmm6 movaps %xmm7,(%esp) movups (%esi),%xmm2 @@ -1861,55 +1927,62 @@ L078cbc_dec_tail: xorps %xmm0,%xmm6 movups %xmm2,(%edi) movups %xmm3,16(%edi) + pxor %xmm3,%xmm3 movups %xmm4,32(%edi) + pxor %xmm4,%xmm4 movups %xmm5,48(%edi) + pxor %xmm5,%xmm5 leal 64(%edi),%edi movaps %xmm6,%xmm2 + pxor %xmm6,%xmm6 subl $80,%eax - jmp L081cbc_dec_tail_collected + jmp L088cbc_dec_tail_collected .align 4,0x90 -L082cbc_dec_one: +L084cbc_dec_one: movups (%edx),%xmm0 movups 16(%edx),%xmm1 leal 32(%edx),%edx xorps %xmm0,%xmm2 -L086dec1_loop_16: +L089dec1_loop_16: .byte 102,15,56,222,209 decl %ecx movups (%edx),%xmm1 leal 16(%edx),%edx - jnz L086dec1_loop_16 + jnz L089dec1_loop_16 .byte 102,15,56,223,209 xorps %xmm7,%xmm2 movaps %xmm6,%xmm7 subl $16,%eax - jmp L081cbc_dec_tail_collected + jmp L088cbc_dec_tail_collected .align 4,0x90 -L083cbc_dec_two: +L085cbc_dec_two: call __aesni_decrypt2 xorps %xmm7,%xmm2 xorps %xmm6,%xmm3 movups %xmm2,(%edi) movaps %xmm3,%xmm2 + pxor %xmm3,%xmm3 leal 16(%edi),%edi movaps %xmm5,%xmm7 subl $32,%eax - jmp L081cbc_dec_tail_collected + jmp L088cbc_dec_tail_collected .align 4,0x90 -L084cbc_dec_three: +L086cbc_dec_three: call __aesni_decrypt3 xorps %xmm7,%xmm2 xorps %xmm6,%xmm3 xorps %xmm5,%xmm4 movups %xmm2,(%edi) movaps %xmm4,%xmm2 + pxor %xmm4,%xmm4 movups %xmm3,16(%edi) + pxor %xmm3,%xmm3 leal 32(%edi),%edi movups 32(%esi),%xmm7 subl $48,%eax - jmp L081cbc_dec_tail_collected + jmp L088cbc_dec_tail_collected .align 4,0x90 -L085cbc_dec_four: +L087cbc_dec_four: call __aesni_decrypt4 movups 16(%esi),%xmm1 movups 32(%esi),%xmm0 @@ -1919,28 +1992,44 @@ L085cbc_dec_four: movups %xmm2,(%edi) xorps %xmm1,%xmm4 movups %xmm3,16(%edi) + pxor %xmm3,%xmm3 xorps %xmm0,%xmm5 movups %xmm4,32(%edi) + pxor %xmm4,%xmm4 leal 48(%edi),%edi movaps %xmm5,%xmm2 + pxor %xmm5,%xmm5 subl $64,%eax -L081cbc_dec_tail_collected: + jmp L088cbc_dec_tail_collected +.align 4,0x90 +L083cbc_dec_clear_tail_collected: + pxor %xmm3,%xmm3 + pxor %xmm4,%xmm4 + pxor %xmm5,%xmm5 + pxor %xmm6,%xmm6 +L088cbc_dec_tail_collected: andl $15,%eax - jnz L087cbc_dec_tail_partial + jnz L090cbc_dec_tail_partial movups %xmm2,(%edi) - jmp L077cbc_ret + pxor %xmm0,%xmm0 + jmp L079cbc_ret .align 4,0x90 -L087cbc_dec_tail_partial: +L090cbc_dec_tail_partial: movaps %xmm2,(%esp) + pxor %xmm0,%xmm0 movl $16,%ecx movl %esp,%esi subl %eax,%ecx .long 2767451785 -L077cbc_ret: + movdqa %xmm2,(%esp) +L079cbc_ret: movl 16(%esp),%esp movl 36(%esp),%ebp + pxor %xmm2,%xmm2 + pxor %xmm1,%xmm1 movups %xmm7,(%ebp) -L072cbc_abort: + pxor %xmm7,%xmm7 +L074cbc_abort: popl %edi popl %esi popl %ebx @@ -1949,52 +2038,62 @@ L072cbc_abort: .private_extern __aesni_set_encrypt_key .align 4 __aesni_set_encrypt_key: + pushl %ebp + pushl %ebx testl %eax,%eax - jz L088bad_pointer + jz L091bad_pointer testl %edx,%edx - jz L088bad_pointer + jz L091bad_pointer + call L092pic +L092pic: + popl %ebx + leal Lkey_const-L092pic(%ebx),%ebx + movl L_OPENSSL_ia32cap_P$non_lazy_ptr-Lkey_const(%ebx),%ebp movups (%eax),%xmm0 xorps %xmm4,%xmm4 + movl 4(%ebp),%ebp leal 16(%edx),%edx + andl $268437504,%ebp cmpl $256,%ecx - je L08914rounds + je L09314rounds cmpl $192,%ecx - je L09012rounds + je L09412rounds cmpl $128,%ecx - jne L091bad_keybits + jne L095bad_keybits .align 4,0x90 -L09210rounds: +L09610rounds: + cmpl $268435456,%ebp + je L09710rounds_alt movl $9,%ecx movups %xmm0,-16(%edx) .byte 102,15,58,223,200,1 - call L093key_128_cold + call L098key_128_cold .byte 102,15,58,223,200,2 - call L094key_128 + call L099key_128 .byte 102,15,58,223,200,4 - call L094key_128 + call L099key_128 .byte 102,15,58,223,200,8 - call L094key_128 + call L099key_128 .byte 102,15,58,223,200,16 - call L094key_128 + call L099key_128 .byte 102,15,58,223,200,32 - call L094key_128 + call L099key_128 .byte 102,15,58,223,200,64 - call L094key_128 + call L099key_128 .byte 102,15,58,223,200,128 - call L094key_128 + call L099key_128 .byte 102,15,58,223,200,27 - call L094key_128 + call L099key_128 .byte 102,15,58,223,200,54 - call L094key_128 + call L099key_128 movups %xmm0,(%edx) movl %ecx,80(%edx) - xorl %eax,%eax - ret + jmp L100good_key .align 4,0x90 -L094key_128: +L099key_128: movups %xmm0,(%edx) leal 16(%edx),%edx -L093key_128_cold: +L098key_128_cold: shufps $16,%xmm0,%xmm4 xorps %xmm4,%xmm0 shufps $140,%xmm0,%xmm4 @@ -2003,38 +2102,91 @@ L093key_128_cold: xorps %xmm1,%xmm0 ret .align 4,0x90 -L09012rounds: +L09710rounds_alt: + movdqa (%ebx),%xmm5 + movl $8,%ecx + movdqa 32(%ebx),%xmm4 + movdqa %xmm0,%xmm2 + movdqu %xmm0,-16(%edx) +L101loop_key128: +.byte 102,15,56,0,197 +.byte 102,15,56,221,196 + pslld $1,%xmm4 + leal 16(%edx),%edx + movdqa %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm3,%xmm2 + pxor %xmm2,%xmm0 + movdqu %xmm0,-16(%edx) + movdqa %xmm0,%xmm2 + decl %ecx + jnz L101loop_key128 + movdqa 48(%ebx),%xmm4 +.byte 102,15,56,0,197 +.byte 102,15,56,221,196 + pslld $1,%xmm4 + movdqa %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm3,%xmm2 + pxor %xmm2,%xmm0 + movdqu %xmm0,(%edx) + movdqa %xmm0,%xmm2 +.byte 102,15,56,0,197 +.byte 102,15,56,221,196 + movdqa %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm3,%xmm2 + pxor %xmm2,%xmm0 + movdqu %xmm0,16(%edx) + movl $9,%ecx + movl %ecx,96(%edx) + jmp L100good_key +.align 4,0x90 +L09412rounds: movq 16(%eax),%xmm2 + cmpl $268435456,%ebp + je L10212rounds_alt movl $11,%ecx movups %xmm0,-16(%edx) .byte 102,15,58,223,202,1 - call L095key_192a_cold + call L103key_192a_cold .byte 102,15,58,223,202,2 - call L096key_192b + call L104key_192b .byte 102,15,58,223,202,4 - call L097key_192a + call L105key_192a .byte 102,15,58,223,202,8 - call L096key_192b + call L104key_192b .byte 102,15,58,223,202,16 - call L097key_192a + call L105key_192a .byte 102,15,58,223,202,32 - call L096key_192b + call L104key_192b .byte 102,15,58,223,202,64 - call L097key_192a + call L105key_192a .byte 102,15,58,223,202,128 - call L096key_192b + call L104key_192b movups %xmm0,(%edx) movl %ecx,48(%edx) - xorl %eax,%eax - ret + jmp L100good_key .align 4,0x90 -L097key_192a: +L105key_192a: movups %xmm0,(%edx) leal 16(%edx),%edx .align 4,0x90 -L095key_192a_cold: +L103key_192a_cold: movaps %xmm2,%xmm5 -L098key_192b_warm: +L106key_192b_warm: shufps $16,%xmm0,%xmm4 movdqa %xmm2,%xmm3 xorps %xmm4,%xmm0 @@ -2048,56 +2200,90 @@ L098key_192b_warm: pxor %xmm3,%xmm2 ret .align 4,0x90 -L096key_192b: +L104key_192b: movaps %xmm0,%xmm3 shufps $68,%xmm0,%xmm5 movups %xmm5,(%edx) shufps $78,%xmm2,%xmm3 movups %xmm3,16(%edx) leal 32(%edx),%edx - jmp L098key_192b_warm + jmp L106key_192b_warm .align 4,0x90 -L08914rounds: +L10212rounds_alt: + movdqa 16(%ebx),%xmm5 + movdqa 32(%ebx),%xmm4 + movl $8,%ecx + movdqu %xmm0,-16(%edx) +L107loop_key192: + movq %xmm2,(%edx) + movdqa %xmm2,%xmm1 +.byte 102,15,56,0,213 +.byte 102,15,56,221,212 + pslld $1,%xmm4 + leal 24(%edx),%edx + movdqa %xmm0,%xmm3 + pslldq $4,%xmm0 + pxor %xmm0,%xmm3 + pslldq $4,%xmm0 + pxor %xmm0,%xmm3 + pslldq $4,%xmm0 + pxor %xmm3,%xmm0 + pshufd $255,%xmm0,%xmm3 + pxor %xmm1,%xmm3 + pslldq $4,%xmm1 + pxor %xmm1,%xmm3 + pxor %xmm2,%xmm0 + pxor %xmm3,%xmm2 + movdqu %xmm0,-16(%edx) + decl %ecx + jnz L107loop_key192 + movl $11,%ecx + movl %ecx,32(%edx) + jmp L100good_key +.align 4,0x90 +L09314rounds: movups 16(%eax),%xmm2 - movl $13,%ecx leal 16(%edx),%edx + cmpl $268435456,%ebp + je L10814rounds_alt + movl $13,%ecx movups %xmm0,-32(%edx) movups %xmm2,-16(%edx) .byte 102,15,58,223,202,1 - call L099key_256a_cold + call L109key_256a_cold .byte 102,15,58,223,200,1 - call L100key_256b + call L110key_256b .byte 102,15,58,223,202,2 - call L101key_256a + call L111key_256a .byte 102,15,58,223,200,2 - call L100key_256b + call L110key_256b .byte 102,15,58,223,202,4 - call L101key_256a + call L111key_256a .byte 102,15,58,223,200,4 - call L100key_256b + call L110key_256b .byte 102,15,58,223,202,8 - call L101key_256a + call L111key_256a .byte 102,15,58,223,200,8 - call L100key_256b + call L110key_256b .byte 102,15,58,223,202,16 - call L101key_256a + call L111key_256a .byte 102,15,58,223,200,16 - call L100key_256b + call L110key_256b .byte 102,15,58,223,202,32 - call L101key_256a + call L111key_256a .byte 102,15,58,223,200,32 - call L100key_256b + call L110key_256b .byte 102,15,58,223,202,64 - call L101key_256a + call L111key_256a movups %xmm0,(%edx) movl %ecx,16(%edx) xorl %eax,%eax - ret + jmp L100good_key .align 4,0x90 -L101key_256a: +L111key_256a: movups %xmm2,(%edx) leal 16(%edx),%edx -L099key_256a_cold: +L109key_256a_cold: shufps $16,%xmm0,%xmm4 xorps %xmm4,%xmm0 shufps $140,%xmm0,%xmm4 @@ -2106,7 +2292,7 @@ L099key_256a_cold: xorps %xmm1,%xmm0 ret .align 4,0x90 -L100key_256b: +L110key_256b: movups %xmm0,(%edx) leal 16(%edx),%edx shufps $16,%xmm2,%xmm4 @@ -2116,13 +2302,70 @@ L100key_256b: shufps $170,%xmm1,%xmm1 xorps %xmm1,%xmm2 ret +.align 4,0x90 +L10814rounds_alt: + movdqa (%ebx),%xmm5 + movdqa 32(%ebx),%xmm4 + movl $7,%ecx + movdqu %xmm0,-32(%edx) + movdqa %xmm2,%xmm1 + movdqu %xmm2,-16(%edx) +L112loop_key256: +.byte 102,15,56,0,213 +.byte 102,15,56,221,212 + movdqa %xmm0,%xmm3 + pslldq $4,%xmm0 + pxor %xmm0,%xmm3 + pslldq $4,%xmm0 + pxor %xmm0,%xmm3 + pslldq $4,%xmm0 + pxor %xmm3,%xmm0 + pslld $1,%xmm4 + pxor %xmm2,%xmm0 + movdqu %xmm0,(%edx) + decl %ecx + jz L113done_key256 + pshufd $255,%xmm0,%xmm2 + pxor %xmm3,%xmm3 +.byte 102,15,56,221,211 + movdqa %xmm1,%xmm3 + pslldq $4,%xmm1 + pxor %xmm1,%xmm3 + pslldq $4,%xmm1 + pxor %xmm1,%xmm3 + pslldq $4,%xmm1 + pxor %xmm3,%xmm1 + pxor %xmm1,%xmm2 + movdqu %xmm2,16(%edx) + leal 32(%edx),%edx + movdqa %xmm2,%xmm1 + jmp L112loop_key256 +L113done_key256: + movl $13,%ecx + movl %ecx,16(%edx) +L100good_key: + pxor %xmm0,%xmm0 + pxor %xmm1,%xmm1 + pxor %xmm2,%xmm2 + pxor %xmm3,%xmm3 + pxor %xmm4,%xmm4 + pxor %xmm5,%xmm5 + xorl %eax,%eax + popl %ebx + popl %ebp + ret .align 2,0x90 -L088bad_pointer: +L091bad_pointer: movl $-1,%eax + popl %ebx + popl %ebp ret .align 2,0x90 -L091bad_keybits: +L095bad_keybits: + pxor %xmm0,%xmm0 movl $-2,%eax + popl %ebx + popl %ebp ret .globl _aesni_set_encrypt_key .private_extern _aesni_set_encrypt_key @@ -2146,7 +2389,7 @@ L_aesni_set_decrypt_key_begin: movl 12(%esp),%edx shll $4,%ecx testl %eax,%eax - jnz L102dec_key_ret + jnz L114dec_key_ret leal 16(%edx,%ecx,1),%eax movups (%edx),%xmm0 movups (%eax),%xmm1 @@ -2154,7 +2397,7 @@ L_aesni_set_decrypt_key_begin: movups %xmm1,(%edx) leal 16(%edx),%edx leal -16(%eax),%eax -L103dec_key_inverse: +L115dec_key_inverse: movups (%edx),%xmm0 movups (%eax),%xmm1 .byte 102,15,56,219,192 @@ -2164,15 +2407,27 @@ L103dec_key_inverse: movups %xmm0,16(%eax) movups %xmm1,-16(%edx) cmpl %edx,%eax - ja L103dec_key_inverse + ja L115dec_key_inverse movups (%edx),%xmm0 .byte 102,15,56,219,192 movups %xmm0,(%edx) + pxor %xmm0,%xmm0 + pxor %xmm1,%xmm1 xorl %eax,%eax -L102dec_key_ret: +L114dec_key_ret: ret +.align 6,0x90 +Lkey_const: +.long 202313229,202313229,202313229,202313229 +.long 67569157,67569157,67569157,67569157 +.long 1,1,1,1 +.long 27,27,27,27 .byte 65,69,83,32,102,111,114,32,73,110,116,101,108,32,65,69 .byte 83,45,78,73,44,32,67,82,89,80,84,79,71,65,77,83 .byte 32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115 .byte 115,108,46,111,114,103,62,0 +.section __IMPORT,__pointers,non_lazy_symbol_pointers +L_OPENSSL_ia32cap_P$non_lazy_ptr: +.indirect_symbol _OPENSSL_ia32cap_P +.long 0 #endif diff --git a/third_party/boringssl/mac-x86/crypto/bn/bn-586.S b/third_party/boringssl/mac-x86/crypto/bn/bn-586.S index 34cf56fdaf945..0f0a94ece3d19 100644 --- a/third_party/boringssl/mac-x86/crypto/bn/bn-586.S +++ b/third_party/boringssl/mac-x86/crypto/bn/bn-586.S @@ -6,6 +6,102 @@ .align 4 _bn_mul_add_words: L_bn_mul_add_words_begin: + call L000PIC_me_up +L000PIC_me_up: + popl %eax + movl L_OPENSSL_ia32cap_P$non_lazy_ptr-L000PIC_me_up(%eax),%eax + btl $26,(%eax) + jnc L001maw_non_sse2 + movl 4(%esp),%eax + movl 8(%esp),%edx + movl 12(%esp),%ecx + movd 16(%esp),%mm0 + pxor %mm1,%mm1 + jmp L002maw_sse2_entry +.align 4,0x90 +L003maw_sse2_unrolled: + movd (%eax),%mm3 + paddq %mm3,%mm1 + movd (%edx),%mm2 + pmuludq %mm0,%mm2 + movd 4(%edx),%mm4 + pmuludq %mm0,%mm4 + movd 8(%edx),%mm6 + pmuludq %mm0,%mm6 + movd 12(%edx),%mm7 + pmuludq %mm0,%mm7 + paddq %mm2,%mm1 + movd 4(%eax),%mm3 + paddq %mm4,%mm3 + movd 8(%eax),%mm5 + paddq %mm6,%mm5 + movd 12(%eax),%mm4 + paddq %mm4,%mm7 + movd %mm1,(%eax) + movd 16(%edx),%mm2 + pmuludq %mm0,%mm2 + psrlq $32,%mm1 + movd 20(%edx),%mm4 + pmuludq %mm0,%mm4 + paddq %mm3,%mm1 + movd 24(%edx),%mm6 + pmuludq %mm0,%mm6 + movd %mm1,4(%eax) + psrlq $32,%mm1 + movd 28(%edx),%mm3 + addl $32,%edx + pmuludq %mm0,%mm3 + paddq %mm5,%mm1 + movd 16(%eax),%mm5 + paddq %mm5,%mm2 + movd %mm1,8(%eax) + psrlq $32,%mm1 + paddq %mm7,%mm1 + movd 20(%eax),%mm5 + paddq %mm5,%mm4 + movd %mm1,12(%eax) + psrlq $32,%mm1 + paddq %mm2,%mm1 + movd 24(%eax),%mm5 + paddq %mm5,%mm6 + movd %mm1,16(%eax) + psrlq $32,%mm1 + paddq %mm4,%mm1 + movd 28(%eax),%mm5 + paddq %mm5,%mm3 + movd %mm1,20(%eax) + psrlq $32,%mm1 + paddq %mm6,%mm1 + movd %mm1,24(%eax) + psrlq $32,%mm1 + paddq %mm3,%mm1 + movd %mm1,28(%eax) + leal 32(%eax),%eax + psrlq $32,%mm1 + subl $8,%ecx + jz L004maw_sse2_exit +L002maw_sse2_entry: + testl $4294967288,%ecx + jnz L003maw_sse2_unrolled +.align 2,0x90 +L005maw_sse2_loop: + movd (%edx),%mm2 + movd (%eax),%mm3 + pmuludq %mm0,%mm2 + leal 4(%edx),%edx + paddq %mm3,%mm1 + paddq %mm2,%mm1 + movd %mm1,(%eax) + subl $1,%ecx + psrlq $32,%mm1 + leal 4(%eax),%eax + jnz L005maw_sse2_loop +L004maw_sse2_exit: + movd %mm1,%eax + emms + ret +.align 4,0x90 +L001maw_non_sse2: pushl %ebp pushl %ebx pushl %esi @@ -18,9 +114,9 @@ L_bn_mul_add_words_begin: andl $4294967288,%ecx movl 32(%esp),%ebp pushl %ecx - jz L000maw_finish + jz L006maw_finish .align 4,0x90 -L001maw_loop: +L007maw_loop: # Round 0 movl (%ebx),%eax mull %ebp @@ -97,13 +193,13 @@ L001maw_loop: subl $8,%ecx leal 32(%ebx),%ebx leal 32(%edi),%edi - jnz L001maw_loop -L000maw_finish: + jnz L007maw_loop +L006maw_finish: movl 32(%esp),%ecx andl $7,%ecx - jnz L002maw_finish2 - jmp L003maw_end -L002maw_finish2: + jnz L008maw_finish2 + jmp L009maw_end +L008maw_finish2: # Tail Round 0 movl (%ebx),%eax mull %ebp @@ -114,7 +210,7 @@ L002maw_finish2: decl %ecx movl %eax,(%edi) movl %edx,%esi - jz L003maw_end + jz L009maw_end # Tail Round 1 movl 4(%ebx),%eax mull %ebp @@ -125,7 +221,7 @@ L002maw_finish2: decl %ecx movl %eax,4(%edi) movl %edx,%esi - jz L003maw_end + jz L009maw_end # Tail Round 2 movl 8(%ebx),%eax mull %ebp @@ -136,7 +232,7 @@ L002maw_finish2: decl %ecx movl %eax,8(%edi) movl %edx,%esi - jz L003maw_end + jz L009maw_end # Tail Round 3 movl 12(%ebx),%eax mull %ebp @@ -147,7 +243,7 @@ L002maw_finish2: decl %ecx movl %eax,12(%edi) movl %edx,%esi - jz L003maw_end + jz L009maw_end # Tail Round 4 movl 16(%ebx),%eax mull %ebp @@ -158,7 +254,7 @@ L002maw_finish2: decl %ecx movl %eax,16(%edi) movl %edx,%esi - jz L003maw_end + jz L009maw_end # Tail Round 5 movl 20(%ebx),%eax mull %ebp @@ -169,7 +265,7 @@ L002maw_finish2: decl %ecx movl %eax,20(%edi) movl %edx,%esi - jz L003maw_end + jz L009maw_end # Tail Round 6 movl 24(%ebx),%eax mull %ebp @@ -179,7 +275,7 @@ L002maw_finish2: adcl $0,%edx movl %eax,24(%edi) movl %edx,%esi -L003maw_end: +L009maw_end: movl %esi,%eax popl %ecx popl %edi @@ -192,6 +288,33 @@ L003maw_end: .align 4 _bn_mul_words: L_bn_mul_words_begin: + call L010PIC_me_up +L010PIC_me_up: + popl %eax + movl L_OPENSSL_ia32cap_P$non_lazy_ptr-L010PIC_me_up(%eax),%eax + btl $26,(%eax) + jnc L011mw_non_sse2 + movl 4(%esp),%eax + movl 8(%esp),%edx + movl 12(%esp),%ecx + movd 16(%esp),%mm0 + pxor %mm1,%mm1 +.align 4,0x90 +L012mw_sse2_loop: + movd (%edx),%mm2 + pmuludq %mm0,%mm2 + leal 4(%edx),%edx + paddq %mm2,%mm1 + movd %mm1,(%eax) + subl $1,%ecx + psrlq $32,%mm1 + leal 4(%eax),%eax + jnz L012mw_sse2_loop + movd %mm1,%eax + emms + ret +.align 4,0x90 +L011mw_non_sse2: pushl %ebp pushl %ebx pushl %esi @@ -203,8 +326,8 @@ L_bn_mul_words_begin: movl 28(%esp),%ebp movl 32(%esp),%ecx andl $4294967288,%ebp - jz L004mw_finish -L005mw_loop: + jz L013mw_finish +L014mw_loop: # Round 0 movl (%ebx),%eax mull %ecx @@ -265,14 +388,14 @@ L005mw_loop: addl $32,%ebx addl $32,%edi subl $8,%ebp - jz L004mw_finish - jmp L005mw_loop -L004mw_finish: + jz L013mw_finish + jmp L014mw_loop +L013mw_finish: movl 28(%esp),%ebp andl $7,%ebp - jnz L006mw_finish2 - jmp L007mw_end -L006mw_finish2: + jnz L015mw_finish2 + jmp L016mw_end +L015mw_finish2: # Tail Round 0 movl (%ebx),%eax mull %ecx @@ -281,7 +404,7 @@ L006mw_finish2: movl %eax,(%edi) movl %edx,%esi decl %ebp - jz L007mw_end + jz L016mw_end # Tail Round 1 movl 4(%ebx),%eax mull %ecx @@ -290,7 +413,7 @@ L006mw_finish2: movl %eax,4(%edi) movl %edx,%esi decl %ebp - jz L007mw_end + jz L016mw_end # Tail Round 2 movl 8(%ebx),%eax mull %ecx @@ -299,7 +422,7 @@ L006mw_finish2: movl %eax,8(%edi) movl %edx,%esi decl %ebp - jz L007mw_end + jz L016mw_end # Tail Round 3 movl 12(%ebx),%eax mull %ecx @@ -308,7 +431,7 @@ L006mw_finish2: movl %eax,12(%edi) movl %edx,%esi decl %ebp - jz L007mw_end + jz L016mw_end # Tail Round 4 movl 16(%ebx),%eax mull %ecx @@ -317,7 +440,7 @@ L006mw_finish2: movl %eax,16(%edi) movl %edx,%esi decl %ebp - jz L007mw_end + jz L016mw_end # Tail Round 5 movl 20(%ebx),%eax mull %ecx @@ -326,7 +449,7 @@ L006mw_finish2: movl %eax,20(%edi) movl %edx,%esi decl %ebp - jz L007mw_end + jz L016mw_end # Tail Round 6 movl 24(%ebx),%eax mull %ecx @@ -334,7 +457,7 @@ L006mw_finish2: adcl $0,%edx movl %eax,24(%edi) movl %edx,%esi -L007mw_end: +L016mw_end: movl %esi,%eax popl %edi popl %esi @@ -346,6 +469,28 @@ L007mw_end: .align 4 _bn_sqr_words: L_bn_sqr_words_begin: + call L017PIC_me_up +L017PIC_me_up: + popl %eax + movl L_OPENSSL_ia32cap_P$non_lazy_ptr-L017PIC_me_up(%eax),%eax + btl $26,(%eax) + jnc L018sqr_non_sse2 + movl 4(%esp),%eax + movl 8(%esp),%edx + movl 12(%esp),%ecx +.align 4,0x90 +L019sqr_sse2_loop: + movd (%edx),%mm0 + pmuludq %mm0,%mm0 + leal 4(%edx),%edx + movq %mm0,(%eax) + subl $1,%ecx + leal 8(%eax),%eax + jnz L019sqr_sse2_loop + emms + ret +.align 4,0x90 +L018sqr_non_sse2: pushl %ebp pushl %ebx pushl %esi @@ -355,8 +500,8 @@ L_bn_sqr_words_begin: movl 24(%esp),%edi movl 28(%esp),%ebx andl $4294967288,%ebx - jz L008sw_finish -L009sw_loop: + jz L020sw_finish +L021sw_loop: # Round 0 movl (%edi),%eax mull %eax @@ -401,59 +546,59 @@ L009sw_loop: addl $32,%edi addl $64,%esi subl $8,%ebx - jnz L009sw_loop -L008sw_finish: + jnz L021sw_loop +L020sw_finish: movl 28(%esp),%ebx andl $7,%ebx - jz L010sw_end + jz L022sw_end # Tail Round 0 movl (%edi),%eax mull %eax movl %eax,(%esi) decl %ebx movl %edx,4(%esi) - jz L010sw_end + jz L022sw_end # Tail Round 1 movl 4(%edi),%eax mull %eax movl %eax,8(%esi) decl %ebx movl %edx,12(%esi) - jz L010sw_end + jz L022sw_end # Tail Round 2 movl 8(%edi),%eax mull %eax movl %eax,16(%esi) decl %ebx movl %edx,20(%esi) - jz L010sw_end + jz L022sw_end # Tail Round 3 movl 12(%edi),%eax mull %eax movl %eax,24(%esi) decl %ebx movl %edx,28(%esi) - jz L010sw_end + jz L022sw_end # Tail Round 4 movl 16(%edi),%eax mull %eax movl %eax,32(%esi) decl %ebx movl %edx,36(%esi) - jz L010sw_end + jz L022sw_end # Tail Round 5 movl 20(%edi),%eax mull %eax movl %eax,40(%esi) decl %ebx movl %edx,44(%esi) - jz L010sw_end + jz L022sw_end # Tail Round 6 movl 24(%edi),%eax mull %eax movl %eax,48(%esi) movl %edx,52(%esi) -L010sw_end: +L022sw_end: popl %edi popl %esi popl %ebx @@ -485,8 +630,8 @@ L_bn_add_words_begin: movl 32(%esp),%ebp xorl %eax,%eax andl $4294967288,%ebp - jz L011aw_finish -L012aw_loop: + jz L023aw_finish +L024aw_loop: # Round 0 movl (%esi),%ecx movl (%edi),%edx @@ -564,11 +709,11 @@ L012aw_loop: addl $32,%edi addl $32,%ebx subl $8,%ebp - jnz L012aw_loop -L011aw_finish: + jnz L024aw_loop +L023aw_finish: movl 32(%esp),%ebp andl $7,%ebp - jz L013aw_end + jz L025aw_end # Tail Round 0 movl (%esi),%ecx movl (%edi),%edx @@ -579,7 +724,7 @@ L011aw_finish: adcl $0,%eax decl %ebp movl %ecx,(%ebx) - jz L013aw_end + jz L025aw_end # Tail Round 1 movl 4(%esi),%ecx movl 4(%edi),%edx @@ -590,7 +735,7 @@ L011aw_finish: adcl $0,%eax decl %ebp movl %ecx,4(%ebx) - jz L013aw_end + jz L025aw_end # Tail Round 2 movl 8(%esi),%ecx movl 8(%edi),%edx @@ -601,7 +746,7 @@ L011aw_finish: adcl $0,%eax decl %ebp movl %ecx,8(%ebx) - jz L013aw_end + jz L025aw_end # Tail Round 3 movl 12(%esi),%ecx movl 12(%edi),%edx @@ -612,7 +757,7 @@ L011aw_finish: adcl $0,%eax decl %ebp movl %ecx,12(%ebx) - jz L013aw_end + jz L025aw_end # Tail Round 4 movl 16(%esi),%ecx movl 16(%edi),%edx @@ -623,7 +768,7 @@ L011aw_finish: adcl $0,%eax decl %ebp movl %ecx,16(%ebx) - jz L013aw_end + jz L025aw_end # Tail Round 5 movl 20(%esi),%ecx movl 20(%edi),%edx @@ -634,7 +779,7 @@ L011aw_finish: adcl $0,%eax decl %ebp movl %ecx,20(%ebx) - jz L013aw_end + jz L025aw_end # Tail Round 6 movl 24(%esi),%ecx movl 24(%edi),%edx @@ -644,7 +789,7 @@ L011aw_finish: addl %edx,%ecx adcl $0,%eax movl %ecx,24(%ebx) -L013aw_end: +L025aw_end: popl %edi popl %esi popl %ebx @@ -666,8 +811,8 @@ L_bn_sub_words_begin: movl 32(%esp),%ebp xorl %eax,%eax andl $4294967288,%ebp - jz L014aw_finish -L015aw_loop: + jz L026aw_finish +L027aw_loop: # Round 0 movl (%esi),%ecx movl (%edi),%edx @@ -745,11 +890,11 @@ L015aw_loop: addl $32,%edi addl $32,%ebx subl $8,%ebp - jnz L015aw_loop -L014aw_finish: + jnz L027aw_loop +L026aw_finish: movl 32(%esp),%ebp andl $7,%ebp - jz L016aw_end + jz L028aw_end # Tail Round 0 movl (%esi),%ecx movl (%edi),%edx @@ -760,7 +905,7 @@ L014aw_finish: adcl $0,%eax decl %ebp movl %ecx,(%ebx) - jz L016aw_end + jz L028aw_end # Tail Round 1 movl 4(%esi),%ecx movl 4(%edi),%edx @@ -771,7 +916,7 @@ L014aw_finish: adcl $0,%eax decl %ebp movl %ecx,4(%ebx) - jz L016aw_end + jz L028aw_end # Tail Round 2 movl 8(%esi),%ecx movl 8(%edi),%edx @@ -782,7 +927,7 @@ L014aw_finish: adcl $0,%eax decl %ebp movl %ecx,8(%ebx) - jz L016aw_end + jz L028aw_end # Tail Round 3 movl 12(%esi),%ecx movl 12(%edi),%edx @@ -793,7 +938,7 @@ L014aw_finish: adcl $0,%eax decl %ebp movl %ecx,12(%ebx) - jz L016aw_end + jz L028aw_end # Tail Round 4 movl 16(%esi),%ecx movl 16(%edi),%edx @@ -804,7 +949,7 @@ L014aw_finish: adcl $0,%eax decl %ebp movl %ecx,16(%ebx) - jz L016aw_end + jz L028aw_end # Tail Round 5 movl 20(%esi),%ecx movl 20(%edi),%edx @@ -815,7 +960,7 @@ L014aw_finish: adcl $0,%eax decl %ebp movl %ecx,20(%ebx) - jz L016aw_end + jz L028aw_end # Tail Round 6 movl 24(%esi),%ecx movl 24(%edi),%edx @@ -825,7 +970,7 @@ L014aw_finish: subl %edx,%ecx adcl $0,%eax movl %ecx,24(%ebx) -L016aw_end: +L028aw_end: popl %edi popl %esi popl %ebx @@ -847,8 +992,8 @@ L_bn_sub_part_words_begin: movl 32(%esp),%ebp xorl %eax,%eax andl $4294967288,%ebp - jz L017aw_finish -L018aw_loop: + jz L029aw_finish +L030aw_loop: # Round 0 movl (%esi),%ecx movl (%edi),%edx @@ -926,11 +1071,11 @@ L018aw_loop: addl $32,%edi addl $32,%ebx subl $8,%ebp - jnz L018aw_loop -L017aw_finish: + jnz L030aw_loop +L029aw_finish: movl 32(%esp),%ebp andl $7,%ebp - jz L019aw_end + jz L031aw_end # Tail Round 0 movl (%esi),%ecx movl (%edi),%edx @@ -944,7 +1089,7 @@ L017aw_finish: addl $4,%edi addl $4,%ebx decl %ebp - jz L019aw_end + jz L031aw_end # Tail Round 1 movl (%esi),%ecx movl (%edi),%edx @@ -958,7 +1103,7 @@ L017aw_finish: addl $4,%edi addl $4,%ebx decl %ebp - jz L019aw_end + jz L031aw_end # Tail Round 2 movl (%esi),%ecx movl (%edi),%edx @@ -972,7 +1117,7 @@ L017aw_finish: addl $4,%edi addl $4,%ebx decl %ebp - jz L019aw_end + jz L031aw_end # Tail Round 3 movl (%esi),%ecx movl (%edi),%edx @@ -986,7 +1131,7 @@ L017aw_finish: addl $4,%edi addl $4,%ebx decl %ebp - jz L019aw_end + jz L031aw_end # Tail Round 4 movl (%esi),%ecx movl (%edi),%edx @@ -1000,7 +1145,7 @@ L017aw_finish: addl $4,%edi addl $4,%ebx decl %ebp - jz L019aw_end + jz L031aw_end # Tail Round 5 movl (%esi),%ecx movl (%edi),%edx @@ -1014,7 +1159,7 @@ L017aw_finish: addl $4,%edi addl $4,%ebx decl %ebp - jz L019aw_end + jz L031aw_end # Tail Round 6 movl (%esi),%ecx movl (%edi),%edx @@ -1027,20 +1172,20 @@ L017aw_finish: addl $4,%esi addl $4,%edi addl $4,%ebx -L019aw_end: +L031aw_end: cmpl $0,36(%esp) - je L020pw_end + je L032pw_end movl 36(%esp),%ebp cmpl $0,%ebp - je L020pw_end - jge L021pw_pos + je L032pw_end + jge L033pw_pos # pw_neg movl $0,%edx subl %ebp,%edx movl %edx,%ebp andl $4294967288,%ebp - jz L022pw_neg_finish -L023pw_neg_loop: + jz L034pw_neg_finish +L035pw_neg_loop: # dl<0 Round 0 movl $0,%ecx movl (%edi),%edx @@ -1117,13 +1262,13 @@ L023pw_neg_loop: addl $32,%edi addl $32,%ebx subl $8,%ebp - jnz L023pw_neg_loop -L022pw_neg_finish: + jnz L035pw_neg_loop +L034pw_neg_finish: movl 36(%esp),%edx movl $0,%ebp subl %edx,%ebp andl $7,%ebp - jz L020pw_end + jz L032pw_end # dl<0 Tail Round 0 movl $0,%ecx movl (%edi),%edx @@ -1134,7 +1279,7 @@ L022pw_neg_finish: adcl $0,%eax decl %ebp movl %ecx,(%ebx) - jz L020pw_end + jz L032pw_end # dl<0 Tail Round 1 movl $0,%ecx movl 4(%edi),%edx @@ -1145,7 +1290,7 @@ L022pw_neg_finish: adcl $0,%eax decl %ebp movl %ecx,4(%ebx) - jz L020pw_end + jz L032pw_end # dl<0 Tail Round 2 movl $0,%ecx movl 8(%edi),%edx @@ -1156,7 +1301,7 @@ L022pw_neg_finish: adcl $0,%eax decl %ebp movl %ecx,8(%ebx) - jz L020pw_end + jz L032pw_end # dl<0 Tail Round 3 movl $0,%ecx movl 12(%edi),%edx @@ -1167,7 +1312,7 @@ L022pw_neg_finish: adcl $0,%eax decl %ebp movl %ecx,12(%ebx) - jz L020pw_end + jz L032pw_end # dl<0 Tail Round 4 movl $0,%ecx movl 16(%edi),%edx @@ -1178,7 +1323,7 @@ L022pw_neg_finish: adcl $0,%eax decl %ebp movl %ecx,16(%ebx) - jz L020pw_end + jz L032pw_end # dl<0 Tail Round 5 movl $0,%ecx movl 20(%edi),%edx @@ -1189,7 +1334,7 @@ L022pw_neg_finish: adcl $0,%eax decl %ebp movl %ecx,20(%ebx) - jz L020pw_end + jz L032pw_end # dl<0 Tail Round 6 movl $0,%ecx movl 24(%edi),%edx @@ -1199,181 +1344,185 @@ L022pw_neg_finish: subl %edx,%ecx adcl $0,%eax movl %ecx,24(%ebx) - jmp L020pw_end -L021pw_pos: + jmp L032pw_end +L033pw_pos: andl $4294967288,%ebp - jz L024pw_pos_finish -L025pw_pos_loop: + jz L036pw_pos_finish +L037pw_pos_loop: # dl>0 Round 0 movl (%esi),%ecx subl %eax,%ecx movl %ecx,(%ebx) - jnc L026pw_nc0 + jnc L038pw_nc0 # dl>0 Round 1 movl 4(%esi),%ecx subl %eax,%ecx movl %ecx,4(%ebx) - jnc L027pw_nc1 + jnc L039pw_nc1 # dl>0 Round 2 movl 8(%esi),%ecx subl %eax,%ecx movl %ecx,8(%ebx) - jnc L028pw_nc2 + jnc L040pw_nc2 # dl>0 Round 3 movl 12(%esi),%ecx subl %eax,%ecx movl %ecx,12(%ebx) - jnc L029pw_nc3 + jnc L041pw_nc3 # dl>0 Round 4 movl 16(%esi),%ecx subl %eax,%ecx movl %ecx,16(%ebx) - jnc L030pw_nc4 + jnc L042pw_nc4 # dl>0 Round 5 movl 20(%esi),%ecx subl %eax,%ecx movl %ecx,20(%ebx) - jnc L031pw_nc5 + jnc L043pw_nc5 # dl>0 Round 6 movl 24(%esi),%ecx subl %eax,%ecx movl %ecx,24(%ebx) - jnc L032pw_nc6 + jnc L044pw_nc6 # dl>0 Round 7 movl 28(%esi),%ecx subl %eax,%ecx movl %ecx,28(%ebx) - jnc L033pw_nc7 + jnc L045pw_nc7 addl $32,%esi addl $32,%ebx subl $8,%ebp - jnz L025pw_pos_loop -L024pw_pos_finish: + jnz L037pw_pos_loop +L036pw_pos_finish: movl 36(%esp),%ebp andl $7,%ebp - jz L020pw_end + jz L032pw_end # dl>0 Tail Round 0 movl (%esi),%ecx subl %eax,%ecx movl %ecx,(%ebx) - jnc L034pw_tail_nc0 + jnc L046pw_tail_nc0 decl %ebp - jz L020pw_end + jz L032pw_end # dl>0 Tail Round 1 movl 4(%esi),%ecx subl %eax,%ecx movl %ecx,4(%ebx) - jnc L035pw_tail_nc1 + jnc L047pw_tail_nc1 decl %ebp - jz L020pw_end + jz L032pw_end # dl>0 Tail Round 2 movl 8(%esi),%ecx subl %eax,%ecx movl %ecx,8(%ebx) - jnc L036pw_tail_nc2 + jnc L048pw_tail_nc2 decl %ebp - jz L020pw_end + jz L032pw_end # dl>0 Tail Round 3 movl 12(%esi),%ecx subl %eax,%ecx movl %ecx,12(%ebx) - jnc L037pw_tail_nc3 + jnc L049pw_tail_nc3 decl %ebp - jz L020pw_end + jz L032pw_end # dl>0 Tail Round 4 movl 16(%esi),%ecx subl %eax,%ecx movl %ecx,16(%ebx) - jnc L038pw_tail_nc4 + jnc L050pw_tail_nc4 decl %ebp - jz L020pw_end + jz L032pw_end # dl>0 Tail Round 5 movl 20(%esi),%ecx subl %eax,%ecx movl %ecx,20(%ebx) - jnc L039pw_tail_nc5 + jnc L051pw_tail_nc5 decl %ebp - jz L020pw_end + jz L032pw_end # dl>0 Tail Round 6 movl 24(%esi),%ecx subl %eax,%ecx movl %ecx,24(%ebx) - jnc L040pw_tail_nc6 + jnc L052pw_tail_nc6 movl $1,%eax - jmp L020pw_end -L041pw_nc_loop: + jmp L032pw_end +L053pw_nc_loop: movl (%esi),%ecx movl %ecx,(%ebx) -L026pw_nc0: +L038pw_nc0: movl 4(%esi),%ecx movl %ecx,4(%ebx) -L027pw_nc1: +L039pw_nc1: movl 8(%esi),%ecx movl %ecx,8(%ebx) -L028pw_nc2: +L040pw_nc2: movl 12(%esi),%ecx movl %ecx,12(%ebx) -L029pw_nc3: +L041pw_nc3: movl 16(%esi),%ecx movl %ecx,16(%ebx) -L030pw_nc4: +L042pw_nc4: movl 20(%esi),%ecx movl %ecx,20(%ebx) -L031pw_nc5: +L043pw_nc5: movl 24(%esi),%ecx movl %ecx,24(%ebx) -L032pw_nc6: +L044pw_nc6: movl 28(%esi),%ecx movl %ecx,28(%ebx) -L033pw_nc7: +L045pw_nc7: addl $32,%esi addl $32,%ebx subl $8,%ebp - jnz L041pw_nc_loop + jnz L053pw_nc_loop movl 36(%esp),%ebp andl $7,%ebp - jz L042pw_nc_end + jz L054pw_nc_end movl (%esi),%ecx movl %ecx,(%ebx) -L034pw_tail_nc0: +L046pw_tail_nc0: decl %ebp - jz L042pw_nc_end + jz L054pw_nc_end movl 4(%esi),%ecx movl %ecx,4(%ebx) -L035pw_tail_nc1: +L047pw_tail_nc1: decl %ebp - jz L042pw_nc_end + jz L054pw_nc_end movl 8(%esi),%ecx movl %ecx,8(%ebx) -L036pw_tail_nc2: +L048pw_tail_nc2: decl %ebp - jz L042pw_nc_end + jz L054pw_nc_end movl 12(%esi),%ecx movl %ecx,12(%ebx) -L037pw_tail_nc3: +L049pw_tail_nc3: decl %ebp - jz L042pw_nc_end + jz L054pw_nc_end movl 16(%esi),%ecx movl %ecx,16(%ebx) -L038pw_tail_nc4: +L050pw_tail_nc4: decl %ebp - jz L042pw_nc_end + jz L054pw_nc_end movl 20(%esi),%ecx movl %ecx,20(%ebx) -L039pw_tail_nc5: +L051pw_tail_nc5: decl %ebp - jz L042pw_nc_end + jz L054pw_nc_end movl 24(%esi),%ecx movl %ecx,24(%ebx) -L040pw_tail_nc6: -L042pw_nc_end: +L052pw_tail_nc6: +L054pw_nc_end: movl $0,%eax -L020pw_end: +L032pw_end: popl %edi popl %esi popl %ebx popl %ebp ret +.section __IMPORT,__pointers,non_lazy_symbol_pointers +L_OPENSSL_ia32cap_P$non_lazy_ptr: +.indirect_symbol _OPENSSL_ia32cap_P +.long 0 #endif diff --git a/third_party/boringssl/mac-x86/crypto/bn/x86-mont.S b/third_party/boringssl/mac-x86/crypto/bn/x86-mont.S index 1b79c5faeb51b..234034b0a0805 100644 --- a/third_party/boringssl/mac-x86/crypto/bn/x86-mont.S +++ b/third_party/boringssl/mac-x86/crypto/bn/x86-mont.S @@ -43,6 +43,126 @@ L_bn_mul_mont_begin: movl %esi,20(%esp) leal -3(%edi),%ebx movl %ebp,24(%esp) + call L001PIC_me_up +L001PIC_me_up: + popl %eax + movl L_OPENSSL_ia32cap_P$non_lazy_ptr-L001PIC_me_up(%eax),%eax + btl $26,(%eax) + jnc L002non_sse2 + movl $-1,%eax + movd %eax,%mm7 + movl 8(%esp),%esi + movl 12(%esp),%edi + movl 16(%esp),%ebp + xorl %edx,%edx + xorl %ecx,%ecx + movd (%edi),%mm4 + movd (%esi),%mm5 + movd (%ebp),%mm3 + pmuludq %mm4,%mm5 + movq %mm5,%mm2 + movq %mm5,%mm0 + pand %mm7,%mm0 + pmuludq 20(%esp),%mm5 + pmuludq %mm5,%mm3 + paddq %mm0,%mm3 + movd 4(%ebp),%mm1 + movd 4(%esi),%mm0 + psrlq $32,%mm2 + psrlq $32,%mm3 + incl %ecx +.align 4,0x90 +L0031st: + pmuludq %mm4,%mm0 + pmuludq %mm5,%mm1 + paddq %mm0,%mm2 + paddq %mm1,%mm3 + movq %mm2,%mm0 + pand %mm7,%mm0 + movd 4(%ebp,%ecx,4),%mm1 + paddq %mm0,%mm3 + movd 4(%esi,%ecx,4),%mm0 + psrlq $32,%mm2 + movd %mm3,28(%esp,%ecx,4) + psrlq $32,%mm3 + leal 1(%ecx),%ecx + cmpl %ebx,%ecx + jl L0031st + pmuludq %mm4,%mm0 + pmuludq %mm5,%mm1 + paddq %mm0,%mm2 + paddq %mm1,%mm3 + movq %mm2,%mm0 + pand %mm7,%mm0 + paddq %mm0,%mm3 + movd %mm3,28(%esp,%ecx,4) + psrlq $32,%mm2 + psrlq $32,%mm3 + paddq %mm2,%mm3 + movq %mm3,32(%esp,%ebx,4) + incl %edx +L004outer: + xorl %ecx,%ecx + movd (%edi,%edx,4),%mm4 + movd (%esi),%mm5 + movd 32(%esp),%mm6 + movd (%ebp),%mm3 + pmuludq %mm4,%mm5 + paddq %mm6,%mm5 + movq %mm5,%mm0 + movq %mm5,%mm2 + pand %mm7,%mm0 + pmuludq 20(%esp),%mm5 + pmuludq %mm5,%mm3 + paddq %mm0,%mm3 + movd 36(%esp),%mm6 + movd 4(%ebp),%mm1 + movd 4(%esi),%mm0 + psrlq $32,%mm2 + psrlq $32,%mm3 + paddq %mm6,%mm2 + incl %ecx + decl %ebx +L005inner: + pmuludq %mm4,%mm0 + pmuludq %mm5,%mm1 + paddq %mm0,%mm2 + paddq %mm1,%mm3 + movq %mm2,%mm0 + movd 36(%esp,%ecx,4),%mm6 + pand %mm7,%mm0 + movd 4(%ebp,%ecx,4),%mm1 + paddq %mm0,%mm3 + movd 4(%esi,%ecx,4),%mm0 + psrlq $32,%mm2 + movd %mm3,28(%esp,%ecx,4) + psrlq $32,%mm3 + paddq %mm6,%mm2 + decl %ebx + leal 1(%ecx),%ecx + jnz L005inner + movl %ecx,%ebx + pmuludq %mm4,%mm0 + pmuludq %mm5,%mm1 + paddq %mm0,%mm2 + paddq %mm1,%mm3 + movq %mm2,%mm0 + pand %mm7,%mm0 + paddq %mm0,%mm3 + movd %mm3,28(%esp,%ecx,4) + psrlq $32,%mm2 + psrlq $32,%mm3 + movd 36(%esp,%ebx,4),%mm6 + paddq %mm2,%mm3 + paddq %mm6,%mm3 + movq %mm3,32(%esp,%ebx,4) + leal 1(%edx),%edx + cmpl %ebx,%edx + jle L004outer + emms + jmp L006common_tail +.align 4,0x90 +L002non_sse2: movl 8(%esp),%esi leal 1(%ebx),%ebp movl 12(%esp),%edi @@ -53,12 +173,12 @@ L_bn_mul_mont_begin: leal 4(%edi,%ebx,4),%eax orl %edx,%ebp movl (%edi),%edi - jz L001bn_sqr_mont + jz L007bn_sqr_mont movl %eax,28(%esp) movl (%esi),%eax xorl %edx,%edx .align 4,0x90 -L002mull: +L008mull: movl %edx,%ebp mull %edi addl %eax,%ebp @@ -67,7 +187,7 @@ L002mull: movl (%esi,%ecx,4),%eax cmpl %ebx,%ecx movl %ebp,28(%esp,%ecx,4) - jl L002mull + jl L008mull movl %edx,%ebp mull %edi movl 20(%esp),%edi @@ -85,9 +205,9 @@ L002mull: movl 4(%esi),%eax adcl $0,%edx incl %ecx - jmp L0032ndmadd + jmp L0092ndmadd .align 4,0x90 -L0041stmadd: +L0101stmadd: movl %edx,%ebp mull %edi addl 32(%esp,%ecx,4),%ebp @@ -98,7 +218,7 @@ L0041stmadd: adcl $0,%edx cmpl %ebx,%ecx movl %ebp,28(%esp,%ecx,4) - jl L0041stmadd + jl L0101stmadd movl %edx,%ebp mull %edi addl 32(%esp,%ebx,4),%eax @@ -121,7 +241,7 @@ L0041stmadd: adcl $0,%edx movl $1,%ecx .align 4,0x90 -L0032ndmadd: +L0092ndmadd: movl %edx,%ebp mull %edi addl 32(%esp,%ecx,4),%ebp @@ -132,7 +252,7 @@ L0032ndmadd: adcl $0,%edx cmpl %ebx,%ecx movl %ebp,24(%esp,%ecx,4) - jl L0032ndmadd + jl L0092ndmadd movl %edx,%ebp mull %edi addl 32(%esp,%ebx,4),%ebp @@ -148,16 +268,16 @@ L0032ndmadd: movl %edx,32(%esp,%ebx,4) cmpl 28(%esp),%ecx movl %eax,36(%esp,%ebx,4) - je L005common_tail + je L006common_tail movl (%ecx),%edi movl 8(%esp),%esi movl %ecx,12(%esp) xorl %ecx,%ecx xorl %edx,%edx movl (%esi),%eax - jmp L0041stmadd + jmp L0101stmadd .align 4,0x90 -L001bn_sqr_mont: +L007bn_sqr_mont: movl %ebx,(%esp) movl %ecx,12(%esp) movl %edi,%eax @@ -168,7 +288,7 @@ L001bn_sqr_mont: andl $1,%ebx incl %ecx .align 4,0x90 -L006sqr: +L011sqr: movl (%esi,%ecx,4),%eax movl %edx,%ebp mull %edi @@ -180,7 +300,7 @@ L006sqr: cmpl (%esp),%ecx movl %eax,%ebx movl %ebp,28(%esp,%ecx,4) - jl L006sqr + jl L011sqr movl (%esi,%ecx,4),%eax movl %edx,%ebp mull %edi @@ -204,7 +324,7 @@ L006sqr: movl 4(%esi),%eax movl $1,%ecx .align 4,0x90 -L0073rdmadd: +L0123rdmadd: movl %edx,%ebp mull %edi addl 32(%esp,%ecx,4),%ebp @@ -223,7 +343,7 @@ L0073rdmadd: adcl $0,%edx cmpl %ebx,%ecx movl %ebp,24(%esp,%ecx,4) - jl L0073rdmadd + jl L0123rdmadd movl %edx,%ebp mull %edi addl 32(%esp,%ebx,4),%ebp @@ -239,7 +359,7 @@ L0073rdmadd: movl %edx,32(%esp,%ebx,4) cmpl %ebx,%ecx movl %eax,36(%esp,%ebx,4) - je L005common_tail + je L006common_tail movl 4(%esi,%ecx,4),%edi leal 1(%ecx),%ecx movl %edi,%eax @@ -251,12 +371,12 @@ L0073rdmadd: xorl %ebp,%ebp cmpl %ebx,%ecx leal 1(%ecx),%ecx - je L008sqrlast + je L013sqrlast movl %edx,%ebx shrl $1,%edx andl $1,%ebx .align 4,0x90 -L009sqradd: +L014sqradd: movl (%esi,%ecx,4),%eax movl %edx,%ebp mull %edi @@ -272,13 +392,13 @@ L009sqradd: cmpl (%esp),%ecx movl %ebp,28(%esp,%ecx,4) movl %eax,%ebx - jle L009sqradd + jle L014sqradd movl %edx,%ebp addl %edx,%edx shrl $31,%ebp addl %ebx,%edx adcl $0,%ebp -L008sqrlast: +L013sqrlast: movl 20(%esp),%edi movl 16(%esp),%esi imull 32(%esp),%edi @@ -293,9 +413,9 @@ L008sqrlast: adcl $0,%edx movl $1,%ecx movl 4(%esi),%eax - jmp L0073rdmadd + jmp L0123rdmadd .align 4,0x90 -L005common_tail: +L006common_tail: movl 16(%esp),%ebp movl 4(%esp),%edi leal 32(%esp),%esi @@ -303,16 +423,16 @@ L005common_tail: movl %ebx,%ecx xorl %edx,%edx .align 4,0x90 -L010sub: +L015sub: sbbl (%ebp,%edx,4),%eax movl %eax,(%edi,%edx,4) decl %ecx movl 4(%esi,%edx,4),%eax leal 1(%edx),%edx - jge L010sub + jge L015sub sbbl $0,%eax .align 4,0x90 -L011copy: +L016copy: movl (%esi,%ebx,4),%edx movl (%edi,%ebx,4),%ebp xorl %ebp,%edx @@ -321,7 +441,7 @@ L011copy: movl %ecx,(%esi,%ebx,4) movl %edx,(%edi,%ebx,4) decl %ebx - jge L011copy + jge L016copy movl 24(%esp),%esp movl $1,%eax L000just_leave: @@ -335,4 +455,8 @@ L000just_leave: .byte 54,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121 .byte 32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46 .byte 111,114,103,62,0 +.section __IMPORT,__pointers,non_lazy_symbol_pointers +L_OPENSSL_ia32cap_P$non_lazy_ptr: +.indirect_symbol _OPENSSL_ia32cap_P +.long 0 #endif diff --git a/third_party/boringssl/mac-x86/crypto/cpu-x86-asm.S b/third_party/boringssl/mac-x86/crypto/cpu-x86-asm.S index 54eb09abb7558..bfb292c893818 100644 --- a/third_party/boringssl/mac-x86/crypto/cpu-x86-asm.S +++ b/third_party/boringssl/mac-x86/crypto/cpu-x86-asm.S @@ -228,6 +228,18 @@ L015PIC_me_up: movl (%ecx),%ecx btl $1,(%ecx) jnc L016no_x87 + andl $83886080,%ecx + cmpl $83886080,%ecx + jne L017no_sse2 + pxor %xmm0,%xmm0 + pxor %xmm1,%xmm1 + pxor %xmm2,%xmm2 + pxor %xmm3,%xmm3 + pxor %xmm4,%xmm4 + pxor %xmm5,%xmm5 + pxor %xmm6,%xmm6 + pxor %xmm7,%xmm7 +L017no_sse2: .long 4007259865,4007259865,4007259865,4007259865,2430851995 L016no_x87: leal 4(%esp),%eax @@ -242,11 +254,11 @@ L_OPENSSL_atomic_add_begin: pushl %ebx nop movl (%edx),%eax -L017spin: +L018spin: leal (%eax,%ecx,1),%ebx nop .long 447811568 - jne L017spin + jne L018spin movl %ebx,%eax popl %ebx ret @@ -282,11 +294,11 @@ L_OPENSSL_indirect_call_begin: _OPENSSL_ia32_rdrand: L_OPENSSL_ia32_rdrand_begin: movl $8,%ecx -L018loop: +L019loop: .byte 15,199,240 - jc L019break - loop L018loop -L019break: + jc L020break + loop L019loop +L020break: cmpl $0,%eax cmovel %ecx,%eax ret diff --git a/third_party/boringssl/mac-x86/crypto/sha/sha1-586.S b/third_party/boringssl/mac-x86/crypto/sha/sha1-586.S index 4dd3feed63750..97aafbf198ab3 100644 --- a/third_party/boringssl/mac-x86/crypto/sha/sha1-586.S +++ b/third_party/boringssl/mac-x86/crypto/sha/sha1-586.S @@ -10,6 +10,23 @@ L_sha1_block_data_order_begin: pushl %ebx pushl %esi pushl %edi + call L000pic_point +L000pic_point: + popl %ebp + movl L_OPENSSL_ia32cap_P$non_lazy_ptr-L000pic_point(%ebp),%esi + leal LK_XX_XX-L000pic_point(%ebp),%ebp + movl (%esi),%eax + movl 4(%esi),%edx + testl $512,%edx + jz L001x86 + movl 8(%esi),%ecx + testl $16777216,%eax + jz L001x86 + testl $536870912,%ecx + jnz Lshaext_shortcut + jmp Lssse3_shortcut +.align 4,0x90 +L001x86: movl 20(%esp),%ebp movl 24(%esp),%esi movl 28(%esp),%eax @@ -18,9 +35,9 @@ L_sha1_block_data_order_begin: addl %esi,%eax movl %eax,104(%esp) movl 16(%ebp),%edi - jmp L000loop + jmp L002loop .align 4,0x90 -L000loop: +L002loop: movl (%esi),%eax movl 4(%esi),%ebx movl 8(%esi),%ecx @@ -1367,15 +1384,1414 @@ L000loop: movl %ebx,12(%ebp) movl %edx,%esi movl %ecx,16(%ebp) - jb L000loop + jb L002loop addl $76,%esp popl %edi popl %esi popl %ebx popl %ebp ret +.private_extern __sha1_block_data_order_shaext +.align 4 +__sha1_block_data_order_shaext: + pushl %ebp + pushl %ebx + pushl %esi + pushl %edi + call L003pic_point +L003pic_point: + popl %ebp + leal LK_XX_XX-L003pic_point(%ebp),%ebp +Lshaext_shortcut: + movl 20(%esp),%edi + movl %esp,%ebx + movl 24(%esp),%esi + movl 28(%esp),%ecx + subl $32,%esp + movdqu (%edi),%xmm0 + movd 16(%edi),%xmm1 + andl $-32,%esp + movdqa 80(%ebp),%xmm3 + movdqu (%esi),%xmm4 + pshufd $27,%xmm0,%xmm0 + movdqu 16(%esi),%xmm5 + pshufd $27,%xmm1,%xmm1 + movdqu 32(%esi),%xmm6 +.byte 102,15,56,0,227 + movdqu 48(%esi),%xmm7 +.byte 102,15,56,0,235 +.byte 102,15,56,0,243 +.byte 102,15,56,0,251 + jmp L004loop_shaext +.align 4,0x90 +L004loop_shaext: + decl %ecx + leal 64(%esi),%eax + movdqa %xmm1,(%esp) + paddd %xmm4,%xmm1 + cmovnel %eax,%esi + movdqa %xmm0,16(%esp) +.byte 15,56,201,229 + movdqa %xmm0,%xmm2 +.byte 15,58,204,193,0 +.byte 15,56,200,213 + pxor %xmm6,%xmm4 +.byte 15,56,201,238 +.byte 15,56,202,231 + movdqa %xmm0,%xmm1 +.byte 15,58,204,194,0 +.byte 15,56,200,206 + pxor %xmm7,%xmm5 +.byte 15,56,202,236 +.byte 15,56,201,247 + movdqa %xmm0,%xmm2 +.byte 15,58,204,193,0 +.byte 15,56,200,215 + pxor %xmm4,%xmm6 +.byte 15,56,201,252 +.byte 15,56,202,245 + movdqa %xmm0,%xmm1 +.byte 15,58,204,194,0 +.byte 15,56,200,204 + pxor %xmm5,%xmm7 +.byte 15,56,202,254 +.byte 15,56,201,229 + movdqa %xmm0,%xmm2 +.byte 15,58,204,193,0 +.byte 15,56,200,213 + pxor %xmm6,%xmm4 +.byte 15,56,201,238 +.byte 15,56,202,231 + movdqa %xmm0,%xmm1 +.byte 15,58,204,194,1 +.byte 15,56,200,206 + pxor %xmm7,%xmm5 +.byte 15,56,202,236 +.byte 15,56,201,247 + movdqa %xmm0,%xmm2 +.byte 15,58,204,193,1 +.byte 15,56,200,215 + pxor %xmm4,%xmm6 +.byte 15,56,201,252 +.byte 15,56,202,245 + movdqa %xmm0,%xmm1 +.byte 15,58,204,194,1 +.byte 15,56,200,204 + pxor %xmm5,%xmm7 +.byte 15,56,202,254 +.byte 15,56,201,229 + movdqa %xmm0,%xmm2 +.byte 15,58,204,193,1 +.byte 15,56,200,213 + pxor %xmm6,%xmm4 +.byte 15,56,201,238 +.byte 15,56,202,231 + movdqa %xmm0,%xmm1 +.byte 15,58,204,194,1 +.byte 15,56,200,206 + pxor %xmm7,%xmm5 +.byte 15,56,202,236 +.byte 15,56,201,247 + movdqa %xmm0,%xmm2 +.byte 15,58,204,193,2 +.byte 15,56,200,215 + pxor %xmm4,%xmm6 +.byte 15,56,201,252 +.byte 15,56,202,245 + movdqa %xmm0,%xmm1 +.byte 15,58,204,194,2 +.byte 15,56,200,204 + pxor %xmm5,%xmm7 +.byte 15,56,202,254 +.byte 15,56,201,229 + movdqa %xmm0,%xmm2 +.byte 15,58,204,193,2 +.byte 15,56,200,213 + pxor %xmm6,%xmm4 +.byte 15,56,201,238 +.byte 15,56,202,231 + movdqa %xmm0,%xmm1 +.byte 15,58,204,194,2 +.byte 15,56,200,206 + pxor %xmm7,%xmm5 +.byte 15,56,202,236 +.byte 15,56,201,247 + movdqa %xmm0,%xmm2 +.byte 15,58,204,193,2 +.byte 15,56,200,215 + pxor %xmm4,%xmm6 +.byte 15,56,201,252 +.byte 15,56,202,245 + movdqa %xmm0,%xmm1 +.byte 15,58,204,194,3 +.byte 15,56,200,204 + pxor %xmm5,%xmm7 +.byte 15,56,202,254 + movdqu (%esi),%xmm4 + movdqa %xmm0,%xmm2 +.byte 15,58,204,193,3 +.byte 15,56,200,213 + movdqu 16(%esi),%xmm5 +.byte 102,15,56,0,227 + movdqa %xmm0,%xmm1 +.byte 15,58,204,194,3 +.byte 15,56,200,206 + movdqu 32(%esi),%xmm6 +.byte 102,15,56,0,235 + movdqa %xmm0,%xmm2 +.byte 15,58,204,193,3 +.byte 15,56,200,215 + movdqu 48(%esi),%xmm7 +.byte 102,15,56,0,243 + movdqa %xmm0,%xmm1 +.byte 15,58,204,194,3 + movdqa (%esp),%xmm2 +.byte 102,15,56,0,251 +.byte 15,56,200,202 + paddd 16(%esp),%xmm0 + jnz L004loop_shaext + pshufd $27,%xmm0,%xmm0 + pshufd $27,%xmm1,%xmm1 + movdqu %xmm0,(%edi) + movd %xmm1,16(%edi) + movl %ebx,%esp + popl %edi + popl %esi + popl %ebx + popl %ebp + ret +.private_extern __sha1_block_data_order_ssse3 +.align 4 +__sha1_block_data_order_ssse3: + pushl %ebp + pushl %ebx + pushl %esi + pushl %edi + call L005pic_point +L005pic_point: + popl %ebp + leal LK_XX_XX-L005pic_point(%ebp),%ebp +Lssse3_shortcut: + movdqa (%ebp),%xmm7 + movdqa 16(%ebp),%xmm0 + movdqa 32(%ebp),%xmm1 + movdqa 48(%ebp),%xmm2 + movdqa 64(%ebp),%xmm6 + movl 20(%esp),%edi + movl 24(%esp),%ebp + movl 28(%esp),%edx + movl %esp,%esi + subl $208,%esp + andl $-64,%esp + movdqa %xmm0,112(%esp) + movdqa %xmm1,128(%esp) + movdqa %xmm2,144(%esp) + shll $6,%edx + movdqa %xmm7,160(%esp) + addl %ebp,%edx + movdqa %xmm6,176(%esp) + addl $64,%ebp + movl %edi,192(%esp) + movl %ebp,196(%esp) + movl %edx,200(%esp) + movl %esi,204(%esp) + movl (%edi),%eax + movl 4(%edi),%ebx + movl 8(%edi),%ecx + movl 12(%edi),%edx + movl 16(%edi),%edi + movl %ebx,%esi + movdqu -64(%ebp),%xmm0 + movdqu -48(%ebp),%xmm1 + movdqu -32(%ebp),%xmm2 + movdqu -16(%ebp),%xmm3 +.byte 102,15,56,0,198 +.byte 102,15,56,0,206 +.byte 102,15,56,0,214 + movdqa %xmm7,96(%esp) +.byte 102,15,56,0,222 + paddd %xmm7,%xmm0 + paddd %xmm7,%xmm1 + paddd %xmm7,%xmm2 + movdqa %xmm0,(%esp) + psubd %xmm7,%xmm0 + movdqa %xmm1,16(%esp) + psubd %xmm7,%xmm1 + movdqa %xmm2,32(%esp) + movl %ecx,%ebp + psubd %xmm7,%xmm2 + xorl %edx,%ebp + pshufd $238,%xmm0,%xmm4 + andl %ebp,%esi + jmp L006loop +.align 4,0x90 +L006loop: + rorl $2,%ebx + xorl %edx,%esi + movl %eax,%ebp + punpcklqdq %xmm1,%xmm4 + movdqa %xmm3,%xmm6 + addl (%esp),%edi + xorl %ecx,%ebx + paddd %xmm3,%xmm7 + movdqa %xmm0,64(%esp) + roll $5,%eax + addl %esi,%edi + psrldq $4,%xmm6 + andl %ebx,%ebp + xorl %ecx,%ebx + pxor %xmm0,%xmm4 + addl %eax,%edi + rorl $7,%eax + pxor %xmm2,%xmm6 + xorl %ecx,%ebp + movl %edi,%esi + addl 4(%esp),%edx + pxor %xmm6,%xmm4 + xorl %ebx,%eax + roll $5,%edi + movdqa %xmm7,48(%esp) + addl %ebp,%edx + andl %eax,%esi + movdqa %xmm4,%xmm0 + xorl %ebx,%eax + addl %edi,%edx + rorl $7,%edi + movdqa %xmm4,%xmm6 + xorl %ebx,%esi + pslldq $12,%xmm0 + paddd %xmm4,%xmm4 + movl %edx,%ebp + addl 8(%esp),%ecx + psrld $31,%xmm6 + xorl %eax,%edi + roll $5,%edx + movdqa %xmm0,%xmm7 + addl %esi,%ecx + andl %edi,%ebp + xorl %eax,%edi + psrld $30,%xmm0 + addl %edx,%ecx + rorl $7,%edx + por %xmm6,%xmm4 + xorl %eax,%ebp + movl %ecx,%esi + addl 12(%esp),%ebx + pslld $2,%xmm7 + xorl %edi,%edx + roll $5,%ecx + pxor %xmm0,%xmm4 + movdqa 96(%esp),%xmm0 + addl %ebp,%ebx + andl %edx,%esi + pxor %xmm7,%xmm4 + pshufd $238,%xmm1,%xmm5 + xorl %edi,%edx + addl %ecx,%ebx + rorl $7,%ecx + xorl %edi,%esi + movl %ebx,%ebp + punpcklqdq %xmm2,%xmm5 + movdqa %xmm4,%xmm7 + addl 16(%esp),%eax + xorl %edx,%ecx + paddd %xmm4,%xmm0 + movdqa %xmm1,80(%esp) + roll $5,%ebx + addl %esi,%eax + psrldq $4,%xmm7 + andl %ecx,%ebp + xorl %edx,%ecx + pxor %xmm1,%xmm5 + addl %ebx,%eax + rorl $7,%ebx + pxor %xmm3,%xmm7 + xorl %edx,%ebp + movl %eax,%esi + addl 20(%esp),%edi + pxor %xmm7,%xmm5 + xorl %ecx,%ebx + roll $5,%eax + movdqa %xmm0,(%esp) + addl %ebp,%edi + andl %ebx,%esi + movdqa %xmm5,%xmm1 + xorl %ecx,%ebx + addl %eax,%edi + rorl $7,%eax + movdqa %xmm5,%xmm7 + xorl %ecx,%esi + pslldq $12,%xmm1 + paddd %xmm5,%xmm5 + movl %edi,%ebp + addl 24(%esp),%edx + psrld $31,%xmm7 + xorl %ebx,%eax + roll $5,%edi + movdqa %xmm1,%xmm0 + addl %esi,%edx + andl %eax,%ebp + xorl %ebx,%eax + psrld $30,%xmm1 + addl %edi,%edx + rorl $7,%edi + por %xmm7,%xmm5 + xorl %ebx,%ebp + movl %edx,%esi + addl 28(%esp),%ecx + pslld $2,%xmm0 + xorl %eax,%edi + roll $5,%edx + pxor %xmm1,%xmm5 + movdqa 112(%esp),%xmm1 + addl %ebp,%ecx + andl %edi,%esi + pxor %xmm0,%xmm5 + pshufd $238,%xmm2,%xmm6 + xorl %eax,%edi + addl %edx,%ecx + rorl $7,%edx + xorl %eax,%esi + movl %ecx,%ebp + punpcklqdq %xmm3,%xmm6 + movdqa %xmm5,%xmm0 + addl 32(%esp),%ebx + xorl %edi,%edx + paddd %xmm5,%xmm1 + movdqa %xmm2,96(%esp) + roll $5,%ecx + addl %esi,%ebx + psrldq $4,%xmm0 + andl %edx,%ebp + xorl %edi,%edx + pxor %xmm2,%xmm6 + addl %ecx,%ebx + rorl $7,%ecx + pxor %xmm4,%xmm0 + xorl %edi,%ebp + movl %ebx,%esi + addl 36(%esp),%eax + pxor %xmm0,%xmm6 + xorl %edx,%ecx + roll $5,%ebx + movdqa %xmm1,16(%esp) + addl %ebp,%eax + andl %ecx,%esi + movdqa %xmm6,%xmm2 + xorl %edx,%ecx + addl %ebx,%eax + rorl $7,%ebx + movdqa %xmm6,%xmm0 + xorl %edx,%esi + pslldq $12,%xmm2 + paddd %xmm6,%xmm6 + movl %eax,%ebp + addl 40(%esp),%edi + psrld $31,%xmm0 + xorl %ecx,%ebx + roll $5,%eax + movdqa %xmm2,%xmm1 + addl %esi,%edi + andl %ebx,%ebp + xorl %ecx,%ebx + psrld $30,%xmm2 + addl %eax,%edi + rorl $7,%eax + por %xmm0,%xmm6 + xorl %ecx,%ebp + movdqa 64(%esp),%xmm0 + movl %edi,%esi + addl 44(%esp),%edx + pslld $2,%xmm1 + xorl %ebx,%eax + roll $5,%edi + pxor %xmm2,%xmm6 + movdqa 112(%esp),%xmm2 + addl %ebp,%edx + andl %eax,%esi + pxor %xmm1,%xmm6 + pshufd $238,%xmm3,%xmm7 + xorl %ebx,%eax + addl %edi,%edx + rorl $7,%edi + xorl %ebx,%esi + movl %edx,%ebp + punpcklqdq %xmm4,%xmm7 + movdqa %xmm6,%xmm1 + addl 48(%esp),%ecx + xorl %eax,%edi + paddd %xmm6,%xmm2 + movdqa %xmm3,64(%esp) + roll $5,%edx + addl %esi,%ecx + psrldq $4,%xmm1 + andl %edi,%ebp + xorl %eax,%edi + pxor %xmm3,%xmm7 + addl %edx,%ecx + rorl $7,%edx + pxor %xmm5,%xmm1 + xorl %eax,%ebp + movl %ecx,%esi + addl 52(%esp),%ebx + pxor %xmm1,%xmm7 + xorl %edi,%edx + roll $5,%ecx + movdqa %xmm2,32(%esp) + addl %ebp,%ebx + andl %edx,%esi + movdqa %xmm7,%xmm3 + xorl %edi,%edx + addl %ecx,%ebx + rorl $7,%ecx + movdqa %xmm7,%xmm1 + xorl %edi,%esi + pslldq $12,%xmm3 + paddd %xmm7,%xmm7 + movl %ebx,%ebp + addl 56(%esp),%eax + psrld $31,%xmm1 + xorl %edx,%ecx + roll $5,%ebx + movdqa %xmm3,%xmm2 + addl %esi,%eax + andl %ecx,%ebp + xorl %edx,%ecx + psrld $30,%xmm3 + addl %ebx,%eax + rorl $7,%ebx + por %xmm1,%xmm7 + xorl %edx,%ebp + movdqa 80(%esp),%xmm1 + movl %eax,%esi + addl 60(%esp),%edi + pslld $2,%xmm2 + xorl %ecx,%ebx + roll $5,%eax + pxor %xmm3,%xmm7 + movdqa 112(%esp),%xmm3 + addl %ebp,%edi + andl %ebx,%esi + pxor %xmm2,%xmm7 + pshufd $238,%xmm6,%xmm2 + xorl %ecx,%ebx + addl %eax,%edi + rorl $7,%eax + pxor %xmm4,%xmm0 + punpcklqdq %xmm7,%xmm2 + xorl %ecx,%esi + movl %edi,%ebp + addl (%esp),%edx + pxor %xmm1,%xmm0 + movdqa %xmm4,80(%esp) + xorl %ebx,%eax + roll $5,%edi + movdqa %xmm3,%xmm4 + addl %esi,%edx + paddd %xmm7,%xmm3 + andl %eax,%ebp + pxor %xmm2,%xmm0 + xorl %ebx,%eax + addl %edi,%edx + rorl $7,%edi + xorl %ebx,%ebp + movdqa %xmm0,%xmm2 + movdqa %xmm3,48(%esp) + movl %edx,%esi + addl 4(%esp),%ecx + xorl %eax,%edi + roll $5,%edx + pslld $2,%xmm0 + addl %ebp,%ecx + andl %edi,%esi + psrld $30,%xmm2 + xorl %eax,%edi + addl %edx,%ecx + rorl $7,%edx + xorl %eax,%esi + movl %ecx,%ebp + addl 8(%esp),%ebx + xorl %edi,%edx + roll $5,%ecx + por %xmm2,%xmm0 + addl %esi,%ebx + andl %edx,%ebp + movdqa 96(%esp),%xmm2 + xorl %edi,%edx + addl %ecx,%ebx + addl 12(%esp),%eax + xorl %edi,%ebp + movl %ebx,%esi + pshufd $238,%xmm7,%xmm3 + roll $5,%ebx + addl %ebp,%eax + xorl %edx,%esi + rorl $7,%ecx + addl %ebx,%eax + addl 16(%esp),%edi + pxor %xmm5,%xmm1 + punpcklqdq %xmm0,%xmm3 + xorl %ecx,%esi + movl %eax,%ebp + roll $5,%eax + pxor %xmm2,%xmm1 + movdqa %xmm5,96(%esp) + addl %esi,%edi + xorl %ecx,%ebp + movdqa %xmm4,%xmm5 + rorl $7,%ebx + paddd %xmm0,%xmm4 + addl %eax,%edi + pxor %xmm3,%xmm1 + addl 20(%esp),%edx + xorl %ebx,%ebp + movl %edi,%esi + roll $5,%edi + movdqa %xmm1,%xmm3 + movdqa %xmm4,(%esp) + addl %ebp,%edx + xorl %ebx,%esi + rorl $7,%eax + addl %edi,%edx + pslld $2,%xmm1 + addl 24(%esp),%ecx + xorl %eax,%esi + psrld $30,%xmm3 + movl %edx,%ebp + roll $5,%edx + addl %esi,%ecx + xorl %eax,%ebp + rorl $7,%edi + addl %edx,%ecx + por %xmm3,%xmm1 + addl 28(%esp),%ebx + xorl %edi,%ebp + movdqa 64(%esp),%xmm3 + movl %ecx,%esi + roll $5,%ecx + addl %ebp,%ebx + xorl %edi,%esi + rorl $7,%edx + pshufd $238,%xmm0,%xmm4 + addl %ecx,%ebx + addl 32(%esp),%eax + pxor %xmm6,%xmm2 + punpcklqdq %xmm1,%xmm4 + xorl %edx,%esi + movl %ebx,%ebp + roll $5,%ebx + pxor %xmm3,%xmm2 + movdqa %xmm6,64(%esp) + addl %esi,%eax + xorl %edx,%ebp + movdqa 128(%esp),%xmm6 + rorl $7,%ecx + paddd %xmm1,%xmm5 + addl %ebx,%eax + pxor %xmm4,%xmm2 + addl 36(%esp),%edi + xorl %ecx,%ebp + movl %eax,%esi + roll $5,%eax + movdqa %xmm2,%xmm4 + movdqa %xmm5,16(%esp) + addl %ebp,%edi + xorl %ecx,%esi + rorl $7,%ebx + addl %eax,%edi + pslld $2,%xmm2 + addl 40(%esp),%edx + xorl %ebx,%esi + psrld $30,%xmm4 + movl %edi,%ebp + roll $5,%edi + addl %esi,%edx + xorl %ebx,%ebp + rorl $7,%eax + addl %edi,%edx + por %xmm4,%xmm2 + addl 44(%esp),%ecx + xorl %eax,%ebp + movdqa 80(%esp),%xmm4 + movl %edx,%esi + roll $5,%edx + addl %ebp,%ecx + xorl %eax,%esi + rorl $7,%edi + pshufd $238,%xmm1,%xmm5 + addl %edx,%ecx + addl 48(%esp),%ebx + pxor %xmm7,%xmm3 + punpcklqdq %xmm2,%xmm5 + xorl %edi,%esi + movl %ecx,%ebp + roll $5,%ecx + pxor %xmm4,%xmm3 + movdqa %xmm7,80(%esp) + addl %esi,%ebx + xorl %edi,%ebp + movdqa %xmm6,%xmm7 + rorl $7,%edx + paddd %xmm2,%xmm6 + addl %ecx,%ebx + pxor %xmm5,%xmm3 + addl 52(%esp),%eax + xorl %edx,%ebp + movl %ebx,%esi + roll $5,%ebx + movdqa %xmm3,%xmm5 + movdqa %xmm6,32(%esp) + addl %ebp,%eax + xorl %edx,%esi + rorl $7,%ecx + addl %ebx,%eax + pslld $2,%xmm3 + addl 56(%esp),%edi + xorl %ecx,%esi + psrld $30,%xmm5 + movl %eax,%ebp + roll $5,%eax + addl %esi,%edi + xorl %ecx,%ebp + rorl $7,%ebx + addl %eax,%edi + por %xmm5,%xmm3 + addl 60(%esp),%edx + xorl %ebx,%ebp + movdqa 96(%esp),%xmm5 + movl %edi,%esi + roll $5,%edi + addl %ebp,%edx + xorl %ebx,%esi + rorl $7,%eax + pshufd $238,%xmm2,%xmm6 + addl %edi,%edx + addl (%esp),%ecx + pxor %xmm0,%xmm4 + punpcklqdq %xmm3,%xmm6 + xorl %eax,%esi + movl %edx,%ebp + roll $5,%edx + pxor %xmm5,%xmm4 + movdqa %xmm0,96(%esp) + addl %esi,%ecx + xorl %eax,%ebp + movdqa %xmm7,%xmm0 + rorl $7,%edi + paddd %xmm3,%xmm7 + addl %edx,%ecx + pxor %xmm6,%xmm4 + addl 4(%esp),%ebx + xorl %edi,%ebp + movl %ecx,%esi + roll $5,%ecx + movdqa %xmm4,%xmm6 + movdqa %xmm7,48(%esp) + addl %ebp,%ebx + xorl %edi,%esi + rorl $7,%edx + addl %ecx,%ebx + pslld $2,%xmm4 + addl 8(%esp),%eax + xorl %edx,%esi + psrld $30,%xmm6 + movl %ebx,%ebp + roll $5,%ebx + addl %esi,%eax + xorl %edx,%ebp + rorl $7,%ecx + addl %ebx,%eax + por %xmm6,%xmm4 + addl 12(%esp),%edi + xorl %ecx,%ebp + movdqa 64(%esp),%xmm6 + movl %eax,%esi + roll $5,%eax + addl %ebp,%edi + xorl %ecx,%esi + rorl $7,%ebx + pshufd $238,%xmm3,%xmm7 + addl %eax,%edi + addl 16(%esp),%edx + pxor %xmm1,%xmm5 + punpcklqdq %xmm4,%xmm7 + xorl %ebx,%esi + movl %edi,%ebp + roll $5,%edi + pxor %xmm6,%xmm5 + movdqa %xmm1,64(%esp) + addl %esi,%edx + xorl %ebx,%ebp + movdqa %xmm0,%xmm1 + rorl $7,%eax + paddd %xmm4,%xmm0 + addl %edi,%edx + pxor %xmm7,%xmm5 + addl 20(%esp),%ecx + xorl %eax,%ebp + movl %edx,%esi + roll $5,%edx + movdqa %xmm5,%xmm7 + movdqa %xmm0,(%esp) + addl %ebp,%ecx + xorl %eax,%esi + rorl $7,%edi + addl %edx,%ecx + pslld $2,%xmm5 + addl 24(%esp),%ebx + xorl %edi,%esi + psrld $30,%xmm7 + movl %ecx,%ebp + roll $5,%ecx + addl %esi,%ebx + xorl %edi,%ebp + rorl $7,%edx + addl %ecx,%ebx + por %xmm7,%xmm5 + addl 28(%esp),%eax + movdqa 80(%esp),%xmm7 + rorl $7,%ecx + movl %ebx,%esi + xorl %edx,%ebp + roll $5,%ebx + pshufd $238,%xmm4,%xmm0 + addl %ebp,%eax + xorl %ecx,%esi + xorl %edx,%ecx + addl %ebx,%eax + addl 32(%esp),%edi + pxor %xmm2,%xmm6 + punpcklqdq %xmm5,%xmm0 + andl %ecx,%esi + xorl %edx,%ecx + rorl $7,%ebx + pxor %xmm7,%xmm6 + movdqa %xmm2,80(%esp) + movl %eax,%ebp + xorl %ecx,%esi + roll $5,%eax + movdqa %xmm1,%xmm2 + addl %esi,%edi + paddd %xmm5,%xmm1 + xorl %ebx,%ebp + pxor %xmm0,%xmm6 + xorl %ecx,%ebx + addl %eax,%edi + addl 36(%esp),%edx + andl %ebx,%ebp + movdqa %xmm6,%xmm0 + movdqa %xmm1,16(%esp) + xorl %ecx,%ebx + rorl $7,%eax + movl %edi,%esi + xorl %ebx,%ebp + roll $5,%edi + pslld $2,%xmm6 + addl %ebp,%edx + xorl %eax,%esi + psrld $30,%xmm0 + xorl %ebx,%eax + addl %edi,%edx + addl 40(%esp),%ecx + andl %eax,%esi + xorl %ebx,%eax + rorl $7,%edi + por %xmm0,%xmm6 + movl %edx,%ebp + xorl %eax,%esi + movdqa 96(%esp),%xmm0 + roll $5,%edx + addl %esi,%ecx + xorl %edi,%ebp + xorl %eax,%edi + addl %edx,%ecx + pshufd $238,%xmm5,%xmm1 + addl 44(%esp),%ebx + andl %edi,%ebp + xorl %eax,%edi + rorl $7,%edx + movl %ecx,%esi + xorl %edi,%ebp + roll $5,%ecx + addl %ebp,%ebx + xorl %edx,%esi + xorl %edi,%edx + addl %ecx,%ebx + addl 48(%esp),%eax + pxor %xmm3,%xmm7 + punpcklqdq %xmm6,%xmm1 + andl %edx,%esi + xorl %edi,%edx + rorl $7,%ecx + pxor %xmm0,%xmm7 + movdqa %xmm3,96(%esp) + movl %ebx,%ebp + xorl %edx,%esi + roll $5,%ebx + movdqa 144(%esp),%xmm3 + addl %esi,%eax + paddd %xmm6,%xmm2 + xorl %ecx,%ebp + pxor %xmm1,%xmm7 + xorl %edx,%ecx + addl %ebx,%eax + addl 52(%esp),%edi + andl %ecx,%ebp + movdqa %xmm7,%xmm1 + movdqa %xmm2,32(%esp) + xorl %edx,%ecx + rorl $7,%ebx + movl %eax,%esi + xorl %ecx,%ebp + roll $5,%eax + pslld $2,%xmm7 + addl %ebp,%edi + xorl %ebx,%esi + psrld $30,%xmm1 + xorl %ecx,%ebx + addl %eax,%edi + addl 56(%esp),%edx + andl %ebx,%esi + xorl %ecx,%ebx + rorl $7,%eax + por %xmm1,%xmm7 + movl %edi,%ebp + xorl %ebx,%esi + movdqa 64(%esp),%xmm1 + roll $5,%edi + addl %esi,%edx + xorl %eax,%ebp + xorl %ebx,%eax + addl %edi,%edx + pshufd $238,%xmm6,%xmm2 + addl 60(%esp),%ecx + andl %eax,%ebp + xorl %ebx,%eax + rorl $7,%edi + movl %edx,%esi + xorl %eax,%ebp + roll $5,%edx + addl %ebp,%ecx + xorl %edi,%esi + xorl %eax,%edi + addl %edx,%ecx + addl (%esp),%ebx + pxor %xmm4,%xmm0 + punpcklqdq %xmm7,%xmm2 + andl %edi,%esi + xorl %eax,%edi + rorl $7,%edx + pxor %xmm1,%xmm0 + movdqa %xmm4,64(%esp) + movl %ecx,%ebp + xorl %edi,%esi + roll $5,%ecx + movdqa %xmm3,%xmm4 + addl %esi,%ebx + paddd %xmm7,%xmm3 + xorl %edx,%ebp + pxor %xmm2,%xmm0 + xorl %edi,%edx + addl %ecx,%ebx + addl 4(%esp),%eax + andl %edx,%ebp + movdqa %xmm0,%xmm2 + movdqa %xmm3,48(%esp) + xorl %edi,%edx + rorl $7,%ecx + movl %ebx,%esi + xorl %edx,%ebp + roll $5,%ebx + pslld $2,%xmm0 + addl %ebp,%eax + xorl %ecx,%esi + psrld $30,%xmm2 + xorl %edx,%ecx + addl %ebx,%eax + addl 8(%esp),%edi + andl %ecx,%esi + xorl %edx,%ecx + rorl $7,%ebx + por %xmm2,%xmm0 + movl %eax,%ebp + xorl %ecx,%esi + movdqa 80(%esp),%xmm2 + roll $5,%eax + addl %esi,%edi + xorl %ebx,%ebp + xorl %ecx,%ebx + addl %eax,%edi + pshufd $238,%xmm7,%xmm3 + addl 12(%esp),%edx + andl %ebx,%ebp + xorl %ecx,%ebx + rorl $7,%eax + movl %edi,%esi + xorl %ebx,%ebp + roll $5,%edi + addl %ebp,%edx + xorl %eax,%esi + xorl %ebx,%eax + addl %edi,%edx + addl 16(%esp),%ecx + pxor %xmm5,%xmm1 + punpcklqdq %xmm0,%xmm3 + andl %eax,%esi + xorl %ebx,%eax + rorl $7,%edi + pxor %xmm2,%xmm1 + movdqa %xmm5,80(%esp) + movl %edx,%ebp + xorl %eax,%esi + roll $5,%edx + movdqa %xmm4,%xmm5 + addl %esi,%ecx + paddd %xmm0,%xmm4 + xorl %edi,%ebp + pxor %xmm3,%xmm1 + xorl %eax,%edi + addl %edx,%ecx + addl 20(%esp),%ebx + andl %edi,%ebp + movdqa %xmm1,%xmm3 + movdqa %xmm4,(%esp) + xorl %eax,%edi + rorl $7,%edx + movl %ecx,%esi + xorl %edi,%ebp + roll $5,%ecx + pslld $2,%xmm1 + addl %ebp,%ebx + xorl %edx,%esi + psrld $30,%xmm3 + xorl %edi,%edx + addl %ecx,%ebx + addl 24(%esp),%eax + andl %edx,%esi + xorl %edi,%edx + rorl $7,%ecx + por %xmm3,%xmm1 + movl %ebx,%ebp + xorl %edx,%esi + movdqa 96(%esp),%xmm3 + roll $5,%ebx + addl %esi,%eax + xorl %ecx,%ebp + xorl %edx,%ecx + addl %ebx,%eax + pshufd $238,%xmm0,%xmm4 + addl 28(%esp),%edi + andl %ecx,%ebp + xorl %edx,%ecx + rorl $7,%ebx + movl %eax,%esi + xorl %ecx,%ebp + roll $5,%eax + addl %ebp,%edi + xorl %ebx,%esi + xorl %ecx,%ebx + addl %eax,%edi + addl 32(%esp),%edx + pxor %xmm6,%xmm2 + punpcklqdq %xmm1,%xmm4 + andl %ebx,%esi + xorl %ecx,%ebx + rorl $7,%eax + pxor %xmm3,%xmm2 + movdqa %xmm6,96(%esp) + movl %edi,%ebp + xorl %ebx,%esi + roll $5,%edi + movdqa %xmm5,%xmm6 + addl %esi,%edx + paddd %xmm1,%xmm5 + xorl %eax,%ebp + pxor %xmm4,%xmm2 + xorl %ebx,%eax + addl %edi,%edx + addl 36(%esp),%ecx + andl %eax,%ebp + movdqa %xmm2,%xmm4 + movdqa %xmm5,16(%esp) + xorl %ebx,%eax + rorl $7,%edi + movl %edx,%esi + xorl %eax,%ebp + roll $5,%edx + pslld $2,%xmm2 + addl %ebp,%ecx + xorl %edi,%esi + psrld $30,%xmm4 + xorl %eax,%edi + addl %edx,%ecx + addl 40(%esp),%ebx + andl %edi,%esi + xorl %eax,%edi + rorl $7,%edx + por %xmm4,%xmm2 + movl %ecx,%ebp + xorl %edi,%esi + movdqa 64(%esp),%xmm4 + roll $5,%ecx + addl %esi,%ebx + xorl %edx,%ebp + xorl %edi,%edx + addl %ecx,%ebx + pshufd $238,%xmm1,%xmm5 + addl 44(%esp),%eax + andl %edx,%ebp + xorl %edi,%edx + rorl $7,%ecx + movl %ebx,%esi + xorl %edx,%ebp + roll $5,%ebx + addl %ebp,%eax + xorl %edx,%esi + addl %ebx,%eax + addl 48(%esp),%edi + pxor %xmm7,%xmm3 + punpcklqdq %xmm2,%xmm5 + xorl %ecx,%esi + movl %eax,%ebp + roll $5,%eax + pxor %xmm4,%xmm3 + movdqa %xmm7,64(%esp) + addl %esi,%edi + xorl %ecx,%ebp + movdqa %xmm6,%xmm7 + rorl $7,%ebx + paddd %xmm2,%xmm6 + addl %eax,%edi + pxor %xmm5,%xmm3 + addl 52(%esp),%edx + xorl %ebx,%ebp + movl %edi,%esi + roll $5,%edi + movdqa %xmm3,%xmm5 + movdqa %xmm6,32(%esp) + addl %ebp,%edx + xorl %ebx,%esi + rorl $7,%eax + addl %edi,%edx + pslld $2,%xmm3 + addl 56(%esp),%ecx + xorl %eax,%esi + psrld $30,%xmm5 + movl %edx,%ebp + roll $5,%edx + addl %esi,%ecx + xorl %eax,%ebp + rorl $7,%edi + addl %edx,%ecx + por %xmm5,%xmm3 + addl 60(%esp),%ebx + xorl %edi,%ebp + movl %ecx,%esi + roll $5,%ecx + addl %ebp,%ebx + xorl %edi,%esi + rorl $7,%edx + addl %ecx,%ebx + addl (%esp),%eax + xorl %edx,%esi + movl %ebx,%ebp + roll $5,%ebx + addl %esi,%eax + xorl %edx,%ebp + rorl $7,%ecx + paddd %xmm3,%xmm7 + addl %ebx,%eax + addl 4(%esp),%edi + xorl %ecx,%ebp + movl %eax,%esi + movdqa %xmm7,48(%esp) + roll $5,%eax + addl %ebp,%edi + xorl %ecx,%esi + rorl $7,%ebx + addl %eax,%edi + addl 8(%esp),%edx + xorl %ebx,%esi + movl %edi,%ebp + roll $5,%edi + addl %esi,%edx + xorl %ebx,%ebp + rorl $7,%eax + addl %edi,%edx + addl 12(%esp),%ecx + xorl %eax,%ebp + movl %edx,%esi + roll $5,%edx + addl %ebp,%ecx + xorl %eax,%esi + rorl $7,%edi + addl %edx,%ecx + movl 196(%esp),%ebp + cmpl 200(%esp),%ebp + je L007done + movdqa 160(%esp),%xmm7 + movdqa 176(%esp),%xmm6 + movdqu (%ebp),%xmm0 + movdqu 16(%ebp),%xmm1 + movdqu 32(%ebp),%xmm2 + movdqu 48(%ebp),%xmm3 + addl $64,%ebp +.byte 102,15,56,0,198 + movl %ebp,196(%esp) + movdqa %xmm7,96(%esp) + addl 16(%esp),%ebx + xorl %edi,%esi + movl %ecx,%ebp + roll $5,%ecx + addl %esi,%ebx + xorl %edi,%ebp + rorl $7,%edx +.byte 102,15,56,0,206 + addl %ecx,%ebx + addl 20(%esp),%eax + xorl %edx,%ebp + movl %ebx,%esi + paddd %xmm7,%xmm0 + roll $5,%ebx + addl %ebp,%eax + xorl %edx,%esi + rorl $7,%ecx + movdqa %xmm0,(%esp) + addl %ebx,%eax + addl 24(%esp),%edi + xorl %ecx,%esi + movl %eax,%ebp + psubd %xmm7,%xmm0 + roll $5,%eax + addl %esi,%edi + xorl %ecx,%ebp + rorl $7,%ebx + addl %eax,%edi + addl 28(%esp),%edx + xorl %ebx,%ebp + movl %edi,%esi + roll $5,%edi + addl %ebp,%edx + xorl %ebx,%esi + rorl $7,%eax + addl %edi,%edx + addl 32(%esp),%ecx + xorl %eax,%esi + movl %edx,%ebp + roll $5,%edx + addl %esi,%ecx + xorl %eax,%ebp + rorl $7,%edi +.byte 102,15,56,0,214 + addl %edx,%ecx + addl 36(%esp),%ebx + xorl %edi,%ebp + movl %ecx,%esi + paddd %xmm7,%xmm1 + roll $5,%ecx + addl %ebp,%ebx + xorl %edi,%esi + rorl $7,%edx + movdqa %xmm1,16(%esp) + addl %ecx,%ebx + addl 40(%esp),%eax + xorl %edx,%esi + movl %ebx,%ebp + psubd %xmm7,%xmm1 + roll $5,%ebx + addl %esi,%eax + xorl %edx,%ebp + rorl $7,%ecx + addl %ebx,%eax + addl 44(%esp),%edi + xorl %ecx,%ebp + movl %eax,%esi + roll $5,%eax + addl %ebp,%edi + xorl %ecx,%esi + rorl $7,%ebx + addl %eax,%edi + addl 48(%esp),%edx + xorl %ebx,%esi + movl %edi,%ebp + roll $5,%edi + addl %esi,%edx + xorl %ebx,%ebp + rorl $7,%eax +.byte 102,15,56,0,222 + addl %edi,%edx + addl 52(%esp),%ecx + xorl %eax,%ebp + movl %edx,%esi + paddd %xmm7,%xmm2 + roll $5,%edx + addl %ebp,%ecx + xorl %eax,%esi + rorl $7,%edi + movdqa %xmm2,32(%esp) + addl %edx,%ecx + addl 56(%esp),%ebx + xorl %edi,%esi + movl %ecx,%ebp + psubd %xmm7,%xmm2 + roll $5,%ecx + addl %esi,%ebx + xorl %edi,%ebp + rorl $7,%edx + addl %ecx,%ebx + addl 60(%esp),%eax + xorl %edx,%ebp + movl %ebx,%esi + roll $5,%ebx + addl %ebp,%eax + rorl $7,%ecx + addl %ebx,%eax + movl 192(%esp),%ebp + addl (%ebp),%eax + addl 4(%ebp),%esi + addl 8(%ebp),%ecx + movl %eax,(%ebp) + addl 12(%ebp),%edx + movl %esi,4(%ebp) + addl 16(%ebp),%edi + movl %ecx,8(%ebp) + movl %ecx,%ebx + movl %edx,12(%ebp) + xorl %edx,%ebx + movl %edi,16(%ebp) + movl %esi,%ebp + pshufd $238,%xmm0,%xmm4 + andl %ebx,%esi + movl %ebp,%ebx + jmp L006loop +.align 4,0x90 +L007done: + addl 16(%esp),%ebx + xorl %edi,%esi + movl %ecx,%ebp + roll $5,%ecx + addl %esi,%ebx + xorl %edi,%ebp + rorl $7,%edx + addl %ecx,%ebx + addl 20(%esp),%eax + xorl %edx,%ebp + movl %ebx,%esi + roll $5,%ebx + addl %ebp,%eax + xorl %edx,%esi + rorl $7,%ecx + addl %ebx,%eax + addl 24(%esp),%edi + xorl %ecx,%esi + movl %eax,%ebp + roll $5,%eax + addl %esi,%edi + xorl %ecx,%ebp + rorl $7,%ebx + addl %eax,%edi + addl 28(%esp),%edx + xorl %ebx,%ebp + movl %edi,%esi + roll $5,%edi + addl %ebp,%edx + xorl %ebx,%esi + rorl $7,%eax + addl %edi,%edx + addl 32(%esp),%ecx + xorl %eax,%esi + movl %edx,%ebp + roll $5,%edx + addl %esi,%ecx + xorl %eax,%ebp + rorl $7,%edi + addl %edx,%ecx + addl 36(%esp),%ebx + xorl %edi,%ebp + movl %ecx,%esi + roll $5,%ecx + addl %ebp,%ebx + xorl %edi,%esi + rorl $7,%edx + addl %ecx,%ebx + addl 40(%esp),%eax + xorl %edx,%esi + movl %ebx,%ebp + roll $5,%ebx + addl %esi,%eax + xorl %edx,%ebp + rorl $7,%ecx + addl %ebx,%eax + addl 44(%esp),%edi + xorl %ecx,%ebp + movl %eax,%esi + roll $5,%eax + addl %ebp,%edi + xorl %ecx,%esi + rorl $7,%ebx + addl %eax,%edi + addl 48(%esp),%edx + xorl %ebx,%esi + movl %edi,%ebp + roll $5,%edi + addl %esi,%edx + xorl %ebx,%ebp + rorl $7,%eax + addl %edi,%edx + addl 52(%esp),%ecx + xorl %eax,%ebp + movl %edx,%esi + roll $5,%edx + addl %ebp,%ecx + xorl %eax,%esi + rorl $7,%edi + addl %edx,%ecx + addl 56(%esp),%ebx + xorl %edi,%esi + movl %ecx,%ebp + roll $5,%ecx + addl %esi,%ebx + xorl %edi,%ebp + rorl $7,%edx + addl %ecx,%ebx + addl 60(%esp),%eax + xorl %edx,%ebp + movl %ebx,%esi + roll $5,%ebx + addl %ebp,%eax + rorl $7,%ecx + addl %ebx,%eax + movl 192(%esp),%ebp + addl (%ebp),%eax + movl 204(%esp),%esp + addl 4(%ebp),%esi + addl 8(%ebp),%ecx + movl %eax,(%ebp) + addl 12(%ebp),%edx + movl %esi,4(%ebp) + addl 16(%ebp),%edi + movl %ecx,8(%ebp) + movl %edx,12(%ebp) + movl %edi,16(%ebp) + popl %edi + popl %esi + popl %ebx + popl %ebp + ret +.align 6,0x90 +LK_XX_XX: +.long 1518500249,1518500249,1518500249,1518500249 +.long 1859775393,1859775393,1859775393,1859775393 +.long 2400959708,2400959708,2400959708,2400959708 +.long 3395469782,3395469782,3395469782,3395469782 +.long 66051,67438087,134810123,202182159 +.byte 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 .byte 83,72,65,49,32,98,108,111,99,107,32,116,114,97,110,115 .byte 102,111,114,109,32,102,111,114,32,120,56,54,44,32,67,82 .byte 89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112 .byte 114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0 +.section __IMPORT,__pointers,non_lazy_symbol_pointers +L_OPENSSL_ia32cap_P$non_lazy_ptr: +.indirect_symbol _OPENSSL_ia32cap_P +.long 0 #endif diff --git a/third_party/boringssl/mac-x86/crypto/sha/sha256-586.S b/third_party/boringssl/mac-x86/crypto/sha/sha256-586.S index d40db0d4413ea..f0ba612fabb90 100644 --- a/third_party/boringssl/mac-x86/crypto/sha/sha256-586.S +++ b/third_party/boringssl/mac-x86/crypto/sha/sha256-586.S @@ -26,6 +26,27 @@ L000pic_point: movl %edi,4(%esp) movl %eax,8(%esp) movl %ebx,12(%esp) + movl L_OPENSSL_ia32cap_P$non_lazy_ptr-L001K256(%ebp),%edx + movl (%edx),%ecx + movl 4(%edx),%ebx + testl $1048576,%ecx + jnz L002loop + movl 8(%edx),%edx + testl $16777216,%ecx + jz L003no_xmm + andl $1073741824,%ecx + andl $268435968,%ebx + testl $536870912,%edx + jnz L004shaext + orl %ebx,%ecx + andl $1342177280,%ecx + cmpl $1342177280,%ecx + testl $512,%ebx + jnz L005SSSE3 +L003no_xmm: + subl %edi,%eax + cmpl $256,%eax + jae L006unrolled jmp L002loop .align 4,0x90 L002loop: @@ -97,7 +118,7 @@ L002loop: movl %ecx,28(%esp) movl %edi,32(%esp) .align 4,0x90 -L00300_15: +L00700_15: movl %edx,%ecx movl 24(%esp),%esi rorl $14,%ecx @@ -135,11 +156,11 @@ L00300_15: addl $4,%ebp addl %ebx,%eax cmpl $3248222580,%esi - jne L00300_15 + jne L00700_15 movl 156(%esp),%ecx - jmp L00416_63 + jmp L00816_63 .align 4,0x90 -L00416_63: +L00816_63: movl %ecx,%ebx movl 104(%esp),%esi rorl $11,%ecx @@ -194,7 +215,7 @@ L00416_63: addl $4,%ebp addl %ebx,%eax cmpl $3329325298,%esi - jne L00416_63 + jne L00816_63 movl 356(%esp),%esi movl 8(%esp),%ebx movl 16(%esp),%ecx @@ -228,207 +249,6 @@ L00416_63: popl %ebx popl %ebp ret -.align 5,0x90 -L005loop_shrd: - movl (%edi),%eax - movl 4(%edi),%ebx - movl 8(%edi),%ecx - bswap %eax - movl 12(%edi),%edx - bswap %ebx - pushl %eax - bswap %ecx - pushl %ebx - bswap %edx - pushl %ecx - pushl %edx - movl 16(%edi),%eax - movl 20(%edi),%ebx - movl 24(%edi),%ecx - bswap %eax - movl 28(%edi),%edx - bswap %ebx - pushl %eax - bswap %ecx - pushl %ebx - bswap %edx - pushl %ecx - pushl %edx - movl 32(%edi),%eax - movl 36(%edi),%ebx - movl 40(%edi),%ecx - bswap %eax - movl 44(%edi),%edx - bswap %ebx - pushl %eax - bswap %ecx - pushl %ebx - bswap %edx - pushl %ecx - pushl %edx - movl 48(%edi),%eax - movl 52(%edi),%ebx - movl 56(%edi),%ecx - bswap %eax - movl 60(%edi),%edx - bswap %ebx - pushl %eax - bswap %ecx - pushl %ebx - bswap %edx - pushl %ecx - pushl %edx - addl $64,%edi - leal -36(%esp),%esp - movl %edi,104(%esp) - movl (%esi),%eax - movl 4(%esi),%ebx - movl 8(%esi),%ecx - movl 12(%esi),%edi - movl %ebx,8(%esp) - xorl %ecx,%ebx - movl %ecx,12(%esp) - movl %edi,16(%esp) - movl %ebx,(%esp) - movl 16(%esi),%edx - movl 20(%esi),%ebx - movl 24(%esi),%ecx - movl 28(%esi),%edi - movl %ebx,24(%esp) - movl %ecx,28(%esp) - movl %edi,32(%esp) -.align 4,0x90 -L00600_15_shrd: - movl %edx,%ecx - movl 24(%esp),%esi - shrdl $14,%ecx,%ecx - movl 28(%esp),%edi - xorl %edx,%ecx - xorl %edi,%esi - movl 96(%esp),%ebx - shrdl $5,%ecx,%ecx - andl %edx,%esi - movl %edx,20(%esp) - xorl %ecx,%edx - addl 32(%esp),%ebx - xorl %edi,%esi - shrdl $6,%edx,%edx - movl %eax,%ecx - addl %esi,%ebx - shrdl $9,%ecx,%ecx - addl %edx,%ebx - movl 8(%esp),%edi - xorl %eax,%ecx - movl %eax,4(%esp) - leal -4(%esp),%esp - shrdl $11,%ecx,%ecx - movl (%ebp),%esi - xorl %eax,%ecx - movl 20(%esp),%edx - xorl %edi,%eax - shrdl $2,%ecx,%ecx - addl %esi,%ebx - movl %eax,(%esp) - addl %ebx,%edx - andl 4(%esp),%eax - addl %ecx,%ebx - xorl %edi,%eax - addl $4,%ebp - addl %ebx,%eax - cmpl $3248222580,%esi - jne L00600_15_shrd - movl 156(%esp),%ecx - jmp L00716_63_shrd -.align 4,0x90 -L00716_63_shrd: - movl %ecx,%ebx - movl 104(%esp),%esi - shrdl $11,%ecx,%ecx - movl %esi,%edi - shrdl $2,%esi,%esi - xorl %ebx,%ecx - shrl $3,%ebx - shrdl $7,%ecx,%ecx - xorl %edi,%esi - xorl %ecx,%ebx - shrdl $17,%esi,%esi - addl 160(%esp),%ebx - shrl $10,%edi - addl 124(%esp),%ebx - movl %edx,%ecx - xorl %esi,%edi - movl 24(%esp),%esi - shrdl $14,%ecx,%ecx - addl %edi,%ebx - movl 28(%esp),%edi - xorl %edx,%ecx - xorl %edi,%esi - movl %ebx,96(%esp) - shrdl $5,%ecx,%ecx - andl %edx,%esi - movl %edx,20(%esp) - xorl %ecx,%edx - addl 32(%esp),%ebx - xorl %edi,%esi - shrdl $6,%edx,%edx - movl %eax,%ecx - addl %esi,%ebx - shrdl $9,%ecx,%ecx - addl %edx,%ebx - movl 8(%esp),%edi - xorl %eax,%ecx - movl %eax,4(%esp) - leal -4(%esp),%esp - shrdl $11,%ecx,%ecx - movl (%ebp),%esi - xorl %eax,%ecx - movl 20(%esp),%edx - xorl %edi,%eax - shrdl $2,%ecx,%ecx - addl %esi,%ebx - movl %eax,(%esp) - addl %ebx,%edx - andl 4(%esp),%eax - addl %ecx,%ebx - xorl %edi,%eax - movl 156(%esp),%ecx - addl $4,%ebp - addl %ebx,%eax - cmpl $3329325298,%esi - jne L00716_63_shrd - movl 356(%esp),%esi - movl 8(%esp),%ebx - movl 16(%esp),%ecx - addl (%esi),%eax - addl 4(%esi),%ebx - addl 8(%esi),%edi - addl 12(%esi),%ecx - movl %eax,(%esi) - movl %ebx,4(%esi) - movl %edi,8(%esi) - movl %ecx,12(%esi) - movl 24(%esp),%eax - movl 28(%esp),%ebx - movl 32(%esp),%ecx - movl 360(%esp),%edi - addl 16(%esi),%edx - addl 20(%esi),%eax - addl 24(%esi),%ebx - addl 28(%esi),%ecx - movl %edx,16(%esi) - movl %eax,20(%esi) - movl %ebx,24(%esi) - movl %ecx,28(%esi) - leal 356(%esp),%esp - subl $256,%ebp - cmpl 8(%esp),%edi - jb L005loop_shrd - movl 12(%esp),%esp - popl %edi - popl %esi - popl %ebx - popl %ebp - ret .align 6,0x90 L001K256: .long 1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298 @@ -439,7 +259,7 @@ L001K256: .byte 112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103 .byte 62,0 .align 4,0x90 -L008unrolled: +L006unrolled: leal -96(%esp),%esp movl (%esi),%eax movl 4(%esi),%ebp @@ -3345,4 +3165,1417 @@ L009grand_loop: popl %ebx popl %ebp ret +.align 5,0x90 +L004shaext: + subl $32,%esp + movdqu (%esi),%xmm1 + leal 128(%ebp),%ebp + movdqu 16(%esi),%xmm2 + movdqa 128(%ebp),%xmm7 + pshufd $27,%xmm1,%xmm0 + pshufd $177,%xmm1,%xmm1 + pshufd $27,%xmm2,%xmm2 +.byte 102,15,58,15,202,8 + punpcklqdq %xmm0,%xmm2 + jmp L010loop_shaext +.align 4,0x90 +L010loop_shaext: + movdqu (%edi),%xmm3 + movdqu 16(%edi),%xmm4 + movdqu 32(%edi),%xmm5 +.byte 102,15,56,0,223 + movdqu 48(%edi),%xmm6 + movdqa %xmm2,16(%esp) + movdqa -128(%ebp),%xmm0 + paddd %xmm3,%xmm0 +.byte 102,15,56,0,231 +.byte 15,56,203,209 + pshufd $14,%xmm0,%xmm0 + nop + movdqa %xmm1,(%esp) +.byte 15,56,203,202 + movdqa -112(%ebp),%xmm0 + paddd %xmm4,%xmm0 +.byte 102,15,56,0,239 +.byte 15,56,203,209 + pshufd $14,%xmm0,%xmm0 + leal 64(%edi),%edi +.byte 15,56,204,220 +.byte 15,56,203,202 + movdqa -96(%ebp),%xmm0 + paddd %xmm5,%xmm0 +.byte 102,15,56,0,247 +.byte 15,56,203,209 + pshufd $14,%xmm0,%xmm0 + movdqa %xmm6,%xmm7 +.byte 102,15,58,15,253,4 + nop + paddd %xmm7,%xmm3 +.byte 15,56,204,229 +.byte 15,56,203,202 + movdqa -80(%ebp),%xmm0 + paddd %xmm6,%xmm0 +.byte 15,56,205,222 +.byte 15,56,203,209 + pshufd $14,%xmm0,%xmm0 + movdqa %xmm3,%xmm7 +.byte 102,15,58,15,254,4 + nop + paddd %xmm7,%xmm4 +.byte 15,56,204,238 +.byte 15,56,203,202 + movdqa -64(%ebp),%xmm0 + paddd %xmm3,%xmm0 +.byte 15,56,205,227 +.byte 15,56,203,209 + pshufd $14,%xmm0,%xmm0 + movdqa %xmm4,%xmm7 +.byte 102,15,58,15,251,4 + nop + paddd %xmm7,%xmm5 +.byte 15,56,204,243 +.byte 15,56,203,202 + movdqa -48(%ebp),%xmm0 + paddd %xmm4,%xmm0 +.byte 15,56,205,236 +.byte 15,56,203,209 + pshufd $14,%xmm0,%xmm0 + movdqa %xmm5,%xmm7 +.byte 102,15,58,15,252,4 + nop + paddd %xmm7,%xmm6 +.byte 15,56,204,220 +.byte 15,56,203,202 + movdqa -32(%ebp),%xmm0 + paddd %xmm5,%xmm0 +.byte 15,56,205,245 +.byte 15,56,203,209 + pshufd $14,%xmm0,%xmm0 + movdqa %xmm6,%xmm7 +.byte 102,15,58,15,253,4 + nop + paddd %xmm7,%xmm3 +.byte 15,56,204,229 +.byte 15,56,203,202 + movdqa -16(%ebp),%xmm0 + paddd %xmm6,%xmm0 +.byte 15,56,205,222 +.byte 15,56,203,209 + pshufd $14,%xmm0,%xmm0 + movdqa %xmm3,%xmm7 +.byte 102,15,58,15,254,4 + nop + paddd %xmm7,%xmm4 +.byte 15,56,204,238 +.byte 15,56,203,202 + movdqa (%ebp),%xmm0 + paddd %xmm3,%xmm0 +.byte 15,56,205,227 +.byte 15,56,203,209 + pshufd $14,%xmm0,%xmm0 + movdqa %xmm4,%xmm7 +.byte 102,15,58,15,251,4 + nop + paddd %xmm7,%xmm5 +.byte 15,56,204,243 +.byte 15,56,203,202 + movdqa 16(%ebp),%xmm0 + paddd %xmm4,%xmm0 +.byte 15,56,205,236 +.byte 15,56,203,209 + pshufd $14,%xmm0,%xmm0 + movdqa %xmm5,%xmm7 +.byte 102,15,58,15,252,4 + nop + paddd %xmm7,%xmm6 +.byte 15,56,204,220 +.byte 15,56,203,202 + movdqa 32(%ebp),%xmm0 + paddd %xmm5,%xmm0 +.byte 15,56,205,245 +.byte 15,56,203,209 + pshufd $14,%xmm0,%xmm0 + movdqa %xmm6,%xmm7 +.byte 102,15,58,15,253,4 + nop + paddd %xmm7,%xmm3 +.byte 15,56,204,229 +.byte 15,56,203,202 + movdqa 48(%ebp),%xmm0 + paddd %xmm6,%xmm0 +.byte 15,56,205,222 +.byte 15,56,203,209 + pshufd $14,%xmm0,%xmm0 + movdqa %xmm3,%xmm7 +.byte 102,15,58,15,254,4 + nop + paddd %xmm7,%xmm4 +.byte 15,56,204,238 +.byte 15,56,203,202 + movdqa 64(%ebp),%xmm0 + paddd %xmm3,%xmm0 +.byte 15,56,205,227 +.byte 15,56,203,209 + pshufd $14,%xmm0,%xmm0 + movdqa %xmm4,%xmm7 +.byte 102,15,58,15,251,4 + nop + paddd %xmm7,%xmm5 +.byte 15,56,204,243 +.byte 15,56,203,202 + movdqa 80(%ebp),%xmm0 + paddd %xmm4,%xmm0 +.byte 15,56,205,236 +.byte 15,56,203,209 + pshufd $14,%xmm0,%xmm0 + movdqa %xmm5,%xmm7 +.byte 102,15,58,15,252,4 +.byte 15,56,203,202 + paddd %xmm7,%xmm6 + movdqa 96(%ebp),%xmm0 + paddd %xmm5,%xmm0 +.byte 15,56,203,209 + pshufd $14,%xmm0,%xmm0 +.byte 15,56,205,245 + movdqa 128(%ebp),%xmm7 +.byte 15,56,203,202 + movdqa 112(%ebp),%xmm0 + paddd %xmm6,%xmm0 + nop +.byte 15,56,203,209 + pshufd $14,%xmm0,%xmm0 + cmpl %edi,%eax + nop +.byte 15,56,203,202 + paddd 16(%esp),%xmm2 + paddd (%esp),%xmm1 + jnz L010loop_shaext + pshufd $177,%xmm2,%xmm2 + pshufd $27,%xmm1,%xmm7 + pshufd $177,%xmm1,%xmm1 + punpckhqdq %xmm2,%xmm1 +.byte 102,15,58,15,215,8 + movl 44(%esp),%esp + movdqu %xmm1,(%esi) + movdqu %xmm2,16(%esi) + popl %edi + popl %esi + popl %ebx + popl %ebp + ret +.align 5,0x90 +L005SSSE3: + leal -96(%esp),%esp + movl (%esi),%eax + movl 4(%esi),%ebx + movl 8(%esi),%ecx + movl 12(%esi),%edi + movl %ebx,4(%esp) + xorl %ecx,%ebx + movl %ecx,8(%esp) + movl %edi,12(%esp) + movl 16(%esi),%edx + movl 20(%esi),%edi + movl 24(%esi),%ecx + movl 28(%esi),%esi + movl %edi,20(%esp) + movl 100(%esp),%edi + movl %ecx,24(%esp) + movl %esi,28(%esp) + movdqa 256(%ebp),%xmm7 + jmp L011grand_ssse3 +.align 4,0x90 +L011grand_ssse3: + movdqu (%edi),%xmm0 + movdqu 16(%edi),%xmm1 + movdqu 32(%edi),%xmm2 + movdqu 48(%edi),%xmm3 + addl $64,%edi +.byte 102,15,56,0,199 + movl %edi,100(%esp) +.byte 102,15,56,0,207 + movdqa (%ebp),%xmm4 +.byte 102,15,56,0,215 + movdqa 16(%ebp),%xmm5 + paddd %xmm0,%xmm4 +.byte 102,15,56,0,223 + movdqa 32(%ebp),%xmm6 + paddd %xmm1,%xmm5 + movdqa 48(%ebp),%xmm7 + movdqa %xmm4,32(%esp) + paddd %xmm2,%xmm6 + movdqa %xmm5,48(%esp) + paddd %xmm3,%xmm7 + movdqa %xmm6,64(%esp) + movdqa %xmm7,80(%esp) + jmp L012ssse3_00_47 +.align 4,0x90 +L012ssse3_00_47: + addl $64,%ebp + movl %edx,%ecx + movdqa %xmm1,%xmm4 + rorl $14,%edx + movl 20(%esp),%esi + movdqa %xmm3,%xmm7 + xorl %ecx,%edx + movl 24(%esp),%edi +.byte 102,15,58,15,224,4 + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi +.byte 102,15,58,15,250,4 + movl %ecx,16(%esp) + xorl %ecx,%edx + xorl %esi,%edi + movdqa %xmm4,%xmm5 + rorl $6,%edx + movl %eax,%ecx + movdqa %xmm4,%xmm6 + addl %edi,%edx + movl 4(%esp),%edi + psrld $3,%xmm4 + movl %eax,%esi + rorl $9,%ecx + paddd %xmm7,%xmm0 + movl %eax,(%esp) + xorl %eax,%ecx + psrld $7,%xmm6 + xorl %edi,%eax + addl 28(%esp),%edx + rorl $11,%ecx + andl %eax,%ebx + pshufd $250,%xmm3,%xmm7 + xorl %esi,%ecx + addl 32(%esp),%edx + pslld $14,%xmm5 + xorl %edi,%ebx + rorl $2,%ecx + pxor %xmm6,%xmm4 + addl %edx,%ebx + addl 12(%esp),%edx + psrld $11,%xmm6 + addl %ecx,%ebx + movl %edx,%ecx + rorl $14,%edx + pxor %xmm5,%xmm4 + movl 16(%esp),%esi + xorl %ecx,%edx + pslld $11,%xmm5 + movl 20(%esp),%edi + xorl %edi,%esi + rorl $5,%edx + pxor %xmm6,%xmm4 + andl %ecx,%esi + movl %ecx,12(%esp) + movdqa %xmm7,%xmm6 + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + pxor %xmm5,%xmm4 + movl %ebx,%ecx + addl %edi,%edx + psrld $10,%xmm7 + movl (%esp),%edi + movl %ebx,%esi + rorl $9,%ecx + paddd %xmm4,%xmm0 + movl %ebx,28(%esp) + xorl %ebx,%ecx + psrlq $17,%xmm6 + xorl %edi,%ebx + addl 24(%esp),%edx + rorl $11,%ecx + pxor %xmm6,%xmm7 + andl %ebx,%eax + xorl %esi,%ecx + psrlq $2,%xmm6 + addl 36(%esp),%edx + xorl %edi,%eax + rorl $2,%ecx + pxor %xmm6,%xmm7 + addl %edx,%eax + addl 8(%esp),%edx + pshufd $128,%xmm7,%xmm7 + addl %ecx,%eax + movl %edx,%ecx + rorl $14,%edx + movl 12(%esp),%esi + xorl %ecx,%edx + movl 16(%esp),%edi + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi + psrldq $8,%xmm7 + movl %ecx,8(%esp) + xorl %ecx,%edx + xorl %esi,%edi + paddd %xmm7,%xmm0 + rorl $6,%edx + movl %eax,%ecx + addl %edi,%edx + movl 28(%esp),%edi + movl %eax,%esi + rorl $9,%ecx + movl %eax,24(%esp) + pshufd $80,%xmm0,%xmm7 + xorl %eax,%ecx + xorl %edi,%eax + addl 20(%esp),%edx + movdqa %xmm7,%xmm6 + rorl $11,%ecx + psrld $10,%xmm7 + andl %eax,%ebx + psrlq $17,%xmm6 + xorl %esi,%ecx + addl 40(%esp),%edx + xorl %edi,%ebx + rorl $2,%ecx + pxor %xmm6,%xmm7 + addl %edx,%ebx + addl 4(%esp),%edx + psrlq $2,%xmm6 + addl %ecx,%ebx + movl %edx,%ecx + rorl $14,%edx + pxor %xmm6,%xmm7 + movl 8(%esp),%esi + xorl %ecx,%edx + movl 12(%esp),%edi + pshufd $8,%xmm7,%xmm7 + xorl %edi,%esi + rorl $5,%edx + movdqa (%ebp),%xmm6 + andl %ecx,%esi + movl %ecx,4(%esp) + pslldq $8,%xmm7 + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + movl %ebx,%ecx + addl %edi,%edx + movl 24(%esp),%edi + movl %ebx,%esi + rorl $9,%ecx + paddd %xmm7,%xmm0 + movl %ebx,20(%esp) + xorl %ebx,%ecx + xorl %edi,%ebx + addl 16(%esp),%edx + paddd %xmm0,%xmm6 + rorl $11,%ecx + andl %ebx,%eax + xorl %esi,%ecx + addl 44(%esp),%edx + xorl %edi,%eax + rorl $2,%ecx + addl %edx,%eax + addl (%esp),%edx + addl %ecx,%eax + movdqa %xmm6,32(%esp) + movl %edx,%ecx + movdqa %xmm2,%xmm4 + rorl $14,%edx + movl 4(%esp),%esi + movdqa %xmm0,%xmm7 + xorl %ecx,%edx + movl 8(%esp),%edi +.byte 102,15,58,15,225,4 + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi +.byte 102,15,58,15,251,4 + movl %ecx,(%esp) + xorl %ecx,%edx + xorl %esi,%edi + movdqa %xmm4,%xmm5 + rorl $6,%edx + movl %eax,%ecx + movdqa %xmm4,%xmm6 + addl %edi,%edx + movl 20(%esp),%edi + psrld $3,%xmm4 + movl %eax,%esi + rorl $9,%ecx + paddd %xmm7,%xmm1 + movl %eax,16(%esp) + xorl %eax,%ecx + psrld $7,%xmm6 + xorl %edi,%eax + addl 12(%esp),%edx + rorl $11,%ecx + andl %eax,%ebx + pshufd $250,%xmm0,%xmm7 + xorl %esi,%ecx + addl 48(%esp),%edx + pslld $14,%xmm5 + xorl %edi,%ebx + rorl $2,%ecx + pxor %xmm6,%xmm4 + addl %edx,%ebx + addl 28(%esp),%edx + psrld $11,%xmm6 + addl %ecx,%ebx + movl %edx,%ecx + rorl $14,%edx + pxor %xmm5,%xmm4 + movl (%esp),%esi + xorl %ecx,%edx + pslld $11,%xmm5 + movl 4(%esp),%edi + xorl %edi,%esi + rorl $5,%edx + pxor %xmm6,%xmm4 + andl %ecx,%esi + movl %ecx,28(%esp) + movdqa %xmm7,%xmm6 + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + pxor %xmm5,%xmm4 + movl %ebx,%ecx + addl %edi,%edx + psrld $10,%xmm7 + movl 16(%esp),%edi + movl %ebx,%esi + rorl $9,%ecx + paddd %xmm4,%xmm1 + movl %ebx,12(%esp) + xorl %ebx,%ecx + psrlq $17,%xmm6 + xorl %edi,%ebx + addl 8(%esp),%edx + rorl $11,%ecx + pxor %xmm6,%xmm7 + andl %ebx,%eax + xorl %esi,%ecx + psrlq $2,%xmm6 + addl 52(%esp),%edx + xorl %edi,%eax + rorl $2,%ecx + pxor %xmm6,%xmm7 + addl %edx,%eax + addl 24(%esp),%edx + pshufd $128,%xmm7,%xmm7 + addl %ecx,%eax + movl %edx,%ecx + rorl $14,%edx + movl 28(%esp),%esi + xorl %ecx,%edx + movl (%esp),%edi + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi + psrldq $8,%xmm7 + movl %ecx,24(%esp) + xorl %ecx,%edx + xorl %esi,%edi + paddd %xmm7,%xmm1 + rorl $6,%edx + movl %eax,%ecx + addl %edi,%edx + movl 12(%esp),%edi + movl %eax,%esi + rorl $9,%ecx + movl %eax,8(%esp) + pshufd $80,%xmm1,%xmm7 + xorl %eax,%ecx + xorl %edi,%eax + addl 4(%esp),%edx + movdqa %xmm7,%xmm6 + rorl $11,%ecx + psrld $10,%xmm7 + andl %eax,%ebx + psrlq $17,%xmm6 + xorl %esi,%ecx + addl 56(%esp),%edx + xorl %edi,%ebx + rorl $2,%ecx + pxor %xmm6,%xmm7 + addl %edx,%ebx + addl 20(%esp),%edx + psrlq $2,%xmm6 + addl %ecx,%ebx + movl %edx,%ecx + rorl $14,%edx + pxor %xmm6,%xmm7 + movl 24(%esp),%esi + xorl %ecx,%edx + movl 28(%esp),%edi + pshufd $8,%xmm7,%xmm7 + xorl %edi,%esi + rorl $5,%edx + movdqa 16(%ebp),%xmm6 + andl %ecx,%esi + movl %ecx,20(%esp) + pslldq $8,%xmm7 + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + movl %ebx,%ecx + addl %edi,%edx + movl 8(%esp),%edi + movl %ebx,%esi + rorl $9,%ecx + paddd %xmm7,%xmm1 + movl %ebx,4(%esp) + xorl %ebx,%ecx + xorl %edi,%ebx + addl (%esp),%edx + paddd %xmm1,%xmm6 + rorl $11,%ecx + andl %ebx,%eax + xorl %esi,%ecx + addl 60(%esp),%edx + xorl %edi,%eax + rorl $2,%ecx + addl %edx,%eax + addl 16(%esp),%edx + addl %ecx,%eax + movdqa %xmm6,48(%esp) + movl %edx,%ecx + movdqa %xmm3,%xmm4 + rorl $14,%edx + movl 20(%esp),%esi + movdqa %xmm1,%xmm7 + xorl %ecx,%edx + movl 24(%esp),%edi +.byte 102,15,58,15,226,4 + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi +.byte 102,15,58,15,248,4 + movl %ecx,16(%esp) + xorl %ecx,%edx + xorl %esi,%edi + movdqa %xmm4,%xmm5 + rorl $6,%edx + movl %eax,%ecx + movdqa %xmm4,%xmm6 + addl %edi,%edx + movl 4(%esp),%edi + psrld $3,%xmm4 + movl %eax,%esi + rorl $9,%ecx + paddd %xmm7,%xmm2 + movl %eax,(%esp) + xorl %eax,%ecx + psrld $7,%xmm6 + xorl %edi,%eax + addl 28(%esp),%edx + rorl $11,%ecx + andl %eax,%ebx + pshufd $250,%xmm1,%xmm7 + xorl %esi,%ecx + addl 64(%esp),%edx + pslld $14,%xmm5 + xorl %edi,%ebx + rorl $2,%ecx + pxor %xmm6,%xmm4 + addl %edx,%ebx + addl 12(%esp),%edx + psrld $11,%xmm6 + addl %ecx,%ebx + movl %edx,%ecx + rorl $14,%edx + pxor %xmm5,%xmm4 + movl 16(%esp),%esi + xorl %ecx,%edx + pslld $11,%xmm5 + movl 20(%esp),%edi + xorl %edi,%esi + rorl $5,%edx + pxor %xmm6,%xmm4 + andl %ecx,%esi + movl %ecx,12(%esp) + movdqa %xmm7,%xmm6 + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + pxor %xmm5,%xmm4 + movl %ebx,%ecx + addl %edi,%edx + psrld $10,%xmm7 + movl (%esp),%edi + movl %ebx,%esi + rorl $9,%ecx + paddd %xmm4,%xmm2 + movl %ebx,28(%esp) + xorl %ebx,%ecx + psrlq $17,%xmm6 + xorl %edi,%ebx + addl 24(%esp),%edx + rorl $11,%ecx + pxor %xmm6,%xmm7 + andl %ebx,%eax + xorl %esi,%ecx + psrlq $2,%xmm6 + addl 68(%esp),%edx + xorl %edi,%eax + rorl $2,%ecx + pxor %xmm6,%xmm7 + addl %edx,%eax + addl 8(%esp),%edx + pshufd $128,%xmm7,%xmm7 + addl %ecx,%eax + movl %edx,%ecx + rorl $14,%edx + movl 12(%esp),%esi + xorl %ecx,%edx + movl 16(%esp),%edi + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi + psrldq $8,%xmm7 + movl %ecx,8(%esp) + xorl %ecx,%edx + xorl %esi,%edi + paddd %xmm7,%xmm2 + rorl $6,%edx + movl %eax,%ecx + addl %edi,%edx + movl 28(%esp),%edi + movl %eax,%esi + rorl $9,%ecx + movl %eax,24(%esp) + pshufd $80,%xmm2,%xmm7 + xorl %eax,%ecx + xorl %edi,%eax + addl 20(%esp),%edx + movdqa %xmm7,%xmm6 + rorl $11,%ecx + psrld $10,%xmm7 + andl %eax,%ebx + psrlq $17,%xmm6 + xorl %esi,%ecx + addl 72(%esp),%edx + xorl %edi,%ebx + rorl $2,%ecx + pxor %xmm6,%xmm7 + addl %edx,%ebx + addl 4(%esp),%edx + psrlq $2,%xmm6 + addl %ecx,%ebx + movl %edx,%ecx + rorl $14,%edx + pxor %xmm6,%xmm7 + movl 8(%esp),%esi + xorl %ecx,%edx + movl 12(%esp),%edi + pshufd $8,%xmm7,%xmm7 + xorl %edi,%esi + rorl $5,%edx + movdqa 32(%ebp),%xmm6 + andl %ecx,%esi + movl %ecx,4(%esp) + pslldq $8,%xmm7 + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + movl %ebx,%ecx + addl %edi,%edx + movl 24(%esp),%edi + movl %ebx,%esi + rorl $9,%ecx + paddd %xmm7,%xmm2 + movl %ebx,20(%esp) + xorl %ebx,%ecx + xorl %edi,%ebx + addl 16(%esp),%edx + paddd %xmm2,%xmm6 + rorl $11,%ecx + andl %ebx,%eax + xorl %esi,%ecx + addl 76(%esp),%edx + xorl %edi,%eax + rorl $2,%ecx + addl %edx,%eax + addl (%esp),%edx + addl %ecx,%eax + movdqa %xmm6,64(%esp) + movl %edx,%ecx + movdqa %xmm0,%xmm4 + rorl $14,%edx + movl 4(%esp),%esi + movdqa %xmm2,%xmm7 + xorl %ecx,%edx + movl 8(%esp),%edi +.byte 102,15,58,15,227,4 + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi +.byte 102,15,58,15,249,4 + movl %ecx,(%esp) + xorl %ecx,%edx + xorl %esi,%edi + movdqa %xmm4,%xmm5 + rorl $6,%edx + movl %eax,%ecx + movdqa %xmm4,%xmm6 + addl %edi,%edx + movl 20(%esp),%edi + psrld $3,%xmm4 + movl %eax,%esi + rorl $9,%ecx + paddd %xmm7,%xmm3 + movl %eax,16(%esp) + xorl %eax,%ecx + psrld $7,%xmm6 + xorl %edi,%eax + addl 12(%esp),%edx + rorl $11,%ecx + andl %eax,%ebx + pshufd $250,%xmm2,%xmm7 + xorl %esi,%ecx + addl 80(%esp),%edx + pslld $14,%xmm5 + xorl %edi,%ebx + rorl $2,%ecx + pxor %xmm6,%xmm4 + addl %edx,%ebx + addl 28(%esp),%edx + psrld $11,%xmm6 + addl %ecx,%ebx + movl %edx,%ecx + rorl $14,%edx + pxor %xmm5,%xmm4 + movl (%esp),%esi + xorl %ecx,%edx + pslld $11,%xmm5 + movl 4(%esp),%edi + xorl %edi,%esi + rorl $5,%edx + pxor %xmm6,%xmm4 + andl %ecx,%esi + movl %ecx,28(%esp) + movdqa %xmm7,%xmm6 + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + pxor %xmm5,%xmm4 + movl %ebx,%ecx + addl %edi,%edx + psrld $10,%xmm7 + movl 16(%esp),%edi + movl %ebx,%esi + rorl $9,%ecx + paddd %xmm4,%xmm3 + movl %ebx,12(%esp) + xorl %ebx,%ecx + psrlq $17,%xmm6 + xorl %edi,%ebx + addl 8(%esp),%edx + rorl $11,%ecx + pxor %xmm6,%xmm7 + andl %ebx,%eax + xorl %esi,%ecx + psrlq $2,%xmm6 + addl 84(%esp),%edx + xorl %edi,%eax + rorl $2,%ecx + pxor %xmm6,%xmm7 + addl %edx,%eax + addl 24(%esp),%edx + pshufd $128,%xmm7,%xmm7 + addl %ecx,%eax + movl %edx,%ecx + rorl $14,%edx + movl 28(%esp),%esi + xorl %ecx,%edx + movl (%esp),%edi + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi + psrldq $8,%xmm7 + movl %ecx,24(%esp) + xorl %ecx,%edx + xorl %esi,%edi + paddd %xmm7,%xmm3 + rorl $6,%edx + movl %eax,%ecx + addl %edi,%edx + movl 12(%esp),%edi + movl %eax,%esi + rorl $9,%ecx + movl %eax,8(%esp) + pshufd $80,%xmm3,%xmm7 + xorl %eax,%ecx + xorl %edi,%eax + addl 4(%esp),%edx + movdqa %xmm7,%xmm6 + rorl $11,%ecx + psrld $10,%xmm7 + andl %eax,%ebx + psrlq $17,%xmm6 + xorl %esi,%ecx + addl 88(%esp),%edx + xorl %edi,%ebx + rorl $2,%ecx + pxor %xmm6,%xmm7 + addl %edx,%ebx + addl 20(%esp),%edx + psrlq $2,%xmm6 + addl %ecx,%ebx + movl %edx,%ecx + rorl $14,%edx + pxor %xmm6,%xmm7 + movl 24(%esp),%esi + xorl %ecx,%edx + movl 28(%esp),%edi + pshufd $8,%xmm7,%xmm7 + xorl %edi,%esi + rorl $5,%edx + movdqa 48(%ebp),%xmm6 + andl %ecx,%esi + movl %ecx,20(%esp) + pslldq $8,%xmm7 + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + movl %ebx,%ecx + addl %edi,%edx + movl 8(%esp),%edi + movl %ebx,%esi + rorl $9,%ecx + paddd %xmm7,%xmm3 + movl %ebx,4(%esp) + xorl %ebx,%ecx + xorl %edi,%ebx + addl (%esp),%edx + paddd %xmm3,%xmm6 + rorl $11,%ecx + andl %ebx,%eax + xorl %esi,%ecx + addl 92(%esp),%edx + xorl %edi,%eax + rorl $2,%ecx + addl %edx,%eax + addl 16(%esp),%edx + addl %ecx,%eax + movdqa %xmm6,80(%esp) + cmpl $66051,64(%ebp) + jne L012ssse3_00_47 + movl %edx,%ecx + rorl $14,%edx + movl 20(%esp),%esi + xorl %ecx,%edx + movl 24(%esp),%edi + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi + movl %ecx,16(%esp) + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + movl %eax,%ecx + addl %edi,%edx + movl 4(%esp),%edi + movl %eax,%esi + rorl $9,%ecx + movl %eax,(%esp) + xorl %eax,%ecx + xorl %edi,%eax + addl 28(%esp),%edx + rorl $11,%ecx + andl %eax,%ebx + xorl %esi,%ecx + addl 32(%esp),%edx + xorl %edi,%ebx + rorl $2,%ecx + addl %edx,%ebx + addl 12(%esp),%edx + addl %ecx,%ebx + movl %edx,%ecx + rorl $14,%edx + movl 16(%esp),%esi + xorl %ecx,%edx + movl 20(%esp),%edi + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi + movl %ecx,12(%esp) + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + movl %ebx,%ecx + addl %edi,%edx + movl (%esp),%edi + movl %ebx,%esi + rorl $9,%ecx + movl %ebx,28(%esp) + xorl %ebx,%ecx + xorl %edi,%ebx + addl 24(%esp),%edx + rorl $11,%ecx + andl %ebx,%eax + xorl %esi,%ecx + addl 36(%esp),%edx + xorl %edi,%eax + rorl $2,%ecx + addl %edx,%eax + addl 8(%esp),%edx + addl %ecx,%eax + movl %edx,%ecx + rorl $14,%edx + movl 12(%esp),%esi + xorl %ecx,%edx + movl 16(%esp),%edi + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi + movl %ecx,8(%esp) + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + movl %eax,%ecx + addl %edi,%edx + movl 28(%esp),%edi + movl %eax,%esi + rorl $9,%ecx + movl %eax,24(%esp) + xorl %eax,%ecx + xorl %edi,%eax + addl 20(%esp),%edx + rorl $11,%ecx + andl %eax,%ebx + xorl %esi,%ecx + addl 40(%esp),%edx + xorl %edi,%ebx + rorl $2,%ecx + addl %edx,%ebx + addl 4(%esp),%edx + addl %ecx,%ebx + movl %edx,%ecx + rorl $14,%edx + movl 8(%esp),%esi + xorl %ecx,%edx + movl 12(%esp),%edi + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi + movl %ecx,4(%esp) + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + movl %ebx,%ecx + addl %edi,%edx + movl 24(%esp),%edi + movl %ebx,%esi + rorl $9,%ecx + movl %ebx,20(%esp) + xorl %ebx,%ecx + xorl %edi,%ebx + addl 16(%esp),%edx + rorl $11,%ecx + andl %ebx,%eax + xorl %esi,%ecx + addl 44(%esp),%edx + xorl %edi,%eax + rorl $2,%ecx + addl %edx,%eax + addl (%esp),%edx + addl %ecx,%eax + movl %edx,%ecx + rorl $14,%edx + movl 4(%esp),%esi + xorl %ecx,%edx + movl 8(%esp),%edi + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi + movl %ecx,(%esp) + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + movl %eax,%ecx + addl %edi,%edx + movl 20(%esp),%edi + movl %eax,%esi + rorl $9,%ecx + movl %eax,16(%esp) + xorl %eax,%ecx + xorl %edi,%eax + addl 12(%esp),%edx + rorl $11,%ecx + andl %eax,%ebx + xorl %esi,%ecx + addl 48(%esp),%edx + xorl %edi,%ebx + rorl $2,%ecx + addl %edx,%ebx + addl 28(%esp),%edx + addl %ecx,%ebx + movl %edx,%ecx + rorl $14,%edx + movl (%esp),%esi + xorl %ecx,%edx + movl 4(%esp),%edi + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi + movl %ecx,28(%esp) + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + movl %ebx,%ecx + addl %edi,%edx + movl 16(%esp),%edi + movl %ebx,%esi + rorl $9,%ecx + movl %ebx,12(%esp) + xorl %ebx,%ecx + xorl %edi,%ebx + addl 8(%esp),%edx + rorl $11,%ecx + andl %ebx,%eax + xorl %esi,%ecx + addl 52(%esp),%edx + xorl %edi,%eax + rorl $2,%ecx + addl %edx,%eax + addl 24(%esp),%edx + addl %ecx,%eax + movl %edx,%ecx + rorl $14,%edx + movl 28(%esp),%esi + xorl %ecx,%edx + movl (%esp),%edi + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi + movl %ecx,24(%esp) + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + movl %eax,%ecx + addl %edi,%edx + movl 12(%esp),%edi + movl %eax,%esi + rorl $9,%ecx + movl %eax,8(%esp) + xorl %eax,%ecx + xorl %edi,%eax + addl 4(%esp),%edx + rorl $11,%ecx + andl %eax,%ebx + xorl %esi,%ecx + addl 56(%esp),%edx + xorl %edi,%ebx + rorl $2,%ecx + addl %edx,%ebx + addl 20(%esp),%edx + addl %ecx,%ebx + movl %edx,%ecx + rorl $14,%edx + movl 24(%esp),%esi + xorl %ecx,%edx + movl 28(%esp),%edi + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi + movl %ecx,20(%esp) + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + movl %ebx,%ecx + addl %edi,%edx + movl 8(%esp),%edi + movl %ebx,%esi + rorl $9,%ecx + movl %ebx,4(%esp) + xorl %ebx,%ecx + xorl %edi,%ebx + addl (%esp),%edx + rorl $11,%ecx + andl %ebx,%eax + xorl %esi,%ecx + addl 60(%esp),%edx + xorl %edi,%eax + rorl $2,%ecx + addl %edx,%eax + addl 16(%esp),%edx + addl %ecx,%eax + movl %edx,%ecx + rorl $14,%edx + movl 20(%esp),%esi + xorl %ecx,%edx + movl 24(%esp),%edi + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi + movl %ecx,16(%esp) + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + movl %eax,%ecx + addl %edi,%edx + movl 4(%esp),%edi + movl %eax,%esi + rorl $9,%ecx + movl %eax,(%esp) + xorl %eax,%ecx + xorl %edi,%eax + addl 28(%esp),%edx + rorl $11,%ecx + andl %eax,%ebx + xorl %esi,%ecx + addl 64(%esp),%edx + xorl %edi,%ebx + rorl $2,%ecx + addl %edx,%ebx + addl 12(%esp),%edx + addl %ecx,%ebx + movl %edx,%ecx + rorl $14,%edx + movl 16(%esp),%esi + xorl %ecx,%edx + movl 20(%esp),%edi + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi + movl %ecx,12(%esp) + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + movl %ebx,%ecx + addl %edi,%edx + movl (%esp),%edi + movl %ebx,%esi + rorl $9,%ecx + movl %ebx,28(%esp) + xorl %ebx,%ecx + xorl %edi,%ebx + addl 24(%esp),%edx + rorl $11,%ecx + andl %ebx,%eax + xorl %esi,%ecx + addl 68(%esp),%edx + xorl %edi,%eax + rorl $2,%ecx + addl %edx,%eax + addl 8(%esp),%edx + addl %ecx,%eax + movl %edx,%ecx + rorl $14,%edx + movl 12(%esp),%esi + xorl %ecx,%edx + movl 16(%esp),%edi + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi + movl %ecx,8(%esp) + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + movl %eax,%ecx + addl %edi,%edx + movl 28(%esp),%edi + movl %eax,%esi + rorl $9,%ecx + movl %eax,24(%esp) + xorl %eax,%ecx + xorl %edi,%eax + addl 20(%esp),%edx + rorl $11,%ecx + andl %eax,%ebx + xorl %esi,%ecx + addl 72(%esp),%edx + xorl %edi,%ebx + rorl $2,%ecx + addl %edx,%ebx + addl 4(%esp),%edx + addl %ecx,%ebx + movl %edx,%ecx + rorl $14,%edx + movl 8(%esp),%esi + xorl %ecx,%edx + movl 12(%esp),%edi + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi + movl %ecx,4(%esp) + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + movl %ebx,%ecx + addl %edi,%edx + movl 24(%esp),%edi + movl %ebx,%esi + rorl $9,%ecx + movl %ebx,20(%esp) + xorl %ebx,%ecx + xorl %edi,%ebx + addl 16(%esp),%edx + rorl $11,%ecx + andl %ebx,%eax + xorl %esi,%ecx + addl 76(%esp),%edx + xorl %edi,%eax + rorl $2,%ecx + addl %edx,%eax + addl (%esp),%edx + addl %ecx,%eax + movl %edx,%ecx + rorl $14,%edx + movl 4(%esp),%esi + xorl %ecx,%edx + movl 8(%esp),%edi + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi + movl %ecx,(%esp) + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + movl %eax,%ecx + addl %edi,%edx + movl 20(%esp),%edi + movl %eax,%esi + rorl $9,%ecx + movl %eax,16(%esp) + xorl %eax,%ecx + xorl %edi,%eax + addl 12(%esp),%edx + rorl $11,%ecx + andl %eax,%ebx + xorl %esi,%ecx + addl 80(%esp),%edx + xorl %edi,%ebx + rorl $2,%ecx + addl %edx,%ebx + addl 28(%esp),%edx + addl %ecx,%ebx + movl %edx,%ecx + rorl $14,%edx + movl (%esp),%esi + xorl %ecx,%edx + movl 4(%esp),%edi + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi + movl %ecx,28(%esp) + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + movl %ebx,%ecx + addl %edi,%edx + movl 16(%esp),%edi + movl %ebx,%esi + rorl $9,%ecx + movl %ebx,12(%esp) + xorl %ebx,%ecx + xorl %edi,%ebx + addl 8(%esp),%edx + rorl $11,%ecx + andl %ebx,%eax + xorl %esi,%ecx + addl 84(%esp),%edx + xorl %edi,%eax + rorl $2,%ecx + addl %edx,%eax + addl 24(%esp),%edx + addl %ecx,%eax + movl %edx,%ecx + rorl $14,%edx + movl 28(%esp),%esi + xorl %ecx,%edx + movl (%esp),%edi + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi + movl %ecx,24(%esp) + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + movl %eax,%ecx + addl %edi,%edx + movl 12(%esp),%edi + movl %eax,%esi + rorl $9,%ecx + movl %eax,8(%esp) + xorl %eax,%ecx + xorl %edi,%eax + addl 4(%esp),%edx + rorl $11,%ecx + andl %eax,%ebx + xorl %esi,%ecx + addl 88(%esp),%edx + xorl %edi,%ebx + rorl $2,%ecx + addl %edx,%ebx + addl 20(%esp),%edx + addl %ecx,%ebx + movl %edx,%ecx + rorl $14,%edx + movl 24(%esp),%esi + xorl %ecx,%edx + movl 28(%esp),%edi + xorl %edi,%esi + rorl $5,%edx + andl %ecx,%esi + movl %ecx,20(%esp) + xorl %ecx,%edx + xorl %esi,%edi + rorl $6,%edx + movl %ebx,%ecx + addl %edi,%edx + movl 8(%esp),%edi + movl %ebx,%esi + rorl $9,%ecx + movl %ebx,4(%esp) + xorl %ebx,%ecx + xorl %edi,%ebx + addl (%esp),%edx + rorl $11,%ecx + andl %ebx,%eax + xorl %esi,%ecx + addl 92(%esp),%edx + xorl %edi,%eax + rorl $2,%ecx + addl %edx,%eax + addl 16(%esp),%edx + addl %ecx,%eax + movl 96(%esp),%esi + xorl %edi,%ebx + movl 12(%esp),%ecx + addl (%esi),%eax + addl 4(%esi),%ebx + addl 8(%esi),%edi + addl 12(%esi),%ecx + movl %eax,(%esi) + movl %ebx,4(%esi) + movl %edi,8(%esi) + movl %ecx,12(%esi) + movl %ebx,4(%esp) + xorl %edi,%ebx + movl %edi,8(%esp) + movl %ecx,12(%esp) + movl 20(%esp),%edi + movl 24(%esp),%ecx + addl 16(%esi),%edx + addl 20(%esi),%edi + addl 24(%esi),%ecx + movl %edx,16(%esi) + movl %edi,20(%esi) + movl %edi,20(%esp) + movl 28(%esp),%edi + movl %ecx,24(%esi) + addl 28(%esi),%edi + movl %ecx,24(%esp) + movl %edi,28(%esi) + movl %edi,28(%esp) + movl 100(%esp),%edi + movdqa 64(%ebp),%xmm7 + subl $192,%ebp + cmpl 104(%esp),%edi + jb L011grand_ssse3 + movl 108(%esp),%esp + popl %edi + popl %esi + popl %ebx + popl %ebp + ret +.section __IMPORT,__pointers,non_lazy_symbol_pointers +L_OPENSSL_ia32cap_P$non_lazy_ptr: +.indirect_symbol _OPENSSL_ia32cap_P +.long 0 #endif diff --git a/third_party/boringssl/mac-x86/crypto/sha/sha512-586.S b/third_party/boringssl/mac-x86/crypto/sha/sha512-586.S index 99dbc317df84f..3066100e6ff92 100644 --- a/third_party/boringssl/mac-x86/crypto/sha/sha512-586.S +++ b/third_party/boringssl/mac-x86/crypto/sha/sha512-586.S @@ -26,6 +26,2269 @@ L000pic_point: movl %edi,4(%esp) movl %eax,8(%esp) movl %ebx,12(%esp) + movl L_OPENSSL_ia32cap_P$non_lazy_ptr-L001K512(%ebp),%edx + movl (%edx),%ecx + testl $67108864,%ecx + jz L002loop_x86 + movl 4(%edx),%edx + movq (%esi),%mm0 + andl $16777216,%ecx + movq 8(%esi),%mm1 + andl $512,%edx + movq 16(%esi),%mm2 + orl %edx,%ecx + movq 24(%esi),%mm3 + movq 32(%esi),%mm4 + movq 40(%esi),%mm5 + movq 48(%esi),%mm6 + movq 56(%esi),%mm7 + cmpl $16777728,%ecx + je L003SSSE3 + subl $80,%esp + jmp L004loop_sse2 +.align 4,0x90 +L004loop_sse2: + movq %mm1,8(%esp) + movq %mm2,16(%esp) + movq %mm3,24(%esp) + movq %mm5,40(%esp) + movq %mm6,48(%esp) + pxor %mm1,%mm2 + movq %mm7,56(%esp) + movq %mm0,%mm3 + movl (%edi),%eax + movl 4(%edi),%ebx + addl $8,%edi + movl $15,%edx + bswap %eax + bswap %ebx + jmp L00500_14_sse2 +.align 4,0x90 +L00500_14_sse2: + movd %eax,%mm1 + movl (%edi),%eax + movd %ebx,%mm7 + movl 4(%edi),%ebx + addl $8,%edi + bswap %eax + bswap %ebx + punpckldq %mm1,%mm7 + movq %mm4,%mm1 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,32(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + movq %mm3,%mm0 + movq %mm7,72(%esp) + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm0,(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 56(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + paddq (%ebp),%mm7 + pxor %mm4,%mm3 + movq 24(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm0,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm0,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 8(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + subl $8,%esp + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm0,%mm2 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + pxor %mm7,%mm6 + movq 40(%esp),%mm5 + paddq %mm2,%mm3 + movq %mm0,%mm2 + addl $8,%ebp + paddq %mm6,%mm3 + movq 48(%esp),%mm6 + decl %edx + jnz L00500_14_sse2 + movd %eax,%mm1 + movd %ebx,%mm7 + punpckldq %mm1,%mm7 + movq %mm4,%mm1 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,32(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + movq %mm3,%mm0 + movq %mm7,72(%esp) + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm0,(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 56(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + paddq (%ebp),%mm7 + pxor %mm4,%mm3 + movq 24(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm0,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm0,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 8(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + subl $8,%esp + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm0,%mm2 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + pxor %mm7,%mm6 + movq 192(%esp),%mm7 + paddq %mm2,%mm3 + movq %mm0,%mm2 + addl $8,%ebp + paddq %mm6,%mm3 + pxor %mm0,%mm0 + movl $32,%edx + jmp L00616_79_sse2 +.align 4,0x90 +L00616_79_sse2: + movq 88(%esp),%mm5 + movq %mm7,%mm1 + psrlq $1,%mm7 + movq %mm5,%mm6 + psrlq $6,%mm5 + psllq $56,%mm1 + paddq %mm3,%mm0 + movq %mm7,%mm3 + psrlq $6,%mm7 + pxor %mm1,%mm3 + psllq $7,%mm1 + pxor %mm7,%mm3 + psrlq $1,%mm7 + pxor %mm1,%mm3 + movq %mm5,%mm1 + psrlq $13,%mm5 + pxor %mm3,%mm7 + psllq $3,%mm6 + pxor %mm5,%mm1 + paddq 200(%esp),%mm7 + pxor %mm6,%mm1 + psrlq $42,%mm5 + paddq 128(%esp),%mm7 + pxor %mm5,%mm1 + psllq $42,%mm6 + movq 40(%esp),%mm5 + pxor %mm6,%mm1 + movq 48(%esp),%mm6 + paddq %mm1,%mm7 + movq %mm4,%mm1 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,32(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + movq %mm7,72(%esp) + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm0,(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 56(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + paddq (%ebp),%mm7 + pxor %mm4,%mm3 + movq 24(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm0,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm0,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 8(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + subl $8,%esp + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm0,%mm2 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + pxor %mm7,%mm6 + movq 192(%esp),%mm7 + paddq %mm6,%mm2 + addl $8,%ebp + movq 88(%esp),%mm5 + movq %mm7,%mm1 + psrlq $1,%mm7 + movq %mm5,%mm6 + psrlq $6,%mm5 + psllq $56,%mm1 + paddq %mm3,%mm2 + movq %mm7,%mm3 + psrlq $6,%mm7 + pxor %mm1,%mm3 + psllq $7,%mm1 + pxor %mm7,%mm3 + psrlq $1,%mm7 + pxor %mm1,%mm3 + movq %mm5,%mm1 + psrlq $13,%mm5 + pxor %mm3,%mm7 + psllq $3,%mm6 + pxor %mm5,%mm1 + paddq 200(%esp),%mm7 + pxor %mm6,%mm1 + psrlq $42,%mm5 + paddq 128(%esp),%mm7 + pxor %mm5,%mm1 + psllq $42,%mm6 + movq 40(%esp),%mm5 + pxor %mm6,%mm1 + movq 48(%esp),%mm6 + paddq %mm1,%mm7 + movq %mm4,%mm1 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,32(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + movq %mm7,72(%esp) + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm2,(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 56(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + paddq (%ebp),%mm7 + pxor %mm4,%mm3 + movq 24(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm2,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm2,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 8(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + subl $8,%esp + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm2,%mm0 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + pxor %mm7,%mm6 + movq 192(%esp),%mm7 + paddq %mm6,%mm0 + addl $8,%ebp + decl %edx + jnz L00616_79_sse2 + paddq %mm3,%mm0 + movq 8(%esp),%mm1 + movq 24(%esp),%mm3 + movq 40(%esp),%mm5 + movq 48(%esp),%mm6 + movq 56(%esp),%mm7 + pxor %mm1,%mm2 + paddq (%esi),%mm0 + paddq 8(%esi),%mm1 + paddq 16(%esi),%mm2 + paddq 24(%esi),%mm3 + paddq 32(%esi),%mm4 + paddq 40(%esi),%mm5 + paddq 48(%esi),%mm6 + paddq 56(%esi),%mm7 + movl $640,%eax + movq %mm0,(%esi) + movq %mm1,8(%esi) + movq %mm2,16(%esi) + movq %mm3,24(%esi) + movq %mm4,32(%esi) + movq %mm5,40(%esi) + movq %mm6,48(%esi) + movq %mm7,56(%esi) + leal (%esp,%eax,1),%esp + subl %eax,%ebp + cmpl 88(%esp),%edi + jb L004loop_sse2 + movl 92(%esp),%esp + emms + popl %edi + popl %esi + popl %ebx + popl %ebp + ret +.align 5,0x90 +L003SSSE3: + leal -64(%esp),%edx + subl $256,%esp + movdqa 640(%ebp),%xmm1 + movdqu (%edi),%xmm0 +.byte 102,15,56,0,193 + movdqa (%ebp),%xmm3 + movdqa %xmm1,%xmm2 + movdqu 16(%edi),%xmm1 + paddq %xmm0,%xmm3 +.byte 102,15,56,0,202 + movdqa %xmm3,-128(%edx) + movdqa 16(%ebp),%xmm4 + movdqa %xmm2,%xmm3 + movdqu 32(%edi),%xmm2 + paddq %xmm1,%xmm4 +.byte 102,15,56,0,211 + movdqa %xmm4,-112(%edx) + movdqa 32(%ebp),%xmm5 + movdqa %xmm3,%xmm4 + movdqu 48(%edi),%xmm3 + paddq %xmm2,%xmm5 +.byte 102,15,56,0,220 + movdqa %xmm5,-96(%edx) + movdqa 48(%ebp),%xmm6 + movdqa %xmm4,%xmm5 + movdqu 64(%edi),%xmm4 + paddq %xmm3,%xmm6 +.byte 102,15,56,0,229 + movdqa %xmm6,-80(%edx) + movdqa 64(%ebp),%xmm7 + movdqa %xmm5,%xmm6 + movdqu 80(%edi),%xmm5 + paddq %xmm4,%xmm7 +.byte 102,15,56,0,238 + movdqa %xmm7,-64(%edx) + movdqa %xmm0,(%edx) + movdqa 80(%ebp),%xmm0 + movdqa %xmm6,%xmm7 + movdqu 96(%edi),%xmm6 + paddq %xmm5,%xmm0 +.byte 102,15,56,0,247 + movdqa %xmm0,-48(%edx) + movdqa %xmm1,16(%edx) + movdqa 96(%ebp),%xmm1 + movdqa %xmm7,%xmm0 + movdqu 112(%edi),%xmm7 + paddq %xmm6,%xmm1 +.byte 102,15,56,0,248 + movdqa %xmm1,-32(%edx) + movdqa %xmm2,32(%edx) + movdqa 112(%ebp),%xmm2 + movdqa (%edx),%xmm0 + paddq %xmm7,%xmm2 + movdqa %xmm2,-16(%edx) + nop +.align 5,0x90 +L007loop_ssse3: + movdqa 16(%edx),%xmm2 + movdqa %xmm3,48(%edx) + leal 128(%ebp),%ebp + movq %mm1,8(%esp) + movl %edi,%ebx + movq %mm2,16(%esp) + leal 128(%edi),%edi + movq %mm3,24(%esp) + cmpl %eax,%edi + movq %mm5,40(%esp) + cmovbl %edi,%ebx + movq %mm6,48(%esp) + movl $4,%ecx + pxor %mm1,%mm2 + movq %mm7,56(%esp) + pxor %mm3,%mm3 + jmp L00800_47_ssse3 +.align 5,0x90 +L00800_47_ssse3: + movdqa %xmm5,%xmm3 + movdqa %xmm2,%xmm1 +.byte 102,15,58,15,208,8 + movdqa %xmm4,(%edx) +.byte 102,15,58,15,220,8 + movdqa %xmm2,%xmm4 + psrlq $7,%xmm2 + paddq %xmm3,%xmm0 + movdqa %xmm4,%xmm3 + psrlq $1,%xmm4 + psllq $56,%xmm3 + pxor %xmm4,%xmm2 + psrlq $7,%xmm4 + pxor %xmm3,%xmm2 + psllq $7,%xmm3 + pxor %xmm4,%xmm2 + movdqa %xmm7,%xmm4 + pxor %xmm3,%xmm2 + movdqa %xmm7,%xmm3 + psrlq $6,%xmm4 + paddq %xmm2,%xmm0 + movdqa %xmm7,%xmm2 + psrlq $19,%xmm3 + psllq $3,%xmm2 + pxor %xmm3,%xmm4 + psrlq $42,%xmm3 + pxor %xmm2,%xmm4 + psllq $42,%xmm2 + pxor %xmm3,%xmm4 + movdqa 32(%edx),%xmm3 + pxor %xmm2,%xmm4 + movdqa (%ebp),%xmm2 + movq %mm4,%mm1 + paddq %xmm4,%xmm0 + movq -128(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,32(%esp) + paddq %xmm0,%xmm2 + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm0 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm0,(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 56(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 24(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm0,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm0,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 8(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm0,%mm2 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + pxor %mm7,%mm6 + movq 32(%esp),%mm5 + paddq %mm6,%mm2 + movq 40(%esp),%mm6 + movq %mm4,%mm1 + movq -120(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,24(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm2 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm2,56(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 48(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 16(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm2,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm2,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq (%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm2,%mm0 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + pxor %mm7,%mm6 + movq 24(%esp),%mm5 + paddq %mm6,%mm0 + movq 32(%esp),%mm6 + movdqa %xmm2,-128(%edx) + movdqa %xmm6,%xmm4 + movdqa %xmm3,%xmm2 +.byte 102,15,58,15,217,8 + movdqa %xmm5,16(%edx) +.byte 102,15,58,15,229,8 + movdqa %xmm3,%xmm5 + psrlq $7,%xmm3 + paddq %xmm4,%xmm1 + movdqa %xmm5,%xmm4 + psrlq $1,%xmm5 + psllq $56,%xmm4 + pxor %xmm5,%xmm3 + psrlq $7,%xmm5 + pxor %xmm4,%xmm3 + psllq $7,%xmm4 + pxor %xmm5,%xmm3 + movdqa %xmm0,%xmm5 + pxor %xmm4,%xmm3 + movdqa %xmm0,%xmm4 + psrlq $6,%xmm5 + paddq %xmm3,%xmm1 + movdqa %xmm0,%xmm3 + psrlq $19,%xmm4 + psllq $3,%xmm3 + pxor %xmm4,%xmm5 + psrlq $42,%xmm4 + pxor %xmm3,%xmm5 + psllq $42,%xmm3 + pxor %xmm4,%xmm5 + movdqa 48(%edx),%xmm4 + pxor %xmm3,%xmm5 + movdqa 16(%ebp),%xmm3 + movq %mm4,%mm1 + paddq %xmm5,%xmm1 + movq -112(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,16(%esp) + paddq %xmm1,%xmm3 + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm0 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm0,48(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 40(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 8(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm0,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm0,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 56(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm0,%mm2 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + pxor %mm7,%mm6 + movq 16(%esp),%mm5 + paddq %mm6,%mm2 + movq 24(%esp),%mm6 + movq %mm4,%mm1 + movq -104(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,8(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm2 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm2,40(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 32(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq (%esp),%mm4 + paddq %mm7,%mm3 + movq %mm2,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm2,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 48(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm2,%mm0 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + pxor %mm7,%mm6 + movq 8(%esp),%mm5 + paddq %mm6,%mm0 + movq 16(%esp),%mm6 + movdqa %xmm3,-112(%edx) + movdqa %xmm7,%xmm5 + movdqa %xmm4,%xmm3 +.byte 102,15,58,15,226,8 + movdqa %xmm6,32(%edx) +.byte 102,15,58,15,238,8 + movdqa %xmm4,%xmm6 + psrlq $7,%xmm4 + paddq %xmm5,%xmm2 + movdqa %xmm6,%xmm5 + psrlq $1,%xmm6 + psllq $56,%xmm5 + pxor %xmm6,%xmm4 + psrlq $7,%xmm6 + pxor %xmm5,%xmm4 + psllq $7,%xmm5 + pxor %xmm6,%xmm4 + movdqa %xmm1,%xmm6 + pxor %xmm5,%xmm4 + movdqa %xmm1,%xmm5 + psrlq $6,%xmm6 + paddq %xmm4,%xmm2 + movdqa %xmm1,%xmm4 + psrlq $19,%xmm5 + psllq $3,%xmm4 + pxor %xmm5,%xmm6 + psrlq $42,%xmm5 + pxor %xmm4,%xmm6 + psllq $42,%xmm4 + pxor %xmm5,%xmm6 + movdqa (%edx),%xmm5 + pxor %xmm4,%xmm6 + movdqa 32(%ebp),%xmm4 + movq %mm4,%mm1 + paddq %xmm6,%xmm2 + movq -96(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,(%esp) + paddq %xmm2,%xmm4 + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm0 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm0,32(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 24(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 56(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm0,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm0,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 40(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm0,%mm2 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + pxor %mm7,%mm6 + movq (%esp),%mm5 + paddq %mm6,%mm2 + movq 8(%esp),%mm6 + movq %mm4,%mm1 + movq -88(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,56(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm2 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm2,24(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 16(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 48(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm2,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm2,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 32(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm2,%mm0 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + pxor %mm7,%mm6 + movq 56(%esp),%mm5 + paddq %mm6,%mm0 + movq (%esp),%mm6 + movdqa %xmm4,-96(%edx) + movdqa %xmm0,%xmm6 + movdqa %xmm5,%xmm4 +.byte 102,15,58,15,235,8 + movdqa %xmm7,48(%edx) +.byte 102,15,58,15,247,8 + movdqa %xmm5,%xmm7 + psrlq $7,%xmm5 + paddq %xmm6,%xmm3 + movdqa %xmm7,%xmm6 + psrlq $1,%xmm7 + psllq $56,%xmm6 + pxor %xmm7,%xmm5 + psrlq $7,%xmm7 + pxor %xmm6,%xmm5 + psllq $7,%xmm6 + pxor %xmm7,%xmm5 + movdqa %xmm2,%xmm7 + pxor %xmm6,%xmm5 + movdqa %xmm2,%xmm6 + psrlq $6,%xmm7 + paddq %xmm5,%xmm3 + movdqa %xmm2,%xmm5 + psrlq $19,%xmm6 + psllq $3,%xmm5 + pxor %xmm6,%xmm7 + psrlq $42,%xmm6 + pxor %xmm5,%xmm7 + psllq $42,%xmm5 + pxor %xmm6,%xmm7 + movdqa 16(%edx),%xmm6 + pxor %xmm5,%xmm7 + movdqa 48(%ebp),%xmm5 + movq %mm4,%mm1 + paddq %xmm7,%xmm3 + movq -80(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,48(%esp) + paddq %xmm3,%xmm5 + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm0 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm0,16(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 8(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 40(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm0,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm0,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 24(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm0,%mm2 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + pxor %mm7,%mm6 + movq 48(%esp),%mm5 + paddq %mm6,%mm2 + movq 56(%esp),%mm6 + movq %mm4,%mm1 + movq -72(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,40(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm2 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm2,8(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq (%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 32(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm2,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm2,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 16(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm2,%mm0 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + pxor %mm7,%mm6 + movq 40(%esp),%mm5 + paddq %mm6,%mm0 + movq 48(%esp),%mm6 + movdqa %xmm5,-80(%edx) + movdqa %xmm1,%xmm7 + movdqa %xmm6,%xmm5 +.byte 102,15,58,15,244,8 + movdqa %xmm0,(%edx) +.byte 102,15,58,15,248,8 + movdqa %xmm6,%xmm0 + psrlq $7,%xmm6 + paddq %xmm7,%xmm4 + movdqa %xmm0,%xmm7 + psrlq $1,%xmm0 + psllq $56,%xmm7 + pxor %xmm0,%xmm6 + psrlq $7,%xmm0 + pxor %xmm7,%xmm6 + psllq $7,%xmm7 + pxor %xmm0,%xmm6 + movdqa %xmm3,%xmm0 + pxor %xmm7,%xmm6 + movdqa %xmm3,%xmm7 + psrlq $6,%xmm0 + paddq %xmm6,%xmm4 + movdqa %xmm3,%xmm6 + psrlq $19,%xmm7 + psllq $3,%xmm6 + pxor %xmm7,%xmm0 + psrlq $42,%xmm7 + pxor %xmm6,%xmm0 + psllq $42,%xmm6 + pxor %xmm7,%xmm0 + movdqa 32(%edx),%xmm7 + pxor %xmm6,%xmm0 + movdqa 64(%ebp),%xmm6 + movq %mm4,%mm1 + paddq %xmm0,%xmm4 + movq -64(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,32(%esp) + paddq %xmm4,%xmm6 + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm0 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm0,(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 56(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 24(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm0,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm0,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 8(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm0,%mm2 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + pxor %mm7,%mm6 + movq 32(%esp),%mm5 + paddq %mm6,%mm2 + movq 40(%esp),%mm6 + movq %mm4,%mm1 + movq -56(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,24(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm2 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm2,56(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 48(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 16(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm2,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm2,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq (%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm2,%mm0 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + pxor %mm7,%mm6 + movq 24(%esp),%mm5 + paddq %mm6,%mm0 + movq 32(%esp),%mm6 + movdqa %xmm6,-64(%edx) + movdqa %xmm2,%xmm0 + movdqa %xmm7,%xmm6 +.byte 102,15,58,15,253,8 + movdqa %xmm1,16(%edx) +.byte 102,15,58,15,193,8 + movdqa %xmm7,%xmm1 + psrlq $7,%xmm7 + paddq %xmm0,%xmm5 + movdqa %xmm1,%xmm0 + psrlq $1,%xmm1 + psllq $56,%xmm0 + pxor %xmm1,%xmm7 + psrlq $7,%xmm1 + pxor %xmm0,%xmm7 + psllq $7,%xmm0 + pxor %xmm1,%xmm7 + movdqa %xmm4,%xmm1 + pxor %xmm0,%xmm7 + movdqa %xmm4,%xmm0 + psrlq $6,%xmm1 + paddq %xmm7,%xmm5 + movdqa %xmm4,%xmm7 + psrlq $19,%xmm0 + psllq $3,%xmm7 + pxor %xmm0,%xmm1 + psrlq $42,%xmm0 + pxor %xmm7,%xmm1 + psllq $42,%xmm7 + pxor %xmm0,%xmm1 + movdqa 48(%edx),%xmm0 + pxor %xmm7,%xmm1 + movdqa 80(%ebp),%xmm7 + movq %mm4,%mm1 + paddq %xmm1,%xmm5 + movq -48(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,16(%esp) + paddq %xmm5,%xmm7 + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm0 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm0,48(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 40(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 8(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm0,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm0,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 56(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm0,%mm2 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + pxor %mm7,%mm6 + movq 16(%esp),%mm5 + paddq %mm6,%mm2 + movq 24(%esp),%mm6 + movq %mm4,%mm1 + movq -40(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,8(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm2 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm2,40(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 32(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq (%esp),%mm4 + paddq %mm7,%mm3 + movq %mm2,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm2,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 48(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm2,%mm0 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + pxor %mm7,%mm6 + movq 8(%esp),%mm5 + paddq %mm6,%mm0 + movq 16(%esp),%mm6 + movdqa %xmm7,-48(%edx) + movdqa %xmm3,%xmm1 + movdqa %xmm0,%xmm7 +.byte 102,15,58,15,198,8 + movdqa %xmm2,32(%edx) +.byte 102,15,58,15,202,8 + movdqa %xmm0,%xmm2 + psrlq $7,%xmm0 + paddq %xmm1,%xmm6 + movdqa %xmm2,%xmm1 + psrlq $1,%xmm2 + psllq $56,%xmm1 + pxor %xmm2,%xmm0 + psrlq $7,%xmm2 + pxor %xmm1,%xmm0 + psllq $7,%xmm1 + pxor %xmm2,%xmm0 + movdqa %xmm5,%xmm2 + pxor %xmm1,%xmm0 + movdqa %xmm5,%xmm1 + psrlq $6,%xmm2 + paddq %xmm0,%xmm6 + movdqa %xmm5,%xmm0 + psrlq $19,%xmm1 + psllq $3,%xmm0 + pxor %xmm1,%xmm2 + psrlq $42,%xmm1 + pxor %xmm0,%xmm2 + psllq $42,%xmm0 + pxor %xmm1,%xmm2 + movdqa (%edx),%xmm1 + pxor %xmm0,%xmm2 + movdqa 96(%ebp),%xmm0 + movq %mm4,%mm1 + paddq %xmm2,%xmm6 + movq -32(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,(%esp) + paddq %xmm6,%xmm0 + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm0 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm0,32(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 24(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 56(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm0,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm0,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 40(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm0,%mm2 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + pxor %mm7,%mm6 + movq (%esp),%mm5 + paddq %mm6,%mm2 + movq 8(%esp),%mm6 + movq %mm4,%mm1 + movq -24(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,56(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm2 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm2,24(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 16(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 48(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm2,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm2,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 32(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm2,%mm0 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + pxor %mm7,%mm6 + movq 56(%esp),%mm5 + paddq %mm6,%mm0 + movq (%esp),%mm6 + movdqa %xmm0,-32(%edx) + movdqa %xmm4,%xmm2 + movdqa %xmm1,%xmm0 +.byte 102,15,58,15,207,8 + movdqa %xmm3,48(%edx) +.byte 102,15,58,15,211,8 + movdqa %xmm1,%xmm3 + psrlq $7,%xmm1 + paddq %xmm2,%xmm7 + movdqa %xmm3,%xmm2 + psrlq $1,%xmm3 + psllq $56,%xmm2 + pxor %xmm3,%xmm1 + psrlq $7,%xmm3 + pxor %xmm2,%xmm1 + psllq $7,%xmm2 + pxor %xmm3,%xmm1 + movdqa %xmm6,%xmm3 + pxor %xmm2,%xmm1 + movdqa %xmm6,%xmm2 + psrlq $6,%xmm3 + paddq %xmm1,%xmm7 + movdqa %xmm6,%xmm1 + psrlq $19,%xmm2 + psllq $3,%xmm1 + pxor %xmm2,%xmm3 + psrlq $42,%xmm2 + pxor %xmm1,%xmm3 + psllq $42,%xmm1 + pxor %xmm2,%xmm3 + movdqa 16(%edx),%xmm2 + pxor %xmm1,%xmm3 + movdqa 112(%ebp),%xmm1 + movq %mm4,%mm1 + paddq %xmm3,%xmm7 + movq -16(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,48(%esp) + paddq %xmm7,%xmm1 + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm0 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm0,16(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 8(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 40(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm0,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm0,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 24(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm0,%mm2 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + pxor %mm7,%mm6 + movq 48(%esp),%mm5 + paddq %mm6,%mm2 + movq 56(%esp),%mm6 + movq %mm4,%mm1 + movq -8(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,40(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm2 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm2,8(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq (%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 32(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm2,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm2,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 16(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm2,%mm0 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + pxor %mm7,%mm6 + movq 40(%esp),%mm5 + paddq %mm6,%mm0 + movq 48(%esp),%mm6 + movdqa %xmm1,-16(%edx) + leal 128(%ebp),%ebp + decl %ecx + jnz L00800_47_ssse3 + movdqa (%ebp),%xmm1 + leal -640(%ebp),%ebp + movdqu (%ebx),%xmm0 +.byte 102,15,56,0,193 + movdqa (%ebp),%xmm3 + movdqa %xmm1,%xmm2 + movdqu 16(%ebx),%xmm1 + paddq %xmm0,%xmm3 +.byte 102,15,56,0,202 + movq %mm4,%mm1 + movq -128(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,32(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm0 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm0,(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 56(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 24(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm0,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm0,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 8(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm0,%mm2 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + pxor %mm7,%mm6 + movq 32(%esp),%mm5 + paddq %mm6,%mm2 + movq 40(%esp),%mm6 + movq %mm4,%mm1 + movq -120(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,24(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm2 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm2,56(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 48(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 16(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm2,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm2,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq (%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm2,%mm0 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + pxor %mm7,%mm6 + movq 24(%esp),%mm5 + paddq %mm6,%mm0 + movq 32(%esp),%mm6 + movdqa %xmm3,-128(%edx) + movdqa 16(%ebp),%xmm4 + movdqa %xmm2,%xmm3 + movdqu 32(%ebx),%xmm2 + paddq %xmm1,%xmm4 +.byte 102,15,56,0,211 + movq %mm4,%mm1 + movq -112(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,16(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm0 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm0,48(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 40(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 8(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm0,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm0,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 56(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm0,%mm2 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + pxor %mm7,%mm6 + movq 16(%esp),%mm5 + paddq %mm6,%mm2 + movq 24(%esp),%mm6 + movq %mm4,%mm1 + movq -104(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,8(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm2 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm2,40(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 32(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq (%esp),%mm4 + paddq %mm7,%mm3 + movq %mm2,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm2,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 48(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm2,%mm0 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + pxor %mm7,%mm6 + movq 8(%esp),%mm5 + paddq %mm6,%mm0 + movq 16(%esp),%mm6 + movdqa %xmm4,-112(%edx) + movdqa 32(%ebp),%xmm5 + movdqa %xmm3,%xmm4 + movdqu 48(%ebx),%xmm3 + paddq %xmm2,%xmm5 +.byte 102,15,56,0,220 + movq %mm4,%mm1 + movq -96(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm0 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm0,32(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 24(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 56(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm0,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm0,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 40(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm0,%mm2 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + pxor %mm7,%mm6 + movq (%esp),%mm5 + paddq %mm6,%mm2 + movq 8(%esp),%mm6 + movq %mm4,%mm1 + movq -88(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,56(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm2 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm2,24(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 16(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 48(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm2,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm2,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 32(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm2,%mm0 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + pxor %mm7,%mm6 + movq 56(%esp),%mm5 + paddq %mm6,%mm0 + movq (%esp),%mm6 + movdqa %xmm5,-96(%edx) + movdqa 48(%ebp),%xmm6 + movdqa %xmm4,%xmm5 + movdqu 64(%ebx),%xmm4 + paddq %xmm3,%xmm6 +.byte 102,15,56,0,229 + movq %mm4,%mm1 + movq -80(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,48(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm0 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm0,16(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 8(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 40(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm0,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm0,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 24(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm0,%mm2 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + pxor %mm7,%mm6 + movq 48(%esp),%mm5 + paddq %mm6,%mm2 + movq 56(%esp),%mm6 + movq %mm4,%mm1 + movq -72(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,40(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm2 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm2,8(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq (%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 32(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm2,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm2,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 16(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm2,%mm0 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + pxor %mm7,%mm6 + movq 40(%esp),%mm5 + paddq %mm6,%mm0 + movq 48(%esp),%mm6 + movdqa %xmm6,-80(%edx) + movdqa 64(%ebp),%xmm7 + movdqa %xmm5,%xmm6 + movdqu 80(%ebx),%xmm5 + paddq %xmm4,%xmm7 +.byte 102,15,56,0,238 + movq %mm4,%mm1 + movq -64(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,32(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm0 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm0,(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 56(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 24(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm0,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm0,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 8(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm0,%mm2 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + pxor %mm7,%mm6 + movq 32(%esp),%mm5 + paddq %mm6,%mm2 + movq 40(%esp),%mm6 + movq %mm4,%mm1 + movq -56(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,24(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm2 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm2,56(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 48(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 16(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm2,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm2,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq (%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm2,%mm0 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + pxor %mm7,%mm6 + movq 24(%esp),%mm5 + paddq %mm6,%mm0 + movq 32(%esp),%mm6 + movdqa %xmm7,-64(%edx) + movdqa %xmm0,(%edx) + movdqa 80(%ebp),%xmm0 + movdqa %xmm6,%xmm7 + movdqu 96(%ebx),%xmm6 + paddq %xmm5,%xmm0 +.byte 102,15,56,0,247 + movq %mm4,%mm1 + movq -48(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,16(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm0 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm0,48(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 40(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 8(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm0,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm0,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 56(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm0,%mm2 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + pxor %mm7,%mm6 + movq 16(%esp),%mm5 + paddq %mm6,%mm2 + movq 24(%esp),%mm6 + movq %mm4,%mm1 + movq -40(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,8(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm2 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm2,40(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 32(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq (%esp),%mm4 + paddq %mm7,%mm3 + movq %mm2,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm2,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 48(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm2,%mm0 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + pxor %mm7,%mm6 + movq 8(%esp),%mm5 + paddq %mm6,%mm0 + movq 16(%esp),%mm6 + movdqa %xmm0,-48(%edx) + movdqa %xmm1,16(%edx) + movdqa 96(%ebp),%xmm1 + movdqa %xmm7,%xmm0 + movdqu 112(%ebx),%xmm7 + paddq %xmm6,%xmm1 +.byte 102,15,56,0,248 + movq %mm4,%mm1 + movq -32(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm0 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm0,32(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 24(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 56(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm0,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm0,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 40(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm0,%mm2 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + pxor %mm7,%mm6 + movq (%esp),%mm5 + paddq %mm6,%mm2 + movq 8(%esp),%mm6 + movq %mm4,%mm1 + movq -24(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,56(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm2 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm2,24(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 16(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 48(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm2,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm2,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 32(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm2,%mm0 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + pxor %mm7,%mm6 + movq 56(%esp),%mm5 + paddq %mm6,%mm0 + movq (%esp),%mm6 + movdqa %xmm1,-32(%edx) + movdqa %xmm2,32(%edx) + movdqa 112(%ebp),%xmm2 + movdqa (%edx),%xmm0 + paddq %xmm7,%xmm2 + movq %mm4,%mm1 + movq -16(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,48(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm0 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm0,16(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq 8(%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 40(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm0,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm0,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 24(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm0,%mm2 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + pxor %mm7,%mm6 + movq 48(%esp),%mm5 + paddq %mm6,%mm2 + movq 56(%esp),%mm6 + movq %mm4,%mm1 + movq -8(%edx),%mm7 + pxor %mm6,%mm5 + psrlq $14,%mm1 + movq %mm4,40(%esp) + pand %mm4,%mm5 + psllq $23,%mm4 + paddq %mm3,%mm2 + movq %mm1,%mm3 + psrlq $4,%mm1 + pxor %mm6,%mm5 + pxor %mm4,%mm3 + psllq $23,%mm4 + pxor %mm1,%mm3 + movq %mm2,8(%esp) + paddq %mm5,%mm7 + pxor %mm4,%mm3 + psrlq $23,%mm1 + paddq (%esp),%mm7 + pxor %mm1,%mm3 + psllq $4,%mm4 + pxor %mm4,%mm3 + movq 32(%esp),%mm4 + paddq %mm7,%mm3 + movq %mm2,%mm5 + psrlq $28,%mm5 + paddq %mm3,%mm4 + movq %mm2,%mm6 + movq %mm5,%mm7 + psllq $25,%mm6 + movq 16(%esp),%mm1 + psrlq $6,%mm5 + pxor %mm6,%mm7 + psllq $5,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm2 + psrlq $5,%mm5 + pxor %mm6,%mm7 + pand %mm2,%mm0 + psllq $6,%mm6 + pxor %mm5,%mm7 + pxor %mm1,%mm0 + pxor %mm7,%mm6 + movq 40(%esp),%mm5 + paddq %mm6,%mm0 + movq 48(%esp),%mm6 + movdqa %xmm2,-16(%edx) + movq 8(%esp),%mm1 + paddq %mm3,%mm0 + movq 24(%esp),%mm3 + movq 56(%esp),%mm7 + pxor %mm1,%mm2 + paddq (%esi),%mm0 + paddq 8(%esi),%mm1 + paddq 16(%esi),%mm2 + paddq 24(%esi),%mm3 + paddq 32(%esi),%mm4 + paddq 40(%esi),%mm5 + paddq 48(%esi),%mm6 + paddq 56(%esi),%mm7 + movq %mm0,(%esi) + movq %mm1,8(%esi) + movq %mm2,16(%esi) + movq %mm3,24(%esi) + movq %mm4,32(%esi) + movq %mm5,40(%esi) + movq %mm6,48(%esi) + movq %mm7,56(%esi) + cmpl %eax,%edi + jb L007loop_ssse3 + movl 76(%edx),%esp + emms + popl %edi + popl %esi + popl %ebx + popl %ebp + ret .align 4,0x90 L002loop_x86: movl (%edi),%eax @@ -131,7 +2394,7 @@ L002loop_x86: movl $16,%ecx .long 2784229001 .align 4,0x90 -L00300_15_x86: +L00900_15_x86: movl 40(%esp),%ecx movl 44(%esp),%edx movl %ecx,%esi @@ -238,9 +2501,9 @@ L00300_15_x86: subl $8,%esp leal 8(%ebp),%ebp cmpb $148,%dl - jne L00300_15_x86 + jne L00900_15_x86 .align 4,0x90 -L00416_79_x86: +L01016_79_x86: movl 312(%esp),%ecx movl 316(%esp),%edx movl %ecx,%esi @@ -413,7 +2676,7 @@ L00416_79_x86: subl $8,%esp leal 8(%ebp),%ebp cmpb $23,%dl - jne L00416_79_x86 + jne L01016_79_x86 movl 840(%esp),%esi movl 844(%esp),%edi movl (%esi),%eax @@ -563,4 +2826,8 @@ L001K512: .byte 67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97 .byte 112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103 .byte 62,0 +.section __IMPORT,__pointers,non_lazy_symbol_pointers +L_OPENSSL_ia32cap_P$non_lazy_ptr: +.indirect_symbol _OPENSSL_ia32cap_P +.long 0 #endif diff --git a/third_party/boringssl/mac-x86_64/crypto/aes/aesni-x86_64.S b/third_party/boringssl/mac-x86_64/crypto/aes/aesni-x86_64.S index 032c94dff9696..69b22c26b9369 100644 --- a/third_party/boringssl/mac-x86_64/crypto/aes/aesni-x86_64.S +++ b/third_party/boringssl/mac-x86_64/crypto/aes/aesni-x86_64.S @@ -19,7 +19,10 @@ L$oop_enc1_1: leaq 16(%rdx),%rdx jnz L$oop_enc1_1 .byte 102,15,56,221,209 + pxor %xmm0,%xmm0 + pxor %xmm1,%xmm1 movups %xmm2,(%rsi) + pxor %xmm2,%xmm2 .byte 0xf3,0xc3 @@ -41,7 +44,10 @@ L$oop_dec1_2: leaq 16(%rdx),%rdx jnz L$oop_dec1_2 .byte 102,15,56,223,209 + pxor %xmm0,%xmm0 + pxor %xmm1,%xmm1 movups %xmm2,(%rsi) + pxor %xmm2,%xmm2 .byte 0xf3,0xc3 @@ -267,21 +273,18 @@ _aesni_encrypt6: pxor %xmm0,%xmm6 .byte 102,15,56,220,225 pxor %xmm0,%xmm7 + movups (%rcx,%rax,1),%xmm0 addq $16,%rax -.byte 102,15,56,220,233 -.byte 102,15,56,220,241 -.byte 102,15,56,220,249 - movups -16(%rcx,%rax,1),%xmm0 jmp L$enc_loop6_enter .p2align 4 L$enc_loop6: .byte 102,15,56,220,209 .byte 102,15,56,220,217 .byte 102,15,56,220,225 +L$enc_loop6_enter: .byte 102,15,56,220,233 .byte 102,15,56,220,241 .byte 102,15,56,220,249 -L$enc_loop6_enter: movups (%rcx,%rax,1),%xmm1 addq $32,%rax .byte 102,15,56,220,208 @@ -324,21 +327,18 @@ _aesni_decrypt6: pxor %xmm0,%xmm6 .byte 102,15,56,222,225 pxor %xmm0,%xmm7 + movups (%rcx,%rax,1),%xmm0 addq $16,%rax -.byte 102,15,56,222,233 -.byte 102,15,56,222,241 -.byte 102,15,56,222,249 - movups -16(%rcx,%rax,1),%xmm0 jmp L$dec_loop6_enter .p2align 4 L$dec_loop6: .byte 102,15,56,222,209 .byte 102,15,56,222,217 .byte 102,15,56,222,225 +L$dec_loop6_enter: .byte 102,15,56,222,233 .byte 102,15,56,222,241 .byte 102,15,56,222,249 -L$dec_loop6_enter: movups (%rcx,%rax,1),%xmm1 addq $32,%rax .byte 102,15,56,222,208 @@ -378,23 +378,18 @@ _aesni_encrypt8: leaq 32(%rcx,%rax,1),%rcx negq %rax .byte 102,15,56,220,209 - addq $16,%rax pxor %xmm0,%xmm7 -.byte 102,15,56,220,217 pxor %xmm0,%xmm8 +.byte 102,15,56,220,217 pxor %xmm0,%xmm9 -.byte 102,15,56,220,225 -.byte 102,15,56,220,233 -.byte 102,15,56,220,241 -.byte 102,15,56,220,249 -.byte 102,68,15,56,220,193 -.byte 102,68,15,56,220,201 - movups -16(%rcx,%rax,1),%xmm0 - jmp L$enc_loop8_enter + movups (%rcx,%rax,1),%xmm0 + addq $16,%rax + jmp L$enc_loop8_inner .p2align 4 L$enc_loop8: .byte 102,15,56,220,209 .byte 102,15,56,220,217 +L$enc_loop8_inner: .byte 102,15,56,220,225 .byte 102,15,56,220,233 .byte 102,15,56,220,241 @@ -447,23 +442,18 @@ _aesni_decrypt8: leaq 32(%rcx,%rax,1),%rcx negq %rax .byte 102,15,56,222,209 - addq $16,%rax pxor %xmm0,%xmm7 -.byte 102,15,56,222,217 pxor %xmm0,%xmm8 +.byte 102,15,56,222,217 pxor %xmm0,%xmm9 -.byte 102,15,56,222,225 -.byte 102,15,56,222,233 -.byte 102,15,56,222,241 -.byte 102,15,56,222,249 -.byte 102,68,15,56,222,193 -.byte 102,68,15,56,222,201 - movups -16(%rcx,%rax,1),%xmm0 - jmp L$dec_loop8_enter + movups (%rcx,%rax,1),%xmm0 + addq $16,%rax + jmp L$dec_loop8_inner .p2align 4 L$dec_loop8: .byte 102,15,56,222,209 .byte 102,15,56,222,217 +L$dec_loop8_inner: .byte 102,15,56,222,225 .byte 102,15,56,222,233 .byte 102,15,56,222,241 @@ -591,6 +581,7 @@ L$ecb_enc_tail: movups 80(%rdi),%xmm7 je L$ecb_enc_six movdqu 96(%rdi),%xmm8 + xorps %xmm9,%xmm9 call _aesni_encrypt8 movups %xmm2,(%rsi) movups %xmm3,16(%rsi) @@ -704,15 +695,23 @@ L$ecb_dec_loop8_enter: jnc L$ecb_dec_loop8 movups %xmm2,(%rsi) + pxor %xmm2,%xmm2 movq %r11,%rcx movups %xmm3,16(%rsi) + pxor %xmm3,%xmm3 movl %r10d,%eax movups %xmm4,32(%rsi) + pxor %xmm4,%xmm4 movups %xmm5,48(%rsi) + pxor %xmm5,%xmm5 movups %xmm6,64(%rsi) + pxor %xmm6,%xmm6 movups %xmm7,80(%rsi) + pxor %xmm7,%xmm7 movups %xmm8,96(%rsi) + pxor %xmm8,%xmm8 movups %xmm9,112(%rsi) + pxor %xmm9,%xmm9 leaq 128(%rsi),%rsi addq $128,%rdx jz L$ecb_ret @@ -735,14 +734,23 @@ L$ecb_dec_tail: je L$ecb_dec_six movups 96(%rdi),%xmm8 movups (%rcx),%xmm0 + xorps %xmm9,%xmm9 call _aesni_decrypt8 movups %xmm2,(%rsi) + pxor %xmm2,%xmm2 movups %xmm3,16(%rsi) + pxor %xmm3,%xmm3 movups %xmm4,32(%rsi) + pxor %xmm4,%xmm4 movups %xmm5,48(%rsi) + pxor %xmm5,%xmm5 movups %xmm6,64(%rsi) + pxor %xmm6,%xmm6 movups %xmm7,80(%rsi) + pxor %xmm7,%xmm7 movups %xmm8,96(%rsi) + pxor %xmm8,%xmm8 + pxor %xmm9,%xmm9 jmp L$ecb_ret .p2align 4 L$ecb_dec_one: @@ -758,49 +766,73 @@ L$oop_dec1_4: jnz L$oop_dec1_4 .byte 102,15,56,223,209 movups %xmm2,(%rsi) + pxor %xmm2,%xmm2 jmp L$ecb_ret .p2align 4 L$ecb_dec_two: call _aesni_decrypt2 movups %xmm2,(%rsi) + pxor %xmm2,%xmm2 movups %xmm3,16(%rsi) + pxor %xmm3,%xmm3 jmp L$ecb_ret .p2align 4 L$ecb_dec_three: call _aesni_decrypt3 movups %xmm2,(%rsi) + pxor %xmm2,%xmm2 movups %xmm3,16(%rsi) + pxor %xmm3,%xmm3 movups %xmm4,32(%rsi) + pxor %xmm4,%xmm4 jmp L$ecb_ret .p2align 4 L$ecb_dec_four: call _aesni_decrypt4 movups %xmm2,(%rsi) + pxor %xmm2,%xmm2 movups %xmm3,16(%rsi) + pxor %xmm3,%xmm3 movups %xmm4,32(%rsi) + pxor %xmm4,%xmm4 movups %xmm5,48(%rsi) + pxor %xmm5,%xmm5 jmp L$ecb_ret .p2align 4 L$ecb_dec_five: xorps %xmm7,%xmm7 call _aesni_decrypt6 movups %xmm2,(%rsi) + pxor %xmm2,%xmm2 movups %xmm3,16(%rsi) + pxor %xmm3,%xmm3 movups %xmm4,32(%rsi) + pxor %xmm4,%xmm4 movups %xmm5,48(%rsi) + pxor %xmm5,%xmm5 movups %xmm6,64(%rsi) + pxor %xmm6,%xmm6 + pxor %xmm7,%xmm7 jmp L$ecb_ret .p2align 4 L$ecb_dec_six: call _aesni_decrypt6 movups %xmm2,(%rsi) + pxor %xmm2,%xmm2 movups %xmm3,16(%rsi) + pxor %xmm3,%xmm3 movups %xmm4,32(%rsi) + pxor %xmm4,%xmm4 movups %xmm5,48(%rsi) + pxor %xmm5,%xmm5 movups %xmm6,64(%rsi) + pxor %xmm6,%xmm6 movups %xmm7,80(%rsi) + pxor %xmm7,%xmm7 L$ecb_ret: + xorps %xmm0,%xmm0 + pxor %xmm1,%xmm1 .byte 0xf3,0xc3 .globl _aesni_ccm64_encrypt_blocks @@ -858,7 +890,13 @@ L$ccm64_enc2_loop: leaq 16(%rsi),%rsi jnz L$ccm64_enc_outer + pxor %xmm0,%xmm0 + pxor %xmm1,%xmm1 + pxor %xmm2,%xmm2 movups %xmm3,(%r9) + pxor %xmm3,%xmm3 + pxor %xmm8,%xmm8 + pxor %xmm6,%xmm6 .byte 0xf3,0xc3 .globl _aesni_ccm64_decrypt_blocks @@ -950,7 +988,13 @@ L$oop_enc1_6: leaq 16(%r11),%r11 jnz L$oop_enc1_6 .byte 102,15,56,221,217 + pxor %xmm0,%xmm0 + pxor %xmm1,%xmm1 + pxor %xmm2,%xmm2 movups %xmm3,(%r9) + pxor %xmm3,%xmm3 + pxor %xmm8,%xmm8 + pxor %xmm6,%xmm6 .byte 0xf3,0xc3 .globl _aesni_ctr32_encrypt_blocks @@ -958,14 +1002,43 @@ L$oop_enc1_6: .p2align 4 _aesni_ctr32_encrypt_blocks: + cmpq $1,%rdx + jne L$ctr32_bulk + + + + movups (%r8),%xmm2 + movups (%rdi),%xmm3 + movl 240(%rcx),%edx + movups (%rcx),%xmm0 + movups 16(%rcx),%xmm1 + leaq 32(%rcx),%rcx + xorps %xmm0,%xmm2 +L$oop_enc1_7: +.byte 102,15,56,220,209 + decl %edx + movups (%rcx),%xmm1 + leaq 16(%rcx),%rcx + jnz L$oop_enc1_7 +.byte 102,15,56,221,209 + pxor %xmm0,%xmm0 + pxor %xmm1,%xmm1 + xorps %xmm3,%xmm2 + pxor %xmm3,%xmm3 + movups %xmm2,(%rsi) + xorps %xmm2,%xmm2 + jmp L$ctr32_epilogue + +.p2align 4 +L$ctr32_bulk: leaq (%rsp),%rax pushq %rbp subq $128,%rsp andq $-16,%rsp leaq -8(%rax),%rbp - cmpq $1,%rdx - je L$ctr32_one_shortcut + + movdqu (%r8),%xmm2 movdqu (%rcx),%xmm0 @@ -1356,11 +1429,14 @@ L$ctr32_enc_done: leaq -128(%rcx),%rcx L$ctr32_tail: + + leaq 16(%rcx),%rcx cmpq $4,%rdx jb L$ctr32_loop3 je L$ctr32_loop4 + shll $4,%eax movdqa 96(%rsp),%xmm8 pxor %xmm9,%xmm9 @@ -1463,30 +1539,33 @@ L$ctr32_loop3: movups 32(%rdi),%xmm12 xorps %xmm12,%xmm4 movups %xmm4,32(%rsi) - jmp L$ctr32_done -.p2align 4 -L$ctr32_one_shortcut: - movups (%r8),%xmm2 - movups (%rdi),%xmm10 - movl 240(%rcx),%eax - movups (%rcx),%xmm0 - movups 16(%rcx),%xmm1 - leaq 32(%rcx),%rcx - xorps %xmm0,%xmm2 -L$oop_enc1_7: -.byte 102,15,56,220,209 - decl %eax - movups (%rcx),%xmm1 - leaq 16(%rcx),%rcx - jnz L$oop_enc1_7 -.byte 102,15,56,221,209 - xorps %xmm10,%xmm2 - movups %xmm2,(%rsi) - jmp L$ctr32_done - -.p2align 4 L$ctr32_done: + xorps %xmm0,%xmm0 + xorl %r11d,%r11d + pxor %xmm1,%xmm1 + pxor %xmm2,%xmm2 + pxor %xmm3,%xmm3 + pxor %xmm4,%xmm4 + pxor %xmm5,%xmm5 + pxor %xmm6,%xmm6 + pxor %xmm7,%xmm7 + movaps %xmm0,0(%rsp) + pxor %xmm8,%xmm8 + movaps %xmm0,16(%rsp) + pxor %xmm9,%xmm9 + movaps %xmm0,32(%rsp) + pxor %xmm10,%xmm10 + movaps %xmm0,48(%rsp) + pxor %xmm11,%xmm11 + movaps %xmm0,64(%rsp) + pxor %xmm12,%xmm12 + movaps %xmm0,80(%rsp) + pxor %xmm13,%xmm13 + movaps %xmm0,96(%rsp) + pxor %xmm14,%xmm14 + movaps %xmm0,112(%rsp) + pxor %xmm15,%xmm15 leaq (%rbp),%rsp popq %rbp L$ctr32_epilogue: @@ -1758,6 +1837,7 @@ L$xts_enc_loop6: shrl $4,%eax L$xts_enc_short: + movl %eax,%r10d pxor %xmm0,%xmm10 addq $96,%rdx @@ -1786,6 +1866,7 @@ L$xts_enc_short: pxor %xmm12,%xmm4 pxor %xmm13,%xmm5 pxor %xmm14,%xmm6 + pxor %xmm7,%xmm7 call _aesni_encrypt6 @@ -1928,6 +2009,29 @@ L$oop_enc1_10: movups %xmm2,-16(%rsi) L$xts_enc_ret: + xorps %xmm0,%xmm0 + pxor %xmm1,%xmm1 + pxor %xmm2,%xmm2 + pxor %xmm3,%xmm3 + pxor %xmm4,%xmm4 + pxor %xmm5,%xmm5 + pxor %xmm6,%xmm6 + pxor %xmm7,%xmm7 + movaps %xmm0,0(%rsp) + pxor %xmm8,%xmm8 + movaps %xmm0,16(%rsp) + pxor %xmm9,%xmm9 + movaps %xmm0,32(%rsp) + pxor %xmm10,%xmm10 + movaps %xmm0,48(%rsp) + pxor %xmm11,%xmm11 + movaps %xmm0,64(%rsp) + pxor %xmm12,%xmm12 + movaps %xmm0,80(%rsp) + pxor %xmm13,%xmm13 + movaps %xmm0,96(%rsp) + pxor %xmm14,%xmm14 + pxor %xmm15,%xmm15 leaq (%rbp),%rsp popq %rbp L$xts_enc_epilogue: @@ -2205,6 +2309,7 @@ L$xts_dec_loop6: shrl $4,%eax L$xts_dec_short: + movl %eax,%r10d pxor %xmm0,%xmm10 pxor %xmm0,%xmm11 @@ -2407,6 +2512,29 @@ L$oop_dec1_14: movups %xmm2,(%rsi) L$xts_dec_ret: + xorps %xmm0,%xmm0 + pxor %xmm1,%xmm1 + pxor %xmm2,%xmm2 + pxor %xmm3,%xmm3 + pxor %xmm4,%xmm4 + pxor %xmm5,%xmm5 + pxor %xmm6,%xmm6 + pxor %xmm7,%xmm7 + movaps %xmm0,0(%rsp) + pxor %xmm8,%xmm8 + movaps %xmm0,16(%rsp) + pxor %xmm9,%xmm9 + movaps %xmm0,32(%rsp) + pxor %xmm10,%xmm10 + movaps %xmm0,48(%rsp) + pxor %xmm11,%xmm11 + movaps %xmm0,64(%rsp) + pxor %xmm12,%xmm12 + movaps %xmm0,80(%rsp) + pxor %xmm13,%xmm13 + movaps %xmm0,96(%rsp) + pxor %xmm14,%xmm14 + pxor %xmm15,%xmm15 leaq (%rbp),%rsp popq %rbp L$xts_dec_epilogue: @@ -2456,7 +2584,11 @@ L$oop_enc1_15: jnc L$cbc_enc_loop addq $16,%rdx jnz L$cbc_enc_tail + pxor %xmm0,%xmm0 + pxor %xmm1,%xmm1 movups %xmm2,(%r8) + pxor %xmm2,%xmm2 + pxor %xmm3,%xmm3 jmp L$cbc_ret L$cbc_enc_tail: @@ -2476,6 +2608,35 @@ L$cbc_enc_tail: .p2align 4 L$cbc_decrypt: + cmpq $16,%rdx + jne L$cbc_decrypt_bulk + + + + movdqu (%rdi),%xmm2 + movdqu (%r8),%xmm3 + movdqa %xmm2,%xmm4 + movups (%rcx),%xmm0 + movups 16(%rcx),%xmm1 + leaq 32(%rcx),%rcx + xorps %xmm0,%xmm2 +L$oop_dec1_16: +.byte 102,15,56,222,209 + decl %r10d + movups (%rcx),%xmm1 + leaq 16(%rcx),%rcx + jnz L$oop_dec1_16 +.byte 102,15,56,223,209 + pxor %xmm0,%xmm0 + pxor %xmm1,%xmm1 + movdqu %xmm4,(%r8) + xorps %xmm3,%xmm2 + pxor %xmm3,%xmm3 + movups %xmm2,(%rsi) + pxor %xmm2,%xmm2 + jmp L$cbc_ret +.p2align 4 +L$cbc_decrypt_bulk: leaq (%rsp),%rax pushq %rbp subq $16,%rsp @@ -2712,7 +2873,7 @@ L$cbc_dec_done: movaps %xmm9,%xmm2 leaq -112(%rcx),%rcx addq $112,%rdx - jle L$cbc_dec_tail_collected + jle L$cbc_dec_clear_tail_collected movups %xmm9,(%rsi) leaq 16(%rsi),%rsi cmpq $80,%rdx @@ -2731,14 +2892,19 @@ L$cbc_dec_six_or_seven: movdqu %xmm2,(%rsi) pxor %xmm12,%xmm4 movdqu %xmm3,16(%rsi) + pxor %xmm3,%xmm3 pxor %xmm13,%xmm5 movdqu %xmm4,32(%rsi) + pxor %xmm4,%xmm4 pxor %xmm14,%xmm6 movdqu %xmm5,48(%rsi) + pxor %xmm5,%xmm5 pxor %xmm15,%xmm7 movdqu %xmm6,64(%rsi) + pxor %xmm6,%xmm6 leaq 80(%rsi),%rsi movdqa %xmm7,%xmm2 + pxor %xmm7,%xmm7 jmp L$cbc_dec_tail_collected .p2align 4 @@ -2753,16 +2919,23 @@ L$cbc_dec_seven: movdqu %xmm2,(%rsi) pxor %xmm12,%xmm4 movdqu %xmm3,16(%rsi) + pxor %xmm3,%xmm3 pxor %xmm13,%xmm5 movdqu %xmm4,32(%rsi) + pxor %xmm4,%xmm4 pxor %xmm14,%xmm6 movdqu %xmm5,48(%rsi) + pxor %xmm5,%xmm5 pxor %xmm15,%xmm7 movdqu %xmm6,64(%rsi) + pxor %xmm6,%xmm6 pxor %xmm9,%xmm8 movdqu %xmm7,80(%rsi) + pxor %xmm7,%xmm7 leaq 96(%rsi),%rsi movdqa %xmm8,%xmm2 + pxor %xmm8,%xmm8 + pxor %xmm9,%xmm9 jmp L$cbc_dec_tail_collected .p2align 4 @@ -2806,7 +2979,7 @@ L$cbc_dec_loop6_enter: movdqa %xmm7,%xmm2 addq $80,%rdx - jle L$cbc_dec_tail_collected + jle L$cbc_dec_clear_tail_collected movups %xmm7,(%rsi) leaq 16(%rsi),%rsi @@ -2841,12 +3014,17 @@ L$cbc_dec_tail: movdqu %xmm2,(%rsi) pxor %xmm12,%xmm4 movdqu %xmm3,16(%rsi) + pxor %xmm3,%xmm3 pxor %xmm13,%xmm5 movdqu %xmm4,32(%rsi) + pxor %xmm4,%xmm4 pxor %xmm14,%xmm6 movdqu %xmm5,48(%rsi) + pxor %xmm5,%xmm5 leaq 64(%rsi),%rsi movdqa %xmm6,%xmm2 + pxor %xmm6,%xmm6 + pxor %xmm7,%xmm7 subq $16,%rdx jmp L$cbc_dec_tail_collected @@ -2857,12 +3035,12 @@ L$cbc_dec_one: movups 16(%rcx),%xmm1 leaq 32(%rcx),%rcx xorps %xmm0,%xmm2 -L$oop_dec1_16: +L$oop_dec1_17: .byte 102,15,56,222,209 decl %eax movups (%rcx),%xmm1 leaq 16(%rcx),%rcx - jnz L$oop_dec1_16 + jnz L$oop_dec1_17 .byte 102,15,56,223,209 xorps %xmm10,%xmm2 movaps %xmm11,%xmm10 @@ -2876,6 +3054,7 @@ L$cbc_dec_two: pxor %xmm11,%xmm3 movdqu %xmm2,(%rsi) movdqa %xmm3,%xmm2 + pxor %xmm3,%xmm3 leaq 16(%rsi),%rsi jmp L$cbc_dec_tail_collected .p2align 4 @@ -2888,7 +3067,9 @@ L$cbc_dec_three: movdqu %xmm2,(%rsi) pxor %xmm12,%xmm4 movdqu %xmm3,16(%rsi) + pxor %xmm3,%xmm3 movdqa %xmm4,%xmm2 + pxor %xmm4,%xmm4 leaq 32(%rsi),%rsi jmp L$cbc_dec_tail_collected .p2align 4 @@ -2901,29 +3082,45 @@ L$cbc_dec_four: movdqu %xmm2,(%rsi) pxor %xmm12,%xmm4 movdqu %xmm3,16(%rsi) + pxor %xmm3,%xmm3 pxor %xmm13,%xmm5 movdqu %xmm4,32(%rsi) + pxor %xmm4,%xmm4 movdqa %xmm5,%xmm2 + pxor %xmm5,%xmm5 leaq 48(%rsi),%rsi jmp L$cbc_dec_tail_collected .p2align 4 +L$cbc_dec_clear_tail_collected: + pxor %xmm3,%xmm3 + pxor %xmm4,%xmm4 + pxor %xmm5,%xmm5 + pxor %xmm6,%xmm6 + pxor %xmm7,%xmm7 + pxor %xmm8,%xmm8 + pxor %xmm9,%xmm9 L$cbc_dec_tail_collected: movups %xmm10,(%r8) andq $15,%rdx jnz L$cbc_dec_tail_partial movups %xmm2,(%rsi) + pxor %xmm2,%xmm2 jmp L$cbc_dec_ret .p2align 4 L$cbc_dec_tail_partial: movaps %xmm2,(%rsp) + pxor %xmm2,%xmm2 movq $16,%rcx movq %rsi,%rdi subq %rdx,%rcx leaq (%rsp),%rsi .long 0x9066A4F3 + movdqa %xmm2,(%rsp) L$cbc_dec_ret: + xorps %xmm0,%xmm0 + pxor %xmm1,%xmm1 leaq (%rbp),%rsp popq %rbp L$cbc_ret: @@ -2962,7 +3159,9 @@ L$dec_key_inverse: movups (%rdx),%xmm0 .byte 102,15,56,219,192 + pxor %xmm1,%xmm1 movups %xmm0,(%rdi) + pxor %xmm0,%xmm0 L$dec_key_ret: addq $8,%rsp .byte 0xf3,0xc3 @@ -2981,8 +3180,10 @@ __aesni_set_encrypt_key: testq %rdx,%rdx jz L$enc_key_ret + movl $268437504,%r10d movups (%rdi),%xmm0 xorps %xmm4,%xmm4 + andl _OPENSSL_ia32cap_P+4(%rip),%r10d leaq 16(%rdx),%rax cmpl $256,%esi je L$14rounds @@ -2993,6 +3194,9 @@ __aesni_set_encrypt_key: L$10rounds: movl $9,%esi + cmpl $268435456,%r10d + je L$10rounds_alt + movups %xmm0,(%rdx) .byte 102,15,58,223,200,1 call L$key_expansion_128_cold @@ -3019,10 +3223,80 @@ L$10rounds: xorl %eax,%eax jmp L$enc_key_ret +.p2align 4 +L$10rounds_alt: + movdqa L$key_rotate(%rip),%xmm5 + movl $8,%r10d + movdqa L$key_rcon1(%rip),%xmm4 + movdqa %xmm0,%xmm2 + movdqu %xmm0,(%rdx) + jmp L$oop_key128 + +.p2align 4 +L$oop_key128: +.byte 102,15,56,0,197 +.byte 102,15,56,221,196 + pslld $1,%xmm4 + leaq 16(%rax),%rax + + movdqa %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm3,%xmm2 + + pxor %xmm2,%xmm0 + movdqu %xmm0,-16(%rax) + movdqa %xmm0,%xmm2 + + decl %r10d + jnz L$oop_key128 + + movdqa L$key_rcon1b(%rip),%xmm4 + +.byte 102,15,56,0,197 +.byte 102,15,56,221,196 + pslld $1,%xmm4 + + movdqa %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm3,%xmm2 + + pxor %xmm2,%xmm0 + movdqu %xmm0,(%rax) + + movdqa %xmm0,%xmm2 +.byte 102,15,56,0,197 +.byte 102,15,56,221,196 + + movdqa %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm3,%xmm2 + + pxor %xmm2,%xmm0 + movdqu %xmm0,16(%rax) + + movl %esi,96(%rax) + xorl %eax,%eax + jmp L$enc_key_ret + .p2align 4 L$12rounds: movq 16(%rdi),%xmm2 movl $11,%esi + cmpl $268435456,%r10d + je L$12rounds_alt + movups %xmm0,(%rdx) .byte 102,15,58,223,202,1 call L$key_expansion_192a_cold @@ -3045,11 +3319,55 @@ L$12rounds: xorq %rax,%rax jmp L$enc_key_ret +.p2align 4 +L$12rounds_alt: + movdqa L$key_rotate192(%rip),%xmm5 + movdqa L$key_rcon1(%rip),%xmm4 + movl $8,%r10d + movdqu %xmm0,(%rdx) + jmp L$oop_key192 + +.p2align 4 +L$oop_key192: + movq %xmm2,0(%rax) + movdqa %xmm2,%xmm1 +.byte 102,15,56,0,213 +.byte 102,15,56,221,212 + pslld $1,%xmm4 + leaq 24(%rax),%rax + + movdqa %xmm0,%xmm3 + pslldq $4,%xmm0 + pxor %xmm0,%xmm3 + pslldq $4,%xmm0 + pxor %xmm0,%xmm3 + pslldq $4,%xmm0 + pxor %xmm3,%xmm0 + + pshufd $255,%xmm0,%xmm3 + pxor %xmm1,%xmm3 + pslldq $4,%xmm1 + pxor %xmm1,%xmm3 + + pxor %xmm2,%xmm0 + pxor %xmm3,%xmm2 + movdqu %xmm0,-16(%rax) + + decl %r10d + jnz L$oop_key192 + + movl %esi,32(%rax) + xorl %eax,%eax + jmp L$enc_key_ret + .p2align 4 L$14rounds: movups 16(%rdi),%xmm2 movl $13,%esi leaq 16(%rax),%rax + cmpl $268435456,%r10d + je L$14rounds_alt + movups %xmm0,(%rdx) movups %xmm2,16(%rdx) .byte 102,15,58,223,202,1 @@ -3083,10 +3401,70 @@ L$14rounds: xorq %rax,%rax jmp L$enc_key_ret +.p2align 4 +L$14rounds_alt: + movdqa L$key_rotate(%rip),%xmm5 + movdqa L$key_rcon1(%rip),%xmm4 + movl $7,%r10d + movdqu %xmm0,0(%rdx) + movdqa %xmm2,%xmm1 + movdqu %xmm2,16(%rdx) + jmp L$oop_key256 + +.p2align 4 +L$oop_key256: +.byte 102,15,56,0,213 +.byte 102,15,56,221,212 + + movdqa %xmm0,%xmm3 + pslldq $4,%xmm0 + pxor %xmm0,%xmm3 + pslldq $4,%xmm0 + pxor %xmm0,%xmm3 + pslldq $4,%xmm0 + pxor %xmm3,%xmm0 + pslld $1,%xmm4 + + pxor %xmm2,%xmm0 + movdqu %xmm0,(%rax) + + decl %r10d + jz L$done_key256 + + pshufd $255,%xmm0,%xmm2 + pxor %xmm3,%xmm3 +.byte 102,15,56,221,211 + + movdqa %xmm1,%xmm3 + pslldq $4,%xmm1 + pxor %xmm1,%xmm3 + pslldq $4,%xmm1 + pxor %xmm1,%xmm3 + pslldq $4,%xmm1 + pxor %xmm3,%xmm1 + + pxor %xmm1,%xmm2 + movdqu %xmm2,16(%rax) + leaq 32(%rax),%rax + movdqa %xmm2,%xmm1 + + jmp L$oop_key256 + +L$done_key256: + movl %esi,16(%rax) + xorl %eax,%eax + jmp L$enc_key_ret + .p2align 4 L$bad_keybits: movq $-2,%rax L$enc_key_ret: + pxor %xmm0,%xmm0 + pxor %xmm1,%xmm1 + pxor %xmm2,%xmm2 + pxor %xmm3,%xmm3 + pxor %xmm4,%xmm4 + pxor %xmm5,%xmm5 addq $8,%rsp .byte 0xf3,0xc3 L$SEH_end_set_encrypt_key: @@ -3172,6 +3550,14 @@ L$xts_magic: .long 0x87,0,1,0 L$increment1: .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 +L$key_rotate: +.long 0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d +L$key_rotate192: +.long 0x04070605,0x04070605,0x04070605,0x04070605 +L$key_rcon1: +.long 1,1,1,1 +L$key_rcon1b: +.long 0x1b,0x1b,0x1b,0x1b .byte 65,69,83,32,102,111,114,32,73,110,116,101,108,32,65,69,83,45,78,73,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0 .p2align 6 diff --git a/third_party/boringssl/mac-x86_64/crypto/rand/rdrand-x86_64.S b/third_party/boringssl/mac-x86_64/crypto/rand/rdrand-x86_64.S new file mode 100644 index 0000000000000..f0df296e1a3c8 --- /dev/null +++ b/third_party/boringssl/mac-x86_64/crypto/rand/rdrand-x86_64.S @@ -0,0 +1,48 @@ +#if defined(__x86_64__) +.text + + + + +.globl _CRYPTO_rdrand +.private_extern _CRYPTO_rdrand + +.p2align 4 +_CRYPTO_rdrand: + xorq %rax,%rax + + +.byte 0x48, 0x0f, 0xc7, 0xf1 + + adcq %rax,%rax + movq %rcx,0(%rdi) + .byte 0xf3,0xc3 + + + + + +.globl _CRYPTO_rdrand_multiple8_buf +.private_extern _CRYPTO_rdrand_multiple8_buf + +.p2align 4 +_CRYPTO_rdrand_multiple8_buf: + testq %rsi,%rsi + jz L$out + movq $8,%rdx +L$loop: + + +.byte 0x48, 0x0f, 0xc7, 0xf1 + jnc L$err + movq %rcx,0(%rdi) + addq %rdx,%rdi + subq %rdx,%rsi + jnz L$loop +L$out: + movq $1,%rax + .byte 0xf3,0xc3 +L$err: + xorq %rax,%rax + .byte 0xf3,0xc3 +#endif diff --git a/third_party/boringssl/update_gypi_and_asm.py b/third_party/boringssl/update_gypi_and_asm.py deleted file mode 100644 index 18356958fa39b..0000000000000 --- a/third_party/boringssl/update_gypi_and_asm.py +++ /dev/null @@ -1,257 +0,0 @@ -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can b -# found in the LICENSE file. - -"""Enumerates the BoringSSL source in src/ and generates two gypi files: - boringssl.gypi and boringssl_tests.gypi.""" - -import os -import subprocess -import sys - - -# OS_ARCH_COMBOS maps from OS and platform to the OpenSSL assembly "style" for -# that platform and the extension used by asm files. -OS_ARCH_COMBOS = [ - ('linux', 'arm', 'elf', [''], 'S'), - ('linux', 'aarch64', 'linux64', [''], 'S'), - ('linux', 'x86', 'elf', ['-fPIC'], 'S'), - ('linux', 'x86_64', 'elf', [''], 'S'), - ('mac', 'x86', 'macosx', ['-fPIC'], 'S'), - ('mac', 'x86_64', 'macosx', [''], 'S'), - ('win', 'x86', 'win32n', [''], 'asm'), - ('win', 'x86_64', 'nasm', [''], 'asm'), -] - -# NON_PERL_FILES enumerates assembly files that are not processed by the -# perlasm system. -NON_PERL_FILES = { - ('linux', 'arm'): [ - 'src/crypto/poly1305/poly1305_arm_asm.S', - 'src/crypto/chacha/chacha_vec_arm.S', - 'src/crypto/cpu-arm-asm.S', - ], -} - -FILE_HEADER = """# Copyright (c) 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# This file is created by update_gypi_and_asm.py. Do not edit manually. - -""" - - -def FindCMakeFiles(directory): - """Returns list of all CMakeLists.txt files recursively in directory.""" - cmakefiles = [] - - for (path, _, filenames) in os.walk(directory): - for filename in filenames: - if filename == 'CMakeLists.txt': - cmakefiles.append(os.path.join(path, filename)) - - return cmakefiles - - -def NoTests(dent, is_dir): - """Filter function that can be passed to FindCFiles in order to remove test - sources.""" - if is_dir: - return dent != 'test' - return 'test.' not in dent and not dent.startswith('example_') - - -def OnlyTests(dent, is_dir): - """Filter function that can be passed to FindCFiles in order to remove - non-test sources.""" - if is_dir: - return True - return '_test.' in dent or dent.startswith('example_') - - -def FindCFiles(directory, filter_func): - """Recurses through directory and returns a list of paths to all the C source - files that pass filter_func.""" - cfiles = [] - - for (path, dirnames, filenames) in os.walk(directory): - for filename in filenames: - if filename.endswith('.c') and filter_func(filename, False): - cfiles.append(os.path.join(path, filename)) - continue - - for (i, dirname) in enumerate(dirnames): - if not filter_func(dirname, True): - del dirnames[i] - - return cfiles - - -def ExtractPerlAsmFromCMakeFile(cmakefile): - """Parses the contents of the CMakeLists.txt file passed as an argument and - returns a list of all the perlasm() directives found in the file.""" - perlasms = [] - with open(cmakefile) as f: - for line in f: - line = line.strip() - if not line.startswith('perlasm('): - continue - if not line.endswith(')'): - raise ValueError('Bad perlasm line in %s' % cmakefile) - # Remove "perlasm(" from start and ")" from end - params = line[8:-1].split() - if len(params) < 2: - raise ValueError('Bad perlasm line in %s' % cmakefile) - perlasms.append({ - 'extra_args': params[2:], - 'input': os.path.join(os.path.dirname(cmakefile), params[1]), - 'output': os.path.join(os.path.dirname(cmakefile), params[0]), - }) - - return perlasms - - -def ReadPerlAsmOperations(): - """Returns a list of all perlasm() directives found in CMake config files in - src/.""" - perlasms = [] - cmakefiles = FindCMakeFiles('src') - - for cmakefile in cmakefiles: - perlasms.extend(ExtractPerlAsmFromCMakeFile(cmakefile)) - - return perlasms - - -def PerlAsm(output_filename, input_filename, perlasm_style, extra_args): - """Runs the a perlasm script and puts the output into output_filename.""" - base_dir = os.path.dirname(output_filename) - if not os.path.isdir(base_dir): - os.makedirs(base_dir) - output = subprocess.check_output( - ['perl', input_filename, perlasm_style] + extra_args) - with open(output_filename, 'w+') as out_file: - out_file.write(output) - - -def ArchForAsmFilename(filename): - """Returns the architectures that a given asm file should be compiled for - based on substrings in the filename.""" - - if 'x86_64' in filename or 'avx2' in filename: - return ['x86_64'] - elif ('x86' in filename and 'x86_64' not in filename) or '586' in filename: - return ['x86'] - elif 'armx' in filename: - return ['arm', 'aarch64'] - elif 'armv8' in filename: - return ['aarch64'] - elif 'arm' in filename: - return ['arm'] - else: - raise ValueError('Unknown arch for asm filename: ' + filename) - - -def WriteAsmFiles(perlasms): - """Generates asm files from perlasm directives for each supported OS x - platform combination.""" - asmfiles = {} - - for osarch in OS_ARCH_COMBOS: - (osname, arch, perlasm_style, extra_args, asm_ext) = osarch - key = (osname, arch) - outDir = '%s-%s' % key - - for perlasm in perlasms: - filename = os.path.basename(perlasm['input']) - output = perlasm['output'] - if not output.startswith('src'): - raise ValueError('output missing src: %s' % output) - output = os.path.join(outDir, output[4:]) - output = output.replace('${ASM_EXT}', asm_ext) - - if arch in ArchForAsmFilename(filename): - PerlAsm(output, perlasm['input'], perlasm_style, - perlasm['extra_args'] + extra_args) - asmfiles.setdefault(key, []).append(output) - - for (key, non_perl_asm_files) in NON_PERL_FILES.iteritems(): - asmfiles.setdefault(key, []).extend(non_perl_asm_files) - - return asmfiles - - -def PrintVariableSection(out, name, files): - out.write(' \'%s\': [\n' % name) - for f in sorted(files): - out.write(' \'%s\',\n' % f) - out.write(' ],\n') - - -def main(): - crypto_c_files = FindCFiles(os.path.join('src', 'crypto'), NoTests) - ssl_c_files = FindCFiles(os.path.join('src', 'ssl'), NoTests) - - # Generate err_data.c - with open('err_data.c', 'w+') as err_data: - subprocess.check_call(['go', 'run', 'err_data_generate.go'], - cwd=os.path.join('src', 'crypto', 'err'), - stdout=err_data) - crypto_c_files.append('err_data.c') - - with open('boringssl.gypi', 'w+') as gypi: - gypi.write(FILE_HEADER + '{\n \'variables\': {\n') - - PrintVariableSection( - gypi, 'boringssl_lib_sources', crypto_c_files + ssl_c_files) - - perlasms = ReadPerlAsmOperations() - - for ((osname, arch), asm_files) in sorted( - WriteAsmFiles(perlasms).iteritems()): - PrintVariableSection(gypi, 'boringssl_%s_%s_sources' % - (osname, arch), asm_files) - - gypi.write(' }\n}\n') - - test_c_files = FindCFiles(os.path.join('src', 'crypto'), OnlyTests) - test_c_files += FindCFiles(os.path.join('src', 'ssl'), OnlyTests) - - with open('boringssl_tests.gypi', 'w+') as test_gypi: - test_gypi.write(FILE_HEADER + '{\n \'targets\': [\n') - - test_names = [] - for test in sorted(test_c_files): - test_name = 'boringssl_%s' % os.path.splitext(os.path.basename(test))[0] - test_gypi.write(""" { - 'target_name': '%s', - 'type': 'executable', - 'dependencies': [ - 'boringssl.gyp:boringssl', - ], - 'sources': [ - '%s', - ], - # TODO(davidben): Fix size_t truncations in BoringSSL. - # https://crbug.com/429039 - 'msvs_disabled_warnings': [ 4267, ], - },\n""" % (test_name, test)) - test_names.append(test_name) - - test_names.sort() - - test_gypi.write(""" ], - 'variables': { - 'boringssl_test_targets': [\n""") - - for test in test_names: - test_gypi.write(""" '%s',\n""" % test) - - test_gypi.write(' ],\n }\n}\n') - - return 0 - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/third_party/boringssl/win-x86/crypto/aes/aesni-x86.asm b/third_party/boringssl/win-x86/crypto/aes/aesni-x86.asm index 845bb35fdbf77..a9a595653f082 100644 --- a/third_party/boringssl/win-x86/crypto/aes/aesni-x86.asm +++ b/third_party/boringssl/win-x86/crypto/aes/aesni-x86.asm @@ -14,6 +14,7 @@ section .text code align=64 %else section .text code %endif +;extern _OPENSSL_ia32cap_P global _aesni_encrypt align 16 _aesni_encrypt: @@ -34,7 +35,10 @@ db 102,15,56,220,209 lea edx,[16+edx] jnz NEAR L$000enc1_loop_1 db 102,15,56,221,209 + pxor xmm0,xmm0 + pxor xmm1,xmm1 movups [eax],xmm2 + pxor xmm2,xmm2 ret global _aesni_decrypt align 16 @@ -56,7 +60,10 @@ db 102,15,56,222,209 lea edx,[16+edx] jnz NEAR L$001dec1_loop_2 db 102,15,56,223,209 + pxor xmm0,xmm0 + pxor xmm1,xmm1 movups [eax],xmm2 + pxor xmm2,xmm2 ret align 16 __aesni_encrypt2: @@ -256,17 +263,15 @@ db 102,15,56,220,217 neg ecx db 102,15,56,220,225 pxor xmm7,xmm0 + movups xmm0,[ecx*1+edx] add ecx,16 -db 102,15,56,220,233 -db 102,15,56,220,241 -db 102,15,56,220,249 - movups xmm0,[ecx*1+edx-16] - jmp NEAR L$_aesni_encrypt6_enter + jmp NEAR L$008_aesni_encrypt6_inner align 16 -L$008enc6_loop: +L$009enc6_loop: db 102,15,56,220,209 db 102,15,56,220,217 db 102,15,56,220,225 +L$008_aesni_encrypt6_inner: db 102,15,56,220,233 db 102,15,56,220,241 db 102,15,56,220,249 @@ -280,7 +285,7 @@ db 102,15,56,220,232 db 102,15,56,220,240 db 102,15,56,220,248 movups xmm0,[ecx*1+edx-16] - jnz NEAR L$008enc6_loop + jnz NEAR L$009enc6_loop db 102,15,56,220,209 db 102,15,56,220,217 db 102,15,56,220,225 @@ -310,17 +315,15 @@ db 102,15,56,222,217 neg ecx db 102,15,56,222,225 pxor xmm7,xmm0 + movups xmm0,[ecx*1+edx] add ecx,16 -db 102,15,56,222,233 -db 102,15,56,222,241 -db 102,15,56,222,249 - movups xmm0,[ecx*1+edx-16] - jmp NEAR L$_aesni_decrypt6_enter + jmp NEAR L$010_aesni_decrypt6_inner align 16 -L$009dec6_loop: +L$011dec6_loop: db 102,15,56,222,209 db 102,15,56,222,217 db 102,15,56,222,225 +L$010_aesni_decrypt6_inner: db 102,15,56,222,233 db 102,15,56,222,241 db 102,15,56,222,249 @@ -334,7 +337,7 @@ db 102,15,56,222,232 db 102,15,56,222,240 db 102,15,56,222,248 movups xmm0,[ecx*1+edx-16] - jnz NEAR L$009dec6_loop + jnz NEAR L$011dec6_loop db 102,15,56,222,209 db 102,15,56,222,217 db 102,15,56,222,225 @@ -362,14 +365,14 @@ L$_aesni_ecb_encrypt_begin: mov edx,DWORD [32+esp] mov ebx,DWORD [36+esp] and eax,-16 - jz NEAR L$010ecb_ret + jz NEAR L$012ecb_ret mov ecx,DWORD [240+edx] test ebx,ebx - jz NEAR L$011ecb_decrypt + jz NEAR L$013ecb_decrypt mov ebp,edx mov ebx,ecx cmp eax,96 - jb NEAR L$012ecb_enc_tail + jb NEAR L$014ecb_enc_tail movdqu xmm2,[esi] movdqu xmm3,[16+esi] movdqu xmm4,[32+esi] @@ -378,9 +381,9 @@ L$_aesni_ecb_encrypt_begin: movdqu xmm7,[80+esi] lea esi,[96+esi] sub eax,96 - jmp NEAR L$013ecb_enc_loop6_enter + jmp NEAR L$015ecb_enc_loop6_enter align 16 -L$014ecb_enc_loop6: +L$016ecb_enc_loop6: movups [edi],xmm2 movdqu xmm2,[esi] movups [16+edi],xmm3 @@ -395,12 +398,12 @@ L$014ecb_enc_loop6: lea edi,[96+edi] movdqu xmm7,[80+esi] lea esi,[96+esi] -L$013ecb_enc_loop6_enter: +L$015ecb_enc_loop6_enter: call __aesni_encrypt6 mov edx,ebp mov ecx,ebx sub eax,96 - jnc NEAR L$014ecb_enc_loop6 + jnc NEAR L$016ecb_enc_loop6 movups [edi],xmm2 movups [16+edi],xmm3 movups [32+edi],xmm4 @@ -409,18 +412,18 @@ L$013ecb_enc_loop6_enter: movups [80+edi],xmm7 lea edi,[96+edi] add eax,96 - jz NEAR L$010ecb_ret -L$012ecb_enc_tail: + jz NEAR L$012ecb_ret +L$014ecb_enc_tail: movups xmm2,[esi] cmp eax,32 - jb NEAR L$015ecb_enc_one + jb NEAR L$017ecb_enc_one movups xmm3,[16+esi] - je NEAR L$016ecb_enc_two + je NEAR L$018ecb_enc_two movups xmm4,[32+esi] cmp eax,64 - jb NEAR L$017ecb_enc_three + jb NEAR L$019ecb_enc_three movups xmm5,[48+esi] - je NEAR L$018ecb_enc_four + je NEAR L$020ecb_enc_four movups xmm6,[64+esi] xorps xmm7,xmm7 call __aesni_encrypt6 @@ -429,49 +432,49 @@ L$012ecb_enc_tail: movups [32+edi],xmm4 movups [48+edi],xmm5 movups [64+edi],xmm6 - jmp NEAR L$010ecb_ret + jmp NEAR L$012ecb_ret align 16 -L$015ecb_enc_one: +L$017ecb_enc_one: movups xmm0,[edx] movups xmm1,[16+edx] lea edx,[32+edx] xorps xmm2,xmm0 -L$019enc1_loop_3: +L$021enc1_loop_3: db 102,15,56,220,209 dec ecx movups xmm1,[edx] lea edx,[16+edx] - jnz NEAR L$019enc1_loop_3 + jnz NEAR L$021enc1_loop_3 db 102,15,56,221,209 movups [edi],xmm2 - jmp NEAR L$010ecb_ret + jmp NEAR L$012ecb_ret align 16 -L$016ecb_enc_two: +L$018ecb_enc_two: call __aesni_encrypt2 movups [edi],xmm2 movups [16+edi],xmm3 - jmp NEAR L$010ecb_ret + jmp NEAR L$012ecb_ret align 16 -L$017ecb_enc_three: +L$019ecb_enc_three: call __aesni_encrypt3 movups [edi],xmm2 movups [16+edi],xmm3 movups [32+edi],xmm4 - jmp NEAR L$010ecb_ret + jmp NEAR L$012ecb_ret align 16 -L$018ecb_enc_four: +L$020ecb_enc_four: call __aesni_encrypt4 movups [edi],xmm2 movups [16+edi],xmm3 movups [32+edi],xmm4 movups [48+edi],xmm5 - jmp NEAR L$010ecb_ret + jmp NEAR L$012ecb_ret align 16 -L$011ecb_decrypt: +L$013ecb_decrypt: mov ebp,edx mov ebx,ecx cmp eax,96 - jb NEAR L$020ecb_dec_tail + jb NEAR L$022ecb_dec_tail movdqu xmm2,[esi] movdqu xmm3,[16+esi] movdqu xmm4,[32+esi] @@ -480,9 +483,9 @@ L$011ecb_decrypt: movdqu xmm7,[80+esi] lea esi,[96+esi] sub eax,96 - jmp NEAR L$021ecb_dec_loop6_enter + jmp NEAR L$023ecb_dec_loop6_enter align 16 -L$022ecb_dec_loop6: +L$024ecb_dec_loop6: movups [edi],xmm2 movdqu xmm2,[esi] movups [16+edi],xmm3 @@ -497,12 +500,12 @@ L$022ecb_dec_loop6: lea edi,[96+edi] movdqu xmm7,[80+esi] lea esi,[96+esi] -L$021ecb_dec_loop6_enter: +L$023ecb_dec_loop6_enter: call __aesni_decrypt6 mov edx,ebp mov ecx,ebx sub eax,96 - jnc NEAR L$022ecb_dec_loop6 + jnc NEAR L$024ecb_dec_loop6 movups [edi],xmm2 movups [16+edi],xmm3 movups [32+edi],xmm4 @@ -511,18 +514,18 @@ L$021ecb_dec_loop6_enter: movups [80+edi],xmm7 lea edi,[96+edi] add eax,96 - jz NEAR L$010ecb_ret -L$020ecb_dec_tail: + jz NEAR L$012ecb_ret +L$022ecb_dec_tail: movups xmm2,[esi] cmp eax,32 - jb NEAR L$023ecb_dec_one + jb NEAR L$025ecb_dec_one movups xmm3,[16+esi] - je NEAR L$024ecb_dec_two + je NEAR L$026ecb_dec_two movups xmm4,[32+esi] cmp eax,64 - jb NEAR L$025ecb_dec_three + jb NEAR L$027ecb_dec_three movups xmm5,[48+esi] - je NEAR L$026ecb_dec_four + je NEAR L$028ecb_dec_four movups xmm6,[64+esi] xorps xmm7,xmm7 call __aesni_decrypt6 @@ -531,43 +534,51 @@ L$020ecb_dec_tail: movups [32+edi],xmm4 movups [48+edi],xmm5 movups [64+edi],xmm6 - jmp NEAR L$010ecb_ret + jmp NEAR L$012ecb_ret align 16 -L$023ecb_dec_one: +L$025ecb_dec_one: movups xmm0,[edx] movups xmm1,[16+edx] lea edx,[32+edx] xorps xmm2,xmm0 -L$027dec1_loop_4: +L$029dec1_loop_4: db 102,15,56,222,209 dec ecx movups xmm1,[edx] lea edx,[16+edx] - jnz NEAR L$027dec1_loop_4 + jnz NEAR L$029dec1_loop_4 db 102,15,56,223,209 movups [edi],xmm2 - jmp NEAR L$010ecb_ret + jmp NEAR L$012ecb_ret align 16 -L$024ecb_dec_two: +L$026ecb_dec_two: call __aesni_decrypt2 movups [edi],xmm2 movups [16+edi],xmm3 - jmp NEAR L$010ecb_ret + jmp NEAR L$012ecb_ret align 16 -L$025ecb_dec_three: +L$027ecb_dec_three: call __aesni_decrypt3 movups [edi],xmm2 movups [16+edi],xmm3 movups [32+edi],xmm4 - jmp NEAR L$010ecb_ret + jmp NEAR L$012ecb_ret align 16 -L$026ecb_dec_four: +L$028ecb_dec_four: call __aesni_decrypt4 movups [edi],xmm2 movups [16+edi],xmm3 movups [32+edi],xmm4 movups [48+edi],xmm5 -L$010ecb_ret: +L$012ecb_ret: + pxor xmm0,xmm0 + pxor xmm1,xmm1 + pxor xmm2,xmm2 + pxor xmm3,xmm3 + pxor xmm4,xmm4 + pxor xmm5,xmm5 + pxor xmm6,xmm6 + pxor xmm7,xmm7 pop edi pop esi pop ebx @@ -612,7 +623,7 @@ L$_aesni_ccm64_encrypt_blocks_begin: lea edx,[32+ecx*1+edx] sub ebx,ecx db 102,15,56,0,253 -L$028ccm64_enc_outer: +L$030ccm64_enc_outer: movups xmm0,[ebp] mov ecx,ebx movups xmm6,[esi] @@ -621,7 +632,7 @@ L$028ccm64_enc_outer: xorps xmm0,xmm6 xorps xmm3,xmm0 movups xmm0,[32+ebp] -L$029ccm64_enc2_loop: +L$031ccm64_enc2_loop: db 102,15,56,220,209 db 102,15,56,220,217 movups xmm1,[ecx*1+edx] @@ -629,7 +640,7 @@ db 102,15,56,220,217 db 102,15,56,220,208 db 102,15,56,220,216 movups xmm0,[ecx*1+edx-16] - jnz NEAR L$029ccm64_enc2_loop + jnz NEAR L$031ccm64_enc2_loop db 102,15,56,220,209 db 102,15,56,220,217 paddq xmm7,[16+esp] @@ -642,10 +653,18 @@ db 102,15,56,221,216 movups [edi],xmm6 db 102,15,56,0,213 lea edi,[16+edi] - jnz NEAR L$028ccm64_enc_outer + jnz NEAR L$030ccm64_enc_outer mov esp,DWORD [48+esp] mov edi,DWORD [40+esp] movups [edi],xmm3 + pxor xmm0,xmm0 + pxor xmm1,xmm1 + pxor xmm2,xmm2 + pxor xmm3,xmm3 + pxor xmm4,xmm4 + pxor xmm5,xmm5 + pxor xmm6,xmm6 + pxor xmm7,xmm7 pop edi pop esi pop ebx @@ -691,12 +710,12 @@ db 102,15,56,0,253 movups xmm1,[16+edx] lea edx,[32+edx] xorps xmm2,xmm0 -L$030enc1_loop_5: +L$032enc1_loop_5: db 102,15,56,220,209 dec ecx movups xmm1,[edx] lea edx,[16+edx] - jnz NEAR L$030enc1_loop_5 + jnz NEAR L$032enc1_loop_5 db 102,15,56,221,209 shl ebx,4 mov ecx,16 @@ -706,16 +725,16 @@ db 102,15,56,221,209 sub ecx,ebx lea edx,[32+ebx*1+ebp] mov ebx,ecx - jmp NEAR L$031ccm64_dec_outer + jmp NEAR L$033ccm64_dec_outer align 16 -L$031ccm64_dec_outer: +L$033ccm64_dec_outer: xorps xmm6,xmm2 movdqa xmm2,xmm7 movups [edi],xmm6 lea edi,[16+edi] db 102,15,56,0,213 sub eax,1 - jz NEAR L$032ccm64_dec_break + jz NEAR L$034ccm64_dec_break movups xmm0,[ebp] mov ecx,ebx movups xmm1,[16+ebp] @@ -723,7 +742,7 @@ db 102,15,56,0,213 xorps xmm2,xmm0 xorps xmm3,xmm6 movups xmm0,[32+ebp] -L$033ccm64_dec2_loop: +L$035ccm64_dec2_loop: db 102,15,56,220,209 db 102,15,56,220,217 movups xmm1,[ecx*1+edx] @@ -731,7 +750,7 @@ db 102,15,56,220,217 db 102,15,56,220,208 db 102,15,56,220,216 movups xmm0,[ecx*1+edx-16] - jnz NEAR L$033ccm64_dec2_loop + jnz NEAR L$035ccm64_dec2_loop movups xmm6,[esi] paddq xmm7,[16+esp] db 102,15,56,220,209 @@ -739,9 +758,9 @@ db 102,15,56,220,217 db 102,15,56,221,208 db 102,15,56,221,216 lea esi,[16+esi] - jmp NEAR L$031ccm64_dec_outer + jmp NEAR L$033ccm64_dec_outer align 16 -L$032ccm64_dec_break: +L$034ccm64_dec_break: mov ecx,DWORD [240+ebp] mov edx,ebp movups xmm0,[edx] @@ -749,16 +768,24 @@ L$032ccm64_dec_break: xorps xmm6,xmm0 lea edx,[32+edx] xorps xmm3,xmm6 -L$034enc1_loop_6: +L$036enc1_loop_6: db 102,15,56,220,217 dec ecx movups xmm1,[edx] lea edx,[16+edx] - jnz NEAR L$034enc1_loop_6 + jnz NEAR L$036enc1_loop_6 db 102,15,56,221,217 mov esp,DWORD [48+esp] mov edi,DWORD [40+esp] movups [edi],xmm3 + pxor xmm0,xmm0 + pxor xmm1,xmm1 + pxor xmm2,xmm2 + pxor xmm3,xmm3 + pxor xmm4,xmm4 + pxor xmm5,xmm5 + pxor xmm6,xmm6 + pxor xmm7,xmm7 pop edi pop esi pop ebx @@ -782,7 +809,7 @@ L$_aesni_ctr32_encrypt_blocks_begin: and esp,-16 mov DWORD [80+esp],ebp cmp eax,1 - je NEAR L$035ctr32_one_shortcut + je NEAR L$037ctr32_one_shortcut movdqu xmm7,[ebx] mov DWORD [esp],202182159 mov DWORD [4+esp],134810123 @@ -820,7 +847,7 @@ db 102,15,56,0,202 pshufd xmm2,xmm0,192 pshufd xmm3,xmm0,128 cmp eax,6 - jb NEAR L$036ctr32_tail + jb NEAR L$038ctr32_tail pxor xmm7,xmm6 shl ecx,4 mov ebx,16 @@ -829,9 +856,9 @@ db 102,15,56,0,202 sub ebx,ecx lea edx,[32+ecx*1+edx] sub eax,6 - jmp NEAR L$037ctr32_loop6 + jmp NEAR L$039ctr32_loop6 align 16 -L$037ctr32_loop6: +L$039ctr32_loop6: pshufd xmm4,xmm0,64 movdqa xmm0,[32+esp] pshufd xmm5,xmm1,192 @@ -885,27 +912,27 @@ db 102,15,56,0,202 lea edi,[96+edi] pshufd xmm3,xmm0,128 sub eax,6 - jnc NEAR L$037ctr32_loop6 + jnc NEAR L$039ctr32_loop6 add eax,6 - jz NEAR L$038ctr32_ret + jz NEAR L$040ctr32_ret movdqu xmm7,[ebp] mov edx,ebp pxor xmm7,[32+esp] mov ecx,DWORD [240+ebp] -L$036ctr32_tail: +L$038ctr32_tail: por xmm2,xmm7 cmp eax,2 - jb NEAR L$039ctr32_one + jb NEAR L$041ctr32_one pshufd xmm4,xmm0,64 por xmm3,xmm7 - je NEAR L$040ctr32_two + je NEAR L$042ctr32_two pshufd xmm5,xmm1,192 por xmm4,xmm7 cmp eax,4 - jb NEAR L$041ctr32_three + jb NEAR L$043ctr32_three pshufd xmm6,xmm1,128 por xmm5,xmm7 - je NEAR L$042ctr32_four + je NEAR L$044ctr32_four por xmm6,xmm7 call __aesni_encrypt6 movups xmm1,[esi] @@ -923,29 +950,29 @@ L$036ctr32_tail: movups [32+edi],xmm4 movups [48+edi],xmm5 movups [64+edi],xmm6 - jmp NEAR L$038ctr32_ret + jmp NEAR L$040ctr32_ret align 16 -L$035ctr32_one_shortcut: +L$037ctr32_one_shortcut: movups xmm2,[ebx] mov ecx,DWORD [240+edx] -L$039ctr32_one: +L$041ctr32_one: movups xmm0,[edx] movups xmm1,[16+edx] lea edx,[32+edx] xorps xmm2,xmm0 -L$043enc1_loop_7: +L$045enc1_loop_7: db 102,15,56,220,209 dec ecx movups xmm1,[edx] lea edx,[16+edx] - jnz NEAR L$043enc1_loop_7 + jnz NEAR L$045enc1_loop_7 db 102,15,56,221,209 movups xmm6,[esi] xorps xmm6,xmm2 movups [edi],xmm6 - jmp NEAR L$038ctr32_ret + jmp NEAR L$040ctr32_ret align 16 -L$040ctr32_two: +L$042ctr32_two: call __aesni_encrypt2 movups xmm5,[esi] movups xmm6,[16+esi] @@ -953,9 +980,9 @@ L$040ctr32_two: xorps xmm3,xmm6 movups [edi],xmm2 movups [16+edi],xmm3 - jmp NEAR L$038ctr32_ret + jmp NEAR L$040ctr32_ret align 16 -L$041ctr32_three: +L$043ctr32_three: call __aesni_encrypt3 movups xmm5,[esi] movups xmm6,[16+esi] @@ -966,9 +993,9 @@ L$041ctr32_three: xorps xmm4,xmm7 movups [16+edi],xmm3 movups [32+edi],xmm4 - jmp NEAR L$038ctr32_ret + jmp NEAR L$040ctr32_ret align 16 -L$042ctr32_four: +L$044ctr32_four: call __aesni_encrypt4 movups xmm6,[esi] movups xmm7,[16+esi] @@ -982,7 +1009,18 @@ L$042ctr32_four: xorps xmm5,xmm0 movups [32+edi],xmm4 movups [48+edi],xmm5 -L$038ctr32_ret: +L$040ctr32_ret: + pxor xmm0,xmm0 + pxor xmm1,xmm1 + pxor xmm2,xmm2 + pxor xmm3,xmm3 + pxor xmm4,xmm4 + movdqa [32+esp],xmm0 + pxor xmm5,xmm5 + movdqa [48+esp],xmm0 + pxor xmm6,xmm6 + movdqa [64+esp],xmm0 + pxor xmm7,xmm7 mov esp,DWORD [80+esp] pop edi pop esi @@ -1005,12 +1043,12 @@ L$_aesni_xts_encrypt_begin: movups xmm1,[16+edx] lea edx,[32+edx] xorps xmm2,xmm0 -L$044enc1_loop_8: +L$046enc1_loop_8: db 102,15,56,220,209 dec ecx movups xmm1,[edx] lea edx,[16+edx] - jnz NEAR L$044enc1_loop_8 + jnz NEAR L$046enc1_loop_8 db 102,15,56,221,209 mov esi,DWORD [20+esp] mov edi,DWORD [24+esp] @@ -1034,14 +1072,14 @@ db 102,15,56,221,209 mov ebp,edx mov ebx,ecx sub eax,96 - jc NEAR L$045xts_enc_short + jc NEAR L$047xts_enc_short shl ecx,4 mov ebx,16 sub ebx,ecx lea edx,[32+ecx*1+edx] - jmp NEAR L$046xts_enc_loop6 + jmp NEAR L$048xts_enc_loop6 align 16 -L$046xts_enc_loop6: +L$048xts_enc_loop6: pshufd xmm2,xmm0,19 pxor xmm0,xmm0 movdqa [esp],xmm1 @@ -1130,23 +1168,23 @@ db 102,15,56,220,249 pcmpgtd xmm0,xmm1 pxor xmm1,xmm2 sub eax,96 - jnc NEAR L$046xts_enc_loop6 + jnc NEAR L$048xts_enc_loop6 mov ecx,DWORD [240+ebp] mov edx,ebp mov ebx,ecx -L$045xts_enc_short: +L$047xts_enc_short: add eax,96 - jz NEAR L$047xts_enc_done6x + jz NEAR L$049xts_enc_done6x movdqa xmm5,xmm1 cmp eax,32 - jb NEAR L$048xts_enc_one + jb NEAR L$050xts_enc_one pshufd xmm2,xmm0,19 pxor xmm0,xmm0 paddq xmm1,xmm1 pand xmm2,xmm3 pcmpgtd xmm0,xmm1 pxor xmm1,xmm2 - je NEAR L$049xts_enc_two + je NEAR L$051xts_enc_two pshufd xmm2,xmm0,19 pxor xmm0,xmm0 movdqa xmm6,xmm1 @@ -1155,7 +1193,7 @@ L$045xts_enc_short: pcmpgtd xmm0,xmm1 pxor xmm1,xmm2 cmp eax,64 - jb NEAR L$050xts_enc_three + jb NEAR L$052xts_enc_three pshufd xmm2,xmm0,19 pxor xmm0,xmm0 movdqa xmm7,xmm1 @@ -1165,7 +1203,7 @@ L$045xts_enc_short: pxor xmm1,xmm2 movdqa [esp],xmm5 movdqa [16+esp],xmm6 - je NEAR L$051xts_enc_four + je NEAR L$053xts_enc_four movdqa [32+esp],xmm7 pshufd xmm7,xmm0,19 movdqa [48+esp],xmm1 @@ -1197,9 +1235,9 @@ L$045xts_enc_short: movups [48+edi],xmm5 movups [64+edi],xmm6 lea edi,[80+edi] - jmp NEAR L$052xts_enc_done + jmp NEAR L$054xts_enc_done align 16 -L$048xts_enc_one: +L$050xts_enc_one: movups xmm2,[esi] lea esi,[16+esi] xorps xmm2,xmm5 @@ -1207,20 +1245,20 @@ L$048xts_enc_one: movups xmm1,[16+edx] lea edx,[32+edx] xorps xmm2,xmm0 -L$053enc1_loop_9: +L$055enc1_loop_9: db 102,15,56,220,209 dec ecx movups xmm1,[edx] lea edx,[16+edx] - jnz NEAR L$053enc1_loop_9 + jnz NEAR L$055enc1_loop_9 db 102,15,56,221,209 xorps xmm2,xmm5 movups [edi],xmm2 lea edi,[16+edi] movdqa xmm1,xmm5 - jmp NEAR L$052xts_enc_done + jmp NEAR L$054xts_enc_done align 16 -L$049xts_enc_two: +L$051xts_enc_two: movaps xmm6,xmm1 movups xmm2,[esi] movups xmm3,[16+esi] @@ -1234,9 +1272,9 @@ L$049xts_enc_two: movups [16+edi],xmm3 lea edi,[32+edi] movdqa xmm1,xmm6 - jmp NEAR L$052xts_enc_done + jmp NEAR L$054xts_enc_done align 16 -L$050xts_enc_three: +L$052xts_enc_three: movaps xmm7,xmm1 movups xmm2,[esi] movups xmm3,[16+esi] @@ -1254,9 +1292,9 @@ L$050xts_enc_three: movups [32+edi],xmm4 lea edi,[48+edi] movdqa xmm1,xmm7 - jmp NEAR L$052xts_enc_done + jmp NEAR L$054xts_enc_done align 16 -L$051xts_enc_four: +L$053xts_enc_four: movaps xmm6,xmm1 movups xmm2,[esi] movups xmm3,[16+esi] @@ -1278,28 +1316,28 @@ L$051xts_enc_four: movups [48+edi],xmm5 lea edi,[64+edi] movdqa xmm1,xmm6 - jmp NEAR L$052xts_enc_done + jmp NEAR L$054xts_enc_done align 16 -L$047xts_enc_done6x: +L$049xts_enc_done6x: mov eax,DWORD [112+esp] and eax,15 - jz NEAR L$054xts_enc_ret + jz NEAR L$056xts_enc_ret movdqa xmm5,xmm1 mov DWORD [112+esp],eax - jmp NEAR L$055xts_enc_steal + jmp NEAR L$057xts_enc_steal align 16 -L$052xts_enc_done: +L$054xts_enc_done: mov eax,DWORD [112+esp] pxor xmm0,xmm0 and eax,15 - jz NEAR L$054xts_enc_ret + jz NEAR L$056xts_enc_ret pcmpgtd xmm0,xmm1 mov DWORD [112+esp],eax pshufd xmm5,xmm0,19 paddq xmm1,xmm1 pand xmm5,[96+esp] pxor xmm5,xmm1 -L$055xts_enc_steal: +L$057xts_enc_steal: movzx ecx,BYTE [esi] movzx edx,BYTE [edi-16] lea esi,[1+esi] @@ -1307,7 +1345,7 @@ L$055xts_enc_steal: mov BYTE [edi],dl lea edi,[1+edi] sub eax,1 - jnz NEAR L$055xts_enc_steal + jnz NEAR L$057xts_enc_steal sub edi,DWORD [112+esp] mov edx,ebp mov ecx,ebx @@ -1317,16 +1355,30 @@ L$055xts_enc_steal: movups xmm1,[16+edx] lea edx,[32+edx] xorps xmm2,xmm0 -L$056enc1_loop_10: +L$058enc1_loop_10: db 102,15,56,220,209 dec ecx movups xmm1,[edx] lea edx,[16+edx] - jnz NEAR L$056enc1_loop_10 + jnz NEAR L$058enc1_loop_10 db 102,15,56,221,209 xorps xmm2,xmm5 movups [edi-16],xmm2 -L$054xts_enc_ret: +L$056xts_enc_ret: + pxor xmm0,xmm0 + pxor xmm1,xmm1 + pxor xmm2,xmm2 + movdqa [esp],xmm0 + pxor xmm3,xmm3 + movdqa [16+esp],xmm0 + pxor xmm4,xmm4 + movdqa [32+esp],xmm0 + pxor xmm5,xmm5 + movdqa [48+esp],xmm0 + pxor xmm6,xmm6 + movdqa [64+esp],xmm0 + pxor xmm7,xmm7 + movdqa [80+esp],xmm0 mov esp,DWORD [116+esp] pop edi pop esi @@ -1349,12 +1401,12 @@ L$_aesni_xts_decrypt_begin: movups xmm1,[16+edx] lea edx,[32+edx] xorps xmm2,xmm0 -L$057enc1_loop_11: +L$059enc1_loop_11: db 102,15,56,220,209 dec ecx movups xmm1,[edx] lea edx,[16+edx] - jnz NEAR L$057enc1_loop_11 + jnz NEAR L$059enc1_loop_11 db 102,15,56,221,209 mov esi,DWORD [20+esp] mov edi,DWORD [24+esp] @@ -1383,14 +1435,14 @@ db 102,15,56,221,209 pcmpgtd xmm0,xmm1 and eax,-16 sub eax,96 - jc NEAR L$058xts_dec_short + jc NEAR L$060xts_dec_short shl ecx,4 mov ebx,16 sub ebx,ecx lea edx,[32+ecx*1+edx] - jmp NEAR L$059xts_dec_loop6 + jmp NEAR L$061xts_dec_loop6 align 16 -L$059xts_dec_loop6: +L$061xts_dec_loop6: pshufd xmm2,xmm0,19 pxor xmm0,xmm0 movdqa [esp],xmm1 @@ -1479,23 +1531,23 @@ db 102,15,56,222,249 pcmpgtd xmm0,xmm1 pxor xmm1,xmm2 sub eax,96 - jnc NEAR L$059xts_dec_loop6 + jnc NEAR L$061xts_dec_loop6 mov ecx,DWORD [240+ebp] mov edx,ebp mov ebx,ecx -L$058xts_dec_short: +L$060xts_dec_short: add eax,96 - jz NEAR L$060xts_dec_done6x + jz NEAR L$062xts_dec_done6x movdqa xmm5,xmm1 cmp eax,32 - jb NEAR L$061xts_dec_one + jb NEAR L$063xts_dec_one pshufd xmm2,xmm0,19 pxor xmm0,xmm0 paddq xmm1,xmm1 pand xmm2,xmm3 pcmpgtd xmm0,xmm1 pxor xmm1,xmm2 - je NEAR L$062xts_dec_two + je NEAR L$064xts_dec_two pshufd xmm2,xmm0,19 pxor xmm0,xmm0 movdqa xmm6,xmm1 @@ -1504,7 +1556,7 @@ L$058xts_dec_short: pcmpgtd xmm0,xmm1 pxor xmm1,xmm2 cmp eax,64 - jb NEAR L$063xts_dec_three + jb NEAR L$065xts_dec_three pshufd xmm2,xmm0,19 pxor xmm0,xmm0 movdqa xmm7,xmm1 @@ -1514,7 +1566,7 @@ L$058xts_dec_short: pxor xmm1,xmm2 movdqa [esp],xmm5 movdqa [16+esp],xmm6 - je NEAR L$064xts_dec_four + je NEAR L$066xts_dec_four movdqa [32+esp],xmm7 pshufd xmm7,xmm0,19 movdqa [48+esp],xmm1 @@ -1546,9 +1598,9 @@ L$058xts_dec_short: movups [48+edi],xmm5 movups [64+edi],xmm6 lea edi,[80+edi] - jmp NEAR L$065xts_dec_done + jmp NEAR L$067xts_dec_done align 16 -L$061xts_dec_one: +L$063xts_dec_one: movups xmm2,[esi] lea esi,[16+esi] xorps xmm2,xmm5 @@ -1556,20 +1608,20 @@ L$061xts_dec_one: movups xmm1,[16+edx] lea edx,[32+edx] xorps xmm2,xmm0 -L$066dec1_loop_12: +L$068dec1_loop_12: db 102,15,56,222,209 dec ecx movups xmm1,[edx] lea edx,[16+edx] - jnz NEAR L$066dec1_loop_12 + jnz NEAR L$068dec1_loop_12 db 102,15,56,223,209 xorps xmm2,xmm5 movups [edi],xmm2 lea edi,[16+edi] movdqa xmm1,xmm5 - jmp NEAR L$065xts_dec_done + jmp NEAR L$067xts_dec_done align 16 -L$062xts_dec_two: +L$064xts_dec_two: movaps xmm6,xmm1 movups xmm2,[esi] movups xmm3,[16+esi] @@ -1583,9 +1635,9 @@ L$062xts_dec_two: movups [16+edi],xmm3 lea edi,[32+edi] movdqa xmm1,xmm6 - jmp NEAR L$065xts_dec_done + jmp NEAR L$067xts_dec_done align 16 -L$063xts_dec_three: +L$065xts_dec_three: movaps xmm7,xmm1 movups xmm2,[esi] movups xmm3,[16+esi] @@ -1603,9 +1655,9 @@ L$063xts_dec_three: movups [32+edi],xmm4 lea edi,[48+edi] movdqa xmm1,xmm7 - jmp NEAR L$065xts_dec_done + jmp NEAR L$067xts_dec_done align 16 -L$064xts_dec_four: +L$066xts_dec_four: movaps xmm6,xmm1 movups xmm2,[esi] movups xmm3,[16+esi] @@ -1627,20 +1679,20 @@ L$064xts_dec_four: movups [48+edi],xmm5 lea edi,[64+edi] movdqa xmm1,xmm6 - jmp NEAR L$065xts_dec_done + jmp NEAR L$067xts_dec_done align 16 -L$060xts_dec_done6x: +L$062xts_dec_done6x: mov eax,DWORD [112+esp] and eax,15 - jz NEAR L$067xts_dec_ret + jz NEAR L$069xts_dec_ret mov DWORD [112+esp],eax - jmp NEAR L$068xts_dec_only_one_more + jmp NEAR L$070xts_dec_only_one_more align 16 -L$065xts_dec_done: +L$067xts_dec_done: mov eax,DWORD [112+esp] pxor xmm0,xmm0 and eax,15 - jz NEAR L$067xts_dec_ret + jz NEAR L$069xts_dec_ret pcmpgtd xmm0,xmm1 mov DWORD [112+esp],eax pshufd xmm2,xmm0,19 @@ -1650,7 +1702,7 @@ L$065xts_dec_done: pand xmm2,xmm3 pcmpgtd xmm0,xmm1 pxor xmm1,xmm2 -L$068xts_dec_only_one_more: +L$070xts_dec_only_one_more: pshufd xmm5,xmm0,19 movdqa xmm6,xmm1 paddq xmm1,xmm1 @@ -1664,16 +1716,16 @@ L$068xts_dec_only_one_more: movups xmm1,[16+edx] lea edx,[32+edx] xorps xmm2,xmm0 -L$069dec1_loop_13: +L$071dec1_loop_13: db 102,15,56,222,209 dec ecx movups xmm1,[edx] lea edx,[16+edx] - jnz NEAR L$069dec1_loop_13 + jnz NEAR L$071dec1_loop_13 db 102,15,56,223,209 xorps xmm2,xmm5 movups [edi],xmm2 -L$070xts_dec_steal: +L$072xts_dec_steal: movzx ecx,BYTE [16+esi] movzx edx,BYTE [edi] lea esi,[1+esi] @@ -1681,7 +1733,7 @@ L$070xts_dec_steal: mov BYTE [16+edi],dl lea edi,[1+edi] sub eax,1 - jnz NEAR L$070xts_dec_steal + jnz NEAR L$072xts_dec_steal sub edi,DWORD [112+esp] mov edx,ebp mov ecx,ebx @@ -1691,16 +1743,30 @@ L$070xts_dec_steal: movups xmm1,[16+edx] lea edx,[32+edx] xorps xmm2,xmm0 -L$071dec1_loop_14: +L$073dec1_loop_14: db 102,15,56,222,209 dec ecx movups xmm1,[edx] lea edx,[16+edx] - jnz NEAR L$071dec1_loop_14 + jnz NEAR L$073dec1_loop_14 db 102,15,56,223,209 xorps xmm2,xmm6 movups [edi],xmm2 -L$067xts_dec_ret: +L$069xts_dec_ret: + pxor xmm0,xmm0 + pxor xmm1,xmm1 + pxor xmm2,xmm2 + movdqa [esp],xmm0 + pxor xmm3,xmm3 + movdqa [16+esp],xmm0 + pxor xmm4,xmm4 + movdqa [32+esp],xmm0 + pxor xmm5,xmm5 + movdqa [48+esp],xmm0 + pxor xmm6,xmm6 + movdqa [64+esp],xmm0 + pxor xmm7,xmm7 + movdqa [80+esp],xmm0 mov esp,DWORD [116+esp] pop edi pop esi @@ -1724,7 +1790,7 @@ L$_aesni_cbc_encrypt_begin: mov edx,DWORD [32+esp] mov ebp,DWORD [36+esp] test eax,eax - jz NEAR L$072cbc_abort + jz NEAR L$074cbc_abort cmp DWORD [40+esp],0 xchg ebx,esp movups xmm7,[ebp] @@ -1732,14 +1798,14 @@ L$_aesni_cbc_encrypt_begin: mov ebp,edx mov DWORD [16+esp],ebx mov ebx,ecx - je NEAR L$073cbc_decrypt + je NEAR L$075cbc_decrypt movaps xmm2,xmm7 cmp eax,16 - jb NEAR L$074cbc_enc_tail + jb NEAR L$076cbc_enc_tail sub eax,16 - jmp NEAR L$075cbc_enc_loop + jmp NEAR L$077cbc_enc_loop align 16 -L$075cbc_enc_loop: +L$077cbc_enc_loop: movups xmm7,[esi] lea esi,[16+esi] movups xmm0,[edx] @@ -1747,24 +1813,25 @@ L$075cbc_enc_loop: xorps xmm7,xmm0 lea edx,[32+edx] xorps xmm2,xmm7 -L$076enc1_loop_15: +L$078enc1_loop_15: db 102,15,56,220,209 dec ecx movups xmm1,[edx] lea edx,[16+edx] - jnz NEAR L$076enc1_loop_15 + jnz NEAR L$078enc1_loop_15 db 102,15,56,221,209 mov ecx,ebx mov edx,ebp movups [edi],xmm2 lea edi,[16+edi] sub eax,16 - jnc NEAR L$075cbc_enc_loop + jnc NEAR L$077cbc_enc_loop add eax,16 - jnz NEAR L$074cbc_enc_tail + jnz NEAR L$076cbc_enc_tail movaps xmm7,xmm2 - jmp NEAR L$077cbc_ret -L$074cbc_enc_tail: + pxor xmm2,xmm2 + jmp NEAR L$079cbc_ret +L$076cbc_enc_tail: mov ecx,eax dd 2767451785 mov ecx,16 @@ -1775,20 +1842,20 @@ dd 2868115081 mov ecx,ebx mov esi,edi mov edx,ebp - jmp NEAR L$075cbc_enc_loop + jmp NEAR L$077cbc_enc_loop align 16 -L$073cbc_decrypt: +L$075cbc_decrypt: cmp eax,80 - jbe NEAR L$078cbc_dec_tail + jbe NEAR L$080cbc_dec_tail movaps [esp],xmm7 sub eax,80 - jmp NEAR L$079cbc_dec_loop6_enter + jmp NEAR L$081cbc_dec_loop6_enter align 16 -L$080cbc_dec_loop6: +L$082cbc_dec_loop6: movaps [esp],xmm0 movups [edi],xmm7 lea edi,[16+edi] -L$079cbc_dec_loop6_enter: +L$081cbc_dec_loop6_enter: movdqu xmm2,[esi] movdqu xmm3,[16+esi] movdqu xmm4,[32+esi] @@ -1818,28 +1885,28 @@ L$079cbc_dec_loop6_enter: movups [64+edi],xmm6 lea edi,[80+edi] sub eax,96 - ja NEAR L$080cbc_dec_loop6 + ja NEAR L$082cbc_dec_loop6 movaps xmm2,xmm7 movaps xmm7,xmm0 add eax,80 - jle NEAR L$081cbc_dec_tail_collected + jle NEAR L$083cbc_dec_clear_tail_collected movups [edi],xmm2 lea edi,[16+edi] -L$078cbc_dec_tail: +L$080cbc_dec_tail: movups xmm2,[esi] movaps xmm6,xmm2 cmp eax,16 - jbe NEAR L$082cbc_dec_one + jbe NEAR L$084cbc_dec_one movups xmm3,[16+esi] movaps xmm5,xmm3 cmp eax,32 - jbe NEAR L$083cbc_dec_two + jbe NEAR L$085cbc_dec_two movups xmm4,[32+esi] cmp eax,48 - jbe NEAR L$084cbc_dec_three + jbe NEAR L$086cbc_dec_three movups xmm5,[48+esi] cmp eax,64 - jbe NEAR L$085cbc_dec_four + jbe NEAR L$087cbc_dec_four movups xmm6,[64+esi] movaps [esp],xmm7 movups xmm2,[esi] @@ -1857,55 +1924,62 @@ L$078cbc_dec_tail: xorps xmm6,xmm0 movups [edi],xmm2 movups [16+edi],xmm3 + pxor xmm3,xmm3 movups [32+edi],xmm4 + pxor xmm4,xmm4 movups [48+edi],xmm5 + pxor xmm5,xmm5 lea edi,[64+edi] movaps xmm2,xmm6 + pxor xmm6,xmm6 sub eax,80 - jmp NEAR L$081cbc_dec_tail_collected + jmp NEAR L$088cbc_dec_tail_collected align 16 -L$082cbc_dec_one: +L$084cbc_dec_one: movups xmm0,[edx] movups xmm1,[16+edx] lea edx,[32+edx] xorps xmm2,xmm0 -L$086dec1_loop_16: +L$089dec1_loop_16: db 102,15,56,222,209 dec ecx movups xmm1,[edx] lea edx,[16+edx] - jnz NEAR L$086dec1_loop_16 + jnz NEAR L$089dec1_loop_16 db 102,15,56,223,209 xorps xmm2,xmm7 movaps xmm7,xmm6 sub eax,16 - jmp NEAR L$081cbc_dec_tail_collected + jmp NEAR L$088cbc_dec_tail_collected align 16 -L$083cbc_dec_two: +L$085cbc_dec_two: call __aesni_decrypt2 xorps xmm2,xmm7 xorps xmm3,xmm6 movups [edi],xmm2 movaps xmm2,xmm3 + pxor xmm3,xmm3 lea edi,[16+edi] movaps xmm7,xmm5 sub eax,32 - jmp NEAR L$081cbc_dec_tail_collected + jmp NEAR L$088cbc_dec_tail_collected align 16 -L$084cbc_dec_three: +L$086cbc_dec_three: call __aesni_decrypt3 xorps xmm2,xmm7 xorps xmm3,xmm6 xorps xmm4,xmm5 movups [edi],xmm2 movaps xmm2,xmm4 + pxor xmm4,xmm4 movups [16+edi],xmm3 + pxor xmm3,xmm3 lea edi,[32+edi] movups xmm7,[32+esi] sub eax,48 - jmp NEAR L$081cbc_dec_tail_collected + jmp NEAR L$088cbc_dec_tail_collected align 16 -L$085cbc_dec_four: +L$087cbc_dec_four: call __aesni_decrypt4 movups xmm1,[16+esi] movups xmm0,[32+esi] @@ -1915,28 +1989,44 @@ L$085cbc_dec_four: movups [edi],xmm2 xorps xmm4,xmm1 movups [16+edi],xmm3 + pxor xmm3,xmm3 xorps xmm5,xmm0 movups [32+edi],xmm4 + pxor xmm4,xmm4 lea edi,[48+edi] movaps xmm2,xmm5 + pxor xmm5,xmm5 sub eax,64 -L$081cbc_dec_tail_collected: + jmp NEAR L$088cbc_dec_tail_collected +align 16 +L$083cbc_dec_clear_tail_collected: + pxor xmm3,xmm3 + pxor xmm4,xmm4 + pxor xmm5,xmm5 + pxor xmm6,xmm6 +L$088cbc_dec_tail_collected: and eax,15 - jnz NEAR L$087cbc_dec_tail_partial + jnz NEAR L$090cbc_dec_tail_partial movups [edi],xmm2 - jmp NEAR L$077cbc_ret + pxor xmm0,xmm0 + jmp NEAR L$079cbc_ret align 16 -L$087cbc_dec_tail_partial: +L$090cbc_dec_tail_partial: movaps [esp],xmm2 + pxor xmm0,xmm0 mov ecx,16 mov esi,esp sub ecx,eax dd 2767451785 -L$077cbc_ret: + movdqa [esp],xmm2 +L$079cbc_ret: mov esp,DWORD [16+esp] mov ebp,DWORD [36+esp] + pxor xmm2,xmm2 + pxor xmm1,xmm1 movups [ebp],xmm7 -L$072cbc_abort: + pxor xmm7,xmm7 +L$074cbc_abort: pop edi pop esi pop ebx @@ -1944,52 +2034,62 @@ L$072cbc_abort: ret align 16 __aesni_set_encrypt_key: + push ebp + push ebx test eax,eax - jz NEAR L$088bad_pointer + jz NEAR L$091bad_pointer test edx,edx - jz NEAR L$088bad_pointer + jz NEAR L$091bad_pointer + call L$092pic +L$092pic: + pop ebx + lea ebx,[(L$key_const-L$092pic)+ebx] + lea ebp,[_OPENSSL_ia32cap_P] movups xmm0,[eax] xorps xmm4,xmm4 + mov ebp,DWORD [4+ebp] lea edx,[16+edx] + and ebp,268437504 cmp ecx,256 - je NEAR L$08914rounds + je NEAR L$09314rounds cmp ecx,192 - je NEAR L$09012rounds + je NEAR L$09412rounds cmp ecx,128 - jne NEAR L$091bad_keybits + jne NEAR L$095bad_keybits align 16 -L$09210rounds: +L$09610rounds: + cmp ebp,268435456 + je NEAR L$09710rounds_alt mov ecx,9 movups [edx-16],xmm0 db 102,15,58,223,200,1 - call L$093key_128_cold + call L$098key_128_cold db 102,15,58,223,200,2 - call L$094key_128 + call L$099key_128 db 102,15,58,223,200,4 - call L$094key_128 + call L$099key_128 db 102,15,58,223,200,8 - call L$094key_128 + call L$099key_128 db 102,15,58,223,200,16 - call L$094key_128 + call L$099key_128 db 102,15,58,223,200,32 - call L$094key_128 + call L$099key_128 db 102,15,58,223,200,64 - call L$094key_128 + call L$099key_128 db 102,15,58,223,200,128 - call L$094key_128 + call L$099key_128 db 102,15,58,223,200,27 - call L$094key_128 + call L$099key_128 db 102,15,58,223,200,54 - call L$094key_128 + call L$099key_128 movups [edx],xmm0 mov DWORD [80+edx],ecx - xor eax,eax - ret + jmp NEAR L$100good_key align 16 -L$094key_128: +L$099key_128: movups [edx],xmm0 lea edx,[16+edx] -L$093key_128_cold: +L$098key_128_cold: shufps xmm4,xmm0,16 xorps xmm0,xmm4 shufps xmm4,xmm0,140 @@ -1998,38 +2098,91 @@ L$093key_128_cold: xorps xmm0,xmm1 ret align 16 -L$09012rounds: +L$09710rounds_alt: + movdqa xmm5,[ebx] + mov ecx,8 + movdqa xmm4,[32+ebx] + movdqa xmm2,xmm0 + movdqu [edx-16],xmm0 +L$101loop_key128: +db 102,15,56,0,197 +db 102,15,56,221,196 + pslld xmm4,1 + lea edx,[16+edx] + movdqa xmm3,xmm2 + pslldq xmm2,4 + pxor xmm3,xmm2 + pslldq xmm2,4 + pxor xmm3,xmm2 + pslldq xmm2,4 + pxor xmm2,xmm3 + pxor xmm0,xmm2 + movdqu [edx-16],xmm0 + movdqa xmm2,xmm0 + dec ecx + jnz NEAR L$101loop_key128 + movdqa xmm4,[48+ebx] +db 102,15,56,0,197 +db 102,15,56,221,196 + pslld xmm4,1 + movdqa xmm3,xmm2 + pslldq xmm2,4 + pxor xmm3,xmm2 + pslldq xmm2,4 + pxor xmm3,xmm2 + pslldq xmm2,4 + pxor xmm2,xmm3 + pxor xmm0,xmm2 + movdqu [edx],xmm0 + movdqa xmm2,xmm0 +db 102,15,56,0,197 +db 102,15,56,221,196 + movdqa xmm3,xmm2 + pslldq xmm2,4 + pxor xmm3,xmm2 + pslldq xmm2,4 + pxor xmm3,xmm2 + pslldq xmm2,4 + pxor xmm2,xmm3 + pxor xmm0,xmm2 + movdqu [16+edx],xmm0 + mov ecx,9 + mov DWORD [96+edx],ecx + jmp NEAR L$100good_key +align 16 +L$09412rounds: movq xmm2,[16+eax] + cmp ebp,268435456 + je NEAR L$10212rounds_alt mov ecx,11 movups [edx-16],xmm0 db 102,15,58,223,202,1 - call L$095key_192a_cold + call L$103key_192a_cold db 102,15,58,223,202,2 - call L$096key_192b + call L$104key_192b db 102,15,58,223,202,4 - call L$097key_192a + call L$105key_192a db 102,15,58,223,202,8 - call L$096key_192b + call L$104key_192b db 102,15,58,223,202,16 - call L$097key_192a + call L$105key_192a db 102,15,58,223,202,32 - call L$096key_192b + call L$104key_192b db 102,15,58,223,202,64 - call L$097key_192a + call L$105key_192a db 102,15,58,223,202,128 - call L$096key_192b + call L$104key_192b movups [edx],xmm0 mov DWORD [48+edx],ecx - xor eax,eax - ret + jmp NEAR L$100good_key align 16 -L$097key_192a: +L$105key_192a: movups [edx],xmm0 lea edx,[16+edx] align 16 -L$095key_192a_cold: +L$103key_192a_cold: movaps xmm5,xmm2 -L$098key_192b_warm: +L$106key_192b_warm: shufps xmm4,xmm0,16 movdqa xmm3,xmm2 xorps xmm0,xmm4 @@ -2043,56 +2196,90 @@ L$098key_192b_warm: pxor xmm2,xmm3 ret align 16 -L$096key_192b: +L$104key_192b: movaps xmm3,xmm0 shufps xmm5,xmm0,68 movups [edx],xmm5 shufps xmm3,xmm2,78 movups [16+edx],xmm3 lea edx,[32+edx] - jmp NEAR L$098key_192b_warm + jmp NEAR L$106key_192b_warm +align 16 +L$10212rounds_alt: + movdqa xmm5,[16+ebx] + movdqa xmm4,[32+ebx] + mov ecx,8 + movdqu [edx-16],xmm0 +L$107loop_key192: + movq [edx],xmm2 + movdqa xmm1,xmm2 +db 102,15,56,0,213 +db 102,15,56,221,212 + pslld xmm4,1 + lea edx,[24+edx] + movdqa xmm3,xmm0 + pslldq xmm0,4 + pxor xmm3,xmm0 + pslldq xmm0,4 + pxor xmm3,xmm0 + pslldq xmm0,4 + pxor xmm0,xmm3 + pshufd xmm3,xmm0,255 + pxor xmm3,xmm1 + pslldq xmm1,4 + pxor xmm3,xmm1 + pxor xmm0,xmm2 + pxor xmm2,xmm3 + movdqu [edx-16],xmm0 + dec ecx + jnz NEAR L$107loop_key192 + mov ecx,11 + mov DWORD [32+edx],ecx + jmp NEAR L$100good_key align 16 -L$08914rounds: +L$09314rounds: movups xmm2,[16+eax] - mov ecx,13 lea edx,[16+edx] + cmp ebp,268435456 + je NEAR L$10814rounds_alt + mov ecx,13 movups [edx-32],xmm0 movups [edx-16],xmm2 db 102,15,58,223,202,1 - call L$099key_256a_cold + call L$109key_256a_cold db 102,15,58,223,200,1 - call L$100key_256b + call L$110key_256b db 102,15,58,223,202,2 - call L$101key_256a + call L$111key_256a db 102,15,58,223,200,2 - call L$100key_256b + call L$110key_256b db 102,15,58,223,202,4 - call L$101key_256a + call L$111key_256a db 102,15,58,223,200,4 - call L$100key_256b + call L$110key_256b db 102,15,58,223,202,8 - call L$101key_256a + call L$111key_256a db 102,15,58,223,200,8 - call L$100key_256b + call L$110key_256b db 102,15,58,223,202,16 - call L$101key_256a + call L$111key_256a db 102,15,58,223,200,16 - call L$100key_256b + call L$110key_256b db 102,15,58,223,202,32 - call L$101key_256a + call L$111key_256a db 102,15,58,223,200,32 - call L$100key_256b + call L$110key_256b db 102,15,58,223,202,64 - call L$101key_256a + call L$111key_256a movups [edx],xmm0 mov DWORD [16+edx],ecx xor eax,eax - ret + jmp NEAR L$100good_key align 16 -L$101key_256a: +L$111key_256a: movups [edx],xmm2 lea edx,[16+edx] -L$099key_256a_cold: +L$109key_256a_cold: shufps xmm4,xmm0,16 xorps xmm0,xmm4 shufps xmm4,xmm0,140 @@ -2101,7 +2288,7 @@ L$099key_256a_cold: xorps xmm0,xmm1 ret align 16 -L$100key_256b: +L$110key_256b: movups [edx],xmm0 lea edx,[16+edx] shufps xmm4,xmm2,16 @@ -2111,13 +2298,70 @@ L$100key_256b: shufps xmm1,xmm1,170 xorps xmm2,xmm1 ret +align 16 +L$10814rounds_alt: + movdqa xmm5,[ebx] + movdqa xmm4,[32+ebx] + mov ecx,7 + movdqu [edx-32],xmm0 + movdqa xmm1,xmm2 + movdqu [edx-16],xmm2 +L$112loop_key256: +db 102,15,56,0,213 +db 102,15,56,221,212 + movdqa xmm3,xmm0 + pslldq xmm0,4 + pxor xmm3,xmm0 + pslldq xmm0,4 + pxor xmm3,xmm0 + pslldq xmm0,4 + pxor xmm0,xmm3 + pslld xmm4,1 + pxor xmm0,xmm2 + movdqu [edx],xmm0 + dec ecx + jz NEAR L$113done_key256 + pshufd xmm2,xmm0,255 + pxor xmm3,xmm3 +db 102,15,56,221,211 + movdqa xmm3,xmm1 + pslldq xmm1,4 + pxor xmm3,xmm1 + pslldq xmm1,4 + pxor xmm3,xmm1 + pslldq xmm1,4 + pxor xmm1,xmm3 + pxor xmm2,xmm1 + movdqu [16+edx],xmm2 + lea edx,[32+edx] + movdqa xmm1,xmm2 + jmp NEAR L$112loop_key256 +L$113done_key256: + mov ecx,13 + mov DWORD [16+edx],ecx +L$100good_key: + pxor xmm0,xmm0 + pxor xmm1,xmm1 + pxor xmm2,xmm2 + pxor xmm3,xmm3 + pxor xmm4,xmm4 + pxor xmm5,xmm5 + xor eax,eax + pop ebx + pop ebp + ret align 4 -L$088bad_pointer: +L$091bad_pointer: mov eax,-1 + pop ebx + pop ebp ret align 4 -L$091bad_keybits: +L$095bad_keybits: + pxor xmm0,xmm0 mov eax,-2 + pop ebx + pop ebp ret global _aesni_set_encrypt_key align 16 @@ -2139,7 +2383,7 @@ L$_aesni_set_decrypt_key_begin: mov edx,DWORD [12+esp] shl ecx,4 test eax,eax - jnz NEAR L$102dec_key_ret + jnz NEAR L$114dec_key_ret lea eax,[16+ecx*1+edx] movups xmm0,[edx] movups xmm1,[eax] @@ -2147,7 +2391,7 @@ L$_aesni_set_decrypt_key_begin: movups [edx],xmm1 lea edx,[16+edx] lea eax,[eax-16] -L$103dec_key_inverse: +L$115dec_key_inverse: movups xmm0,[edx] movups xmm1,[eax] db 102,15,56,219,192 @@ -2157,14 +2401,24 @@ db 102,15,56,219,201 movups [16+eax],xmm0 movups [edx-16],xmm1 cmp eax,edx - ja NEAR L$103dec_key_inverse + ja NEAR L$115dec_key_inverse movups xmm0,[edx] db 102,15,56,219,192 movups [edx],xmm0 + pxor xmm0,xmm0 + pxor xmm1,xmm1 xor eax,eax -L$102dec_key_ret: +L$114dec_key_ret: ret +align 64 +L$key_const: +dd 202313229,202313229,202313229,202313229 +dd 67569157,67569157,67569157,67569157 +dd 1,1,1,1 +dd 27,27,27,27 db 65,69,83,32,102,111,114,32,73,110,116,101,108,32,65,69 db 83,45,78,73,44,32,67,82,89,80,84,79,71,65,77,83 db 32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115 db 115,108,46,111,114,103,62,0 +segment .bss +common _OPENSSL_ia32cap_P 16 diff --git a/third_party/boringssl/win-x86/crypto/bn/bn-586.asm b/third_party/boringssl/win-x86/crypto/bn/bn-586.asm index 04420a999a54a..b222040acae93 100644 --- a/third_party/boringssl/win-x86/crypto/bn/bn-586.asm +++ b/third_party/boringssl/win-x86/crypto/bn/bn-586.asm @@ -14,10 +14,104 @@ section .text code align=64 %else section .text code %endif +;extern _OPENSSL_ia32cap_P global _bn_mul_add_words align 16 _bn_mul_add_words: L$_bn_mul_add_words_begin: + lea eax,[_OPENSSL_ia32cap_P] + bt DWORD [eax],26 + jnc NEAR L$000maw_non_sse2 + mov eax,DWORD [4+esp] + mov edx,DWORD [8+esp] + mov ecx,DWORD [12+esp] + movd mm0,DWORD [16+esp] + pxor mm1,mm1 + jmp NEAR L$001maw_sse2_entry +align 16 +L$002maw_sse2_unrolled: + movd mm3,DWORD [eax] + paddq mm1,mm3 + movd mm2,DWORD [edx] + pmuludq mm2,mm0 + movd mm4,DWORD [4+edx] + pmuludq mm4,mm0 + movd mm6,DWORD [8+edx] + pmuludq mm6,mm0 + movd mm7,DWORD [12+edx] + pmuludq mm7,mm0 + paddq mm1,mm2 + movd mm3,DWORD [4+eax] + paddq mm3,mm4 + movd mm5,DWORD [8+eax] + paddq mm5,mm6 + movd mm4,DWORD [12+eax] + paddq mm7,mm4 + movd DWORD [eax],mm1 + movd mm2,DWORD [16+edx] + pmuludq mm2,mm0 + psrlq mm1,32 + movd mm4,DWORD [20+edx] + pmuludq mm4,mm0 + paddq mm1,mm3 + movd mm6,DWORD [24+edx] + pmuludq mm6,mm0 + movd DWORD [4+eax],mm1 + psrlq mm1,32 + movd mm3,DWORD [28+edx] + add edx,32 + pmuludq mm3,mm0 + paddq mm1,mm5 + movd mm5,DWORD [16+eax] + paddq mm2,mm5 + movd DWORD [8+eax],mm1 + psrlq mm1,32 + paddq mm1,mm7 + movd mm5,DWORD [20+eax] + paddq mm4,mm5 + movd DWORD [12+eax],mm1 + psrlq mm1,32 + paddq mm1,mm2 + movd mm5,DWORD [24+eax] + paddq mm6,mm5 + movd DWORD [16+eax],mm1 + psrlq mm1,32 + paddq mm1,mm4 + movd mm5,DWORD [28+eax] + paddq mm3,mm5 + movd DWORD [20+eax],mm1 + psrlq mm1,32 + paddq mm1,mm6 + movd DWORD [24+eax],mm1 + psrlq mm1,32 + paddq mm1,mm3 + movd DWORD [28+eax],mm1 + lea eax,[32+eax] + psrlq mm1,32 + sub ecx,8 + jz NEAR L$003maw_sse2_exit +L$001maw_sse2_entry: + test ecx,4294967288 + jnz NEAR L$002maw_sse2_unrolled +align 4 +L$004maw_sse2_loop: + movd mm2,DWORD [edx] + movd mm3,DWORD [eax] + pmuludq mm2,mm0 + lea edx,[4+edx] + paddq mm1,mm3 + paddq mm1,mm2 + movd DWORD [eax],mm1 + sub ecx,1 + psrlq mm1,32 + lea eax,[4+eax] + jnz NEAR L$004maw_sse2_loop +L$003maw_sse2_exit: + movd eax,mm1 + emms + ret +align 16 +L$000maw_non_sse2: push ebp push ebx push esi @@ -30,9 +124,9 @@ L$_bn_mul_add_words_begin: and ecx,4294967288 mov ebp,DWORD [32+esp] push ecx - jz NEAR L$000maw_finish + jz NEAR L$005maw_finish align 16 -L$001maw_loop: +L$006maw_loop: ; Round 0 mov eax,DWORD [ebx] mul ebp @@ -109,13 +203,13 @@ L$001maw_loop: sub ecx,8 lea ebx,[32+ebx] lea edi,[32+edi] - jnz NEAR L$001maw_loop -L$000maw_finish: + jnz NEAR L$006maw_loop +L$005maw_finish: mov ecx,DWORD [32+esp] and ecx,7 - jnz NEAR L$002maw_finish2 - jmp NEAR L$003maw_end -L$002maw_finish2: + jnz NEAR L$007maw_finish2 + jmp NEAR L$008maw_end +L$007maw_finish2: ; Tail Round 0 mov eax,DWORD [ebx] mul ebp @@ -126,7 +220,7 @@ L$002maw_finish2: dec ecx mov DWORD [edi],eax mov esi,edx - jz NEAR L$003maw_end + jz NEAR L$008maw_end ; Tail Round 1 mov eax,DWORD [4+ebx] mul ebp @@ -137,7 +231,7 @@ L$002maw_finish2: dec ecx mov DWORD [4+edi],eax mov esi,edx - jz NEAR L$003maw_end + jz NEAR L$008maw_end ; Tail Round 2 mov eax,DWORD [8+ebx] mul ebp @@ -148,7 +242,7 @@ L$002maw_finish2: dec ecx mov DWORD [8+edi],eax mov esi,edx - jz NEAR L$003maw_end + jz NEAR L$008maw_end ; Tail Round 3 mov eax,DWORD [12+ebx] mul ebp @@ -159,7 +253,7 @@ L$002maw_finish2: dec ecx mov DWORD [12+edi],eax mov esi,edx - jz NEAR L$003maw_end + jz NEAR L$008maw_end ; Tail Round 4 mov eax,DWORD [16+ebx] mul ebp @@ -170,7 +264,7 @@ L$002maw_finish2: dec ecx mov DWORD [16+edi],eax mov esi,edx - jz NEAR L$003maw_end + jz NEAR L$008maw_end ; Tail Round 5 mov eax,DWORD [20+ebx] mul ebp @@ -181,7 +275,7 @@ L$002maw_finish2: dec ecx mov DWORD [20+edi],eax mov esi,edx - jz NEAR L$003maw_end + jz NEAR L$008maw_end ; Tail Round 6 mov eax,DWORD [24+ebx] mul ebp @@ -191,7 +285,7 @@ L$002maw_finish2: adc edx,0 mov DWORD [24+edi],eax mov esi,edx -L$003maw_end: +L$008maw_end: mov eax,esi pop ecx pop edi @@ -203,6 +297,30 @@ global _bn_mul_words align 16 _bn_mul_words: L$_bn_mul_words_begin: + lea eax,[_OPENSSL_ia32cap_P] + bt DWORD [eax],26 + jnc NEAR L$009mw_non_sse2 + mov eax,DWORD [4+esp] + mov edx,DWORD [8+esp] + mov ecx,DWORD [12+esp] + movd mm0,DWORD [16+esp] + pxor mm1,mm1 +align 16 +L$010mw_sse2_loop: + movd mm2,DWORD [edx] + pmuludq mm2,mm0 + lea edx,[4+edx] + paddq mm1,mm2 + movd DWORD [eax],mm1 + sub ecx,1 + psrlq mm1,32 + lea eax,[4+eax] + jnz NEAR L$010mw_sse2_loop + movd eax,mm1 + emms + ret +align 16 +L$009mw_non_sse2: push ebp push ebx push esi @@ -214,8 +332,8 @@ L$_bn_mul_words_begin: mov ebp,DWORD [28+esp] mov ecx,DWORD [32+esp] and ebp,4294967288 - jz NEAR L$004mw_finish -L$005mw_loop: + jz NEAR L$011mw_finish +L$012mw_loop: ; Round 0 mov eax,DWORD [ebx] mul ecx @@ -276,14 +394,14 @@ L$005mw_loop: add ebx,32 add edi,32 sub ebp,8 - jz NEAR L$004mw_finish - jmp NEAR L$005mw_loop -L$004mw_finish: + jz NEAR L$011mw_finish + jmp NEAR L$012mw_loop +L$011mw_finish: mov ebp,DWORD [28+esp] and ebp,7 - jnz NEAR L$006mw_finish2 - jmp NEAR L$007mw_end -L$006mw_finish2: + jnz NEAR L$013mw_finish2 + jmp NEAR L$014mw_end +L$013mw_finish2: ; Tail Round 0 mov eax,DWORD [ebx] mul ecx @@ -292,7 +410,7 @@ L$006mw_finish2: mov DWORD [edi],eax mov esi,edx dec ebp - jz NEAR L$007mw_end + jz NEAR L$014mw_end ; Tail Round 1 mov eax,DWORD [4+ebx] mul ecx @@ -301,7 +419,7 @@ L$006mw_finish2: mov DWORD [4+edi],eax mov esi,edx dec ebp - jz NEAR L$007mw_end + jz NEAR L$014mw_end ; Tail Round 2 mov eax,DWORD [8+ebx] mul ecx @@ -310,7 +428,7 @@ L$006mw_finish2: mov DWORD [8+edi],eax mov esi,edx dec ebp - jz NEAR L$007mw_end + jz NEAR L$014mw_end ; Tail Round 3 mov eax,DWORD [12+ebx] mul ecx @@ -319,7 +437,7 @@ L$006mw_finish2: mov DWORD [12+edi],eax mov esi,edx dec ebp - jz NEAR L$007mw_end + jz NEAR L$014mw_end ; Tail Round 4 mov eax,DWORD [16+ebx] mul ecx @@ -328,7 +446,7 @@ L$006mw_finish2: mov DWORD [16+edi],eax mov esi,edx dec ebp - jz NEAR L$007mw_end + jz NEAR L$014mw_end ; Tail Round 5 mov eax,DWORD [20+ebx] mul ecx @@ -337,7 +455,7 @@ L$006mw_finish2: mov DWORD [20+edi],eax mov esi,edx dec ebp - jz NEAR L$007mw_end + jz NEAR L$014mw_end ; Tail Round 6 mov eax,DWORD [24+ebx] mul ecx @@ -345,7 +463,7 @@ L$006mw_finish2: adc edx,0 mov DWORD [24+edi],eax mov esi,edx -L$007mw_end: +L$014mw_end: mov eax,esi pop edi pop esi @@ -356,6 +474,25 @@ global _bn_sqr_words align 16 _bn_sqr_words: L$_bn_sqr_words_begin: + lea eax,[_OPENSSL_ia32cap_P] + bt DWORD [eax],26 + jnc NEAR L$015sqr_non_sse2 + mov eax,DWORD [4+esp] + mov edx,DWORD [8+esp] + mov ecx,DWORD [12+esp] +align 16 +L$016sqr_sse2_loop: + movd mm0,DWORD [edx] + pmuludq mm0,mm0 + lea edx,[4+edx] + movq [eax],mm0 + sub ecx,1 + lea eax,[8+eax] + jnz NEAR L$016sqr_sse2_loop + emms + ret +align 16 +L$015sqr_non_sse2: push ebp push ebx push esi @@ -365,8 +502,8 @@ L$_bn_sqr_words_begin: mov edi,DWORD [24+esp] mov ebx,DWORD [28+esp] and ebx,4294967288 - jz NEAR L$008sw_finish -L$009sw_loop: + jz NEAR L$017sw_finish +L$018sw_loop: ; Round 0 mov eax,DWORD [edi] mul eax @@ -411,59 +548,59 @@ L$009sw_loop: add edi,32 add esi,64 sub ebx,8 - jnz NEAR L$009sw_loop -L$008sw_finish: + jnz NEAR L$018sw_loop +L$017sw_finish: mov ebx,DWORD [28+esp] and ebx,7 - jz NEAR L$010sw_end + jz NEAR L$019sw_end ; Tail Round 0 mov eax,DWORD [edi] mul eax mov DWORD [esi],eax dec ebx mov DWORD [4+esi],edx - jz NEAR L$010sw_end + jz NEAR L$019sw_end ; Tail Round 1 mov eax,DWORD [4+edi] mul eax mov DWORD [8+esi],eax dec ebx mov DWORD [12+esi],edx - jz NEAR L$010sw_end + jz NEAR L$019sw_end ; Tail Round 2 mov eax,DWORD [8+edi] mul eax mov DWORD [16+esi],eax dec ebx mov DWORD [20+esi],edx - jz NEAR L$010sw_end + jz NEAR L$019sw_end ; Tail Round 3 mov eax,DWORD [12+edi] mul eax mov DWORD [24+esi],eax dec ebx mov DWORD [28+esi],edx - jz NEAR L$010sw_end + jz NEAR L$019sw_end ; Tail Round 4 mov eax,DWORD [16+edi] mul eax mov DWORD [32+esi],eax dec ebx mov DWORD [36+esi],edx - jz NEAR L$010sw_end + jz NEAR L$019sw_end ; Tail Round 5 mov eax,DWORD [20+edi] mul eax mov DWORD [40+esi],eax dec ebx mov DWORD [44+esi],edx - jz NEAR L$010sw_end + jz NEAR L$019sw_end ; Tail Round 6 mov eax,DWORD [24+edi] mul eax mov DWORD [48+esi],eax mov DWORD [52+esi],edx -L$010sw_end: +L$019sw_end: pop edi pop esi pop ebx @@ -493,8 +630,8 @@ L$_bn_add_words_begin: mov ebp,DWORD [32+esp] xor eax,eax and ebp,4294967288 - jz NEAR L$011aw_finish -L$012aw_loop: + jz NEAR L$020aw_finish +L$021aw_loop: ; Round 0 mov ecx,DWORD [esi] mov edx,DWORD [edi] @@ -572,11 +709,11 @@ L$012aw_loop: add edi,32 add ebx,32 sub ebp,8 - jnz NEAR L$012aw_loop -L$011aw_finish: + jnz NEAR L$021aw_loop +L$020aw_finish: mov ebp,DWORD [32+esp] and ebp,7 - jz NEAR L$013aw_end + jz NEAR L$022aw_end ; Tail Round 0 mov ecx,DWORD [esi] mov edx,DWORD [edi] @@ -587,7 +724,7 @@ L$011aw_finish: adc eax,0 dec ebp mov DWORD [ebx],ecx - jz NEAR L$013aw_end + jz NEAR L$022aw_end ; Tail Round 1 mov ecx,DWORD [4+esi] mov edx,DWORD [4+edi] @@ -598,7 +735,7 @@ L$011aw_finish: adc eax,0 dec ebp mov DWORD [4+ebx],ecx - jz NEAR L$013aw_end + jz NEAR L$022aw_end ; Tail Round 2 mov ecx,DWORD [8+esi] mov edx,DWORD [8+edi] @@ -609,7 +746,7 @@ L$011aw_finish: adc eax,0 dec ebp mov DWORD [8+ebx],ecx - jz NEAR L$013aw_end + jz NEAR L$022aw_end ; Tail Round 3 mov ecx,DWORD [12+esi] mov edx,DWORD [12+edi] @@ -620,7 +757,7 @@ L$011aw_finish: adc eax,0 dec ebp mov DWORD [12+ebx],ecx - jz NEAR L$013aw_end + jz NEAR L$022aw_end ; Tail Round 4 mov ecx,DWORD [16+esi] mov edx,DWORD [16+edi] @@ -631,7 +768,7 @@ L$011aw_finish: adc eax,0 dec ebp mov DWORD [16+ebx],ecx - jz NEAR L$013aw_end + jz NEAR L$022aw_end ; Tail Round 5 mov ecx,DWORD [20+esi] mov edx,DWORD [20+edi] @@ -642,7 +779,7 @@ L$011aw_finish: adc eax,0 dec ebp mov DWORD [20+ebx],ecx - jz NEAR L$013aw_end + jz NEAR L$022aw_end ; Tail Round 6 mov ecx,DWORD [24+esi] mov edx,DWORD [24+edi] @@ -652,7 +789,7 @@ L$011aw_finish: add ecx,edx adc eax,0 mov DWORD [24+ebx],ecx -L$013aw_end: +L$022aw_end: pop edi pop esi pop ebx @@ -673,8 +810,8 @@ L$_bn_sub_words_begin: mov ebp,DWORD [32+esp] xor eax,eax and ebp,4294967288 - jz NEAR L$014aw_finish -L$015aw_loop: + jz NEAR L$023aw_finish +L$024aw_loop: ; Round 0 mov ecx,DWORD [esi] mov edx,DWORD [edi] @@ -752,11 +889,11 @@ L$015aw_loop: add edi,32 add ebx,32 sub ebp,8 - jnz NEAR L$015aw_loop -L$014aw_finish: + jnz NEAR L$024aw_loop +L$023aw_finish: mov ebp,DWORD [32+esp] and ebp,7 - jz NEAR L$016aw_end + jz NEAR L$025aw_end ; Tail Round 0 mov ecx,DWORD [esi] mov edx,DWORD [edi] @@ -767,7 +904,7 @@ L$014aw_finish: adc eax,0 dec ebp mov DWORD [ebx],ecx - jz NEAR L$016aw_end + jz NEAR L$025aw_end ; Tail Round 1 mov ecx,DWORD [4+esi] mov edx,DWORD [4+edi] @@ -778,7 +915,7 @@ L$014aw_finish: adc eax,0 dec ebp mov DWORD [4+ebx],ecx - jz NEAR L$016aw_end + jz NEAR L$025aw_end ; Tail Round 2 mov ecx,DWORD [8+esi] mov edx,DWORD [8+edi] @@ -789,7 +926,7 @@ L$014aw_finish: adc eax,0 dec ebp mov DWORD [8+ebx],ecx - jz NEAR L$016aw_end + jz NEAR L$025aw_end ; Tail Round 3 mov ecx,DWORD [12+esi] mov edx,DWORD [12+edi] @@ -800,7 +937,7 @@ L$014aw_finish: adc eax,0 dec ebp mov DWORD [12+ebx],ecx - jz NEAR L$016aw_end + jz NEAR L$025aw_end ; Tail Round 4 mov ecx,DWORD [16+esi] mov edx,DWORD [16+edi] @@ -811,7 +948,7 @@ L$014aw_finish: adc eax,0 dec ebp mov DWORD [16+ebx],ecx - jz NEAR L$016aw_end + jz NEAR L$025aw_end ; Tail Round 5 mov ecx,DWORD [20+esi] mov edx,DWORD [20+edi] @@ -822,7 +959,7 @@ L$014aw_finish: adc eax,0 dec ebp mov DWORD [20+ebx],ecx - jz NEAR L$016aw_end + jz NEAR L$025aw_end ; Tail Round 6 mov ecx,DWORD [24+esi] mov edx,DWORD [24+edi] @@ -832,7 +969,7 @@ L$014aw_finish: sub ecx,edx adc eax,0 mov DWORD [24+ebx],ecx -L$016aw_end: +L$025aw_end: pop edi pop esi pop ebx @@ -853,8 +990,8 @@ L$_bn_sub_part_words_begin: mov ebp,DWORD [32+esp] xor eax,eax and ebp,4294967288 - jz NEAR L$017aw_finish -L$018aw_loop: + jz NEAR L$026aw_finish +L$027aw_loop: ; Round 0 mov ecx,DWORD [esi] mov edx,DWORD [edi] @@ -932,11 +1069,11 @@ L$018aw_loop: add edi,32 add ebx,32 sub ebp,8 - jnz NEAR L$018aw_loop -L$017aw_finish: + jnz NEAR L$027aw_loop +L$026aw_finish: mov ebp,DWORD [32+esp] and ebp,7 - jz NEAR L$019aw_end + jz NEAR L$028aw_end ; Tail Round 0 mov ecx,DWORD [esi] mov edx,DWORD [edi] @@ -950,7 +1087,7 @@ L$017aw_finish: add edi,4 add ebx,4 dec ebp - jz NEAR L$019aw_end + jz NEAR L$028aw_end ; Tail Round 1 mov ecx,DWORD [esi] mov edx,DWORD [edi] @@ -964,7 +1101,7 @@ L$017aw_finish: add edi,4 add ebx,4 dec ebp - jz NEAR L$019aw_end + jz NEAR L$028aw_end ; Tail Round 2 mov ecx,DWORD [esi] mov edx,DWORD [edi] @@ -978,7 +1115,7 @@ L$017aw_finish: add edi,4 add ebx,4 dec ebp - jz NEAR L$019aw_end + jz NEAR L$028aw_end ; Tail Round 3 mov ecx,DWORD [esi] mov edx,DWORD [edi] @@ -992,7 +1129,7 @@ L$017aw_finish: add edi,4 add ebx,4 dec ebp - jz NEAR L$019aw_end + jz NEAR L$028aw_end ; Tail Round 4 mov ecx,DWORD [esi] mov edx,DWORD [edi] @@ -1006,7 +1143,7 @@ L$017aw_finish: add edi,4 add ebx,4 dec ebp - jz NEAR L$019aw_end + jz NEAR L$028aw_end ; Tail Round 5 mov ecx,DWORD [esi] mov edx,DWORD [edi] @@ -1020,7 +1157,7 @@ L$017aw_finish: add edi,4 add ebx,4 dec ebp - jz NEAR L$019aw_end + jz NEAR L$028aw_end ; Tail Round 6 mov ecx,DWORD [esi] mov edx,DWORD [edi] @@ -1033,20 +1170,20 @@ L$017aw_finish: add esi,4 add edi,4 add ebx,4 -L$019aw_end: +L$028aw_end: cmp DWORD [36+esp],0 - je NEAR L$020pw_end + je NEAR L$029pw_end mov ebp,DWORD [36+esp] cmp ebp,0 - je NEAR L$020pw_end - jge NEAR L$021pw_pos + je NEAR L$029pw_end + jge NEAR L$030pw_pos ; pw_neg mov edx,0 sub edx,ebp mov ebp,edx and ebp,4294967288 - jz NEAR L$022pw_neg_finish -L$023pw_neg_loop: + jz NEAR L$031pw_neg_finish +L$032pw_neg_loop: ; dl<0 Round 0 mov ecx,0 mov edx,DWORD [edi] @@ -1123,13 +1260,13 @@ L$023pw_neg_loop: add edi,32 add ebx,32 sub ebp,8 - jnz NEAR L$023pw_neg_loop -L$022pw_neg_finish: + jnz NEAR L$032pw_neg_loop +L$031pw_neg_finish: mov edx,DWORD [36+esp] mov ebp,0 sub ebp,edx and ebp,7 - jz NEAR L$020pw_end + jz NEAR L$029pw_end ; dl<0 Tail Round 0 mov ecx,0 mov edx,DWORD [edi] @@ -1140,7 +1277,7 @@ L$022pw_neg_finish: adc eax,0 dec ebp mov DWORD [ebx],ecx - jz NEAR L$020pw_end + jz NEAR L$029pw_end ; dl<0 Tail Round 1 mov ecx,0 mov edx,DWORD [4+edi] @@ -1151,7 +1288,7 @@ L$022pw_neg_finish: adc eax,0 dec ebp mov DWORD [4+ebx],ecx - jz NEAR L$020pw_end + jz NEAR L$029pw_end ; dl<0 Tail Round 2 mov ecx,0 mov edx,DWORD [8+edi] @@ -1162,7 +1299,7 @@ L$022pw_neg_finish: adc eax,0 dec ebp mov DWORD [8+ebx],ecx - jz NEAR L$020pw_end + jz NEAR L$029pw_end ; dl<0 Tail Round 3 mov ecx,0 mov edx,DWORD [12+edi] @@ -1173,7 +1310,7 @@ L$022pw_neg_finish: adc eax,0 dec ebp mov DWORD [12+ebx],ecx - jz NEAR L$020pw_end + jz NEAR L$029pw_end ; dl<0 Tail Round 4 mov ecx,0 mov edx,DWORD [16+edi] @@ -1184,7 +1321,7 @@ L$022pw_neg_finish: adc eax,0 dec ebp mov DWORD [16+ebx],ecx - jz NEAR L$020pw_end + jz NEAR L$029pw_end ; dl<0 Tail Round 5 mov ecx,0 mov edx,DWORD [20+edi] @@ -1195,7 +1332,7 @@ L$022pw_neg_finish: adc eax,0 dec ebp mov DWORD [20+ebx],ecx - jz NEAR L$020pw_end + jz NEAR L$029pw_end ; dl<0 Tail Round 6 mov ecx,0 mov edx,DWORD [24+edi] @@ -1205,180 +1342,182 @@ L$022pw_neg_finish: sub ecx,edx adc eax,0 mov DWORD [24+ebx],ecx - jmp NEAR L$020pw_end -L$021pw_pos: + jmp NEAR L$029pw_end +L$030pw_pos: and ebp,4294967288 - jz NEAR L$024pw_pos_finish -L$025pw_pos_loop: + jz NEAR L$033pw_pos_finish +L$034pw_pos_loop: ; dl>0 Round 0 mov ecx,DWORD [esi] sub ecx,eax mov DWORD [ebx],ecx - jnc NEAR L$026pw_nc0 + jnc NEAR L$035pw_nc0 ; dl>0 Round 1 mov ecx,DWORD [4+esi] sub ecx,eax mov DWORD [4+ebx],ecx - jnc NEAR L$027pw_nc1 + jnc NEAR L$036pw_nc1 ; dl>0 Round 2 mov ecx,DWORD [8+esi] sub ecx,eax mov DWORD [8+ebx],ecx - jnc NEAR L$028pw_nc2 + jnc NEAR L$037pw_nc2 ; dl>0 Round 3 mov ecx,DWORD [12+esi] sub ecx,eax mov DWORD [12+ebx],ecx - jnc NEAR L$029pw_nc3 + jnc NEAR L$038pw_nc3 ; dl>0 Round 4 mov ecx,DWORD [16+esi] sub ecx,eax mov DWORD [16+ebx],ecx - jnc NEAR L$030pw_nc4 + jnc NEAR L$039pw_nc4 ; dl>0 Round 5 mov ecx,DWORD [20+esi] sub ecx,eax mov DWORD [20+ebx],ecx - jnc NEAR L$031pw_nc5 + jnc NEAR L$040pw_nc5 ; dl>0 Round 6 mov ecx,DWORD [24+esi] sub ecx,eax mov DWORD [24+ebx],ecx - jnc NEAR L$032pw_nc6 + jnc NEAR L$041pw_nc6 ; dl>0 Round 7 mov ecx,DWORD [28+esi] sub ecx,eax mov DWORD [28+ebx],ecx - jnc NEAR L$033pw_nc7 + jnc NEAR L$042pw_nc7 ; add esi,32 add ebx,32 sub ebp,8 - jnz NEAR L$025pw_pos_loop -L$024pw_pos_finish: + jnz NEAR L$034pw_pos_loop +L$033pw_pos_finish: mov ebp,DWORD [36+esp] and ebp,7 - jz NEAR L$020pw_end + jz NEAR L$029pw_end ; dl>0 Tail Round 0 mov ecx,DWORD [esi] sub ecx,eax mov DWORD [ebx],ecx - jnc NEAR L$034pw_tail_nc0 + jnc NEAR L$043pw_tail_nc0 dec ebp - jz NEAR L$020pw_end + jz NEAR L$029pw_end ; dl>0 Tail Round 1 mov ecx,DWORD [4+esi] sub ecx,eax mov DWORD [4+ebx],ecx - jnc NEAR L$035pw_tail_nc1 + jnc NEAR L$044pw_tail_nc1 dec ebp - jz NEAR L$020pw_end + jz NEAR L$029pw_end ; dl>0 Tail Round 2 mov ecx,DWORD [8+esi] sub ecx,eax mov DWORD [8+ebx],ecx - jnc NEAR L$036pw_tail_nc2 + jnc NEAR L$045pw_tail_nc2 dec ebp - jz NEAR L$020pw_end + jz NEAR L$029pw_end ; dl>0 Tail Round 3 mov ecx,DWORD [12+esi] sub ecx,eax mov DWORD [12+ebx],ecx - jnc NEAR L$037pw_tail_nc3 + jnc NEAR L$046pw_tail_nc3 dec ebp - jz NEAR L$020pw_end + jz NEAR L$029pw_end ; dl>0 Tail Round 4 mov ecx,DWORD [16+esi] sub ecx,eax mov DWORD [16+ebx],ecx - jnc NEAR L$038pw_tail_nc4 + jnc NEAR L$047pw_tail_nc4 dec ebp - jz NEAR L$020pw_end + jz NEAR L$029pw_end ; dl>0 Tail Round 5 mov ecx,DWORD [20+esi] sub ecx,eax mov DWORD [20+ebx],ecx - jnc NEAR L$039pw_tail_nc5 + jnc NEAR L$048pw_tail_nc5 dec ebp - jz NEAR L$020pw_end + jz NEAR L$029pw_end ; dl>0 Tail Round 6 mov ecx,DWORD [24+esi] sub ecx,eax mov DWORD [24+ebx],ecx - jnc NEAR L$040pw_tail_nc6 + jnc NEAR L$049pw_tail_nc6 mov eax,1 - jmp NEAR L$020pw_end -L$041pw_nc_loop: + jmp NEAR L$029pw_end +L$050pw_nc_loop: mov ecx,DWORD [esi] mov DWORD [ebx],ecx -L$026pw_nc0: +L$035pw_nc0: mov ecx,DWORD [4+esi] mov DWORD [4+ebx],ecx -L$027pw_nc1: +L$036pw_nc1: mov ecx,DWORD [8+esi] mov DWORD [8+ebx],ecx -L$028pw_nc2: +L$037pw_nc2: mov ecx,DWORD [12+esi] mov DWORD [12+ebx],ecx -L$029pw_nc3: +L$038pw_nc3: mov ecx,DWORD [16+esi] mov DWORD [16+ebx],ecx -L$030pw_nc4: +L$039pw_nc4: mov ecx,DWORD [20+esi] mov DWORD [20+ebx],ecx -L$031pw_nc5: +L$040pw_nc5: mov ecx,DWORD [24+esi] mov DWORD [24+ebx],ecx -L$032pw_nc6: +L$041pw_nc6: mov ecx,DWORD [28+esi] mov DWORD [28+ebx],ecx -L$033pw_nc7: +L$042pw_nc7: ; add esi,32 add ebx,32 sub ebp,8 - jnz NEAR L$041pw_nc_loop + jnz NEAR L$050pw_nc_loop mov ebp,DWORD [36+esp] and ebp,7 - jz NEAR L$042pw_nc_end + jz NEAR L$051pw_nc_end mov ecx,DWORD [esi] mov DWORD [ebx],ecx -L$034pw_tail_nc0: +L$043pw_tail_nc0: dec ebp - jz NEAR L$042pw_nc_end + jz NEAR L$051pw_nc_end mov ecx,DWORD [4+esi] mov DWORD [4+ebx],ecx -L$035pw_tail_nc1: +L$044pw_tail_nc1: dec ebp - jz NEAR L$042pw_nc_end + jz NEAR L$051pw_nc_end mov ecx,DWORD [8+esi] mov DWORD [8+ebx],ecx -L$036pw_tail_nc2: +L$045pw_tail_nc2: dec ebp - jz NEAR L$042pw_nc_end + jz NEAR L$051pw_nc_end mov ecx,DWORD [12+esi] mov DWORD [12+ebx],ecx -L$037pw_tail_nc3: +L$046pw_tail_nc3: dec ebp - jz NEAR L$042pw_nc_end + jz NEAR L$051pw_nc_end mov ecx,DWORD [16+esi] mov DWORD [16+ebx],ecx -L$038pw_tail_nc4: +L$047pw_tail_nc4: dec ebp - jz NEAR L$042pw_nc_end + jz NEAR L$051pw_nc_end mov ecx,DWORD [20+esi] mov DWORD [20+ebx],ecx -L$039pw_tail_nc5: +L$048pw_tail_nc5: dec ebp - jz NEAR L$042pw_nc_end + jz NEAR L$051pw_nc_end mov ecx,DWORD [24+esi] mov DWORD [24+ebx],ecx -L$040pw_tail_nc6: -L$042pw_nc_end: +L$049pw_tail_nc6: +L$051pw_nc_end: mov eax,0 -L$020pw_end: +L$029pw_end: pop edi pop esi pop ebx pop ebp ret +segment .bss +common _OPENSSL_ia32cap_P 16 diff --git a/third_party/boringssl/win-x86/crypto/bn/x86-mont.asm b/third_party/boringssl/win-x86/crypto/bn/x86-mont.asm index f07165fb0f259..de7b949927258 100644 --- a/third_party/boringssl/win-x86/crypto/bn/x86-mont.asm +++ b/third_party/boringssl/win-x86/crypto/bn/x86-mont.asm @@ -14,6 +14,7 @@ section .text code align=64 %else section .text code %endif +;extern _OPENSSL_ia32cap_P global _bn_mul_mont align 16 _bn_mul_mont: @@ -55,6 +56,123 @@ L$_bn_mul_mont_begin: mov DWORD [20+esp],esi lea ebx,[edi-3] mov DWORD [24+esp],ebp + lea eax,[_OPENSSL_ia32cap_P] + bt DWORD [eax],26 + jnc NEAR L$001non_sse2 + mov eax,-1 + movd mm7,eax + mov esi,DWORD [8+esp] + mov edi,DWORD [12+esp] + mov ebp,DWORD [16+esp] + xor edx,edx + xor ecx,ecx + movd mm4,DWORD [edi] + movd mm5,DWORD [esi] + movd mm3,DWORD [ebp] + pmuludq mm5,mm4 + movq mm2,mm5 + movq mm0,mm5 + pand mm0,mm7 + pmuludq mm5,[20+esp] + pmuludq mm3,mm5 + paddq mm3,mm0 + movd mm1,DWORD [4+ebp] + movd mm0,DWORD [4+esi] + psrlq mm2,32 + psrlq mm3,32 + inc ecx +align 16 +L$0021st: + pmuludq mm0,mm4 + pmuludq mm1,mm5 + paddq mm2,mm0 + paddq mm3,mm1 + movq mm0,mm2 + pand mm0,mm7 + movd mm1,DWORD [4+ecx*4+ebp] + paddq mm3,mm0 + movd mm0,DWORD [4+ecx*4+esi] + psrlq mm2,32 + movd DWORD [28+ecx*4+esp],mm3 + psrlq mm3,32 + lea ecx,[1+ecx] + cmp ecx,ebx + jl NEAR L$0021st + pmuludq mm0,mm4 + pmuludq mm1,mm5 + paddq mm2,mm0 + paddq mm3,mm1 + movq mm0,mm2 + pand mm0,mm7 + paddq mm3,mm0 + movd DWORD [28+ecx*4+esp],mm3 + psrlq mm2,32 + psrlq mm3,32 + paddq mm3,mm2 + movq [32+ebx*4+esp],mm3 + inc edx +L$003outer: + xor ecx,ecx + movd mm4,DWORD [edx*4+edi] + movd mm5,DWORD [esi] + movd mm6,DWORD [32+esp] + movd mm3,DWORD [ebp] + pmuludq mm5,mm4 + paddq mm5,mm6 + movq mm0,mm5 + movq mm2,mm5 + pand mm0,mm7 + pmuludq mm5,[20+esp] + pmuludq mm3,mm5 + paddq mm3,mm0 + movd mm6,DWORD [36+esp] + movd mm1,DWORD [4+ebp] + movd mm0,DWORD [4+esi] + psrlq mm2,32 + psrlq mm3,32 + paddq mm2,mm6 + inc ecx + dec ebx +L$004inner: + pmuludq mm0,mm4 + pmuludq mm1,mm5 + paddq mm2,mm0 + paddq mm3,mm1 + movq mm0,mm2 + movd mm6,DWORD [36+ecx*4+esp] + pand mm0,mm7 + movd mm1,DWORD [4+ecx*4+ebp] + paddq mm3,mm0 + movd mm0,DWORD [4+ecx*4+esi] + psrlq mm2,32 + movd DWORD [28+ecx*4+esp],mm3 + psrlq mm3,32 + paddq mm2,mm6 + dec ebx + lea ecx,[1+ecx] + jnz NEAR L$004inner + mov ebx,ecx + pmuludq mm0,mm4 + pmuludq mm1,mm5 + paddq mm2,mm0 + paddq mm3,mm1 + movq mm0,mm2 + pand mm0,mm7 + paddq mm3,mm0 + movd DWORD [28+ecx*4+esp],mm3 + psrlq mm2,32 + psrlq mm3,32 + movd mm6,DWORD [36+ebx*4+esp] + paddq mm3,mm2 + paddq mm3,mm6 + movq [32+ebx*4+esp],mm3 + lea edx,[1+edx] + cmp edx,ebx + jle NEAR L$003outer + emms + jmp NEAR L$005common_tail +align 16 +L$001non_sse2: mov esi,DWORD [8+esp] lea ebp,[1+ebx] mov edi,DWORD [12+esp] @@ -65,12 +183,12 @@ L$_bn_mul_mont_begin: lea eax,[4+ebx*4+edi] or ebp,edx mov edi,DWORD [edi] - jz NEAR L$001bn_sqr_mont + jz NEAR L$006bn_sqr_mont mov DWORD [28+esp],eax mov eax,DWORD [esi] xor edx,edx align 16 -L$002mull: +L$007mull: mov ebp,edx mul edi add ebp,eax @@ -79,7 +197,7 @@ L$002mull: mov eax,DWORD [ecx*4+esi] cmp ecx,ebx mov DWORD [28+ecx*4+esp],ebp - jl NEAR L$002mull + jl NEAR L$007mull mov ebp,edx mul edi mov edi,DWORD [20+esp] @@ -97,9 +215,9 @@ L$002mull: mov eax,DWORD [4+esi] adc edx,0 inc ecx - jmp NEAR L$0032ndmadd + jmp NEAR L$0082ndmadd align 16 -L$0041stmadd: +L$0091stmadd: mov ebp,edx mul edi add ebp,DWORD [32+ecx*4+esp] @@ -110,7 +228,7 @@ L$0041stmadd: adc edx,0 cmp ecx,ebx mov DWORD [28+ecx*4+esp],ebp - jl NEAR L$0041stmadd + jl NEAR L$0091stmadd mov ebp,edx mul edi add eax,DWORD [32+ebx*4+esp] @@ -133,7 +251,7 @@ L$0041stmadd: adc edx,0 mov ecx,1 align 16 -L$0032ndmadd: +L$0082ndmadd: mov ebp,edx mul edi add ebp,DWORD [32+ecx*4+esp] @@ -144,7 +262,7 @@ L$0032ndmadd: adc edx,0 cmp ecx,ebx mov DWORD [24+ecx*4+esp],ebp - jl NEAR L$0032ndmadd + jl NEAR L$0082ndmadd mov ebp,edx mul edi add ebp,DWORD [32+ebx*4+esp] @@ -167,9 +285,9 @@ L$0032ndmadd: xor ecx,ecx xor edx,edx mov eax,DWORD [esi] - jmp NEAR L$0041stmadd + jmp NEAR L$0091stmadd align 16 -L$001bn_sqr_mont: +L$006bn_sqr_mont: mov DWORD [esp],ebx mov DWORD [12+esp],ecx mov eax,edi @@ -180,7 +298,7 @@ L$001bn_sqr_mont: and ebx,1 inc ecx align 16 -L$006sqr: +L$010sqr: mov eax,DWORD [ecx*4+esi] mov ebp,edx mul edi @@ -192,7 +310,7 @@ L$006sqr: cmp ecx,DWORD [esp] mov ebx,eax mov DWORD [28+ecx*4+esp],ebp - jl NEAR L$006sqr + jl NEAR L$010sqr mov eax,DWORD [ecx*4+esi] mov ebp,edx mul edi @@ -216,7 +334,7 @@ L$006sqr: mov eax,DWORD [4+esi] mov ecx,1 align 16 -L$0073rdmadd: +L$0113rdmadd: mov ebp,edx mul edi add ebp,DWORD [32+ecx*4+esp] @@ -235,7 +353,7 @@ L$0073rdmadd: adc edx,0 cmp ecx,ebx mov DWORD [24+ecx*4+esp],ebp - jl NEAR L$0073rdmadd + jl NEAR L$0113rdmadd mov ebp,edx mul edi add ebp,DWORD [32+ebx*4+esp] @@ -263,12 +381,12 @@ L$0073rdmadd: xor ebp,ebp cmp ecx,ebx lea ecx,[1+ecx] - je NEAR L$008sqrlast + je NEAR L$012sqrlast mov ebx,edx shr edx,1 and ebx,1 align 16 -L$009sqradd: +L$013sqradd: mov eax,DWORD [ecx*4+esi] mov ebp,edx mul edi @@ -284,13 +402,13 @@ L$009sqradd: cmp ecx,DWORD [esp] mov DWORD [28+ecx*4+esp],ebp mov ebx,eax - jle NEAR L$009sqradd + jle NEAR L$013sqradd mov ebp,edx add edx,edx shr ebp,31 add edx,ebx adc ebp,0 -L$008sqrlast: +L$012sqrlast: mov edi,DWORD [20+esp] mov esi,DWORD [16+esp] imul edi,DWORD [32+esp] @@ -305,7 +423,7 @@ L$008sqrlast: adc edx,0 mov ecx,1 mov eax,DWORD [4+esi] - jmp NEAR L$0073rdmadd + jmp NEAR L$0113rdmadd align 16 L$005common_tail: mov ebp,DWORD [16+esp] @@ -315,16 +433,16 @@ L$005common_tail: mov ecx,ebx xor edx,edx align 16 -L$010sub: +L$014sub: sbb eax,DWORD [edx*4+ebp] mov DWORD [edx*4+edi],eax dec ecx mov eax,DWORD [4+edx*4+esi] lea edx,[1+edx] - jge NEAR L$010sub + jge NEAR L$014sub sbb eax,0 align 16 -L$011copy: +L$015copy: mov edx,DWORD [ebx*4+esi] mov ebp,DWORD [ebx*4+edi] xor edx,ebp @@ -333,7 +451,7 @@ L$011copy: mov DWORD [ebx*4+esi],ecx mov DWORD [ebx*4+edi],edx dec ebx - jge NEAR L$011copy + jge NEAR L$015copy mov esp,DWORD [24+esp] mov eax,1 L$000just_leave: @@ -347,3 +465,5 @@ db 112,108,105,99,97,116,105,111,110,32,102,111,114,32,120,56 db 54,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121 db 32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46 db 111,114,103,62,0 +segment .bss +common _OPENSSL_ia32cap_P 16 diff --git a/third_party/boringssl/win-x86/crypto/cpu-x86-asm.asm b/third_party/boringssl/win-x86/crypto/cpu-x86-asm.asm index df7993fa1717b..4317a73bc884d 100644 --- a/third_party/boringssl/win-x86/crypto/cpu-x86-asm.asm +++ b/third_party/boringssl/win-x86/crypto/cpu-x86-asm.asm @@ -228,6 +228,18 @@ L$_OPENSSL_wipe_cpu_begin: mov ecx,DWORD [ecx] bt DWORD [ecx],1 jnc NEAR L$013no_x87 + and ecx,83886080 + cmp ecx,83886080 + jne NEAR L$014no_sse2 + pxor xmm0,xmm0 + pxor xmm1,xmm1 + pxor xmm2,xmm2 + pxor xmm3,xmm3 + pxor xmm4,xmm4 + pxor xmm5,xmm5 + pxor xmm6,xmm6 + pxor xmm7,xmm7 +L$014no_sse2: dd 4007259865,4007259865,4007259865,4007259865,2430851995 L$013no_x87: lea eax,[4+esp] @@ -241,11 +253,11 @@ L$_OPENSSL_atomic_add_begin: push ebx nop mov eax,DWORD [edx] -L$014spin: +L$015spin: lea ebx,[ecx*1+eax] nop dd 447811568 - jne NEAR L$014spin + jne NEAR L$015spin mov eax,ebx pop ebx ret @@ -279,11 +291,11 @@ align 16 _OPENSSL_ia32_rdrand: L$_OPENSSL_ia32_rdrand_begin: mov ecx,8 -L$015loop: +L$016loop: db 15,199,240 - jc NEAR L$016break - loop L$015loop -L$016break: + jc NEAR L$017break + loop L$016loop +L$017break: cmp eax,0 cmove eax,ecx ret diff --git a/third_party/boringssl/win-x86/crypto/sha/sha1-586.asm b/third_party/boringssl/win-x86/crypto/sha/sha1-586.asm index 6d33d34306b36..e24449d200687 100644 --- a/third_party/boringssl/win-x86/crypto/sha/sha1-586.asm +++ b/third_party/boringssl/win-x86/crypto/sha/sha1-586.asm @@ -14,6 +14,7 @@ section .text code align=64 %else section .text code %endif +;extern _OPENSSL_ia32cap_P global _sha1_block_data_order align 16 _sha1_block_data_order: @@ -22,6 +23,23 @@ L$_sha1_block_data_order_begin: push ebx push esi push edi + call L$000pic_point +L$000pic_point: + pop ebp + lea esi,[_OPENSSL_ia32cap_P] + lea ebp,[(L$K_XX_XX-L$000pic_point)+ebp] + mov eax,DWORD [esi] + mov edx,DWORD [4+esi] + test edx,512 + jz NEAR L$001x86 + mov ecx,DWORD [8+esi] + test eax,16777216 + jz NEAR L$001x86 + test ecx,536870912 + jnz NEAR L$shaext_shortcut + jmp NEAR L$ssse3_shortcut +align 16 +L$001x86: mov ebp,DWORD [20+esp] mov esi,DWORD [24+esp] mov eax,DWORD [28+esp] @@ -30,9 +48,9 @@ L$_sha1_block_data_order_begin: add eax,esi mov DWORD [104+esp],eax mov edi,DWORD [16+ebp] - jmp NEAR L$000loop + jmp NEAR L$002loop align 16 -L$000loop: +L$002loop: mov eax,DWORD [esi] mov ebx,DWORD [4+esi] mov ecx,DWORD [8+esi] @@ -1379,14 +1397,1409 @@ L$000loop: mov DWORD [12+ebp],ebx mov esi,edx mov DWORD [16+ebp],ecx - jb NEAR L$000loop + jb NEAR L$002loop add esp,76 pop edi pop esi pop ebx pop ebp ret +align 16 +__sha1_block_data_order_shaext: + push ebp + push ebx + push esi + push edi + call L$003pic_point +L$003pic_point: + pop ebp + lea ebp,[(L$K_XX_XX-L$003pic_point)+ebp] +L$shaext_shortcut: + mov edi,DWORD [20+esp] + mov ebx,esp + mov esi,DWORD [24+esp] + mov ecx,DWORD [28+esp] + sub esp,32 + movdqu xmm0,[edi] + movd xmm1,DWORD [16+edi] + and esp,-32 + movdqa xmm3,[80+ebp] + movdqu xmm4,[esi] + pshufd xmm0,xmm0,27 + movdqu xmm5,[16+esi] + pshufd xmm1,xmm1,27 + movdqu xmm6,[32+esi] +db 102,15,56,0,227 + movdqu xmm7,[48+esi] +db 102,15,56,0,235 +db 102,15,56,0,243 +db 102,15,56,0,251 + jmp NEAR L$004loop_shaext +align 16 +L$004loop_shaext: + dec ecx + lea eax,[64+esi] + movdqa [esp],xmm1 + paddd xmm1,xmm4 + cmovne esi,eax + movdqa [16+esp],xmm0 +db 15,56,201,229 + movdqa xmm2,xmm0 +db 15,58,204,193,0 +db 15,56,200,213 + pxor xmm4,xmm6 +db 15,56,201,238 +db 15,56,202,231 + movdqa xmm1,xmm0 +db 15,58,204,194,0 +db 15,56,200,206 + pxor xmm5,xmm7 +db 15,56,202,236 +db 15,56,201,247 + movdqa xmm2,xmm0 +db 15,58,204,193,0 +db 15,56,200,215 + pxor xmm6,xmm4 +db 15,56,201,252 +db 15,56,202,245 + movdqa xmm1,xmm0 +db 15,58,204,194,0 +db 15,56,200,204 + pxor xmm7,xmm5 +db 15,56,202,254 +db 15,56,201,229 + movdqa xmm2,xmm0 +db 15,58,204,193,0 +db 15,56,200,213 + pxor xmm4,xmm6 +db 15,56,201,238 +db 15,56,202,231 + movdqa xmm1,xmm0 +db 15,58,204,194,1 +db 15,56,200,206 + pxor xmm5,xmm7 +db 15,56,202,236 +db 15,56,201,247 + movdqa xmm2,xmm0 +db 15,58,204,193,1 +db 15,56,200,215 + pxor xmm6,xmm4 +db 15,56,201,252 +db 15,56,202,245 + movdqa xmm1,xmm0 +db 15,58,204,194,1 +db 15,56,200,204 + pxor xmm7,xmm5 +db 15,56,202,254 +db 15,56,201,229 + movdqa xmm2,xmm0 +db 15,58,204,193,1 +db 15,56,200,213 + pxor xmm4,xmm6 +db 15,56,201,238 +db 15,56,202,231 + movdqa xmm1,xmm0 +db 15,58,204,194,1 +db 15,56,200,206 + pxor xmm5,xmm7 +db 15,56,202,236 +db 15,56,201,247 + movdqa xmm2,xmm0 +db 15,58,204,193,2 +db 15,56,200,215 + pxor xmm6,xmm4 +db 15,56,201,252 +db 15,56,202,245 + movdqa xmm1,xmm0 +db 15,58,204,194,2 +db 15,56,200,204 + pxor xmm7,xmm5 +db 15,56,202,254 +db 15,56,201,229 + movdqa xmm2,xmm0 +db 15,58,204,193,2 +db 15,56,200,213 + pxor xmm4,xmm6 +db 15,56,201,238 +db 15,56,202,231 + movdqa xmm1,xmm0 +db 15,58,204,194,2 +db 15,56,200,206 + pxor xmm5,xmm7 +db 15,56,202,236 +db 15,56,201,247 + movdqa xmm2,xmm0 +db 15,58,204,193,2 +db 15,56,200,215 + pxor xmm6,xmm4 +db 15,56,201,252 +db 15,56,202,245 + movdqa xmm1,xmm0 +db 15,58,204,194,3 +db 15,56,200,204 + pxor xmm7,xmm5 +db 15,56,202,254 + movdqu xmm4,[esi] + movdqa xmm2,xmm0 +db 15,58,204,193,3 +db 15,56,200,213 + movdqu xmm5,[16+esi] +db 102,15,56,0,227 + movdqa xmm1,xmm0 +db 15,58,204,194,3 +db 15,56,200,206 + movdqu xmm6,[32+esi] +db 102,15,56,0,235 + movdqa xmm2,xmm0 +db 15,58,204,193,3 +db 15,56,200,215 + movdqu xmm7,[48+esi] +db 102,15,56,0,243 + movdqa xmm1,xmm0 +db 15,58,204,194,3 + movdqa xmm2,[esp] +db 102,15,56,0,251 +db 15,56,200,202 + paddd xmm0,[16+esp] + jnz NEAR L$004loop_shaext + pshufd xmm0,xmm0,27 + pshufd xmm1,xmm1,27 + movdqu [edi],xmm0 + movd DWORD [16+edi],xmm1 + mov esp,ebx + pop edi + pop esi + pop ebx + pop ebp + ret +align 16 +__sha1_block_data_order_ssse3: + push ebp + push ebx + push esi + push edi + call L$005pic_point +L$005pic_point: + pop ebp + lea ebp,[(L$K_XX_XX-L$005pic_point)+ebp] +L$ssse3_shortcut: + movdqa xmm7,[ebp] + movdqa xmm0,[16+ebp] + movdqa xmm1,[32+ebp] + movdqa xmm2,[48+ebp] + movdqa xmm6,[64+ebp] + mov edi,DWORD [20+esp] + mov ebp,DWORD [24+esp] + mov edx,DWORD [28+esp] + mov esi,esp + sub esp,208 + and esp,-64 + movdqa [112+esp],xmm0 + movdqa [128+esp],xmm1 + movdqa [144+esp],xmm2 + shl edx,6 + movdqa [160+esp],xmm7 + add edx,ebp + movdqa [176+esp],xmm6 + add ebp,64 + mov DWORD [192+esp],edi + mov DWORD [196+esp],ebp + mov DWORD [200+esp],edx + mov DWORD [204+esp],esi + mov eax,DWORD [edi] + mov ebx,DWORD [4+edi] + mov ecx,DWORD [8+edi] + mov edx,DWORD [12+edi] + mov edi,DWORD [16+edi] + mov esi,ebx + movdqu xmm0,[ebp-64] + movdqu xmm1,[ebp-48] + movdqu xmm2,[ebp-32] + movdqu xmm3,[ebp-16] +db 102,15,56,0,198 +db 102,15,56,0,206 +db 102,15,56,0,214 + movdqa [96+esp],xmm7 +db 102,15,56,0,222 + paddd xmm0,xmm7 + paddd xmm1,xmm7 + paddd xmm2,xmm7 + movdqa [esp],xmm0 + psubd xmm0,xmm7 + movdqa [16+esp],xmm1 + psubd xmm1,xmm7 + movdqa [32+esp],xmm2 + mov ebp,ecx + psubd xmm2,xmm7 + xor ebp,edx + pshufd xmm4,xmm0,238 + and esi,ebp + jmp NEAR L$006loop +align 16 +L$006loop: + ror ebx,2 + xor esi,edx + mov ebp,eax + punpcklqdq xmm4,xmm1 + movdqa xmm6,xmm3 + add edi,DWORD [esp] + xor ebx,ecx + paddd xmm7,xmm3 + movdqa [64+esp],xmm0 + rol eax,5 + add edi,esi + psrldq xmm6,4 + and ebp,ebx + xor ebx,ecx + pxor xmm4,xmm0 + add edi,eax + ror eax,7 + pxor xmm6,xmm2 + xor ebp,ecx + mov esi,edi + add edx,DWORD [4+esp] + pxor xmm4,xmm6 + xor eax,ebx + rol edi,5 + movdqa [48+esp],xmm7 + add edx,ebp + and esi,eax + movdqa xmm0,xmm4 + xor eax,ebx + add edx,edi + ror edi,7 + movdqa xmm6,xmm4 + xor esi,ebx + pslldq xmm0,12 + paddd xmm4,xmm4 + mov ebp,edx + add ecx,DWORD [8+esp] + psrld xmm6,31 + xor edi,eax + rol edx,5 + movdqa xmm7,xmm0 + add ecx,esi + and ebp,edi + xor edi,eax + psrld xmm0,30 + add ecx,edx + ror edx,7 + por xmm4,xmm6 + xor ebp,eax + mov esi,ecx + add ebx,DWORD [12+esp] + pslld xmm7,2 + xor edx,edi + rol ecx,5 + pxor xmm4,xmm0 + movdqa xmm0,[96+esp] + add ebx,ebp + and esi,edx + pxor xmm4,xmm7 + pshufd xmm5,xmm1,238 + xor edx,edi + add ebx,ecx + ror ecx,7 + xor esi,edi + mov ebp,ebx + punpcklqdq xmm5,xmm2 + movdqa xmm7,xmm4 + add eax,DWORD [16+esp] + xor ecx,edx + paddd xmm0,xmm4 + movdqa [80+esp],xmm1 + rol ebx,5 + add eax,esi + psrldq xmm7,4 + and ebp,ecx + xor ecx,edx + pxor xmm5,xmm1 + add eax,ebx + ror ebx,7 + pxor xmm7,xmm3 + xor ebp,edx + mov esi,eax + add edi,DWORD [20+esp] + pxor xmm5,xmm7 + xor ebx,ecx + rol eax,5 + movdqa [esp],xmm0 + add edi,ebp + and esi,ebx + movdqa xmm1,xmm5 + xor ebx,ecx + add edi,eax + ror eax,7 + movdqa xmm7,xmm5 + xor esi,ecx + pslldq xmm1,12 + paddd xmm5,xmm5 + mov ebp,edi + add edx,DWORD [24+esp] + psrld xmm7,31 + xor eax,ebx + rol edi,5 + movdqa xmm0,xmm1 + add edx,esi + and ebp,eax + xor eax,ebx + psrld xmm1,30 + add edx,edi + ror edi,7 + por xmm5,xmm7 + xor ebp,ebx + mov esi,edx + add ecx,DWORD [28+esp] + pslld xmm0,2 + xor edi,eax + rol edx,5 + pxor xmm5,xmm1 + movdqa xmm1,[112+esp] + add ecx,ebp + and esi,edi + pxor xmm5,xmm0 + pshufd xmm6,xmm2,238 + xor edi,eax + add ecx,edx + ror edx,7 + xor esi,eax + mov ebp,ecx + punpcklqdq xmm6,xmm3 + movdqa xmm0,xmm5 + add ebx,DWORD [32+esp] + xor edx,edi + paddd xmm1,xmm5 + movdqa [96+esp],xmm2 + rol ecx,5 + add ebx,esi + psrldq xmm0,4 + and ebp,edx + xor edx,edi + pxor xmm6,xmm2 + add ebx,ecx + ror ecx,7 + pxor xmm0,xmm4 + xor ebp,edi + mov esi,ebx + add eax,DWORD [36+esp] + pxor xmm6,xmm0 + xor ecx,edx + rol ebx,5 + movdqa [16+esp],xmm1 + add eax,ebp + and esi,ecx + movdqa xmm2,xmm6 + xor ecx,edx + add eax,ebx + ror ebx,7 + movdqa xmm0,xmm6 + xor esi,edx + pslldq xmm2,12 + paddd xmm6,xmm6 + mov ebp,eax + add edi,DWORD [40+esp] + psrld xmm0,31 + xor ebx,ecx + rol eax,5 + movdqa xmm1,xmm2 + add edi,esi + and ebp,ebx + xor ebx,ecx + psrld xmm2,30 + add edi,eax + ror eax,7 + por xmm6,xmm0 + xor ebp,ecx + movdqa xmm0,[64+esp] + mov esi,edi + add edx,DWORD [44+esp] + pslld xmm1,2 + xor eax,ebx + rol edi,5 + pxor xmm6,xmm2 + movdqa xmm2,[112+esp] + add edx,ebp + and esi,eax + pxor xmm6,xmm1 + pshufd xmm7,xmm3,238 + xor eax,ebx + add edx,edi + ror edi,7 + xor esi,ebx + mov ebp,edx + punpcklqdq xmm7,xmm4 + movdqa xmm1,xmm6 + add ecx,DWORD [48+esp] + xor edi,eax + paddd xmm2,xmm6 + movdqa [64+esp],xmm3 + rol edx,5 + add ecx,esi + psrldq xmm1,4 + and ebp,edi + xor edi,eax + pxor xmm7,xmm3 + add ecx,edx + ror edx,7 + pxor xmm1,xmm5 + xor ebp,eax + mov esi,ecx + add ebx,DWORD [52+esp] + pxor xmm7,xmm1 + xor edx,edi + rol ecx,5 + movdqa [32+esp],xmm2 + add ebx,ebp + and esi,edx + movdqa xmm3,xmm7 + xor edx,edi + add ebx,ecx + ror ecx,7 + movdqa xmm1,xmm7 + xor esi,edi + pslldq xmm3,12 + paddd xmm7,xmm7 + mov ebp,ebx + add eax,DWORD [56+esp] + psrld xmm1,31 + xor ecx,edx + rol ebx,5 + movdqa xmm2,xmm3 + add eax,esi + and ebp,ecx + xor ecx,edx + psrld xmm3,30 + add eax,ebx + ror ebx,7 + por xmm7,xmm1 + xor ebp,edx + movdqa xmm1,[80+esp] + mov esi,eax + add edi,DWORD [60+esp] + pslld xmm2,2 + xor ebx,ecx + rol eax,5 + pxor xmm7,xmm3 + movdqa xmm3,[112+esp] + add edi,ebp + and esi,ebx + pxor xmm7,xmm2 + pshufd xmm2,xmm6,238 + xor ebx,ecx + add edi,eax + ror eax,7 + pxor xmm0,xmm4 + punpcklqdq xmm2,xmm7 + xor esi,ecx + mov ebp,edi + add edx,DWORD [esp] + pxor xmm0,xmm1 + movdqa [80+esp],xmm4 + xor eax,ebx + rol edi,5 + movdqa xmm4,xmm3 + add edx,esi + paddd xmm3,xmm7 + and ebp,eax + pxor xmm0,xmm2 + xor eax,ebx + add edx,edi + ror edi,7 + xor ebp,ebx + movdqa xmm2,xmm0 + movdqa [48+esp],xmm3 + mov esi,edx + add ecx,DWORD [4+esp] + xor edi,eax + rol edx,5 + pslld xmm0,2 + add ecx,ebp + and esi,edi + psrld xmm2,30 + xor edi,eax + add ecx,edx + ror edx,7 + xor esi,eax + mov ebp,ecx + add ebx,DWORD [8+esp] + xor edx,edi + rol ecx,5 + por xmm0,xmm2 + add ebx,esi + and ebp,edx + movdqa xmm2,[96+esp] + xor edx,edi + add ebx,ecx + add eax,DWORD [12+esp] + xor ebp,edi + mov esi,ebx + pshufd xmm3,xmm7,238 + rol ebx,5 + add eax,ebp + xor esi,edx + ror ecx,7 + add eax,ebx + add edi,DWORD [16+esp] + pxor xmm1,xmm5 + punpcklqdq xmm3,xmm0 + xor esi,ecx + mov ebp,eax + rol eax,5 + pxor xmm1,xmm2 + movdqa [96+esp],xmm5 + add edi,esi + xor ebp,ecx + movdqa xmm5,xmm4 + ror ebx,7 + paddd xmm4,xmm0 + add edi,eax + pxor xmm1,xmm3 + add edx,DWORD [20+esp] + xor ebp,ebx + mov esi,edi + rol edi,5 + movdqa xmm3,xmm1 + movdqa [esp],xmm4 + add edx,ebp + xor esi,ebx + ror eax,7 + add edx,edi + pslld xmm1,2 + add ecx,DWORD [24+esp] + xor esi,eax + psrld xmm3,30 + mov ebp,edx + rol edx,5 + add ecx,esi + xor ebp,eax + ror edi,7 + add ecx,edx + por xmm1,xmm3 + add ebx,DWORD [28+esp] + xor ebp,edi + movdqa xmm3,[64+esp] + mov esi,ecx + rol ecx,5 + add ebx,ebp + xor esi,edi + ror edx,7 + pshufd xmm4,xmm0,238 + add ebx,ecx + add eax,DWORD [32+esp] + pxor xmm2,xmm6 + punpcklqdq xmm4,xmm1 + xor esi,edx + mov ebp,ebx + rol ebx,5 + pxor xmm2,xmm3 + movdqa [64+esp],xmm6 + add eax,esi + xor ebp,edx + movdqa xmm6,[128+esp] + ror ecx,7 + paddd xmm5,xmm1 + add eax,ebx + pxor xmm2,xmm4 + add edi,DWORD [36+esp] + xor ebp,ecx + mov esi,eax + rol eax,5 + movdqa xmm4,xmm2 + movdqa [16+esp],xmm5 + add edi,ebp + xor esi,ecx + ror ebx,7 + add edi,eax + pslld xmm2,2 + add edx,DWORD [40+esp] + xor esi,ebx + psrld xmm4,30 + mov ebp,edi + rol edi,5 + add edx,esi + xor ebp,ebx + ror eax,7 + add edx,edi + por xmm2,xmm4 + add ecx,DWORD [44+esp] + xor ebp,eax + movdqa xmm4,[80+esp] + mov esi,edx + rol edx,5 + add ecx,ebp + xor esi,eax + ror edi,7 + pshufd xmm5,xmm1,238 + add ecx,edx + add ebx,DWORD [48+esp] + pxor xmm3,xmm7 + punpcklqdq xmm5,xmm2 + xor esi,edi + mov ebp,ecx + rol ecx,5 + pxor xmm3,xmm4 + movdqa [80+esp],xmm7 + add ebx,esi + xor ebp,edi + movdqa xmm7,xmm6 + ror edx,7 + paddd xmm6,xmm2 + add ebx,ecx + pxor xmm3,xmm5 + add eax,DWORD [52+esp] + xor ebp,edx + mov esi,ebx + rol ebx,5 + movdqa xmm5,xmm3 + movdqa [32+esp],xmm6 + add eax,ebp + xor esi,edx + ror ecx,7 + add eax,ebx + pslld xmm3,2 + add edi,DWORD [56+esp] + xor esi,ecx + psrld xmm5,30 + mov ebp,eax + rol eax,5 + add edi,esi + xor ebp,ecx + ror ebx,7 + add edi,eax + por xmm3,xmm5 + add edx,DWORD [60+esp] + xor ebp,ebx + movdqa xmm5,[96+esp] + mov esi,edi + rol edi,5 + add edx,ebp + xor esi,ebx + ror eax,7 + pshufd xmm6,xmm2,238 + add edx,edi + add ecx,DWORD [esp] + pxor xmm4,xmm0 + punpcklqdq xmm6,xmm3 + xor esi,eax + mov ebp,edx + rol edx,5 + pxor xmm4,xmm5 + movdqa [96+esp],xmm0 + add ecx,esi + xor ebp,eax + movdqa xmm0,xmm7 + ror edi,7 + paddd xmm7,xmm3 + add ecx,edx + pxor xmm4,xmm6 + add ebx,DWORD [4+esp] + xor ebp,edi + mov esi,ecx + rol ecx,5 + movdqa xmm6,xmm4 + movdqa [48+esp],xmm7 + add ebx,ebp + xor esi,edi + ror edx,7 + add ebx,ecx + pslld xmm4,2 + add eax,DWORD [8+esp] + xor esi,edx + psrld xmm6,30 + mov ebp,ebx + rol ebx,5 + add eax,esi + xor ebp,edx + ror ecx,7 + add eax,ebx + por xmm4,xmm6 + add edi,DWORD [12+esp] + xor ebp,ecx + movdqa xmm6,[64+esp] + mov esi,eax + rol eax,5 + add edi,ebp + xor esi,ecx + ror ebx,7 + pshufd xmm7,xmm3,238 + add edi,eax + add edx,DWORD [16+esp] + pxor xmm5,xmm1 + punpcklqdq xmm7,xmm4 + xor esi,ebx + mov ebp,edi + rol edi,5 + pxor xmm5,xmm6 + movdqa [64+esp],xmm1 + add edx,esi + xor ebp,ebx + movdqa xmm1,xmm0 + ror eax,7 + paddd xmm0,xmm4 + add edx,edi + pxor xmm5,xmm7 + add ecx,DWORD [20+esp] + xor ebp,eax + mov esi,edx + rol edx,5 + movdqa xmm7,xmm5 + movdqa [esp],xmm0 + add ecx,ebp + xor esi,eax + ror edi,7 + add ecx,edx + pslld xmm5,2 + add ebx,DWORD [24+esp] + xor esi,edi + psrld xmm7,30 + mov ebp,ecx + rol ecx,5 + add ebx,esi + xor ebp,edi + ror edx,7 + add ebx,ecx + por xmm5,xmm7 + add eax,DWORD [28+esp] + movdqa xmm7,[80+esp] + ror ecx,7 + mov esi,ebx + xor ebp,edx + rol ebx,5 + pshufd xmm0,xmm4,238 + add eax,ebp + xor esi,ecx + xor ecx,edx + add eax,ebx + add edi,DWORD [32+esp] + pxor xmm6,xmm2 + punpcklqdq xmm0,xmm5 + and esi,ecx + xor ecx,edx + ror ebx,7 + pxor xmm6,xmm7 + movdqa [80+esp],xmm2 + mov ebp,eax + xor esi,ecx + rol eax,5 + movdqa xmm2,xmm1 + add edi,esi + paddd xmm1,xmm5 + xor ebp,ebx + pxor xmm6,xmm0 + xor ebx,ecx + add edi,eax + add edx,DWORD [36+esp] + and ebp,ebx + movdqa xmm0,xmm6 + movdqa [16+esp],xmm1 + xor ebx,ecx + ror eax,7 + mov esi,edi + xor ebp,ebx + rol edi,5 + pslld xmm6,2 + add edx,ebp + xor esi,eax + psrld xmm0,30 + xor eax,ebx + add edx,edi + add ecx,DWORD [40+esp] + and esi,eax + xor eax,ebx + ror edi,7 + por xmm6,xmm0 + mov ebp,edx + xor esi,eax + movdqa xmm0,[96+esp] + rol edx,5 + add ecx,esi + xor ebp,edi + xor edi,eax + add ecx,edx + pshufd xmm1,xmm5,238 + add ebx,DWORD [44+esp] + and ebp,edi + xor edi,eax + ror edx,7 + mov esi,ecx + xor ebp,edi + rol ecx,5 + add ebx,ebp + xor esi,edx + xor edx,edi + add ebx,ecx + add eax,DWORD [48+esp] + pxor xmm7,xmm3 + punpcklqdq xmm1,xmm6 + and esi,edx + xor edx,edi + ror ecx,7 + pxor xmm7,xmm0 + movdqa [96+esp],xmm3 + mov ebp,ebx + xor esi,edx + rol ebx,5 + movdqa xmm3,[144+esp] + add eax,esi + paddd xmm2,xmm6 + xor ebp,ecx + pxor xmm7,xmm1 + xor ecx,edx + add eax,ebx + add edi,DWORD [52+esp] + and ebp,ecx + movdqa xmm1,xmm7 + movdqa [32+esp],xmm2 + xor ecx,edx + ror ebx,7 + mov esi,eax + xor ebp,ecx + rol eax,5 + pslld xmm7,2 + add edi,ebp + xor esi,ebx + psrld xmm1,30 + xor ebx,ecx + add edi,eax + add edx,DWORD [56+esp] + and esi,ebx + xor ebx,ecx + ror eax,7 + por xmm7,xmm1 + mov ebp,edi + xor esi,ebx + movdqa xmm1,[64+esp] + rol edi,5 + add edx,esi + xor ebp,eax + xor eax,ebx + add edx,edi + pshufd xmm2,xmm6,238 + add ecx,DWORD [60+esp] + and ebp,eax + xor eax,ebx + ror edi,7 + mov esi,edx + xor ebp,eax + rol edx,5 + add ecx,ebp + xor esi,edi + xor edi,eax + add ecx,edx + add ebx,DWORD [esp] + pxor xmm0,xmm4 + punpcklqdq xmm2,xmm7 + and esi,edi + xor edi,eax + ror edx,7 + pxor xmm0,xmm1 + movdqa [64+esp],xmm4 + mov ebp,ecx + xor esi,edi + rol ecx,5 + movdqa xmm4,xmm3 + add ebx,esi + paddd xmm3,xmm7 + xor ebp,edx + pxor xmm0,xmm2 + xor edx,edi + add ebx,ecx + add eax,DWORD [4+esp] + and ebp,edx + movdqa xmm2,xmm0 + movdqa [48+esp],xmm3 + xor edx,edi + ror ecx,7 + mov esi,ebx + xor ebp,edx + rol ebx,5 + pslld xmm0,2 + add eax,ebp + xor esi,ecx + psrld xmm2,30 + xor ecx,edx + add eax,ebx + add edi,DWORD [8+esp] + and esi,ecx + xor ecx,edx + ror ebx,7 + por xmm0,xmm2 + mov ebp,eax + xor esi,ecx + movdqa xmm2,[80+esp] + rol eax,5 + add edi,esi + xor ebp,ebx + xor ebx,ecx + add edi,eax + pshufd xmm3,xmm7,238 + add edx,DWORD [12+esp] + and ebp,ebx + xor ebx,ecx + ror eax,7 + mov esi,edi + xor ebp,ebx + rol edi,5 + add edx,ebp + xor esi,eax + xor eax,ebx + add edx,edi + add ecx,DWORD [16+esp] + pxor xmm1,xmm5 + punpcklqdq xmm3,xmm0 + and esi,eax + xor eax,ebx + ror edi,7 + pxor xmm1,xmm2 + movdqa [80+esp],xmm5 + mov ebp,edx + xor esi,eax + rol edx,5 + movdqa xmm5,xmm4 + add ecx,esi + paddd xmm4,xmm0 + xor ebp,edi + pxor xmm1,xmm3 + xor edi,eax + add ecx,edx + add ebx,DWORD [20+esp] + and ebp,edi + movdqa xmm3,xmm1 + movdqa [esp],xmm4 + xor edi,eax + ror edx,7 + mov esi,ecx + xor ebp,edi + rol ecx,5 + pslld xmm1,2 + add ebx,ebp + xor esi,edx + psrld xmm3,30 + xor edx,edi + add ebx,ecx + add eax,DWORD [24+esp] + and esi,edx + xor edx,edi + ror ecx,7 + por xmm1,xmm3 + mov ebp,ebx + xor esi,edx + movdqa xmm3,[96+esp] + rol ebx,5 + add eax,esi + xor ebp,ecx + xor ecx,edx + add eax,ebx + pshufd xmm4,xmm0,238 + add edi,DWORD [28+esp] + and ebp,ecx + xor ecx,edx + ror ebx,7 + mov esi,eax + xor ebp,ecx + rol eax,5 + add edi,ebp + xor esi,ebx + xor ebx,ecx + add edi,eax + add edx,DWORD [32+esp] + pxor xmm2,xmm6 + punpcklqdq xmm4,xmm1 + and esi,ebx + xor ebx,ecx + ror eax,7 + pxor xmm2,xmm3 + movdqa [96+esp],xmm6 + mov ebp,edi + xor esi,ebx + rol edi,5 + movdqa xmm6,xmm5 + add edx,esi + paddd xmm5,xmm1 + xor ebp,eax + pxor xmm2,xmm4 + xor eax,ebx + add edx,edi + add ecx,DWORD [36+esp] + and ebp,eax + movdqa xmm4,xmm2 + movdqa [16+esp],xmm5 + xor eax,ebx + ror edi,7 + mov esi,edx + xor ebp,eax + rol edx,5 + pslld xmm2,2 + add ecx,ebp + xor esi,edi + psrld xmm4,30 + xor edi,eax + add ecx,edx + add ebx,DWORD [40+esp] + and esi,edi + xor edi,eax + ror edx,7 + por xmm2,xmm4 + mov ebp,ecx + xor esi,edi + movdqa xmm4,[64+esp] + rol ecx,5 + add ebx,esi + xor ebp,edx + xor edx,edi + add ebx,ecx + pshufd xmm5,xmm1,238 + add eax,DWORD [44+esp] + and ebp,edx + xor edx,edi + ror ecx,7 + mov esi,ebx + xor ebp,edx + rol ebx,5 + add eax,ebp + xor esi,edx + add eax,ebx + add edi,DWORD [48+esp] + pxor xmm3,xmm7 + punpcklqdq xmm5,xmm2 + xor esi,ecx + mov ebp,eax + rol eax,5 + pxor xmm3,xmm4 + movdqa [64+esp],xmm7 + add edi,esi + xor ebp,ecx + movdqa xmm7,xmm6 + ror ebx,7 + paddd xmm6,xmm2 + add edi,eax + pxor xmm3,xmm5 + add edx,DWORD [52+esp] + xor ebp,ebx + mov esi,edi + rol edi,5 + movdqa xmm5,xmm3 + movdqa [32+esp],xmm6 + add edx,ebp + xor esi,ebx + ror eax,7 + add edx,edi + pslld xmm3,2 + add ecx,DWORD [56+esp] + xor esi,eax + psrld xmm5,30 + mov ebp,edx + rol edx,5 + add ecx,esi + xor ebp,eax + ror edi,7 + add ecx,edx + por xmm3,xmm5 + add ebx,DWORD [60+esp] + xor ebp,edi + mov esi,ecx + rol ecx,5 + add ebx,ebp + xor esi,edi + ror edx,7 + add ebx,ecx + add eax,DWORD [esp] + xor esi,edx + mov ebp,ebx + rol ebx,5 + add eax,esi + xor ebp,edx + ror ecx,7 + paddd xmm7,xmm3 + add eax,ebx + add edi,DWORD [4+esp] + xor ebp,ecx + mov esi,eax + movdqa [48+esp],xmm7 + rol eax,5 + add edi,ebp + xor esi,ecx + ror ebx,7 + add edi,eax + add edx,DWORD [8+esp] + xor esi,ebx + mov ebp,edi + rol edi,5 + add edx,esi + xor ebp,ebx + ror eax,7 + add edx,edi + add ecx,DWORD [12+esp] + xor ebp,eax + mov esi,edx + rol edx,5 + add ecx,ebp + xor esi,eax + ror edi,7 + add ecx,edx + mov ebp,DWORD [196+esp] + cmp ebp,DWORD [200+esp] + je NEAR L$007done + movdqa xmm7,[160+esp] + movdqa xmm6,[176+esp] + movdqu xmm0,[ebp] + movdqu xmm1,[16+ebp] + movdqu xmm2,[32+ebp] + movdqu xmm3,[48+ebp] + add ebp,64 +db 102,15,56,0,198 + mov DWORD [196+esp],ebp + movdqa [96+esp],xmm7 + add ebx,DWORD [16+esp] + xor esi,edi + mov ebp,ecx + rol ecx,5 + add ebx,esi + xor ebp,edi + ror edx,7 +db 102,15,56,0,206 + add ebx,ecx + add eax,DWORD [20+esp] + xor ebp,edx + mov esi,ebx + paddd xmm0,xmm7 + rol ebx,5 + add eax,ebp + xor esi,edx + ror ecx,7 + movdqa [esp],xmm0 + add eax,ebx + add edi,DWORD [24+esp] + xor esi,ecx + mov ebp,eax + psubd xmm0,xmm7 + rol eax,5 + add edi,esi + xor ebp,ecx + ror ebx,7 + add edi,eax + add edx,DWORD [28+esp] + xor ebp,ebx + mov esi,edi + rol edi,5 + add edx,ebp + xor esi,ebx + ror eax,7 + add edx,edi + add ecx,DWORD [32+esp] + xor esi,eax + mov ebp,edx + rol edx,5 + add ecx,esi + xor ebp,eax + ror edi,7 +db 102,15,56,0,214 + add ecx,edx + add ebx,DWORD [36+esp] + xor ebp,edi + mov esi,ecx + paddd xmm1,xmm7 + rol ecx,5 + add ebx,ebp + xor esi,edi + ror edx,7 + movdqa [16+esp],xmm1 + add ebx,ecx + add eax,DWORD [40+esp] + xor esi,edx + mov ebp,ebx + psubd xmm1,xmm7 + rol ebx,5 + add eax,esi + xor ebp,edx + ror ecx,7 + add eax,ebx + add edi,DWORD [44+esp] + xor ebp,ecx + mov esi,eax + rol eax,5 + add edi,ebp + xor esi,ecx + ror ebx,7 + add edi,eax + add edx,DWORD [48+esp] + xor esi,ebx + mov ebp,edi + rol edi,5 + add edx,esi + xor ebp,ebx + ror eax,7 +db 102,15,56,0,222 + add edx,edi + add ecx,DWORD [52+esp] + xor ebp,eax + mov esi,edx + paddd xmm2,xmm7 + rol edx,5 + add ecx,ebp + xor esi,eax + ror edi,7 + movdqa [32+esp],xmm2 + add ecx,edx + add ebx,DWORD [56+esp] + xor esi,edi + mov ebp,ecx + psubd xmm2,xmm7 + rol ecx,5 + add ebx,esi + xor ebp,edi + ror edx,7 + add ebx,ecx + add eax,DWORD [60+esp] + xor ebp,edx + mov esi,ebx + rol ebx,5 + add eax,ebp + ror ecx,7 + add eax,ebx + mov ebp,DWORD [192+esp] + add eax,DWORD [ebp] + add esi,DWORD [4+ebp] + add ecx,DWORD [8+ebp] + mov DWORD [ebp],eax + add edx,DWORD [12+ebp] + mov DWORD [4+ebp],esi + add edi,DWORD [16+ebp] + mov DWORD [8+ebp],ecx + mov ebx,ecx + mov DWORD [12+ebp],edx + xor ebx,edx + mov DWORD [16+ebp],edi + mov ebp,esi + pshufd xmm4,xmm0,238 + and esi,ebx + mov ebx,ebp + jmp NEAR L$006loop +align 16 +L$007done: + add ebx,DWORD [16+esp] + xor esi,edi + mov ebp,ecx + rol ecx,5 + add ebx,esi + xor ebp,edi + ror edx,7 + add ebx,ecx + add eax,DWORD [20+esp] + xor ebp,edx + mov esi,ebx + rol ebx,5 + add eax,ebp + xor esi,edx + ror ecx,7 + add eax,ebx + add edi,DWORD [24+esp] + xor esi,ecx + mov ebp,eax + rol eax,5 + add edi,esi + xor ebp,ecx + ror ebx,7 + add edi,eax + add edx,DWORD [28+esp] + xor ebp,ebx + mov esi,edi + rol edi,5 + add edx,ebp + xor esi,ebx + ror eax,7 + add edx,edi + add ecx,DWORD [32+esp] + xor esi,eax + mov ebp,edx + rol edx,5 + add ecx,esi + xor ebp,eax + ror edi,7 + add ecx,edx + add ebx,DWORD [36+esp] + xor ebp,edi + mov esi,ecx + rol ecx,5 + add ebx,ebp + xor esi,edi + ror edx,7 + add ebx,ecx + add eax,DWORD [40+esp] + xor esi,edx + mov ebp,ebx + rol ebx,5 + add eax,esi + xor ebp,edx + ror ecx,7 + add eax,ebx + add edi,DWORD [44+esp] + xor ebp,ecx + mov esi,eax + rol eax,5 + add edi,ebp + xor esi,ecx + ror ebx,7 + add edi,eax + add edx,DWORD [48+esp] + xor esi,ebx + mov ebp,edi + rol edi,5 + add edx,esi + xor ebp,ebx + ror eax,7 + add edx,edi + add ecx,DWORD [52+esp] + xor ebp,eax + mov esi,edx + rol edx,5 + add ecx,ebp + xor esi,eax + ror edi,7 + add ecx,edx + add ebx,DWORD [56+esp] + xor esi,edi + mov ebp,ecx + rol ecx,5 + add ebx,esi + xor ebp,edi + ror edx,7 + add ebx,ecx + add eax,DWORD [60+esp] + xor ebp,edx + mov esi,ebx + rol ebx,5 + add eax,ebp + ror ecx,7 + add eax,ebx + mov ebp,DWORD [192+esp] + add eax,DWORD [ebp] + mov esp,DWORD [204+esp] + add esi,DWORD [4+ebp] + add ecx,DWORD [8+ebp] + mov DWORD [ebp],eax + add edx,DWORD [12+ebp] + mov DWORD [4+ebp],esi + add edi,DWORD [16+ebp] + mov DWORD [8+ebp],ecx + mov DWORD [12+ebp],edx + mov DWORD [16+ebp],edi + pop edi + pop esi + pop ebx + pop ebp + ret +align 64 +L$K_XX_XX: +dd 1518500249,1518500249,1518500249,1518500249 +dd 1859775393,1859775393,1859775393,1859775393 +dd 2400959708,2400959708,2400959708,2400959708 +dd 3395469782,3395469782,3395469782,3395469782 +dd 66051,67438087,134810123,202182159 +db 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 db 83,72,65,49,32,98,108,111,99,107,32,116,114,97,110,115 db 102,111,114,109,32,102,111,114,32,120,56,54,44,32,67,82 db 89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112 db 114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0 +segment .bss +common _OPENSSL_ia32cap_P 16 diff --git a/third_party/boringssl/win-x86/crypto/sha/sha256-586.asm b/third_party/boringssl/win-x86/crypto/sha/sha256-586.asm index 56b2b72a75060..fe36bc5c9adc8 100644 --- a/third_party/boringssl/win-x86/crypto/sha/sha256-586.asm +++ b/third_party/boringssl/win-x86/crypto/sha/sha256-586.asm @@ -39,6 +39,27 @@ L$000pic_point: mov DWORD [4+esp],edi mov DWORD [8+esp],eax mov DWORD [12+esp],ebx + lea edx,[_OPENSSL_ia32cap_P] + mov ecx,DWORD [edx] + mov ebx,DWORD [4+edx] + test ecx,1048576 + jnz NEAR L$002loop + mov edx,DWORD [8+edx] + test ecx,16777216 + jz NEAR L$003no_xmm + and ecx,1073741824 + and ebx,268435968 + test edx,536870912 + jnz NEAR L$004shaext + or ecx,ebx + and ecx,1342177280 + cmp ecx,1342177280 + test ebx,512 + jnz NEAR L$005SSSE3 +L$003no_xmm: + sub eax,edi + cmp eax,256 + jae NEAR L$006unrolled jmp NEAR L$002loop align 16 L$002loop: @@ -110,7 +131,7 @@ L$002loop: mov DWORD [28+esp],ecx mov DWORD [32+esp],edi align 16 -L$00300_15: +L$00700_15: mov ecx,edx mov esi,DWORD [24+esp] ror ecx,14 @@ -148,11 +169,11 @@ L$00300_15: add ebp,4 add eax,ebx cmp esi,3248222580 - jne NEAR L$00300_15 + jne NEAR L$00700_15 mov ecx,DWORD [156+esp] - jmp NEAR L$00416_63 + jmp NEAR L$00816_63 align 16 -L$00416_63: +L$00816_63: mov ebx,ecx mov esi,DWORD [104+esp] ror ecx,11 @@ -207,7 +228,7 @@ L$00416_63: add ebp,4 add eax,ebx cmp esi,3329325298 - jne NEAR L$00416_63 + jne NEAR L$00816_63 mov esi,DWORD [356+esp] mov ebx,DWORD [8+esp] mov ecx,DWORD [16+esp] @@ -241,207 +262,6 @@ L$00416_63: pop ebx pop ebp ret -align 32 -L$005loop_shrd: - mov eax,DWORD [edi] - mov ebx,DWORD [4+edi] - mov ecx,DWORD [8+edi] - bswap eax - mov edx,DWORD [12+edi] - bswap ebx - push eax - bswap ecx - push ebx - bswap edx - push ecx - push edx - mov eax,DWORD [16+edi] - mov ebx,DWORD [20+edi] - mov ecx,DWORD [24+edi] - bswap eax - mov edx,DWORD [28+edi] - bswap ebx - push eax - bswap ecx - push ebx - bswap edx - push ecx - push edx - mov eax,DWORD [32+edi] - mov ebx,DWORD [36+edi] - mov ecx,DWORD [40+edi] - bswap eax - mov edx,DWORD [44+edi] - bswap ebx - push eax - bswap ecx - push ebx - bswap edx - push ecx - push edx - mov eax,DWORD [48+edi] - mov ebx,DWORD [52+edi] - mov ecx,DWORD [56+edi] - bswap eax - mov edx,DWORD [60+edi] - bswap ebx - push eax - bswap ecx - push ebx - bswap edx - push ecx - push edx - add edi,64 - lea esp,[esp-36] - mov DWORD [104+esp],edi - mov eax,DWORD [esi] - mov ebx,DWORD [4+esi] - mov ecx,DWORD [8+esi] - mov edi,DWORD [12+esi] - mov DWORD [8+esp],ebx - xor ebx,ecx - mov DWORD [12+esp],ecx - mov DWORD [16+esp],edi - mov DWORD [esp],ebx - mov edx,DWORD [16+esi] - mov ebx,DWORD [20+esi] - mov ecx,DWORD [24+esi] - mov edi,DWORD [28+esi] - mov DWORD [24+esp],ebx - mov DWORD [28+esp],ecx - mov DWORD [32+esp],edi -align 16 -L$00600_15_shrd: - mov ecx,edx - mov esi,DWORD [24+esp] - shrd ecx,ecx,14 - mov edi,DWORD [28+esp] - xor ecx,edx - xor esi,edi - mov ebx,DWORD [96+esp] - shrd ecx,ecx,5 - and esi,edx - mov DWORD [20+esp],edx - xor edx,ecx - add ebx,DWORD [32+esp] - xor esi,edi - shrd edx,edx,6 - mov ecx,eax - add ebx,esi - shrd ecx,ecx,9 - add ebx,edx - mov edi,DWORD [8+esp] - xor ecx,eax - mov DWORD [4+esp],eax - lea esp,[esp-4] - shrd ecx,ecx,11 - mov esi,DWORD [ebp] - xor ecx,eax - mov edx,DWORD [20+esp] - xor eax,edi - shrd ecx,ecx,2 - add ebx,esi - mov DWORD [esp],eax - add edx,ebx - and eax,DWORD [4+esp] - add ebx,ecx - xor eax,edi - add ebp,4 - add eax,ebx - cmp esi,3248222580 - jne NEAR L$00600_15_shrd - mov ecx,DWORD [156+esp] - jmp NEAR L$00716_63_shrd -align 16 -L$00716_63_shrd: - mov ebx,ecx - mov esi,DWORD [104+esp] - shrd ecx,ecx,11 - mov edi,esi - shrd esi,esi,2 - xor ecx,ebx - shr ebx,3 - shrd ecx,ecx,7 - xor esi,edi - xor ebx,ecx - shrd esi,esi,17 - add ebx,DWORD [160+esp] - shr edi,10 - add ebx,DWORD [124+esp] - mov ecx,edx - xor edi,esi - mov esi,DWORD [24+esp] - shrd ecx,ecx,14 - add ebx,edi - mov edi,DWORD [28+esp] - xor ecx,edx - xor esi,edi - mov DWORD [96+esp],ebx - shrd ecx,ecx,5 - and esi,edx - mov DWORD [20+esp],edx - xor edx,ecx - add ebx,DWORD [32+esp] - xor esi,edi - shrd edx,edx,6 - mov ecx,eax - add ebx,esi - shrd ecx,ecx,9 - add ebx,edx - mov edi,DWORD [8+esp] - xor ecx,eax - mov DWORD [4+esp],eax - lea esp,[esp-4] - shrd ecx,ecx,11 - mov esi,DWORD [ebp] - xor ecx,eax - mov edx,DWORD [20+esp] - xor eax,edi - shrd ecx,ecx,2 - add ebx,esi - mov DWORD [esp],eax - add edx,ebx - and eax,DWORD [4+esp] - add ebx,ecx - xor eax,edi - mov ecx,DWORD [156+esp] - add ebp,4 - add eax,ebx - cmp esi,3329325298 - jne NEAR L$00716_63_shrd - mov esi,DWORD [356+esp] - mov ebx,DWORD [8+esp] - mov ecx,DWORD [16+esp] - add eax,DWORD [esi] - add ebx,DWORD [4+esi] - add edi,DWORD [8+esi] - add ecx,DWORD [12+esi] - mov DWORD [esi],eax - mov DWORD [4+esi],ebx - mov DWORD [8+esi],edi - mov DWORD [12+esi],ecx - mov eax,DWORD [24+esp] - mov ebx,DWORD [28+esp] - mov ecx,DWORD [32+esp] - mov edi,DWORD [360+esp] - add edx,DWORD [16+esi] - add eax,DWORD [20+esi] - add ebx,DWORD [24+esi] - add ecx,DWORD [28+esi] - mov DWORD [16+esi],edx - mov DWORD [20+esi],eax - mov DWORD [24+esi],ebx - mov DWORD [28+esi],ecx - lea esp,[356+esp] - sub ebp,256 - cmp edi,DWORD [8+esp] - jb NEAR L$005loop_shrd - mov esp,DWORD [12+esp] - pop edi - pop esi - pop ebx - pop ebp - ret align 64 L$001K256: dd 1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298 @@ -452,7 +272,7 @@ db 67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97 db 112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103 db 62,0 align 16 -L$008unrolled: +L$006unrolled: lea esp,[esp-96] mov eax,DWORD [esi] mov ebp,DWORD [4+esi] @@ -3358,5 +3178,1414 @@ L$009grand_loop: pop ebx pop ebp ret +align 32 +L$004shaext: + sub esp,32 + movdqu xmm1,[esi] + lea ebp,[128+ebp] + movdqu xmm2,[16+esi] + movdqa xmm7,[128+ebp] + pshufd xmm0,xmm1,27 + pshufd xmm1,xmm1,177 + pshufd xmm2,xmm2,27 +db 102,15,58,15,202,8 + punpcklqdq xmm2,xmm0 + jmp NEAR L$010loop_shaext +align 16 +L$010loop_shaext: + movdqu xmm3,[edi] + movdqu xmm4,[16+edi] + movdqu xmm5,[32+edi] +db 102,15,56,0,223 + movdqu xmm6,[48+edi] + movdqa [16+esp],xmm2 + movdqa xmm0,[ebp-128] + paddd xmm0,xmm3 +db 102,15,56,0,231 +db 15,56,203,209 + pshufd xmm0,xmm0,14 + nop + movdqa [esp],xmm1 +db 15,56,203,202 + movdqa xmm0,[ebp-112] + paddd xmm0,xmm4 +db 102,15,56,0,239 +db 15,56,203,209 + pshufd xmm0,xmm0,14 + lea edi,[64+edi] +db 15,56,204,220 +db 15,56,203,202 + movdqa xmm0,[ebp-96] + paddd xmm0,xmm5 +db 102,15,56,0,247 +db 15,56,203,209 + pshufd xmm0,xmm0,14 + movdqa xmm7,xmm6 +db 102,15,58,15,253,4 + nop + paddd xmm3,xmm7 +db 15,56,204,229 +db 15,56,203,202 + movdqa xmm0,[ebp-80] + paddd xmm0,xmm6 +db 15,56,205,222 +db 15,56,203,209 + pshufd xmm0,xmm0,14 + movdqa xmm7,xmm3 +db 102,15,58,15,254,4 + nop + paddd xmm4,xmm7 +db 15,56,204,238 +db 15,56,203,202 + movdqa xmm0,[ebp-64] + paddd xmm0,xmm3 +db 15,56,205,227 +db 15,56,203,209 + pshufd xmm0,xmm0,14 + movdqa xmm7,xmm4 +db 102,15,58,15,251,4 + nop + paddd xmm5,xmm7 +db 15,56,204,243 +db 15,56,203,202 + movdqa xmm0,[ebp-48] + paddd xmm0,xmm4 +db 15,56,205,236 +db 15,56,203,209 + pshufd xmm0,xmm0,14 + movdqa xmm7,xmm5 +db 102,15,58,15,252,4 + nop + paddd xmm6,xmm7 +db 15,56,204,220 +db 15,56,203,202 + movdqa xmm0,[ebp-32] + paddd xmm0,xmm5 +db 15,56,205,245 +db 15,56,203,209 + pshufd xmm0,xmm0,14 + movdqa xmm7,xmm6 +db 102,15,58,15,253,4 + nop + paddd xmm3,xmm7 +db 15,56,204,229 +db 15,56,203,202 + movdqa xmm0,[ebp-16] + paddd xmm0,xmm6 +db 15,56,205,222 +db 15,56,203,209 + pshufd xmm0,xmm0,14 + movdqa xmm7,xmm3 +db 102,15,58,15,254,4 + nop + paddd xmm4,xmm7 +db 15,56,204,238 +db 15,56,203,202 + movdqa xmm0,[ebp] + paddd xmm0,xmm3 +db 15,56,205,227 +db 15,56,203,209 + pshufd xmm0,xmm0,14 + movdqa xmm7,xmm4 +db 102,15,58,15,251,4 + nop + paddd xmm5,xmm7 +db 15,56,204,243 +db 15,56,203,202 + movdqa xmm0,[16+ebp] + paddd xmm0,xmm4 +db 15,56,205,236 +db 15,56,203,209 + pshufd xmm0,xmm0,14 + movdqa xmm7,xmm5 +db 102,15,58,15,252,4 + nop + paddd xmm6,xmm7 +db 15,56,204,220 +db 15,56,203,202 + movdqa xmm0,[32+ebp] + paddd xmm0,xmm5 +db 15,56,205,245 +db 15,56,203,209 + pshufd xmm0,xmm0,14 + movdqa xmm7,xmm6 +db 102,15,58,15,253,4 + nop + paddd xmm3,xmm7 +db 15,56,204,229 +db 15,56,203,202 + movdqa xmm0,[48+ebp] + paddd xmm0,xmm6 +db 15,56,205,222 +db 15,56,203,209 + pshufd xmm0,xmm0,14 + movdqa xmm7,xmm3 +db 102,15,58,15,254,4 + nop + paddd xmm4,xmm7 +db 15,56,204,238 +db 15,56,203,202 + movdqa xmm0,[64+ebp] + paddd xmm0,xmm3 +db 15,56,205,227 +db 15,56,203,209 + pshufd xmm0,xmm0,14 + movdqa xmm7,xmm4 +db 102,15,58,15,251,4 + nop + paddd xmm5,xmm7 +db 15,56,204,243 +db 15,56,203,202 + movdqa xmm0,[80+ebp] + paddd xmm0,xmm4 +db 15,56,205,236 +db 15,56,203,209 + pshufd xmm0,xmm0,14 + movdqa xmm7,xmm5 +db 102,15,58,15,252,4 +db 15,56,203,202 + paddd xmm6,xmm7 + movdqa xmm0,[96+ebp] + paddd xmm0,xmm5 +db 15,56,203,209 + pshufd xmm0,xmm0,14 +db 15,56,205,245 + movdqa xmm7,[128+ebp] +db 15,56,203,202 + movdqa xmm0,[112+ebp] + paddd xmm0,xmm6 + nop +db 15,56,203,209 + pshufd xmm0,xmm0,14 + cmp eax,edi + nop +db 15,56,203,202 + paddd xmm2,[16+esp] + paddd xmm1,[esp] + jnz NEAR L$010loop_shaext + pshufd xmm2,xmm2,177 + pshufd xmm7,xmm1,27 + pshufd xmm1,xmm1,177 + punpckhqdq xmm1,xmm2 +db 102,15,58,15,215,8 + mov esp,DWORD [44+esp] + movdqu [esi],xmm1 + movdqu [16+esi],xmm2 + pop edi + pop esi + pop ebx + pop ebp + ret +align 32 +L$005SSSE3: + lea esp,[esp-96] + mov eax,DWORD [esi] + mov ebx,DWORD [4+esi] + mov ecx,DWORD [8+esi] + mov edi,DWORD [12+esi] + mov DWORD [4+esp],ebx + xor ebx,ecx + mov DWORD [8+esp],ecx + mov DWORD [12+esp],edi + mov edx,DWORD [16+esi] + mov edi,DWORD [20+esi] + mov ecx,DWORD [24+esi] + mov esi,DWORD [28+esi] + mov DWORD [20+esp],edi + mov edi,DWORD [100+esp] + mov DWORD [24+esp],ecx + mov DWORD [28+esp],esi + movdqa xmm7,[256+ebp] + jmp NEAR L$011grand_ssse3 +align 16 +L$011grand_ssse3: + movdqu xmm0,[edi] + movdqu xmm1,[16+edi] + movdqu xmm2,[32+edi] + movdqu xmm3,[48+edi] + add edi,64 +db 102,15,56,0,199 + mov DWORD [100+esp],edi +db 102,15,56,0,207 + movdqa xmm4,[ebp] +db 102,15,56,0,215 + movdqa xmm5,[16+ebp] + paddd xmm4,xmm0 +db 102,15,56,0,223 + movdqa xmm6,[32+ebp] + paddd xmm5,xmm1 + movdqa xmm7,[48+ebp] + movdqa [32+esp],xmm4 + paddd xmm6,xmm2 + movdqa [48+esp],xmm5 + paddd xmm7,xmm3 + movdqa [64+esp],xmm6 + movdqa [80+esp],xmm7 + jmp NEAR L$012ssse3_00_47 +align 16 +L$012ssse3_00_47: + add ebp,64 + mov ecx,edx + movdqa xmm4,xmm1 + ror edx,14 + mov esi,DWORD [20+esp] + movdqa xmm7,xmm3 + xor edx,ecx + mov edi,DWORD [24+esp] +db 102,15,58,15,224,4 + xor esi,edi + ror edx,5 + and esi,ecx +db 102,15,58,15,250,4 + mov DWORD [16+esp],ecx + xor edx,ecx + xor edi,esi + movdqa xmm5,xmm4 + ror edx,6 + mov ecx,eax + movdqa xmm6,xmm4 + add edx,edi + mov edi,DWORD [4+esp] + psrld xmm4,3 + mov esi,eax + ror ecx,9 + paddd xmm0,xmm7 + mov DWORD [esp],eax + xor ecx,eax + psrld xmm6,7 + xor eax,edi + add edx,DWORD [28+esp] + ror ecx,11 + and ebx,eax + pshufd xmm7,xmm3,250 + xor ecx,esi + add edx,DWORD [32+esp] + pslld xmm5,14 + xor ebx,edi + ror ecx,2 + pxor xmm4,xmm6 + add ebx,edx + add edx,DWORD [12+esp] + psrld xmm6,11 + add ebx,ecx + mov ecx,edx + ror edx,14 + pxor xmm4,xmm5 + mov esi,DWORD [16+esp] + xor edx,ecx + pslld xmm5,11 + mov edi,DWORD [20+esp] + xor esi,edi + ror edx,5 + pxor xmm4,xmm6 + and esi,ecx + mov DWORD [12+esp],ecx + movdqa xmm6,xmm7 + xor edx,ecx + xor edi,esi + ror edx,6 + pxor xmm4,xmm5 + mov ecx,ebx + add edx,edi + psrld xmm7,10 + mov edi,DWORD [esp] + mov esi,ebx + ror ecx,9 + paddd xmm0,xmm4 + mov DWORD [28+esp],ebx + xor ecx,ebx + psrlq xmm6,17 + xor ebx,edi + add edx,DWORD [24+esp] + ror ecx,11 + pxor xmm7,xmm6 + and eax,ebx + xor ecx,esi + psrlq xmm6,2 + add edx,DWORD [36+esp] + xor eax,edi + ror ecx,2 + pxor xmm7,xmm6 + add eax,edx + add edx,DWORD [8+esp] + pshufd xmm7,xmm7,128 + add eax,ecx + mov ecx,edx + ror edx,14 + mov esi,DWORD [12+esp] + xor edx,ecx + mov edi,DWORD [16+esp] + xor esi,edi + ror edx,5 + and esi,ecx + psrldq xmm7,8 + mov DWORD [8+esp],ecx + xor edx,ecx + xor edi,esi + paddd xmm0,xmm7 + ror edx,6 + mov ecx,eax + add edx,edi + mov edi,DWORD [28+esp] + mov esi,eax + ror ecx,9 + mov DWORD [24+esp],eax + pshufd xmm7,xmm0,80 + xor ecx,eax + xor eax,edi + add edx,DWORD [20+esp] + movdqa xmm6,xmm7 + ror ecx,11 + psrld xmm7,10 + and ebx,eax + psrlq xmm6,17 + xor ecx,esi + add edx,DWORD [40+esp] + xor ebx,edi + ror ecx,2 + pxor xmm7,xmm6 + add ebx,edx + add edx,DWORD [4+esp] + psrlq xmm6,2 + add ebx,ecx + mov ecx,edx + ror edx,14 + pxor xmm7,xmm6 + mov esi,DWORD [8+esp] + xor edx,ecx + mov edi,DWORD [12+esp] + pshufd xmm7,xmm7,8 + xor esi,edi + ror edx,5 + movdqa xmm6,[ebp] + and esi,ecx + mov DWORD [4+esp],ecx + pslldq xmm7,8 + xor edx,ecx + xor edi,esi + ror edx,6 + mov ecx,ebx + add edx,edi + mov edi,DWORD [24+esp] + mov esi,ebx + ror ecx,9 + paddd xmm0,xmm7 + mov DWORD [20+esp],ebx + xor ecx,ebx + xor ebx,edi + add edx,DWORD [16+esp] + paddd xmm6,xmm0 + ror ecx,11 + and eax,ebx + xor ecx,esi + add edx,DWORD [44+esp] + xor eax,edi + ror ecx,2 + add eax,edx + add edx,DWORD [esp] + add eax,ecx + movdqa [32+esp],xmm6 + mov ecx,edx + movdqa xmm4,xmm2 + ror edx,14 + mov esi,DWORD [4+esp] + movdqa xmm7,xmm0 + xor edx,ecx + mov edi,DWORD [8+esp] +db 102,15,58,15,225,4 + xor esi,edi + ror edx,5 + and esi,ecx +db 102,15,58,15,251,4 + mov DWORD [esp],ecx + xor edx,ecx + xor edi,esi + movdqa xmm5,xmm4 + ror edx,6 + mov ecx,eax + movdqa xmm6,xmm4 + add edx,edi + mov edi,DWORD [20+esp] + psrld xmm4,3 + mov esi,eax + ror ecx,9 + paddd xmm1,xmm7 + mov DWORD [16+esp],eax + xor ecx,eax + psrld xmm6,7 + xor eax,edi + add edx,DWORD [12+esp] + ror ecx,11 + and ebx,eax + pshufd xmm7,xmm0,250 + xor ecx,esi + add edx,DWORD [48+esp] + pslld xmm5,14 + xor ebx,edi + ror ecx,2 + pxor xmm4,xmm6 + add ebx,edx + add edx,DWORD [28+esp] + psrld xmm6,11 + add ebx,ecx + mov ecx,edx + ror edx,14 + pxor xmm4,xmm5 + mov esi,DWORD [esp] + xor edx,ecx + pslld xmm5,11 + mov edi,DWORD [4+esp] + xor esi,edi + ror edx,5 + pxor xmm4,xmm6 + and esi,ecx + mov DWORD [28+esp],ecx + movdqa xmm6,xmm7 + xor edx,ecx + xor edi,esi + ror edx,6 + pxor xmm4,xmm5 + mov ecx,ebx + add edx,edi + psrld xmm7,10 + mov edi,DWORD [16+esp] + mov esi,ebx + ror ecx,9 + paddd xmm1,xmm4 + mov DWORD [12+esp],ebx + xor ecx,ebx + psrlq xmm6,17 + xor ebx,edi + add edx,DWORD [8+esp] + ror ecx,11 + pxor xmm7,xmm6 + and eax,ebx + xor ecx,esi + psrlq xmm6,2 + add edx,DWORD [52+esp] + xor eax,edi + ror ecx,2 + pxor xmm7,xmm6 + add eax,edx + add edx,DWORD [24+esp] + pshufd xmm7,xmm7,128 + add eax,ecx + mov ecx,edx + ror edx,14 + mov esi,DWORD [28+esp] + xor edx,ecx + mov edi,DWORD [esp] + xor esi,edi + ror edx,5 + and esi,ecx + psrldq xmm7,8 + mov DWORD [24+esp],ecx + xor edx,ecx + xor edi,esi + paddd xmm1,xmm7 + ror edx,6 + mov ecx,eax + add edx,edi + mov edi,DWORD [12+esp] + mov esi,eax + ror ecx,9 + mov DWORD [8+esp],eax + pshufd xmm7,xmm1,80 + xor ecx,eax + xor eax,edi + add edx,DWORD [4+esp] + movdqa xmm6,xmm7 + ror ecx,11 + psrld xmm7,10 + and ebx,eax + psrlq xmm6,17 + xor ecx,esi + add edx,DWORD [56+esp] + xor ebx,edi + ror ecx,2 + pxor xmm7,xmm6 + add ebx,edx + add edx,DWORD [20+esp] + psrlq xmm6,2 + add ebx,ecx + mov ecx,edx + ror edx,14 + pxor xmm7,xmm6 + mov esi,DWORD [24+esp] + xor edx,ecx + mov edi,DWORD [28+esp] + pshufd xmm7,xmm7,8 + xor esi,edi + ror edx,5 + movdqa xmm6,[16+ebp] + and esi,ecx + mov DWORD [20+esp],ecx + pslldq xmm7,8 + xor edx,ecx + xor edi,esi + ror edx,6 + mov ecx,ebx + add edx,edi + mov edi,DWORD [8+esp] + mov esi,ebx + ror ecx,9 + paddd xmm1,xmm7 + mov DWORD [4+esp],ebx + xor ecx,ebx + xor ebx,edi + add edx,DWORD [esp] + paddd xmm6,xmm1 + ror ecx,11 + and eax,ebx + xor ecx,esi + add edx,DWORD [60+esp] + xor eax,edi + ror ecx,2 + add eax,edx + add edx,DWORD [16+esp] + add eax,ecx + movdqa [48+esp],xmm6 + mov ecx,edx + movdqa xmm4,xmm3 + ror edx,14 + mov esi,DWORD [20+esp] + movdqa xmm7,xmm1 + xor edx,ecx + mov edi,DWORD [24+esp] +db 102,15,58,15,226,4 + xor esi,edi + ror edx,5 + and esi,ecx +db 102,15,58,15,248,4 + mov DWORD [16+esp],ecx + xor edx,ecx + xor edi,esi + movdqa xmm5,xmm4 + ror edx,6 + mov ecx,eax + movdqa xmm6,xmm4 + add edx,edi + mov edi,DWORD [4+esp] + psrld xmm4,3 + mov esi,eax + ror ecx,9 + paddd xmm2,xmm7 + mov DWORD [esp],eax + xor ecx,eax + psrld xmm6,7 + xor eax,edi + add edx,DWORD [28+esp] + ror ecx,11 + and ebx,eax + pshufd xmm7,xmm1,250 + xor ecx,esi + add edx,DWORD [64+esp] + pslld xmm5,14 + xor ebx,edi + ror ecx,2 + pxor xmm4,xmm6 + add ebx,edx + add edx,DWORD [12+esp] + psrld xmm6,11 + add ebx,ecx + mov ecx,edx + ror edx,14 + pxor xmm4,xmm5 + mov esi,DWORD [16+esp] + xor edx,ecx + pslld xmm5,11 + mov edi,DWORD [20+esp] + xor esi,edi + ror edx,5 + pxor xmm4,xmm6 + and esi,ecx + mov DWORD [12+esp],ecx + movdqa xmm6,xmm7 + xor edx,ecx + xor edi,esi + ror edx,6 + pxor xmm4,xmm5 + mov ecx,ebx + add edx,edi + psrld xmm7,10 + mov edi,DWORD [esp] + mov esi,ebx + ror ecx,9 + paddd xmm2,xmm4 + mov DWORD [28+esp],ebx + xor ecx,ebx + psrlq xmm6,17 + xor ebx,edi + add edx,DWORD [24+esp] + ror ecx,11 + pxor xmm7,xmm6 + and eax,ebx + xor ecx,esi + psrlq xmm6,2 + add edx,DWORD [68+esp] + xor eax,edi + ror ecx,2 + pxor xmm7,xmm6 + add eax,edx + add edx,DWORD [8+esp] + pshufd xmm7,xmm7,128 + add eax,ecx + mov ecx,edx + ror edx,14 + mov esi,DWORD [12+esp] + xor edx,ecx + mov edi,DWORD [16+esp] + xor esi,edi + ror edx,5 + and esi,ecx + psrldq xmm7,8 + mov DWORD [8+esp],ecx + xor edx,ecx + xor edi,esi + paddd xmm2,xmm7 + ror edx,6 + mov ecx,eax + add edx,edi + mov edi,DWORD [28+esp] + mov esi,eax + ror ecx,9 + mov DWORD [24+esp],eax + pshufd xmm7,xmm2,80 + xor ecx,eax + xor eax,edi + add edx,DWORD [20+esp] + movdqa xmm6,xmm7 + ror ecx,11 + psrld xmm7,10 + and ebx,eax + psrlq xmm6,17 + xor ecx,esi + add edx,DWORD [72+esp] + xor ebx,edi + ror ecx,2 + pxor xmm7,xmm6 + add ebx,edx + add edx,DWORD [4+esp] + psrlq xmm6,2 + add ebx,ecx + mov ecx,edx + ror edx,14 + pxor xmm7,xmm6 + mov esi,DWORD [8+esp] + xor edx,ecx + mov edi,DWORD [12+esp] + pshufd xmm7,xmm7,8 + xor esi,edi + ror edx,5 + movdqa xmm6,[32+ebp] + and esi,ecx + mov DWORD [4+esp],ecx + pslldq xmm7,8 + xor edx,ecx + xor edi,esi + ror edx,6 + mov ecx,ebx + add edx,edi + mov edi,DWORD [24+esp] + mov esi,ebx + ror ecx,9 + paddd xmm2,xmm7 + mov DWORD [20+esp],ebx + xor ecx,ebx + xor ebx,edi + add edx,DWORD [16+esp] + paddd xmm6,xmm2 + ror ecx,11 + and eax,ebx + xor ecx,esi + add edx,DWORD [76+esp] + xor eax,edi + ror ecx,2 + add eax,edx + add edx,DWORD [esp] + add eax,ecx + movdqa [64+esp],xmm6 + mov ecx,edx + movdqa xmm4,xmm0 + ror edx,14 + mov esi,DWORD [4+esp] + movdqa xmm7,xmm2 + xor edx,ecx + mov edi,DWORD [8+esp] +db 102,15,58,15,227,4 + xor esi,edi + ror edx,5 + and esi,ecx +db 102,15,58,15,249,4 + mov DWORD [esp],ecx + xor edx,ecx + xor edi,esi + movdqa xmm5,xmm4 + ror edx,6 + mov ecx,eax + movdqa xmm6,xmm4 + add edx,edi + mov edi,DWORD [20+esp] + psrld xmm4,3 + mov esi,eax + ror ecx,9 + paddd xmm3,xmm7 + mov DWORD [16+esp],eax + xor ecx,eax + psrld xmm6,7 + xor eax,edi + add edx,DWORD [12+esp] + ror ecx,11 + and ebx,eax + pshufd xmm7,xmm2,250 + xor ecx,esi + add edx,DWORD [80+esp] + pslld xmm5,14 + xor ebx,edi + ror ecx,2 + pxor xmm4,xmm6 + add ebx,edx + add edx,DWORD [28+esp] + psrld xmm6,11 + add ebx,ecx + mov ecx,edx + ror edx,14 + pxor xmm4,xmm5 + mov esi,DWORD [esp] + xor edx,ecx + pslld xmm5,11 + mov edi,DWORD [4+esp] + xor esi,edi + ror edx,5 + pxor xmm4,xmm6 + and esi,ecx + mov DWORD [28+esp],ecx + movdqa xmm6,xmm7 + xor edx,ecx + xor edi,esi + ror edx,6 + pxor xmm4,xmm5 + mov ecx,ebx + add edx,edi + psrld xmm7,10 + mov edi,DWORD [16+esp] + mov esi,ebx + ror ecx,9 + paddd xmm3,xmm4 + mov DWORD [12+esp],ebx + xor ecx,ebx + psrlq xmm6,17 + xor ebx,edi + add edx,DWORD [8+esp] + ror ecx,11 + pxor xmm7,xmm6 + and eax,ebx + xor ecx,esi + psrlq xmm6,2 + add edx,DWORD [84+esp] + xor eax,edi + ror ecx,2 + pxor xmm7,xmm6 + add eax,edx + add edx,DWORD [24+esp] + pshufd xmm7,xmm7,128 + add eax,ecx + mov ecx,edx + ror edx,14 + mov esi,DWORD [28+esp] + xor edx,ecx + mov edi,DWORD [esp] + xor esi,edi + ror edx,5 + and esi,ecx + psrldq xmm7,8 + mov DWORD [24+esp],ecx + xor edx,ecx + xor edi,esi + paddd xmm3,xmm7 + ror edx,6 + mov ecx,eax + add edx,edi + mov edi,DWORD [12+esp] + mov esi,eax + ror ecx,9 + mov DWORD [8+esp],eax + pshufd xmm7,xmm3,80 + xor ecx,eax + xor eax,edi + add edx,DWORD [4+esp] + movdqa xmm6,xmm7 + ror ecx,11 + psrld xmm7,10 + and ebx,eax + psrlq xmm6,17 + xor ecx,esi + add edx,DWORD [88+esp] + xor ebx,edi + ror ecx,2 + pxor xmm7,xmm6 + add ebx,edx + add edx,DWORD [20+esp] + psrlq xmm6,2 + add ebx,ecx + mov ecx,edx + ror edx,14 + pxor xmm7,xmm6 + mov esi,DWORD [24+esp] + xor edx,ecx + mov edi,DWORD [28+esp] + pshufd xmm7,xmm7,8 + xor esi,edi + ror edx,5 + movdqa xmm6,[48+ebp] + and esi,ecx + mov DWORD [20+esp],ecx + pslldq xmm7,8 + xor edx,ecx + xor edi,esi + ror edx,6 + mov ecx,ebx + add edx,edi + mov edi,DWORD [8+esp] + mov esi,ebx + ror ecx,9 + paddd xmm3,xmm7 + mov DWORD [4+esp],ebx + xor ecx,ebx + xor ebx,edi + add edx,DWORD [esp] + paddd xmm6,xmm3 + ror ecx,11 + and eax,ebx + xor ecx,esi + add edx,DWORD [92+esp] + xor eax,edi + ror ecx,2 + add eax,edx + add edx,DWORD [16+esp] + add eax,ecx + movdqa [80+esp],xmm6 + cmp DWORD [64+ebp],66051 + jne NEAR L$012ssse3_00_47 + mov ecx,edx + ror edx,14 + mov esi,DWORD [20+esp] + xor edx,ecx + mov edi,DWORD [24+esp] + xor esi,edi + ror edx,5 + and esi,ecx + mov DWORD [16+esp],ecx + xor edx,ecx + xor edi,esi + ror edx,6 + mov ecx,eax + add edx,edi + mov edi,DWORD [4+esp] + mov esi,eax + ror ecx,9 + mov DWORD [esp],eax + xor ecx,eax + xor eax,edi + add edx,DWORD [28+esp] + ror ecx,11 + and ebx,eax + xor ecx,esi + add edx,DWORD [32+esp] + xor ebx,edi + ror ecx,2 + add ebx,edx + add edx,DWORD [12+esp] + add ebx,ecx + mov ecx,edx + ror edx,14 + mov esi,DWORD [16+esp] + xor edx,ecx + mov edi,DWORD [20+esp] + xor esi,edi + ror edx,5 + and esi,ecx + mov DWORD [12+esp],ecx + xor edx,ecx + xor edi,esi + ror edx,6 + mov ecx,ebx + add edx,edi + mov edi,DWORD [esp] + mov esi,ebx + ror ecx,9 + mov DWORD [28+esp],ebx + xor ecx,ebx + xor ebx,edi + add edx,DWORD [24+esp] + ror ecx,11 + and eax,ebx + xor ecx,esi + add edx,DWORD [36+esp] + xor eax,edi + ror ecx,2 + add eax,edx + add edx,DWORD [8+esp] + add eax,ecx + mov ecx,edx + ror edx,14 + mov esi,DWORD [12+esp] + xor edx,ecx + mov edi,DWORD [16+esp] + xor esi,edi + ror edx,5 + and esi,ecx + mov DWORD [8+esp],ecx + xor edx,ecx + xor edi,esi + ror edx,6 + mov ecx,eax + add edx,edi + mov edi,DWORD [28+esp] + mov esi,eax + ror ecx,9 + mov DWORD [24+esp],eax + xor ecx,eax + xor eax,edi + add edx,DWORD [20+esp] + ror ecx,11 + and ebx,eax + xor ecx,esi + add edx,DWORD [40+esp] + xor ebx,edi + ror ecx,2 + add ebx,edx + add edx,DWORD [4+esp] + add ebx,ecx + mov ecx,edx + ror edx,14 + mov esi,DWORD [8+esp] + xor edx,ecx + mov edi,DWORD [12+esp] + xor esi,edi + ror edx,5 + and esi,ecx + mov DWORD [4+esp],ecx + xor edx,ecx + xor edi,esi + ror edx,6 + mov ecx,ebx + add edx,edi + mov edi,DWORD [24+esp] + mov esi,ebx + ror ecx,9 + mov DWORD [20+esp],ebx + xor ecx,ebx + xor ebx,edi + add edx,DWORD [16+esp] + ror ecx,11 + and eax,ebx + xor ecx,esi + add edx,DWORD [44+esp] + xor eax,edi + ror ecx,2 + add eax,edx + add edx,DWORD [esp] + add eax,ecx + mov ecx,edx + ror edx,14 + mov esi,DWORD [4+esp] + xor edx,ecx + mov edi,DWORD [8+esp] + xor esi,edi + ror edx,5 + and esi,ecx + mov DWORD [esp],ecx + xor edx,ecx + xor edi,esi + ror edx,6 + mov ecx,eax + add edx,edi + mov edi,DWORD [20+esp] + mov esi,eax + ror ecx,9 + mov DWORD [16+esp],eax + xor ecx,eax + xor eax,edi + add edx,DWORD [12+esp] + ror ecx,11 + and ebx,eax + xor ecx,esi + add edx,DWORD [48+esp] + xor ebx,edi + ror ecx,2 + add ebx,edx + add edx,DWORD [28+esp] + add ebx,ecx + mov ecx,edx + ror edx,14 + mov esi,DWORD [esp] + xor edx,ecx + mov edi,DWORD [4+esp] + xor esi,edi + ror edx,5 + and esi,ecx + mov DWORD [28+esp],ecx + xor edx,ecx + xor edi,esi + ror edx,6 + mov ecx,ebx + add edx,edi + mov edi,DWORD [16+esp] + mov esi,ebx + ror ecx,9 + mov DWORD [12+esp],ebx + xor ecx,ebx + xor ebx,edi + add edx,DWORD [8+esp] + ror ecx,11 + and eax,ebx + xor ecx,esi + add edx,DWORD [52+esp] + xor eax,edi + ror ecx,2 + add eax,edx + add edx,DWORD [24+esp] + add eax,ecx + mov ecx,edx + ror edx,14 + mov esi,DWORD [28+esp] + xor edx,ecx + mov edi,DWORD [esp] + xor esi,edi + ror edx,5 + and esi,ecx + mov DWORD [24+esp],ecx + xor edx,ecx + xor edi,esi + ror edx,6 + mov ecx,eax + add edx,edi + mov edi,DWORD [12+esp] + mov esi,eax + ror ecx,9 + mov DWORD [8+esp],eax + xor ecx,eax + xor eax,edi + add edx,DWORD [4+esp] + ror ecx,11 + and ebx,eax + xor ecx,esi + add edx,DWORD [56+esp] + xor ebx,edi + ror ecx,2 + add ebx,edx + add edx,DWORD [20+esp] + add ebx,ecx + mov ecx,edx + ror edx,14 + mov esi,DWORD [24+esp] + xor edx,ecx + mov edi,DWORD [28+esp] + xor esi,edi + ror edx,5 + and esi,ecx + mov DWORD [20+esp],ecx + xor edx,ecx + xor edi,esi + ror edx,6 + mov ecx,ebx + add edx,edi + mov edi,DWORD [8+esp] + mov esi,ebx + ror ecx,9 + mov DWORD [4+esp],ebx + xor ecx,ebx + xor ebx,edi + add edx,DWORD [esp] + ror ecx,11 + and eax,ebx + xor ecx,esi + add edx,DWORD [60+esp] + xor eax,edi + ror ecx,2 + add eax,edx + add edx,DWORD [16+esp] + add eax,ecx + mov ecx,edx + ror edx,14 + mov esi,DWORD [20+esp] + xor edx,ecx + mov edi,DWORD [24+esp] + xor esi,edi + ror edx,5 + and esi,ecx + mov DWORD [16+esp],ecx + xor edx,ecx + xor edi,esi + ror edx,6 + mov ecx,eax + add edx,edi + mov edi,DWORD [4+esp] + mov esi,eax + ror ecx,9 + mov DWORD [esp],eax + xor ecx,eax + xor eax,edi + add edx,DWORD [28+esp] + ror ecx,11 + and ebx,eax + xor ecx,esi + add edx,DWORD [64+esp] + xor ebx,edi + ror ecx,2 + add ebx,edx + add edx,DWORD [12+esp] + add ebx,ecx + mov ecx,edx + ror edx,14 + mov esi,DWORD [16+esp] + xor edx,ecx + mov edi,DWORD [20+esp] + xor esi,edi + ror edx,5 + and esi,ecx + mov DWORD [12+esp],ecx + xor edx,ecx + xor edi,esi + ror edx,6 + mov ecx,ebx + add edx,edi + mov edi,DWORD [esp] + mov esi,ebx + ror ecx,9 + mov DWORD [28+esp],ebx + xor ecx,ebx + xor ebx,edi + add edx,DWORD [24+esp] + ror ecx,11 + and eax,ebx + xor ecx,esi + add edx,DWORD [68+esp] + xor eax,edi + ror ecx,2 + add eax,edx + add edx,DWORD [8+esp] + add eax,ecx + mov ecx,edx + ror edx,14 + mov esi,DWORD [12+esp] + xor edx,ecx + mov edi,DWORD [16+esp] + xor esi,edi + ror edx,5 + and esi,ecx + mov DWORD [8+esp],ecx + xor edx,ecx + xor edi,esi + ror edx,6 + mov ecx,eax + add edx,edi + mov edi,DWORD [28+esp] + mov esi,eax + ror ecx,9 + mov DWORD [24+esp],eax + xor ecx,eax + xor eax,edi + add edx,DWORD [20+esp] + ror ecx,11 + and ebx,eax + xor ecx,esi + add edx,DWORD [72+esp] + xor ebx,edi + ror ecx,2 + add ebx,edx + add edx,DWORD [4+esp] + add ebx,ecx + mov ecx,edx + ror edx,14 + mov esi,DWORD [8+esp] + xor edx,ecx + mov edi,DWORD [12+esp] + xor esi,edi + ror edx,5 + and esi,ecx + mov DWORD [4+esp],ecx + xor edx,ecx + xor edi,esi + ror edx,6 + mov ecx,ebx + add edx,edi + mov edi,DWORD [24+esp] + mov esi,ebx + ror ecx,9 + mov DWORD [20+esp],ebx + xor ecx,ebx + xor ebx,edi + add edx,DWORD [16+esp] + ror ecx,11 + and eax,ebx + xor ecx,esi + add edx,DWORD [76+esp] + xor eax,edi + ror ecx,2 + add eax,edx + add edx,DWORD [esp] + add eax,ecx + mov ecx,edx + ror edx,14 + mov esi,DWORD [4+esp] + xor edx,ecx + mov edi,DWORD [8+esp] + xor esi,edi + ror edx,5 + and esi,ecx + mov DWORD [esp],ecx + xor edx,ecx + xor edi,esi + ror edx,6 + mov ecx,eax + add edx,edi + mov edi,DWORD [20+esp] + mov esi,eax + ror ecx,9 + mov DWORD [16+esp],eax + xor ecx,eax + xor eax,edi + add edx,DWORD [12+esp] + ror ecx,11 + and ebx,eax + xor ecx,esi + add edx,DWORD [80+esp] + xor ebx,edi + ror ecx,2 + add ebx,edx + add edx,DWORD [28+esp] + add ebx,ecx + mov ecx,edx + ror edx,14 + mov esi,DWORD [esp] + xor edx,ecx + mov edi,DWORD [4+esp] + xor esi,edi + ror edx,5 + and esi,ecx + mov DWORD [28+esp],ecx + xor edx,ecx + xor edi,esi + ror edx,6 + mov ecx,ebx + add edx,edi + mov edi,DWORD [16+esp] + mov esi,ebx + ror ecx,9 + mov DWORD [12+esp],ebx + xor ecx,ebx + xor ebx,edi + add edx,DWORD [8+esp] + ror ecx,11 + and eax,ebx + xor ecx,esi + add edx,DWORD [84+esp] + xor eax,edi + ror ecx,2 + add eax,edx + add edx,DWORD [24+esp] + add eax,ecx + mov ecx,edx + ror edx,14 + mov esi,DWORD [28+esp] + xor edx,ecx + mov edi,DWORD [esp] + xor esi,edi + ror edx,5 + and esi,ecx + mov DWORD [24+esp],ecx + xor edx,ecx + xor edi,esi + ror edx,6 + mov ecx,eax + add edx,edi + mov edi,DWORD [12+esp] + mov esi,eax + ror ecx,9 + mov DWORD [8+esp],eax + xor ecx,eax + xor eax,edi + add edx,DWORD [4+esp] + ror ecx,11 + and ebx,eax + xor ecx,esi + add edx,DWORD [88+esp] + xor ebx,edi + ror ecx,2 + add ebx,edx + add edx,DWORD [20+esp] + add ebx,ecx + mov ecx,edx + ror edx,14 + mov esi,DWORD [24+esp] + xor edx,ecx + mov edi,DWORD [28+esp] + xor esi,edi + ror edx,5 + and esi,ecx + mov DWORD [20+esp],ecx + xor edx,ecx + xor edi,esi + ror edx,6 + mov ecx,ebx + add edx,edi + mov edi,DWORD [8+esp] + mov esi,ebx + ror ecx,9 + mov DWORD [4+esp],ebx + xor ecx,ebx + xor ebx,edi + add edx,DWORD [esp] + ror ecx,11 + and eax,ebx + xor ecx,esi + add edx,DWORD [92+esp] + xor eax,edi + ror ecx,2 + add eax,edx + add edx,DWORD [16+esp] + add eax,ecx + mov esi,DWORD [96+esp] + xor ebx,edi + mov ecx,DWORD [12+esp] + add eax,DWORD [esi] + add ebx,DWORD [4+esi] + add edi,DWORD [8+esi] + add ecx,DWORD [12+esi] + mov DWORD [esi],eax + mov DWORD [4+esi],ebx + mov DWORD [8+esi],edi + mov DWORD [12+esi],ecx + mov DWORD [4+esp],ebx + xor ebx,edi + mov DWORD [8+esp],edi + mov DWORD [12+esp],ecx + mov edi,DWORD [20+esp] + mov ecx,DWORD [24+esp] + add edx,DWORD [16+esi] + add edi,DWORD [20+esi] + add ecx,DWORD [24+esi] + mov DWORD [16+esi],edx + mov DWORD [20+esi],edi + mov DWORD [20+esp],edi + mov edi,DWORD [28+esp] + mov DWORD [24+esi],ecx + add edi,DWORD [28+esi] + mov DWORD [24+esp],ecx + mov DWORD [28+esi],edi + mov DWORD [28+esp],edi + mov edi,DWORD [100+esp] + movdqa xmm7,[64+ebp] + sub ebp,192 + cmp edi,DWORD [104+esp] + jb NEAR L$011grand_ssse3 + mov esp,DWORD [108+esp] + pop edi + pop esi + pop ebx + pop ebp + ret segment .bss common _OPENSSL_ia32cap_P 16 diff --git a/third_party/boringssl/win-x86/crypto/sha/sha512-586.asm b/third_party/boringssl/win-x86/crypto/sha/sha512-586.asm index fc688d78411f2..88ed0b380d088 100644 --- a/third_party/boringssl/win-x86/crypto/sha/sha512-586.asm +++ b/third_party/boringssl/win-x86/crypto/sha/sha512-586.asm @@ -14,6 +14,7 @@ section .text code align=64 %else section .text code %endif +;extern _OPENSSL_ia32cap_P global _sha512_block_data_order align 16 _sha512_block_data_order: @@ -38,6 +39,2269 @@ L$000pic_point: mov DWORD [4+esp],edi mov DWORD [8+esp],eax mov DWORD [12+esp],ebx + lea edx,[_OPENSSL_ia32cap_P] + mov ecx,DWORD [edx] + test ecx,67108864 + jz NEAR L$002loop_x86 + mov edx,DWORD [4+edx] + movq mm0,[esi] + and ecx,16777216 + movq mm1,[8+esi] + and edx,512 + movq mm2,[16+esi] + or ecx,edx + movq mm3,[24+esi] + movq mm4,[32+esi] + movq mm5,[40+esi] + movq mm6,[48+esi] + movq mm7,[56+esi] + cmp ecx,16777728 + je NEAR L$003SSSE3 + sub esp,80 + jmp NEAR L$004loop_sse2 +align 16 +L$004loop_sse2: + movq [8+esp],mm1 + movq [16+esp],mm2 + movq [24+esp],mm3 + movq [40+esp],mm5 + movq [48+esp],mm6 + pxor mm2,mm1 + movq [56+esp],mm7 + movq mm3,mm0 + mov eax,DWORD [edi] + mov ebx,DWORD [4+edi] + add edi,8 + mov edx,15 + bswap eax + bswap ebx + jmp NEAR L$00500_14_sse2 +align 16 +L$00500_14_sse2: + movd mm1,eax + mov eax,DWORD [edi] + movd mm7,ebx + mov ebx,DWORD [4+edi] + add edi,8 + bswap eax + bswap ebx + punpckldq mm7,mm1 + movq mm1,mm4 + pxor mm5,mm6 + psrlq mm1,14 + movq [32+esp],mm4 + pand mm5,mm4 + psllq mm4,23 + movq mm0,mm3 + movq [72+esp],mm7 + movq mm3,mm1 + psrlq mm1,4 + pxor mm5,mm6 + pxor mm3,mm4 + psllq mm4,23 + pxor mm3,mm1 + movq [esp],mm0 + paddq mm7,mm5 + pxor mm3,mm4 + psrlq mm1,23 + paddq mm7,[56+esp] + pxor mm3,mm1 + psllq mm4,4 + paddq mm7,[ebp] + pxor mm3,mm4 + movq mm4,[24+esp] + paddq mm3,mm7 + movq mm5,mm0 + psrlq mm5,28 + paddq mm4,mm3 + movq mm6,mm0 + movq mm7,mm5 + psllq mm6,25 + movq mm1,[8+esp] + psrlq mm5,6 + pxor mm7,mm6 + sub esp,8 + psllq mm6,5 + pxor mm7,mm5 + pxor mm0,mm1 + psrlq mm5,5 + pxor mm7,mm6 + pand mm2,mm0 + psllq mm6,6 + pxor mm7,mm5 + pxor mm2,mm1 + pxor mm6,mm7 + movq mm5,[40+esp] + paddq mm3,mm2 + movq mm2,mm0 + add ebp,8 + paddq mm3,mm6 + movq mm6,[48+esp] + dec edx + jnz NEAR L$00500_14_sse2 + movd mm1,eax + movd mm7,ebx + punpckldq mm7,mm1 + movq mm1,mm4 + pxor mm5,mm6 + psrlq mm1,14 + movq [32+esp],mm4 + pand mm5,mm4 + psllq mm4,23 + movq mm0,mm3 + movq [72+esp],mm7 + movq mm3,mm1 + psrlq mm1,4 + pxor mm5,mm6 + pxor mm3,mm4 + psllq mm4,23 + pxor mm3,mm1 + movq [esp],mm0 + paddq mm7,mm5 + pxor mm3,mm4 + psrlq mm1,23 + paddq mm7,[56+esp] + pxor mm3,mm1 + psllq mm4,4 + paddq mm7,[ebp] + pxor mm3,mm4 + movq mm4,[24+esp] + paddq mm3,mm7 + movq mm5,mm0 + psrlq mm5,28 + paddq mm4,mm3 + movq mm6,mm0 + movq mm7,mm5 + psllq mm6,25 + movq mm1,[8+esp] + psrlq mm5,6 + pxor mm7,mm6 + sub esp,8 + psllq mm6,5 + pxor mm7,mm5 + pxor mm0,mm1 + psrlq mm5,5 + pxor mm7,mm6 + pand mm2,mm0 + psllq mm6,6 + pxor mm7,mm5 + pxor mm2,mm1 + pxor mm6,mm7 + movq mm7,[192+esp] + paddq mm3,mm2 + movq mm2,mm0 + add ebp,8 + paddq mm3,mm6 + pxor mm0,mm0 + mov edx,32 + jmp NEAR L$00616_79_sse2 +align 16 +L$00616_79_sse2: + movq mm5,[88+esp] + movq mm1,mm7 + psrlq mm7,1 + movq mm6,mm5 + psrlq mm5,6 + psllq mm1,56 + paddq mm0,mm3 + movq mm3,mm7 + psrlq mm7,6 + pxor mm3,mm1 + psllq mm1,7 + pxor mm3,mm7 + psrlq mm7,1 + pxor mm3,mm1 + movq mm1,mm5 + psrlq mm5,13 + pxor mm7,mm3 + psllq mm6,3 + pxor mm1,mm5 + paddq mm7,[200+esp] + pxor mm1,mm6 + psrlq mm5,42 + paddq mm7,[128+esp] + pxor mm1,mm5 + psllq mm6,42 + movq mm5,[40+esp] + pxor mm1,mm6 + movq mm6,[48+esp] + paddq mm7,mm1 + movq mm1,mm4 + pxor mm5,mm6 + psrlq mm1,14 + movq [32+esp],mm4 + pand mm5,mm4 + psllq mm4,23 + movq [72+esp],mm7 + movq mm3,mm1 + psrlq mm1,4 + pxor mm5,mm6 + pxor mm3,mm4 + psllq mm4,23 + pxor mm3,mm1 + movq [esp],mm0 + paddq mm7,mm5 + pxor mm3,mm4 + psrlq mm1,23 + paddq mm7,[56+esp] + pxor mm3,mm1 + psllq mm4,4 + paddq mm7,[ebp] + pxor mm3,mm4 + movq mm4,[24+esp] + paddq mm3,mm7 + movq mm5,mm0 + psrlq mm5,28 + paddq mm4,mm3 + movq mm6,mm0 + movq mm7,mm5 + psllq mm6,25 + movq mm1,[8+esp] + psrlq mm5,6 + pxor mm7,mm6 + sub esp,8 + psllq mm6,5 + pxor mm7,mm5 + pxor mm0,mm1 + psrlq mm5,5 + pxor mm7,mm6 + pand mm2,mm0 + psllq mm6,6 + pxor mm7,mm5 + pxor mm2,mm1 + pxor mm6,mm7 + movq mm7,[192+esp] + paddq mm2,mm6 + add ebp,8 + movq mm5,[88+esp] + movq mm1,mm7 + psrlq mm7,1 + movq mm6,mm5 + psrlq mm5,6 + psllq mm1,56 + paddq mm2,mm3 + movq mm3,mm7 + psrlq mm7,6 + pxor mm3,mm1 + psllq mm1,7 + pxor mm3,mm7 + psrlq mm7,1 + pxor mm3,mm1 + movq mm1,mm5 + psrlq mm5,13 + pxor mm7,mm3 + psllq mm6,3 + pxor mm1,mm5 + paddq mm7,[200+esp] + pxor mm1,mm6 + psrlq mm5,42 + paddq mm7,[128+esp] + pxor mm1,mm5 + psllq mm6,42 + movq mm5,[40+esp] + pxor mm1,mm6 + movq mm6,[48+esp] + paddq mm7,mm1 + movq mm1,mm4 + pxor mm5,mm6 + psrlq mm1,14 + movq [32+esp],mm4 + pand mm5,mm4 + psllq mm4,23 + movq [72+esp],mm7 + movq mm3,mm1 + psrlq mm1,4 + pxor mm5,mm6 + pxor mm3,mm4 + psllq mm4,23 + pxor mm3,mm1 + movq [esp],mm2 + paddq mm7,mm5 + pxor mm3,mm4 + psrlq mm1,23 + paddq mm7,[56+esp] + pxor mm3,mm1 + psllq mm4,4 + paddq mm7,[ebp] + pxor mm3,mm4 + movq mm4,[24+esp] + paddq mm3,mm7 + movq mm5,mm2 + psrlq mm5,28 + paddq mm4,mm3 + movq mm6,mm2 + movq mm7,mm5 + psllq mm6,25 + movq mm1,[8+esp] + psrlq mm5,6 + pxor mm7,mm6 + sub esp,8 + psllq mm6,5 + pxor mm7,mm5 + pxor mm2,mm1 + psrlq mm5,5 + pxor mm7,mm6 + pand mm0,mm2 + psllq mm6,6 + pxor mm7,mm5 + pxor mm0,mm1 + pxor mm6,mm7 + movq mm7,[192+esp] + paddq mm0,mm6 + add ebp,8 + dec edx + jnz NEAR L$00616_79_sse2 + paddq mm0,mm3 + movq mm1,[8+esp] + movq mm3,[24+esp] + movq mm5,[40+esp] + movq mm6,[48+esp] + movq mm7,[56+esp] + pxor mm2,mm1 + paddq mm0,[esi] + paddq mm1,[8+esi] + paddq mm2,[16+esi] + paddq mm3,[24+esi] + paddq mm4,[32+esi] + paddq mm5,[40+esi] + paddq mm6,[48+esi] + paddq mm7,[56+esi] + mov eax,640 + movq [esi],mm0 + movq [8+esi],mm1 + movq [16+esi],mm2 + movq [24+esi],mm3 + movq [32+esi],mm4 + movq [40+esi],mm5 + movq [48+esi],mm6 + movq [56+esi],mm7 + lea esp,[eax*1+esp] + sub ebp,eax + cmp edi,DWORD [88+esp] + jb NEAR L$004loop_sse2 + mov esp,DWORD [92+esp] + emms + pop edi + pop esi + pop ebx + pop ebp + ret +align 32 +L$003SSSE3: + lea edx,[esp-64] + sub esp,256 + movdqa xmm1,[640+ebp] + movdqu xmm0,[edi] +db 102,15,56,0,193 + movdqa xmm3,[ebp] + movdqa xmm2,xmm1 + movdqu xmm1,[16+edi] + paddq xmm3,xmm0 +db 102,15,56,0,202 + movdqa [edx-128],xmm3 + movdqa xmm4,[16+ebp] + movdqa xmm3,xmm2 + movdqu xmm2,[32+edi] + paddq xmm4,xmm1 +db 102,15,56,0,211 + movdqa [edx-112],xmm4 + movdqa xmm5,[32+ebp] + movdqa xmm4,xmm3 + movdqu xmm3,[48+edi] + paddq xmm5,xmm2 +db 102,15,56,0,220 + movdqa [edx-96],xmm5 + movdqa xmm6,[48+ebp] + movdqa xmm5,xmm4 + movdqu xmm4,[64+edi] + paddq xmm6,xmm3 +db 102,15,56,0,229 + movdqa [edx-80],xmm6 + movdqa xmm7,[64+ebp] + movdqa xmm6,xmm5 + movdqu xmm5,[80+edi] + paddq xmm7,xmm4 +db 102,15,56,0,238 + movdqa [edx-64],xmm7 + movdqa [edx],xmm0 + movdqa xmm0,[80+ebp] + movdqa xmm7,xmm6 + movdqu xmm6,[96+edi] + paddq xmm0,xmm5 +db 102,15,56,0,247 + movdqa [edx-48],xmm0 + movdqa [16+edx],xmm1 + movdqa xmm1,[96+ebp] + movdqa xmm0,xmm7 + movdqu xmm7,[112+edi] + paddq xmm1,xmm6 +db 102,15,56,0,248 + movdqa [edx-32],xmm1 + movdqa [32+edx],xmm2 + movdqa xmm2,[112+ebp] + movdqa xmm0,[edx] + paddq xmm2,xmm7 + movdqa [edx-16],xmm2 + nop +align 32 +L$007loop_ssse3: + movdqa xmm2,[16+edx] + movdqa [48+edx],xmm3 + lea ebp,[128+ebp] + movq [8+esp],mm1 + mov ebx,edi + movq [16+esp],mm2 + lea edi,[128+edi] + movq [24+esp],mm3 + cmp edi,eax + movq [40+esp],mm5 + cmovb ebx,edi + movq [48+esp],mm6 + mov ecx,4 + pxor mm2,mm1 + movq [56+esp],mm7 + pxor mm3,mm3 + jmp NEAR L$00800_47_ssse3 +align 32 +L$00800_47_ssse3: + movdqa xmm3,xmm5 + movdqa xmm1,xmm2 +db 102,15,58,15,208,8 + movdqa [edx],xmm4 +db 102,15,58,15,220,8 + movdqa xmm4,xmm2 + psrlq xmm2,7 + paddq xmm0,xmm3 + movdqa xmm3,xmm4 + psrlq xmm4,1 + psllq xmm3,56 + pxor xmm2,xmm4 + psrlq xmm4,7 + pxor xmm2,xmm3 + psllq xmm3,7 + pxor xmm2,xmm4 + movdqa xmm4,xmm7 + pxor xmm2,xmm3 + movdqa xmm3,xmm7 + psrlq xmm4,6 + paddq xmm0,xmm2 + movdqa xmm2,xmm7 + psrlq xmm3,19 + psllq xmm2,3 + pxor xmm4,xmm3 + psrlq xmm3,42 + pxor xmm4,xmm2 + psllq xmm2,42 + pxor xmm4,xmm3 + movdqa xmm3,[32+edx] + pxor xmm4,xmm2 + movdqa xmm2,[ebp] + movq mm1,mm4 + paddq xmm0,xmm4 + movq mm7,[edx-128] + pxor mm5,mm6 + psrlq mm1,14 + movq [32+esp],mm4 + paddq xmm2,xmm0 + pand mm5,mm4 + psllq mm4,23 + paddq mm0,mm3 + movq mm3,mm1 + psrlq mm1,4 + pxor mm5,mm6 + pxor mm3,mm4 + psllq mm4,23 + pxor mm3,mm1 + movq [esp],mm0 + paddq mm7,mm5 + pxor mm3,mm4 + psrlq mm1,23 + paddq mm7,[56+esp] + pxor mm3,mm1 + psllq mm4,4 + pxor mm3,mm4 + movq mm4,[24+esp] + paddq mm3,mm7 + movq mm5,mm0 + psrlq mm5,28 + paddq mm4,mm3 + movq mm6,mm0 + movq mm7,mm5 + psllq mm6,25 + movq mm1,[8+esp] + psrlq mm5,6 + pxor mm7,mm6 + psllq mm6,5 + pxor mm7,mm5 + pxor mm0,mm1 + psrlq mm5,5 + pxor mm7,mm6 + pand mm2,mm0 + psllq mm6,6 + pxor mm7,mm5 + pxor mm2,mm1 + pxor mm6,mm7 + movq mm5,[32+esp] + paddq mm2,mm6 + movq mm6,[40+esp] + movq mm1,mm4 + movq mm7,[edx-120] + pxor mm5,mm6 + psrlq mm1,14 + movq [24+esp],mm4 + pand mm5,mm4 + psllq mm4,23 + paddq mm2,mm3 + movq mm3,mm1 + psrlq mm1,4 + pxor mm5,mm6 + pxor mm3,mm4 + psllq mm4,23 + pxor mm3,mm1 + movq [56+esp],mm2 + paddq mm7,mm5 + pxor mm3,mm4 + psrlq mm1,23 + paddq mm7,[48+esp] + pxor mm3,mm1 + psllq mm4,4 + pxor mm3,mm4 + movq mm4,[16+esp] + paddq mm3,mm7 + movq mm5,mm2 + psrlq mm5,28 + paddq mm4,mm3 + movq mm6,mm2 + movq mm7,mm5 + psllq mm6,25 + movq mm1,[esp] + psrlq mm5,6 + pxor mm7,mm6 + psllq mm6,5 + pxor mm7,mm5 + pxor mm2,mm1 + psrlq mm5,5 + pxor mm7,mm6 + pand mm0,mm2 + psllq mm6,6 + pxor mm7,mm5 + pxor mm0,mm1 + pxor mm6,mm7 + movq mm5,[24+esp] + paddq mm0,mm6 + movq mm6,[32+esp] + movdqa [edx-128],xmm2 + movdqa xmm4,xmm6 + movdqa xmm2,xmm3 +db 102,15,58,15,217,8 + movdqa [16+edx],xmm5 +db 102,15,58,15,229,8 + movdqa xmm5,xmm3 + psrlq xmm3,7 + paddq xmm1,xmm4 + movdqa xmm4,xmm5 + psrlq xmm5,1 + psllq xmm4,56 + pxor xmm3,xmm5 + psrlq xmm5,7 + pxor xmm3,xmm4 + psllq xmm4,7 + pxor xmm3,xmm5 + movdqa xmm5,xmm0 + pxor xmm3,xmm4 + movdqa xmm4,xmm0 + psrlq xmm5,6 + paddq xmm1,xmm3 + movdqa xmm3,xmm0 + psrlq xmm4,19 + psllq xmm3,3 + pxor xmm5,xmm4 + psrlq xmm4,42 + pxor xmm5,xmm3 + psllq xmm3,42 + pxor xmm5,xmm4 + movdqa xmm4,[48+edx] + pxor xmm5,xmm3 + movdqa xmm3,[16+ebp] + movq mm1,mm4 + paddq xmm1,xmm5 + movq mm7,[edx-112] + pxor mm5,mm6 + psrlq mm1,14 + movq [16+esp],mm4 + paddq xmm3,xmm1 + pand mm5,mm4 + psllq mm4,23 + paddq mm0,mm3 + movq mm3,mm1 + psrlq mm1,4 + pxor mm5,mm6 + pxor mm3,mm4 + psllq mm4,23 + pxor mm3,mm1 + movq [48+esp],mm0 + paddq mm7,mm5 + pxor mm3,mm4 + psrlq mm1,23 + paddq mm7,[40+esp] + pxor mm3,mm1 + psllq mm4,4 + pxor mm3,mm4 + movq mm4,[8+esp] + paddq mm3,mm7 + movq mm5,mm0 + psrlq mm5,28 + paddq mm4,mm3 + movq mm6,mm0 + movq mm7,mm5 + psllq mm6,25 + movq mm1,[56+esp] + psrlq mm5,6 + pxor mm7,mm6 + psllq mm6,5 + pxor mm7,mm5 + pxor mm0,mm1 + psrlq mm5,5 + pxor mm7,mm6 + pand mm2,mm0 + psllq mm6,6 + pxor mm7,mm5 + pxor mm2,mm1 + pxor mm6,mm7 + movq mm5,[16+esp] + paddq mm2,mm6 + movq mm6,[24+esp] + movq mm1,mm4 + movq mm7,[edx-104] + pxor mm5,mm6 + psrlq mm1,14 + movq [8+esp],mm4 + pand mm5,mm4 + psllq mm4,23 + paddq mm2,mm3 + movq mm3,mm1 + psrlq mm1,4 + pxor mm5,mm6 + pxor mm3,mm4 + psllq mm4,23 + pxor mm3,mm1 + movq [40+esp],mm2 + paddq mm7,mm5 + pxor mm3,mm4 + psrlq mm1,23 + paddq mm7,[32+esp] + pxor mm3,mm1 + psllq mm4,4 + pxor mm3,mm4 + movq mm4,[esp] + paddq mm3,mm7 + movq mm5,mm2 + psrlq mm5,28 + paddq mm4,mm3 + movq mm6,mm2 + movq mm7,mm5 + psllq mm6,25 + movq mm1,[48+esp] + psrlq mm5,6 + pxor mm7,mm6 + psllq mm6,5 + pxor mm7,mm5 + pxor mm2,mm1 + psrlq mm5,5 + pxor mm7,mm6 + pand mm0,mm2 + psllq mm6,6 + pxor mm7,mm5 + pxor mm0,mm1 + pxor mm6,mm7 + movq mm5,[8+esp] + paddq mm0,mm6 + movq mm6,[16+esp] + movdqa [edx-112],xmm3 + movdqa xmm5,xmm7 + movdqa xmm3,xmm4 +db 102,15,58,15,226,8 + movdqa [32+edx],xmm6 +db 102,15,58,15,238,8 + movdqa xmm6,xmm4 + psrlq xmm4,7 + paddq xmm2,xmm5 + movdqa xmm5,xmm6 + psrlq xmm6,1 + psllq xmm5,56 + pxor xmm4,xmm6 + psrlq xmm6,7 + pxor xmm4,xmm5 + psllq xmm5,7 + pxor xmm4,xmm6 + movdqa xmm6,xmm1 + pxor xmm4,xmm5 + movdqa xmm5,xmm1 + psrlq xmm6,6 + paddq xmm2,xmm4 + movdqa xmm4,xmm1 + psrlq xmm5,19 + psllq xmm4,3 + pxor xmm6,xmm5 + psrlq xmm5,42 + pxor xmm6,xmm4 + psllq xmm4,42 + pxor xmm6,xmm5 + movdqa xmm5,[edx] + pxor xmm6,xmm4 + movdqa xmm4,[32+ebp] + movq mm1,mm4 + paddq xmm2,xmm6 + movq mm7,[edx-96] + pxor mm5,mm6 + psrlq mm1,14 + movq [esp],mm4 + paddq xmm4,xmm2 + pand mm5,mm4 + psllq mm4,23 + paddq mm0,mm3 + movq mm3,mm1 + psrlq mm1,4 + pxor mm5,mm6 + pxor mm3,mm4 + psllq mm4,23 + pxor mm3,mm1 + movq [32+esp],mm0 + paddq mm7,mm5 + pxor mm3,mm4 + psrlq mm1,23 + paddq mm7,[24+esp] + pxor mm3,mm1 + psllq mm4,4 + pxor mm3,mm4 + movq mm4,[56+esp] + paddq mm3,mm7 + movq mm5,mm0 + psrlq mm5,28 + paddq mm4,mm3 + movq mm6,mm0 + movq mm7,mm5 + psllq mm6,25 + movq mm1,[40+esp] + psrlq mm5,6 + pxor mm7,mm6 + psllq mm6,5 + pxor mm7,mm5 + pxor mm0,mm1 + psrlq mm5,5 + pxor mm7,mm6 + pand mm2,mm0 + psllq mm6,6 + pxor mm7,mm5 + pxor mm2,mm1 + pxor mm6,mm7 + movq mm5,[esp] + paddq mm2,mm6 + movq mm6,[8+esp] + movq mm1,mm4 + movq mm7,[edx-88] + pxor mm5,mm6 + psrlq mm1,14 + movq [56+esp],mm4 + pand mm5,mm4 + psllq mm4,23 + paddq mm2,mm3 + movq mm3,mm1 + psrlq mm1,4 + pxor mm5,mm6 + pxor mm3,mm4 + psllq mm4,23 + pxor mm3,mm1 + movq [24+esp],mm2 + paddq mm7,mm5 + pxor mm3,mm4 + psrlq mm1,23 + paddq mm7,[16+esp] + pxor mm3,mm1 + psllq mm4,4 + pxor mm3,mm4 + movq mm4,[48+esp] + paddq mm3,mm7 + movq mm5,mm2 + psrlq mm5,28 + paddq mm4,mm3 + movq mm6,mm2 + movq mm7,mm5 + psllq mm6,25 + movq mm1,[32+esp] + psrlq mm5,6 + pxor mm7,mm6 + psllq mm6,5 + pxor mm7,mm5 + pxor mm2,mm1 + psrlq mm5,5 + pxor mm7,mm6 + pand mm0,mm2 + psllq mm6,6 + pxor mm7,mm5 + pxor mm0,mm1 + pxor mm6,mm7 + movq mm5,[56+esp] + paddq mm0,mm6 + movq mm6,[esp] + movdqa [edx-96],xmm4 + movdqa xmm6,xmm0 + movdqa xmm4,xmm5 +db 102,15,58,15,235,8 + movdqa [48+edx],xmm7 +db 102,15,58,15,247,8 + movdqa xmm7,xmm5 + psrlq xmm5,7 + paddq xmm3,xmm6 + movdqa xmm6,xmm7 + psrlq xmm7,1 + psllq xmm6,56 + pxor xmm5,xmm7 + psrlq xmm7,7 + pxor xmm5,xmm6 + psllq xmm6,7 + pxor xmm5,xmm7 + movdqa xmm7,xmm2 + pxor xmm5,xmm6 + movdqa xmm6,xmm2 + psrlq xmm7,6 + paddq xmm3,xmm5 + movdqa xmm5,xmm2 + psrlq xmm6,19 + psllq xmm5,3 + pxor xmm7,xmm6 + psrlq xmm6,42 + pxor xmm7,xmm5 + psllq xmm5,42 + pxor xmm7,xmm6 + movdqa xmm6,[16+edx] + pxor xmm7,xmm5 + movdqa xmm5,[48+ebp] + movq mm1,mm4 + paddq xmm3,xmm7 + movq mm7,[edx-80] + pxor mm5,mm6 + psrlq mm1,14 + movq [48+esp],mm4 + paddq xmm5,xmm3 + pand mm5,mm4 + psllq mm4,23 + paddq mm0,mm3 + movq mm3,mm1 + psrlq mm1,4 + pxor mm5,mm6 + pxor mm3,mm4 + psllq mm4,23 + pxor mm3,mm1 + movq [16+esp],mm0 + paddq mm7,mm5 + pxor mm3,mm4 + psrlq mm1,23 + paddq mm7,[8+esp] + pxor mm3,mm1 + psllq mm4,4 + pxor mm3,mm4 + movq mm4,[40+esp] + paddq mm3,mm7 + movq mm5,mm0 + psrlq mm5,28 + paddq mm4,mm3 + movq mm6,mm0 + movq mm7,mm5 + psllq mm6,25 + movq mm1,[24+esp] + psrlq mm5,6 + pxor mm7,mm6 + psllq mm6,5 + pxor mm7,mm5 + pxor mm0,mm1 + psrlq mm5,5 + pxor mm7,mm6 + pand mm2,mm0 + psllq mm6,6 + pxor mm7,mm5 + pxor mm2,mm1 + pxor mm6,mm7 + movq mm5,[48+esp] + paddq mm2,mm6 + movq mm6,[56+esp] + movq mm1,mm4 + movq mm7,[edx-72] + pxor mm5,mm6 + psrlq mm1,14 + movq [40+esp],mm4 + pand mm5,mm4 + psllq mm4,23 + paddq mm2,mm3 + movq mm3,mm1 + psrlq mm1,4 + pxor mm5,mm6 + pxor mm3,mm4 + psllq mm4,23 + pxor mm3,mm1 + movq [8+esp],mm2 + paddq mm7,mm5 + pxor mm3,mm4 + psrlq mm1,23 + paddq mm7,[esp] + pxor mm3,mm1 + psllq mm4,4 + pxor mm3,mm4 + movq mm4,[32+esp] + paddq mm3,mm7 + movq mm5,mm2 + psrlq mm5,28 + paddq mm4,mm3 + movq mm6,mm2 + movq mm7,mm5 + psllq mm6,25 + movq mm1,[16+esp] + psrlq mm5,6 + pxor mm7,mm6 + psllq mm6,5 + pxor mm7,mm5 + pxor mm2,mm1 + psrlq mm5,5 + pxor mm7,mm6 + pand mm0,mm2 + psllq mm6,6 + pxor mm7,mm5 + pxor mm0,mm1 + pxor mm6,mm7 + movq mm5,[40+esp] + paddq mm0,mm6 + movq mm6,[48+esp] + movdqa [edx-80],xmm5 + movdqa xmm7,xmm1 + movdqa xmm5,xmm6 +db 102,15,58,15,244,8 + movdqa [edx],xmm0 +db 102,15,58,15,248,8 + movdqa xmm0,xmm6 + psrlq xmm6,7 + paddq xmm4,xmm7 + movdqa xmm7,xmm0 + psrlq xmm0,1 + psllq xmm7,56 + pxor xmm6,xmm0 + psrlq xmm0,7 + pxor xmm6,xmm7 + psllq xmm7,7 + pxor xmm6,xmm0 + movdqa xmm0,xmm3 + pxor xmm6,xmm7 + movdqa xmm7,xmm3 + psrlq xmm0,6 + paddq xmm4,xmm6 + movdqa xmm6,xmm3 + psrlq xmm7,19 + psllq xmm6,3 + pxor xmm0,xmm7 + psrlq xmm7,42 + pxor xmm0,xmm6 + psllq xmm6,42 + pxor xmm0,xmm7 + movdqa xmm7,[32+edx] + pxor xmm0,xmm6 + movdqa xmm6,[64+ebp] + movq mm1,mm4 + paddq xmm4,xmm0 + movq mm7,[edx-64] + pxor mm5,mm6 + psrlq mm1,14 + movq [32+esp],mm4 + paddq xmm6,xmm4 + pand mm5,mm4 + psllq mm4,23 + paddq mm0,mm3 + movq mm3,mm1 + psrlq mm1,4 + pxor mm5,mm6 + pxor mm3,mm4 + psllq mm4,23 + pxor mm3,mm1 + movq [esp],mm0 + paddq mm7,mm5 + pxor mm3,mm4 + psrlq mm1,23 + paddq mm7,[56+esp] + pxor mm3,mm1 + psllq mm4,4 + pxor mm3,mm4 + movq mm4,[24+esp] + paddq mm3,mm7 + movq mm5,mm0 + psrlq mm5,28 + paddq mm4,mm3 + movq mm6,mm0 + movq mm7,mm5 + psllq mm6,25 + movq mm1,[8+esp] + psrlq mm5,6 + pxor mm7,mm6 + psllq mm6,5 + pxor mm7,mm5 + pxor mm0,mm1 + psrlq mm5,5 + pxor mm7,mm6 + pand mm2,mm0 + psllq mm6,6 + pxor mm7,mm5 + pxor mm2,mm1 + pxor mm6,mm7 + movq mm5,[32+esp] + paddq mm2,mm6 + movq mm6,[40+esp] + movq mm1,mm4 + movq mm7,[edx-56] + pxor mm5,mm6 + psrlq mm1,14 + movq [24+esp],mm4 + pand mm5,mm4 + psllq mm4,23 + paddq mm2,mm3 + movq mm3,mm1 + psrlq mm1,4 + pxor mm5,mm6 + pxor mm3,mm4 + psllq mm4,23 + pxor mm3,mm1 + movq [56+esp],mm2 + paddq mm7,mm5 + pxor mm3,mm4 + psrlq mm1,23 + paddq mm7,[48+esp] + pxor mm3,mm1 + psllq mm4,4 + pxor mm3,mm4 + movq mm4,[16+esp] + paddq mm3,mm7 + movq mm5,mm2 + psrlq mm5,28 + paddq mm4,mm3 + movq mm6,mm2 + movq mm7,mm5 + psllq mm6,25 + movq mm1,[esp] + psrlq mm5,6 + pxor mm7,mm6 + psllq mm6,5 + pxor mm7,mm5 + pxor mm2,mm1 + psrlq mm5,5 + pxor mm7,mm6 + pand mm0,mm2 + psllq mm6,6 + pxor mm7,mm5 + pxor mm0,mm1 + pxor mm6,mm7 + movq mm5,[24+esp] + paddq mm0,mm6 + movq mm6,[32+esp] + movdqa [edx-64],xmm6 + movdqa xmm0,xmm2 + movdqa xmm6,xmm7 +db 102,15,58,15,253,8 + movdqa [16+edx],xmm1 +db 102,15,58,15,193,8 + movdqa xmm1,xmm7 + psrlq xmm7,7 + paddq xmm5,xmm0 + movdqa xmm0,xmm1 + psrlq xmm1,1 + psllq xmm0,56 + pxor xmm7,xmm1 + psrlq xmm1,7 + pxor xmm7,xmm0 + psllq xmm0,7 + pxor xmm7,xmm1 + movdqa xmm1,xmm4 + pxor xmm7,xmm0 + movdqa xmm0,xmm4 + psrlq xmm1,6 + paddq xmm5,xmm7 + movdqa xmm7,xmm4 + psrlq xmm0,19 + psllq xmm7,3 + pxor xmm1,xmm0 + psrlq xmm0,42 + pxor xmm1,xmm7 + psllq xmm7,42 + pxor xmm1,xmm0 + movdqa xmm0,[48+edx] + pxor xmm1,xmm7 + movdqa xmm7,[80+ebp] + movq mm1,mm4 + paddq xmm5,xmm1 + movq mm7,[edx-48] + pxor mm5,mm6 + psrlq mm1,14 + movq [16+esp],mm4 + paddq xmm7,xmm5 + pand mm5,mm4 + psllq mm4,23 + paddq mm0,mm3 + movq mm3,mm1 + psrlq mm1,4 + pxor mm5,mm6 + pxor mm3,mm4 + psllq mm4,23 + pxor mm3,mm1 + movq [48+esp],mm0 + paddq mm7,mm5 + pxor mm3,mm4 + psrlq mm1,23 + paddq mm7,[40+esp] + pxor mm3,mm1 + psllq mm4,4 + pxor mm3,mm4 + movq mm4,[8+esp] + paddq mm3,mm7 + movq mm5,mm0 + psrlq mm5,28 + paddq mm4,mm3 + movq mm6,mm0 + movq mm7,mm5 + psllq mm6,25 + movq mm1,[56+esp] + psrlq mm5,6 + pxor mm7,mm6 + psllq mm6,5 + pxor mm7,mm5 + pxor mm0,mm1 + psrlq mm5,5 + pxor mm7,mm6 + pand mm2,mm0 + psllq mm6,6 + pxor mm7,mm5 + pxor mm2,mm1 + pxor mm6,mm7 + movq mm5,[16+esp] + paddq mm2,mm6 + movq mm6,[24+esp] + movq mm1,mm4 + movq mm7,[edx-40] + pxor mm5,mm6 + psrlq mm1,14 + movq [8+esp],mm4 + pand mm5,mm4 + psllq mm4,23 + paddq mm2,mm3 + movq mm3,mm1 + psrlq mm1,4 + pxor mm5,mm6 + pxor mm3,mm4 + psllq mm4,23 + pxor mm3,mm1 + movq [40+esp],mm2 + paddq mm7,mm5 + pxor mm3,mm4 + psrlq mm1,23 + paddq mm7,[32+esp] + pxor mm3,mm1 + psllq mm4,4 + pxor mm3,mm4 + movq mm4,[esp] + paddq mm3,mm7 + movq mm5,mm2 + psrlq mm5,28 + paddq mm4,mm3 + movq mm6,mm2 + movq mm7,mm5 + psllq mm6,25 + movq mm1,[48+esp] + psrlq mm5,6 + pxor mm7,mm6 + psllq mm6,5 + pxor mm7,mm5 + pxor mm2,mm1 + psrlq mm5,5 + pxor mm7,mm6 + pand mm0,mm2 + psllq mm6,6 + pxor mm7,mm5 + pxor mm0,mm1 + pxor mm6,mm7 + movq mm5,[8+esp] + paddq mm0,mm6 + movq mm6,[16+esp] + movdqa [edx-48],xmm7 + movdqa xmm1,xmm3 + movdqa xmm7,xmm0 +db 102,15,58,15,198,8 + movdqa [32+edx],xmm2 +db 102,15,58,15,202,8 + movdqa xmm2,xmm0 + psrlq xmm0,7 + paddq xmm6,xmm1 + movdqa xmm1,xmm2 + psrlq xmm2,1 + psllq xmm1,56 + pxor xmm0,xmm2 + psrlq xmm2,7 + pxor xmm0,xmm1 + psllq xmm1,7 + pxor xmm0,xmm2 + movdqa xmm2,xmm5 + pxor xmm0,xmm1 + movdqa xmm1,xmm5 + psrlq xmm2,6 + paddq xmm6,xmm0 + movdqa xmm0,xmm5 + psrlq xmm1,19 + psllq xmm0,3 + pxor xmm2,xmm1 + psrlq xmm1,42 + pxor xmm2,xmm0 + psllq xmm0,42 + pxor xmm2,xmm1 + movdqa xmm1,[edx] + pxor xmm2,xmm0 + movdqa xmm0,[96+ebp] + movq mm1,mm4 + paddq xmm6,xmm2 + movq mm7,[edx-32] + pxor mm5,mm6 + psrlq mm1,14 + movq [esp],mm4 + paddq xmm0,xmm6 + pand mm5,mm4 + psllq mm4,23 + paddq mm0,mm3 + movq mm3,mm1 + psrlq mm1,4 + pxor mm5,mm6 + pxor mm3,mm4 + psllq mm4,23 + pxor mm3,mm1 + movq [32+esp],mm0 + paddq mm7,mm5 + pxor mm3,mm4 + psrlq mm1,23 + paddq mm7,[24+esp] + pxor mm3,mm1 + psllq mm4,4 + pxor mm3,mm4 + movq mm4,[56+esp] + paddq mm3,mm7 + movq mm5,mm0 + psrlq mm5,28 + paddq mm4,mm3 + movq mm6,mm0 + movq mm7,mm5 + psllq mm6,25 + movq mm1,[40+esp] + psrlq mm5,6 + pxor mm7,mm6 + psllq mm6,5 + pxor mm7,mm5 + pxor mm0,mm1 + psrlq mm5,5 + pxor mm7,mm6 + pand mm2,mm0 + psllq mm6,6 + pxor mm7,mm5 + pxor mm2,mm1 + pxor mm6,mm7 + movq mm5,[esp] + paddq mm2,mm6 + movq mm6,[8+esp] + movq mm1,mm4 + movq mm7,[edx-24] + pxor mm5,mm6 + psrlq mm1,14 + movq [56+esp],mm4 + pand mm5,mm4 + psllq mm4,23 + paddq mm2,mm3 + movq mm3,mm1 + psrlq mm1,4 + pxor mm5,mm6 + pxor mm3,mm4 + psllq mm4,23 + pxor mm3,mm1 + movq [24+esp],mm2 + paddq mm7,mm5 + pxor mm3,mm4 + psrlq mm1,23 + paddq mm7,[16+esp] + pxor mm3,mm1 + psllq mm4,4 + pxor mm3,mm4 + movq mm4,[48+esp] + paddq mm3,mm7 + movq mm5,mm2 + psrlq mm5,28 + paddq mm4,mm3 + movq mm6,mm2 + movq mm7,mm5 + psllq mm6,25 + movq mm1,[32+esp] + psrlq mm5,6 + pxor mm7,mm6 + psllq mm6,5 + pxor mm7,mm5 + pxor mm2,mm1 + psrlq mm5,5 + pxor mm7,mm6 + pand mm0,mm2 + psllq mm6,6 + pxor mm7,mm5 + pxor mm0,mm1 + pxor mm6,mm7 + movq mm5,[56+esp] + paddq mm0,mm6 + movq mm6,[esp] + movdqa [edx-32],xmm0 + movdqa xmm2,xmm4 + movdqa xmm0,xmm1 +db 102,15,58,15,207,8 + movdqa [48+edx],xmm3 +db 102,15,58,15,211,8 + movdqa xmm3,xmm1 + psrlq xmm1,7 + paddq xmm7,xmm2 + movdqa xmm2,xmm3 + psrlq xmm3,1 + psllq xmm2,56 + pxor xmm1,xmm3 + psrlq xmm3,7 + pxor xmm1,xmm2 + psllq xmm2,7 + pxor xmm1,xmm3 + movdqa xmm3,xmm6 + pxor xmm1,xmm2 + movdqa xmm2,xmm6 + psrlq xmm3,6 + paddq xmm7,xmm1 + movdqa xmm1,xmm6 + psrlq xmm2,19 + psllq xmm1,3 + pxor xmm3,xmm2 + psrlq xmm2,42 + pxor xmm3,xmm1 + psllq xmm1,42 + pxor xmm3,xmm2 + movdqa xmm2,[16+edx] + pxor xmm3,xmm1 + movdqa xmm1,[112+ebp] + movq mm1,mm4 + paddq xmm7,xmm3 + movq mm7,[edx-16] + pxor mm5,mm6 + psrlq mm1,14 + movq [48+esp],mm4 + paddq xmm1,xmm7 + pand mm5,mm4 + psllq mm4,23 + paddq mm0,mm3 + movq mm3,mm1 + psrlq mm1,4 + pxor mm5,mm6 + pxor mm3,mm4 + psllq mm4,23 + pxor mm3,mm1 + movq [16+esp],mm0 + paddq mm7,mm5 + pxor mm3,mm4 + psrlq mm1,23 + paddq mm7,[8+esp] + pxor mm3,mm1 + psllq mm4,4 + pxor mm3,mm4 + movq mm4,[40+esp] + paddq mm3,mm7 + movq mm5,mm0 + psrlq mm5,28 + paddq mm4,mm3 + movq mm6,mm0 + movq mm7,mm5 + psllq mm6,25 + movq mm1,[24+esp] + psrlq mm5,6 + pxor mm7,mm6 + psllq mm6,5 + pxor mm7,mm5 + pxor mm0,mm1 + psrlq mm5,5 + pxor mm7,mm6 + pand mm2,mm0 + psllq mm6,6 + pxor mm7,mm5 + pxor mm2,mm1 + pxor mm6,mm7 + movq mm5,[48+esp] + paddq mm2,mm6 + movq mm6,[56+esp] + movq mm1,mm4 + movq mm7,[edx-8] + pxor mm5,mm6 + psrlq mm1,14 + movq [40+esp],mm4 + pand mm5,mm4 + psllq mm4,23 + paddq mm2,mm3 + movq mm3,mm1 + psrlq mm1,4 + pxor mm5,mm6 + pxor mm3,mm4 + psllq mm4,23 + pxor mm3,mm1 + movq [8+esp],mm2 + paddq mm7,mm5 + pxor mm3,mm4 + psrlq mm1,23 + paddq mm7,[esp] + pxor mm3,mm1 + psllq mm4,4 + pxor mm3,mm4 + movq mm4,[32+esp] + paddq mm3,mm7 + movq mm5,mm2 + psrlq mm5,28 + paddq mm4,mm3 + movq mm6,mm2 + movq mm7,mm5 + psllq mm6,25 + movq mm1,[16+esp] + psrlq mm5,6 + pxor mm7,mm6 + psllq mm6,5 + pxor mm7,mm5 + pxor mm2,mm1 + psrlq mm5,5 + pxor mm7,mm6 + pand mm0,mm2 + psllq mm6,6 + pxor mm7,mm5 + pxor mm0,mm1 + pxor mm6,mm7 + movq mm5,[40+esp] + paddq mm0,mm6 + movq mm6,[48+esp] + movdqa [edx-16],xmm1 + lea ebp,[128+ebp] + dec ecx + jnz NEAR L$00800_47_ssse3 + movdqa xmm1,[ebp] + lea ebp,[ebp-640] + movdqu xmm0,[ebx] +db 102,15,56,0,193 + movdqa xmm3,[ebp] + movdqa xmm2,xmm1 + movdqu xmm1,[16+ebx] + paddq xmm3,xmm0 +db 102,15,56,0,202 + movq mm1,mm4 + movq mm7,[edx-128] + pxor mm5,mm6 + psrlq mm1,14 + movq [32+esp],mm4 + pand mm5,mm4 + psllq mm4,23 + paddq mm0,mm3 + movq mm3,mm1 + psrlq mm1,4 + pxor mm5,mm6 + pxor mm3,mm4 + psllq mm4,23 + pxor mm3,mm1 + movq [esp],mm0 + paddq mm7,mm5 + pxor mm3,mm4 + psrlq mm1,23 + paddq mm7,[56+esp] + pxor mm3,mm1 + psllq mm4,4 + pxor mm3,mm4 + movq mm4,[24+esp] + paddq mm3,mm7 + movq mm5,mm0 + psrlq mm5,28 + paddq mm4,mm3 + movq mm6,mm0 + movq mm7,mm5 + psllq mm6,25 + movq mm1,[8+esp] + psrlq mm5,6 + pxor mm7,mm6 + psllq mm6,5 + pxor mm7,mm5 + pxor mm0,mm1 + psrlq mm5,5 + pxor mm7,mm6 + pand mm2,mm0 + psllq mm6,6 + pxor mm7,mm5 + pxor mm2,mm1 + pxor mm6,mm7 + movq mm5,[32+esp] + paddq mm2,mm6 + movq mm6,[40+esp] + movq mm1,mm4 + movq mm7,[edx-120] + pxor mm5,mm6 + psrlq mm1,14 + movq [24+esp],mm4 + pand mm5,mm4 + psllq mm4,23 + paddq mm2,mm3 + movq mm3,mm1 + psrlq mm1,4 + pxor mm5,mm6 + pxor mm3,mm4 + psllq mm4,23 + pxor mm3,mm1 + movq [56+esp],mm2 + paddq mm7,mm5 + pxor mm3,mm4 + psrlq mm1,23 + paddq mm7,[48+esp] + pxor mm3,mm1 + psllq mm4,4 + pxor mm3,mm4 + movq mm4,[16+esp] + paddq mm3,mm7 + movq mm5,mm2 + psrlq mm5,28 + paddq mm4,mm3 + movq mm6,mm2 + movq mm7,mm5 + psllq mm6,25 + movq mm1,[esp] + psrlq mm5,6 + pxor mm7,mm6 + psllq mm6,5 + pxor mm7,mm5 + pxor mm2,mm1 + psrlq mm5,5 + pxor mm7,mm6 + pand mm0,mm2 + psllq mm6,6 + pxor mm7,mm5 + pxor mm0,mm1 + pxor mm6,mm7 + movq mm5,[24+esp] + paddq mm0,mm6 + movq mm6,[32+esp] + movdqa [edx-128],xmm3 + movdqa xmm4,[16+ebp] + movdqa xmm3,xmm2 + movdqu xmm2,[32+ebx] + paddq xmm4,xmm1 +db 102,15,56,0,211 + movq mm1,mm4 + movq mm7,[edx-112] + pxor mm5,mm6 + psrlq mm1,14 + movq [16+esp],mm4 + pand mm5,mm4 + psllq mm4,23 + paddq mm0,mm3 + movq mm3,mm1 + psrlq mm1,4 + pxor mm5,mm6 + pxor mm3,mm4 + psllq mm4,23 + pxor mm3,mm1 + movq [48+esp],mm0 + paddq mm7,mm5 + pxor mm3,mm4 + psrlq mm1,23 + paddq mm7,[40+esp] + pxor mm3,mm1 + psllq mm4,4 + pxor mm3,mm4 + movq mm4,[8+esp] + paddq mm3,mm7 + movq mm5,mm0 + psrlq mm5,28 + paddq mm4,mm3 + movq mm6,mm0 + movq mm7,mm5 + psllq mm6,25 + movq mm1,[56+esp] + psrlq mm5,6 + pxor mm7,mm6 + psllq mm6,5 + pxor mm7,mm5 + pxor mm0,mm1 + psrlq mm5,5 + pxor mm7,mm6 + pand mm2,mm0 + psllq mm6,6 + pxor mm7,mm5 + pxor mm2,mm1 + pxor mm6,mm7 + movq mm5,[16+esp] + paddq mm2,mm6 + movq mm6,[24+esp] + movq mm1,mm4 + movq mm7,[edx-104] + pxor mm5,mm6 + psrlq mm1,14 + movq [8+esp],mm4 + pand mm5,mm4 + psllq mm4,23 + paddq mm2,mm3 + movq mm3,mm1 + psrlq mm1,4 + pxor mm5,mm6 + pxor mm3,mm4 + psllq mm4,23 + pxor mm3,mm1 + movq [40+esp],mm2 + paddq mm7,mm5 + pxor mm3,mm4 + psrlq mm1,23 + paddq mm7,[32+esp] + pxor mm3,mm1 + psllq mm4,4 + pxor mm3,mm4 + movq mm4,[esp] + paddq mm3,mm7 + movq mm5,mm2 + psrlq mm5,28 + paddq mm4,mm3 + movq mm6,mm2 + movq mm7,mm5 + psllq mm6,25 + movq mm1,[48+esp] + psrlq mm5,6 + pxor mm7,mm6 + psllq mm6,5 + pxor mm7,mm5 + pxor mm2,mm1 + psrlq mm5,5 + pxor mm7,mm6 + pand mm0,mm2 + psllq mm6,6 + pxor mm7,mm5 + pxor mm0,mm1 + pxor mm6,mm7 + movq mm5,[8+esp] + paddq mm0,mm6 + movq mm6,[16+esp] + movdqa [edx-112],xmm4 + movdqa xmm5,[32+ebp] + movdqa xmm4,xmm3 + movdqu xmm3,[48+ebx] + paddq xmm5,xmm2 +db 102,15,56,0,220 + movq mm1,mm4 + movq mm7,[edx-96] + pxor mm5,mm6 + psrlq mm1,14 + movq [esp],mm4 + pand mm5,mm4 + psllq mm4,23 + paddq mm0,mm3 + movq mm3,mm1 + psrlq mm1,4 + pxor mm5,mm6 + pxor mm3,mm4 + psllq mm4,23 + pxor mm3,mm1 + movq [32+esp],mm0 + paddq mm7,mm5 + pxor mm3,mm4 + psrlq mm1,23 + paddq mm7,[24+esp] + pxor mm3,mm1 + psllq mm4,4 + pxor mm3,mm4 + movq mm4,[56+esp] + paddq mm3,mm7 + movq mm5,mm0 + psrlq mm5,28 + paddq mm4,mm3 + movq mm6,mm0 + movq mm7,mm5 + psllq mm6,25 + movq mm1,[40+esp] + psrlq mm5,6 + pxor mm7,mm6 + psllq mm6,5 + pxor mm7,mm5 + pxor mm0,mm1 + psrlq mm5,5 + pxor mm7,mm6 + pand mm2,mm0 + psllq mm6,6 + pxor mm7,mm5 + pxor mm2,mm1 + pxor mm6,mm7 + movq mm5,[esp] + paddq mm2,mm6 + movq mm6,[8+esp] + movq mm1,mm4 + movq mm7,[edx-88] + pxor mm5,mm6 + psrlq mm1,14 + movq [56+esp],mm4 + pand mm5,mm4 + psllq mm4,23 + paddq mm2,mm3 + movq mm3,mm1 + psrlq mm1,4 + pxor mm5,mm6 + pxor mm3,mm4 + psllq mm4,23 + pxor mm3,mm1 + movq [24+esp],mm2 + paddq mm7,mm5 + pxor mm3,mm4 + psrlq mm1,23 + paddq mm7,[16+esp] + pxor mm3,mm1 + psllq mm4,4 + pxor mm3,mm4 + movq mm4,[48+esp] + paddq mm3,mm7 + movq mm5,mm2 + psrlq mm5,28 + paddq mm4,mm3 + movq mm6,mm2 + movq mm7,mm5 + psllq mm6,25 + movq mm1,[32+esp] + psrlq mm5,6 + pxor mm7,mm6 + psllq mm6,5 + pxor mm7,mm5 + pxor mm2,mm1 + psrlq mm5,5 + pxor mm7,mm6 + pand mm0,mm2 + psllq mm6,6 + pxor mm7,mm5 + pxor mm0,mm1 + pxor mm6,mm7 + movq mm5,[56+esp] + paddq mm0,mm6 + movq mm6,[esp] + movdqa [edx-96],xmm5 + movdqa xmm6,[48+ebp] + movdqa xmm5,xmm4 + movdqu xmm4,[64+ebx] + paddq xmm6,xmm3 +db 102,15,56,0,229 + movq mm1,mm4 + movq mm7,[edx-80] + pxor mm5,mm6 + psrlq mm1,14 + movq [48+esp],mm4 + pand mm5,mm4 + psllq mm4,23 + paddq mm0,mm3 + movq mm3,mm1 + psrlq mm1,4 + pxor mm5,mm6 + pxor mm3,mm4 + psllq mm4,23 + pxor mm3,mm1 + movq [16+esp],mm0 + paddq mm7,mm5 + pxor mm3,mm4 + psrlq mm1,23 + paddq mm7,[8+esp] + pxor mm3,mm1 + psllq mm4,4 + pxor mm3,mm4 + movq mm4,[40+esp] + paddq mm3,mm7 + movq mm5,mm0 + psrlq mm5,28 + paddq mm4,mm3 + movq mm6,mm0 + movq mm7,mm5 + psllq mm6,25 + movq mm1,[24+esp] + psrlq mm5,6 + pxor mm7,mm6 + psllq mm6,5 + pxor mm7,mm5 + pxor mm0,mm1 + psrlq mm5,5 + pxor mm7,mm6 + pand mm2,mm0 + psllq mm6,6 + pxor mm7,mm5 + pxor mm2,mm1 + pxor mm6,mm7 + movq mm5,[48+esp] + paddq mm2,mm6 + movq mm6,[56+esp] + movq mm1,mm4 + movq mm7,[edx-72] + pxor mm5,mm6 + psrlq mm1,14 + movq [40+esp],mm4 + pand mm5,mm4 + psllq mm4,23 + paddq mm2,mm3 + movq mm3,mm1 + psrlq mm1,4 + pxor mm5,mm6 + pxor mm3,mm4 + psllq mm4,23 + pxor mm3,mm1 + movq [8+esp],mm2 + paddq mm7,mm5 + pxor mm3,mm4 + psrlq mm1,23 + paddq mm7,[esp] + pxor mm3,mm1 + psllq mm4,4 + pxor mm3,mm4 + movq mm4,[32+esp] + paddq mm3,mm7 + movq mm5,mm2 + psrlq mm5,28 + paddq mm4,mm3 + movq mm6,mm2 + movq mm7,mm5 + psllq mm6,25 + movq mm1,[16+esp] + psrlq mm5,6 + pxor mm7,mm6 + psllq mm6,5 + pxor mm7,mm5 + pxor mm2,mm1 + psrlq mm5,5 + pxor mm7,mm6 + pand mm0,mm2 + psllq mm6,6 + pxor mm7,mm5 + pxor mm0,mm1 + pxor mm6,mm7 + movq mm5,[40+esp] + paddq mm0,mm6 + movq mm6,[48+esp] + movdqa [edx-80],xmm6 + movdqa xmm7,[64+ebp] + movdqa xmm6,xmm5 + movdqu xmm5,[80+ebx] + paddq xmm7,xmm4 +db 102,15,56,0,238 + movq mm1,mm4 + movq mm7,[edx-64] + pxor mm5,mm6 + psrlq mm1,14 + movq [32+esp],mm4 + pand mm5,mm4 + psllq mm4,23 + paddq mm0,mm3 + movq mm3,mm1 + psrlq mm1,4 + pxor mm5,mm6 + pxor mm3,mm4 + psllq mm4,23 + pxor mm3,mm1 + movq [esp],mm0 + paddq mm7,mm5 + pxor mm3,mm4 + psrlq mm1,23 + paddq mm7,[56+esp] + pxor mm3,mm1 + psllq mm4,4 + pxor mm3,mm4 + movq mm4,[24+esp] + paddq mm3,mm7 + movq mm5,mm0 + psrlq mm5,28 + paddq mm4,mm3 + movq mm6,mm0 + movq mm7,mm5 + psllq mm6,25 + movq mm1,[8+esp] + psrlq mm5,6 + pxor mm7,mm6 + psllq mm6,5 + pxor mm7,mm5 + pxor mm0,mm1 + psrlq mm5,5 + pxor mm7,mm6 + pand mm2,mm0 + psllq mm6,6 + pxor mm7,mm5 + pxor mm2,mm1 + pxor mm6,mm7 + movq mm5,[32+esp] + paddq mm2,mm6 + movq mm6,[40+esp] + movq mm1,mm4 + movq mm7,[edx-56] + pxor mm5,mm6 + psrlq mm1,14 + movq [24+esp],mm4 + pand mm5,mm4 + psllq mm4,23 + paddq mm2,mm3 + movq mm3,mm1 + psrlq mm1,4 + pxor mm5,mm6 + pxor mm3,mm4 + psllq mm4,23 + pxor mm3,mm1 + movq [56+esp],mm2 + paddq mm7,mm5 + pxor mm3,mm4 + psrlq mm1,23 + paddq mm7,[48+esp] + pxor mm3,mm1 + psllq mm4,4 + pxor mm3,mm4 + movq mm4,[16+esp] + paddq mm3,mm7 + movq mm5,mm2 + psrlq mm5,28 + paddq mm4,mm3 + movq mm6,mm2 + movq mm7,mm5 + psllq mm6,25 + movq mm1,[esp] + psrlq mm5,6 + pxor mm7,mm6 + psllq mm6,5 + pxor mm7,mm5 + pxor mm2,mm1 + psrlq mm5,5 + pxor mm7,mm6 + pand mm0,mm2 + psllq mm6,6 + pxor mm7,mm5 + pxor mm0,mm1 + pxor mm6,mm7 + movq mm5,[24+esp] + paddq mm0,mm6 + movq mm6,[32+esp] + movdqa [edx-64],xmm7 + movdqa [edx],xmm0 + movdqa xmm0,[80+ebp] + movdqa xmm7,xmm6 + movdqu xmm6,[96+ebx] + paddq xmm0,xmm5 +db 102,15,56,0,247 + movq mm1,mm4 + movq mm7,[edx-48] + pxor mm5,mm6 + psrlq mm1,14 + movq [16+esp],mm4 + pand mm5,mm4 + psllq mm4,23 + paddq mm0,mm3 + movq mm3,mm1 + psrlq mm1,4 + pxor mm5,mm6 + pxor mm3,mm4 + psllq mm4,23 + pxor mm3,mm1 + movq [48+esp],mm0 + paddq mm7,mm5 + pxor mm3,mm4 + psrlq mm1,23 + paddq mm7,[40+esp] + pxor mm3,mm1 + psllq mm4,4 + pxor mm3,mm4 + movq mm4,[8+esp] + paddq mm3,mm7 + movq mm5,mm0 + psrlq mm5,28 + paddq mm4,mm3 + movq mm6,mm0 + movq mm7,mm5 + psllq mm6,25 + movq mm1,[56+esp] + psrlq mm5,6 + pxor mm7,mm6 + psllq mm6,5 + pxor mm7,mm5 + pxor mm0,mm1 + psrlq mm5,5 + pxor mm7,mm6 + pand mm2,mm0 + psllq mm6,6 + pxor mm7,mm5 + pxor mm2,mm1 + pxor mm6,mm7 + movq mm5,[16+esp] + paddq mm2,mm6 + movq mm6,[24+esp] + movq mm1,mm4 + movq mm7,[edx-40] + pxor mm5,mm6 + psrlq mm1,14 + movq [8+esp],mm4 + pand mm5,mm4 + psllq mm4,23 + paddq mm2,mm3 + movq mm3,mm1 + psrlq mm1,4 + pxor mm5,mm6 + pxor mm3,mm4 + psllq mm4,23 + pxor mm3,mm1 + movq [40+esp],mm2 + paddq mm7,mm5 + pxor mm3,mm4 + psrlq mm1,23 + paddq mm7,[32+esp] + pxor mm3,mm1 + psllq mm4,4 + pxor mm3,mm4 + movq mm4,[esp] + paddq mm3,mm7 + movq mm5,mm2 + psrlq mm5,28 + paddq mm4,mm3 + movq mm6,mm2 + movq mm7,mm5 + psllq mm6,25 + movq mm1,[48+esp] + psrlq mm5,6 + pxor mm7,mm6 + psllq mm6,5 + pxor mm7,mm5 + pxor mm2,mm1 + psrlq mm5,5 + pxor mm7,mm6 + pand mm0,mm2 + psllq mm6,6 + pxor mm7,mm5 + pxor mm0,mm1 + pxor mm6,mm7 + movq mm5,[8+esp] + paddq mm0,mm6 + movq mm6,[16+esp] + movdqa [edx-48],xmm0 + movdqa [16+edx],xmm1 + movdqa xmm1,[96+ebp] + movdqa xmm0,xmm7 + movdqu xmm7,[112+ebx] + paddq xmm1,xmm6 +db 102,15,56,0,248 + movq mm1,mm4 + movq mm7,[edx-32] + pxor mm5,mm6 + psrlq mm1,14 + movq [esp],mm4 + pand mm5,mm4 + psllq mm4,23 + paddq mm0,mm3 + movq mm3,mm1 + psrlq mm1,4 + pxor mm5,mm6 + pxor mm3,mm4 + psllq mm4,23 + pxor mm3,mm1 + movq [32+esp],mm0 + paddq mm7,mm5 + pxor mm3,mm4 + psrlq mm1,23 + paddq mm7,[24+esp] + pxor mm3,mm1 + psllq mm4,4 + pxor mm3,mm4 + movq mm4,[56+esp] + paddq mm3,mm7 + movq mm5,mm0 + psrlq mm5,28 + paddq mm4,mm3 + movq mm6,mm0 + movq mm7,mm5 + psllq mm6,25 + movq mm1,[40+esp] + psrlq mm5,6 + pxor mm7,mm6 + psllq mm6,5 + pxor mm7,mm5 + pxor mm0,mm1 + psrlq mm5,5 + pxor mm7,mm6 + pand mm2,mm0 + psllq mm6,6 + pxor mm7,mm5 + pxor mm2,mm1 + pxor mm6,mm7 + movq mm5,[esp] + paddq mm2,mm6 + movq mm6,[8+esp] + movq mm1,mm4 + movq mm7,[edx-24] + pxor mm5,mm6 + psrlq mm1,14 + movq [56+esp],mm4 + pand mm5,mm4 + psllq mm4,23 + paddq mm2,mm3 + movq mm3,mm1 + psrlq mm1,4 + pxor mm5,mm6 + pxor mm3,mm4 + psllq mm4,23 + pxor mm3,mm1 + movq [24+esp],mm2 + paddq mm7,mm5 + pxor mm3,mm4 + psrlq mm1,23 + paddq mm7,[16+esp] + pxor mm3,mm1 + psllq mm4,4 + pxor mm3,mm4 + movq mm4,[48+esp] + paddq mm3,mm7 + movq mm5,mm2 + psrlq mm5,28 + paddq mm4,mm3 + movq mm6,mm2 + movq mm7,mm5 + psllq mm6,25 + movq mm1,[32+esp] + psrlq mm5,6 + pxor mm7,mm6 + psllq mm6,5 + pxor mm7,mm5 + pxor mm2,mm1 + psrlq mm5,5 + pxor mm7,mm6 + pand mm0,mm2 + psllq mm6,6 + pxor mm7,mm5 + pxor mm0,mm1 + pxor mm6,mm7 + movq mm5,[56+esp] + paddq mm0,mm6 + movq mm6,[esp] + movdqa [edx-32],xmm1 + movdqa [32+edx],xmm2 + movdqa xmm2,[112+ebp] + movdqa xmm0,[edx] + paddq xmm2,xmm7 + movq mm1,mm4 + movq mm7,[edx-16] + pxor mm5,mm6 + psrlq mm1,14 + movq [48+esp],mm4 + pand mm5,mm4 + psllq mm4,23 + paddq mm0,mm3 + movq mm3,mm1 + psrlq mm1,4 + pxor mm5,mm6 + pxor mm3,mm4 + psllq mm4,23 + pxor mm3,mm1 + movq [16+esp],mm0 + paddq mm7,mm5 + pxor mm3,mm4 + psrlq mm1,23 + paddq mm7,[8+esp] + pxor mm3,mm1 + psllq mm4,4 + pxor mm3,mm4 + movq mm4,[40+esp] + paddq mm3,mm7 + movq mm5,mm0 + psrlq mm5,28 + paddq mm4,mm3 + movq mm6,mm0 + movq mm7,mm5 + psllq mm6,25 + movq mm1,[24+esp] + psrlq mm5,6 + pxor mm7,mm6 + psllq mm6,5 + pxor mm7,mm5 + pxor mm0,mm1 + psrlq mm5,5 + pxor mm7,mm6 + pand mm2,mm0 + psllq mm6,6 + pxor mm7,mm5 + pxor mm2,mm1 + pxor mm6,mm7 + movq mm5,[48+esp] + paddq mm2,mm6 + movq mm6,[56+esp] + movq mm1,mm4 + movq mm7,[edx-8] + pxor mm5,mm6 + psrlq mm1,14 + movq [40+esp],mm4 + pand mm5,mm4 + psllq mm4,23 + paddq mm2,mm3 + movq mm3,mm1 + psrlq mm1,4 + pxor mm5,mm6 + pxor mm3,mm4 + psllq mm4,23 + pxor mm3,mm1 + movq [8+esp],mm2 + paddq mm7,mm5 + pxor mm3,mm4 + psrlq mm1,23 + paddq mm7,[esp] + pxor mm3,mm1 + psllq mm4,4 + pxor mm3,mm4 + movq mm4,[32+esp] + paddq mm3,mm7 + movq mm5,mm2 + psrlq mm5,28 + paddq mm4,mm3 + movq mm6,mm2 + movq mm7,mm5 + psllq mm6,25 + movq mm1,[16+esp] + psrlq mm5,6 + pxor mm7,mm6 + psllq mm6,5 + pxor mm7,mm5 + pxor mm2,mm1 + psrlq mm5,5 + pxor mm7,mm6 + pand mm0,mm2 + psllq mm6,6 + pxor mm7,mm5 + pxor mm0,mm1 + pxor mm6,mm7 + movq mm5,[40+esp] + paddq mm0,mm6 + movq mm6,[48+esp] + movdqa [edx-16],xmm2 + movq mm1,[8+esp] + paddq mm0,mm3 + movq mm3,[24+esp] + movq mm7,[56+esp] + pxor mm2,mm1 + paddq mm0,[esi] + paddq mm1,[8+esi] + paddq mm2,[16+esi] + paddq mm3,[24+esi] + paddq mm4,[32+esi] + paddq mm5,[40+esi] + paddq mm6,[48+esi] + paddq mm7,[56+esi] + movq [esi],mm0 + movq [8+esi],mm1 + movq [16+esi],mm2 + movq [24+esi],mm3 + movq [32+esi],mm4 + movq [40+esi],mm5 + movq [48+esi],mm6 + movq [56+esi],mm7 + cmp edi,eax + jb NEAR L$007loop_ssse3 + mov esp,DWORD [76+edx] + emms + pop edi + pop esi + pop ebx + pop ebp + ret align 16 L$002loop_x86: mov eax,DWORD [edi] @@ -143,7 +2407,7 @@ L$002loop_x86: mov ecx,16 dd 2784229001 align 16 -L$00300_15_x86: +L$00900_15_x86: mov ecx,DWORD [40+esp] mov edx,DWORD [44+esp] mov esi,ecx @@ -250,9 +2514,9 @@ L$00300_15_x86: sub esp,8 lea ebp,[8+ebp] cmp dl,148 - jne NEAR L$00300_15_x86 + jne NEAR L$00900_15_x86 align 16 -L$00416_79_x86: +L$01016_79_x86: mov ecx,DWORD [312+esp] mov edx,DWORD [316+esp] mov esi,ecx @@ -425,7 +2689,7 @@ L$00416_79_x86: sub esp,8 lea ebp,[8+ebp] cmp dl,23 - jne NEAR L$00416_79_x86 + jne NEAR L$01016_79_x86 mov esi,DWORD [840+esp] mov edi,DWORD [844+esp] mov eax,DWORD [esi] @@ -575,3 +2839,5 @@ db 110,115,102,111,114,109,32,102,111,114,32,120,56,54,44,32 db 67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97 db 112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103 db 62,0 +segment .bss +common _OPENSSL_ia32cap_P 16 diff --git a/third_party/boringssl/win-x86_64/crypto/aes/aesni-x86_64.asm b/third_party/boringssl/win-x86_64/crypto/aes/aesni-x86_64.asm index e1c9e0e0203fe..cf313d1ae9a63 100644 --- a/third_party/boringssl/win-x86_64/crypto/aes/aesni-x86_64.asm +++ b/third_party/boringssl/win-x86_64/crypto/aes/aesni-x86_64.asm @@ -22,7 +22,10 @@ DB 102,15,56,220,209 lea r8,[16+r8] jnz NEAR $L$oop_enc1_1 DB 102,15,56,221,209 + pxor xmm0,xmm0 + pxor xmm1,xmm1 movups XMMWORD[rdx],xmm2 + pxor xmm2,xmm2 DB 0F3h,0C3h ;repret @@ -43,7 +46,10 @@ DB 102,15,56,222,209 lea r8,[16+r8] jnz NEAR $L$oop_dec1_2 DB 102,15,56,223,209 + pxor xmm0,xmm0 + pxor xmm1,xmm1 movups XMMWORD[rdx],xmm2 + pxor xmm2,xmm2 DB 0F3h,0C3h ;repret @@ -269,21 +275,18 @@ DB 102,15,56,220,217 pxor xmm6,xmm0 DB 102,15,56,220,225 pxor xmm7,xmm0 + movups xmm0,XMMWORD[rax*1+rcx] add rax,16 -DB 102,15,56,220,233 -DB 102,15,56,220,241 -DB 102,15,56,220,249 - movups xmm0,XMMWORD[((-16))+rax*1+rcx] jmp NEAR $L$enc_loop6_enter ALIGN 16 $L$enc_loop6: DB 102,15,56,220,209 DB 102,15,56,220,217 DB 102,15,56,220,225 +$L$enc_loop6_enter: DB 102,15,56,220,233 DB 102,15,56,220,241 DB 102,15,56,220,249 -$L$enc_loop6_enter: movups xmm1,XMMWORD[rax*1+rcx] add rax,32 DB 102,15,56,220,208 @@ -326,21 +329,18 @@ DB 102,15,56,222,217 pxor xmm6,xmm0 DB 102,15,56,222,225 pxor xmm7,xmm0 + movups xmm0,XMMWORD[rax*1+rcx] add rax,16 -DB 102,15,56,222,233 -DB 102,15,56,222,241 -DB 102,15,56,222,249 - movups xmm0,XMMWORD[((-16))+rax*1+rcx] jmp NEAR $L$dec_loop6_enter ALIGN 16 $L$dec_loop6: DB 102,15,56,222,209 DB 102,15,56,222,217 DB 102,15,56,222,225 +$L$dec_loop6_enter: DB 102,15,56,222,233 DB 102,15,56,222,241 DB 102,15,56,222,249 -$L$dec_loop6_enter: movups xmm1,XMMWORD[rax*1+rcx] add rax,32 DB 102,15,56,222,208 @@ -380,23 +380,18 @@ _aesni_encrypt8: lea rcx,[32+rax*1+rcx] neg rax DB 102,15,56,220,209 - add rax,16 pxor xmm7,xmm0 -DB 102,15,56,220,217 pxor xmm8,xmm0 +DB 102,15,56,220,217 pxor xmm9,xmm0 -DB 102,15,56,220,225 -DB 102,15,56,220,233 -DB 102,15,56,220,241 -DB 102,15,56,220,249 -DB 102,68,15,56,220,193 -DB 102,68,15,56,220,201 - movups xmm0,XMMWORD[((-16))+rax*1+rcx] - jmp NEAR $L$enc_loop8_enter + movups xmm0,XMMWORD[rax*1+rcx] + add rax,16 + jmp NEAR $L$enc_loop8_inner ALIGN 16 $L$enc_loop8: DB 102,15,56,220,209 DB 102,15,56,220,217 +$L$enc_loop8_inner: DB 102,15,56,220,225 DB 102,15,56,220,233 DB 102,15,56,220,241 @@ -449,23 +444,18 @@ _aesni_decrypt8: lea rcx,[32+rax*1+rcx] neg rax DB 102,15,56,222,209 - add rax,16 pxor xmm7,xmm0 -DB 102,15,56,222,217 pxor xmm8,xmm0 +DB 102,15,56,222,217 pxor xmm9,xmm0 -DB 102,15,56,222,225 -DB 102,15,56,222,233 -DB 102,15,56,222,241 -DB 102,15,56,222,249 -DB 102,68,15,56,222,193 -DB 102,68,15,56,222,201 - movups xmm0,XMMWORD[((-16))+rax*1+rcx] - jmp NEAR $L$dec_loop8_enter + movups xmm0,XMMWORD[rax*1+rcx] + add rax,16 + jmp NEAR $L$dec_loop8_inner ALIGN 16 $L$dec_loop8: DB 102,15,56,222,209 DB 102,15,56,222,217 +$L$dec_loop8_inner: DB 102,15,56,222,225 DB 102,15,56,222,233 DB 102,15,56,222,241 @@ -609,6 +599,7 @@ $L$ecb_enc_tail: movups xmm7,XMMWORD[80+rdi] je NEAR $L$ecb_enc_six movdqu xmm8,XMMWORD[96+rdi] + xorps xmm9,xmm9 call _aesni_encrypt8 movups XMMWORD[rsi],xmm2 movups XMMWORD[16+rsi],xmm3 @@ -722,15 +713,23 @@ $L$ecb_dec_loop8_enter: jnc NEAR $L$ecb_dec_loop8 movups XMMWORD[rsi],xmm2 + pxor xmm2,xmm2 mov rcx,r11 movups XMMWORD[16+rsi],xmm3 + pxor xmm3,xmm3 mov eax,r10d movups XMMWORD[32+rsi],xmm4 + pxor xmm4,xmm4 movups XMMWORD[48+rsi],xmm5 + pxor xmm5,xmm5 movups XMMWORD[64+rsi],xmm6 + pxor xmm6,xmm6 movups XMMWORD[80+rsi],xmm7 + pxor xmm7,xmm7 movups XMMWORD[96+rsi],xmm8 + pxor xmm8,xmm8 movups XMMWORD[112+rsi],xmm9 + pxor xmm9,xmm9 lea rsi,[128+rsi] add rdx,0x80 jz NEAR $L$ecb_ret @@ -753,14 +752,23 @@ $L$ecb_dec_tail: je NEAR $L$ecb_dec_six movups xmm8,XMMWORD[96+rdi] movups xmm0,XMMWORD[rcx] + xorps xmm9,xmm9 call _aesni_decrypt8 movups XMMWORD[rsi],xmm2 + pxor xmm2,xmm2 movups XMMWORD[16+rsi],xmm3 + pxor xmm3,xmm3 movups XMMWORD[32+rsi],xmm4 + pxor xmm4,xmm4 movups XMMWORD[48+rsi],xmm5 + pxor xmm5,xmm5 movups XMMWORD[64+rsi],xmm6 + pxor xmm6,xmm6 movups XMMWORD[80+rsi],xmm7 + pxor xmm7,xmm7 movups XMMWORD[96+rsi],xmm8 + pxor xmm8,xmm8 + pxor xmm9,xmm9 jmp NEAR $L$ecb_ret ALIGN 16 $L$ecb_dec_one: @@ -776,53 +784,81 @@ DB 102,15,56,222,209 jnz NEAR $L$oop_dec1_4 DB 102,15,56,223,209 movups XMMWORD[rsi],xmm2 + pxor xmm2,xmm2 jmp NEAR $L$ecb_ret ALIGN 16 $L$ecb_dec_two: call _aesni_decrypt2 movups XMMWORD[rsi],xmm2 + pxor xmm2,xmm2 movups XMMWORD[16+rsi],xmm3 + pxor xmm3,xmm3 jmp NEAR $L$ecb_ret ALIGN 16 $L$ecb_dec_three: call _aesni_decrypt3 movups XMMWORD[rsi],xmm2 + pxor xmm2,xmm2 movups XMMWORD[16+rsi],xmm3 + pxor xmm3,xmm3 movups XMMWORD[32+rsi],xmm4 + pxor xmm4,xmm4 jmp NEAR $L$ecb_ret ALIGN 16 $L$ecb_dec_four: call _aesni_decrypt4 movups XMMWORD[rsi],xmm2 + pxor xmm2,xmm2 movups XMMWORD[16+rsi],xmm3 + pxor xmm3,xmm3 movups XMMWORD[32+rsi],xmm4 + pxor xmm4,xmm4 movups XMMWORD[48+rsi],xmm5 + pxor xmm5,xmm5 jmp NEAR $L$ecb_ret ALIGN 16 $L$ecb_dec_five: xorps xmm7,xmm7 call _aesni_decrypt6 movups XMMWORD[rsi],xmm2 + pxor xmm2,xmm2 movups XMMWORD[16+rsi],xmm3 + pxor xmm3,xmm3 movups XMMWORD[32+rsi],xmm4 + pxor xmm4,xmm4 movups XMMWORD[48+rsi],xmm5 + pxor xmm5,xmm5 movups XMMWORD[64+rsi],xmm6 + pxor xmm6,xmm6 + pxor xmm7,xmm7 jmp NEAR $L$ecb_ret ALIGN 16 $L$ecb_dec_six: call _aesni_decrypt6 movups XMMWORD[rsi],xmm2 + pxor xmm2,xmm2 movups XMMWORD[16+rsi],xmm3 + pxor xmm3,xmm3 movups XMMWORD[32+rsi],xmm4 + pxor xmm4,xmm4 movups XMMWORD[48+rsi],xmm5 + pxor xmm5,xmm5 movups XMMWORD[64+rsi],xmm6 + pxor xmm6,xmm6 movups XMMWORD[80+rsi],xmm7 + pxor xmm7,xmm7 $L$ecb_ret: + xorps xmm0,xmm0 + pxor xmm1,xmm1 movaps xmm6,XMMWORD[rsp] + movaps XMMWORD[rsp],xmm0 movaps xmm7,XMMWORD[16+rsp] + movaps XMMWORD[16+rsp],xmm0 movaps xmm8,XMMWORD[32+rsp] + movaps XMMWORD[32+rsp],xmm0 movaps xmm9,XMMWORD[48+rsp] + movaps XMMWORD[48+rsp],xmm0 lea rsp,[88+rsp] $L$ecb_enc_ret: mov rdi,QWORD[8+rsp] ;WIN64 epilogue @@ -901,11 +937,21 @@ DB 102,15,56,0,215 lea rsi,[16+rsi] jnz NEAR $L$ccm64_enc_outer + pxor xmm0,xmm0 + pxor xmm1,xmm1 + pxor xmm2,xmm2 movups XMMWORD[r9],xmm3 + pxor xmm3,xmm3 + pxor xmm8,xmm8 + pxor xmm6,xmm6 movaps xmm6,XMMWORD[rsp] + movaps XMMWORD[rsp],xmm0 movaps xmm7,XMMWORD[16+rsp] + movaps XMMWORD[16+rsp],xmm0 movaps xmm8,XMMWORD[32+rsp] + movaps XMMWORD[32+rsp],xmm0 movaps xmm9,XMMWORD[48+rsp] + movaps XMMWORD[48+rsp],xmm0 lea rsp,[88+rsp] $L$ccm64_enc_ret: mov rdi,QWORD[8+rsp] ;WIN64 epilogue @@ -1018,11 +1064,21 @@ DB 102,15,56,220,217 lea r11,[16+r11] jnz NEAR $L$oop_enc1_6 DB 102,15,56,221,217 + pxor xmm0,xmm0 + pxor xmm1,xmm1 + pxor xmm2,xmm2 movups XMMWORD[r9],xmm3 + pxor xmm3,xmm3 + pxor xmm8,xmm8 + pxor xmm6,xmm6 movaps xmm6,XMMWORD[rsp] + movaps XMMWORD[rsp],xmm0 movaps xmm7,XMMWORD[16+rsp] + movaps XMMWORD[16+rsp],xmm0 movaps xmm8,XMMWORD[32+rsp] + movaps XMMWORD[32+rsp],xmm0 movaps xmm9,XMMWORD[48+rsp] + movaps XMMWORD[48+rsp],xmm0 lea rsp,[88+rsp] $L$ccm64_dec_ret: mov rdi,QWORD[8+rsp] ;WIN64 epilogue @@ -1044,6 +1100,35 @@ $L$SEH_begin_aesni_ctr32_encrypt_blocks: mov r8,QWORD[40+rsp] + cmp rdx,1 + jne NEAR $L$ctr32_bulk + + + + movups xmm2,XMMWORD[r8] + movups xmm3,XMMWORD[rdi] + mov edx,DWORD[240+rcx] + movups xmm0,XMMWORD[rcx] + movups xmm1,XMMWORD[16+rcx] + lea rcx,[32+rcx] + xorps xmm2,xmm0 +$L$oop_enc1_7: +DB 102,15,56,220,209 + dec edx + movups xmm1,XMMWORD[rcx] + lea rcx,[16+rcx] + jnz NEAR $L$oop_enc1_7 +DB 102,15,56,221,209 + pxor xmm0,xmm0 + pxor xmm1,xmm1 + xorps xmm2,xmm3 + pxor xmm3,xmm3 + movups XMMWORD[rsi],xmm2 + xorps xmm2,xmm2 + jmp NEAR $L$ctr32_epilogue + +ALIGN 16 +$L$ctr32_bulk: lea rax,[rsp] push rbp sub rsp,288 @@ -1061,8 +1146,8 @@ $L$SEH_begin_aesni_ctr32_encrypt_blocks: $L$ctr32_body: lea rbp,[((-8))+rax] - cmp rdx,1 - je NEAR $L$ctr32_one_shortcut + + movdqu xmm2,XMMWORD[r8] movdqu xmm0,XMMWORD[rcx] @@ -1453,11 +1538,14 @@ DB 102,69,15,56,221,202 lea rcx,[((-128))+rcx] $L$ctr32_tail: + + lea rcx,[16+rcx] cmp rdx,4 jb NEAR $L$ctr32_loop3 je NEAR $L$ctr32_loop4 + shl eax,4 movdqa xmm8,XMMWORD[96+rsp] pxor xmm9,xmm9 @@ -1560,40 +1648,43 @@ DB 102,15,56,221,225 movups xmm12,XMMWORD[32+rdi] xorps xmm4,xmm12 movups XMMWORD[32+rsi],xmm4 - jmp NEAR $L$ctr32_done -ALIGN 16 -$L$ctr32_one_shortcut: - movups xmm2,XMMWORD[r8] - movups xmm10,XMMWORD[rdi] - mov eax,DWORD[240+rcx] - movups xmm0,XMMWORD[rcx] - movups xmm1,XMMWORD[16+rcx] - lea rcx,[32+rcx] - xorps xmm2,xmm0 -$L$oop_enc1_7: -DB 102,15,56,220,209 - dec eax - movups xmm1,XMMWORD[rcx] - lea rcx,[16+rcx] - jnz NEAR $L$oop_enc1_7 -DB 102,15,56,221,209 - xorps xmm2,xmm10 - movups XMMWORD[rsi],xmm2 - jmp NEAR $L$ctr32_done - -ALIGN 16 $L$ctr32_done: + xorps xmm0,xmm0 + xor r11d,r11d + pxor xmm1,xmm1 + pxor xmm2,xmm2 + pxor xmm3,xmm3 + pxor xmm4,xmm4 + pxor xmm5,xmm5 movaps xmm6,XMMWORD[((-160))+rbp] + movaps XMMWORD[(-160)+rbp],xmm0 movaps xmm7,XMMWORD[((-144))+rbp] + movaps XMMWORD[(-144)+rbp],xmm0 movaps xmm8,XMMWORD[((-128))+rbp] + movaps XMMWORD[(-128)+rbp],xmm0 movaps xmm9,XMMWORD[((-112))+rbp] + movaps XMMWORD[(-112)+rbp],xmm0 movaps xmm10,XMMWORD[((-96))+rbp] + movaps XMMWORD[(-96)+rbp],xmm0 movaps xmm11,XMMWORD[((-80))+rbp] + movaps XMMWORD[(-80)+rbp],xmm0 movaps xmm12,XMMWORD[((-64))+rbp] + movaps XMMWORD[(-64)+rbp],xmm0 movaps xmm13,XMMWORD[((-48))+rbp] + movaps XMMWORD[(-48)+rbp],xmm0 movaps xmm14,XMMWORD[((-32))+rbp] + movaps XMMWORD[(-32)+rbp],xmm0 movaps xmm15,XMMWORD[((-16))+rbp] + movaps XMMWORD[(-16)+rbp],xmm0 + movaps XMMWORD[rsp],xmm0 + movaps XMMWORD[16+rsp],xmm0 + movaps XMMWORD[32+rsp],xmm0 + movaps XMMWORD[48+rsp],xmm0 + movaps XMMWORD[64+rsp],xmm0 + movaps XMMWORD[80+rsp],xmm0 + movaps XMMWORD[96+rsp],xmm0 + movaps XMMWORD[112+rsp],xmm0 lea rsp,[rbp] pop rbp $L$ctr32_epilogue: @@ -1889,6 +1980,7 @@ DB 102,15,56,221,124,36,80 shr eax,4 $L$xts_enc_short: + mov r10d,eax pxor xmm10,xmm0 add rdx,16*6 @@ -1917,6 +2009,7 @@ $L$xts_enc_short: pxor xmm4,xmm12 pxor xmm5,xmm13 pxor xmm6,xmm14 + pxor xmm7,xmm7 call _aesni_encrypt6 @@ -2059,16 +2152,39 @@ DB 102,15,56,221,209 movups XMMWORD[(-16)+rsi],xmm2 $L$xts_enc_ret: + xorps xmm0,xmm0 + pxor xmm1,xmm1 + pxor xmm2,xmm2 + pxor xmm3,xmm3 + pxor xmm4,xmm4 + pxor xmm5,xmm5 movaps xmm6,XMMWORD[((-160))+rbp] + movaps XMMWORD[(-160)+rbp],xmm0 movaps xmm7,XMMWORD[((-144))+rbp] + movaps XMMWORD[(-144)+rbp],xmm0 movaps xmm8,XMMWORD[((-128))+rbp] + movaps XMMWORD[(-128)+rbp],xmm0 movaps xmm9,XMMWORD[((-112))+rbp] + movaps XMMWORD[(-112)+rbp],xmm0 movaps xmm10,XMMWORD[((-96))+rbp] + movaps XMMWORD[(-96)+rbp],xmm0 movaps xmm11,XMMWORD[((-80))+rbp] + movaps XMMWORD[(-80)+rbp],xmm0 movaps xmm12,XMMWORD[((-64))+rbp] + movaps XMMWORD[(-64)+rbp],xmm0 movaps xmm13,XMMWORD[((-48))+rbp] + movaps XMMWORD[(-48)+rbp],xmm0 movaps xmm14,XMMWORD[((-32))+rbp] + movaps XMMWORD[(-32)+rbp],xmm0 movaps xmm15,XMMWORD[((-16))+rbp] + movaps XMMWORD[(-16)+rbp],xmm0 + movaps XMMWORD[rsp],xmm0 + movaps XMMWORD[16+rsp],xmm0 + movaps XMMWORD[32+rsp],xmm0 + movaps XMMWORD[48+rsp],xmm0 + movaps XMMWORD[64+rsp],xmm0 + movaps XMMWORD[80+rsp],xmm0 + movaps XMMWORD[96+rsp],xmm0 lea rsp,[rbp] pop rbp $L$xts_enc_epilogue: @@ -2370,6 +2486,7 @@ DB 102,15,56,223,124,36,80 shr eax,4 $L$xts_dec_short: + mov r10d,eax pxor xmm10,xmm0 pxor xmm11,xmm0 @@ -2572,16 +2689,39 @@ DB 102,15,56,223,209 movups XMMWORD[rsi],xmm2 $L$xts_dec_ret: + xorps xmm0,xmm0 + pxor xmm1,xmm1 + pxor xmm2,xmm2 + pxor xmm3,xmm3 + pxor xmm4,xmm4 + pxor xmm5,xmm5 movaps xmm6,XMMWORD[((-160))+rbp] + movaps XMMWORD[(-160)+rbp],xmm0 movaps xmm7,XMMWORD[((-144))+rbp] + movaps XMMWORD[(-144)+rbp],xmm0 movaps xmm8,XMMWORD[((-128))+rbp] + movaps XMMWORD[(-128)+rbp],xmm0 movaps xmm9,XMMWORD[((-112))+rbp] + movaps XMMWORD[(-112)+rbp],xmm0 movaps xmm10,XMMWORD[((-96))+rbp] + movaps XMMWORD[(-96)+rbp],xmm0 movaps xmm11,XMMWORD[((-80))+rbp] + movaps XMMWORD[(-80)+rbp],xmm0 movaps xmm12,XMMWORD[((-64))+rbp] + movaps XMMWORD[(-64)+rbp],xmm0 movaps xmm13,XMMWORD[((-48))+rbp] + movaps XMMWORD[(-48)+rbp],xmm0 movaps xmm14,XMMWORD[((-32))+rbp] + movaps XMMWORD[(-32)+rbp],xmm0 movaps xmm15,XMMWORD[((-16))+rbp] + movaps XMMWORD[(-16)+rbp],xmm0 + movaps XMMWORD[rsp],xmm0 + movaps XMMWORD[16+rsp],xmm0 + movaps XMMWORD[32+rsp],xmm0 + movaps XMMWORD[48+rsp],xmm0 + movaps XMMWORD[64+rsp],xmm0 + movaps XMMWORD[80+rsp],xmm0 + movaps XMMWORD[96+rsp],xmm0 lea rsp,[rbp] pop rbp $L$xts_dec_epilogue: @@ -2644,7 +2784,11 @@ DB 102,15,56,221,209 jnc NEAR $L$cbc_enc_loop add rdx,16 jnz NEAR $L$cbc_enc_tail + pxor xmm0,xmm0 + pxor xmm1,xmm1 movups XMMWORD[r8],xmm2 + pxor xmm2,xmm2 + pxor xmm3,xmm3 jmp NEAR $L$cbc_ret $L$cbc_enc_tail: @@ -2664,6 +2808,35 @@ $L$cbc_enc_tail: ALIGN 16 $L$cbc_decrypt: + cmp rdx,16 + jne NEAR $L$cbc_decrypt_bulk + + + + movdqu xmm2,XMMWORD[rdi] + movdqu xmm3,XMMWORD[r8] + movdqa xmm4,xmm2 + movups xmm0,XMMWORD[rcx] + movups xmm1,XMMWORD[16+rcx] + lea rcx,[32+rcx] + xorps xmm2,xmm0 +$L$oop_dec1_16: +DB 102,15,56,222,209 + dec r10d + movups xmm1,XMMWORD[rcx] + lea rcx,[16+rcx] + jnz NEAR $L$oop_dec1_16 +DB 102,15,56,223,209 + pxor xmm0,xmm0 + pxor xmm1,xmm1 + movdqu XMMWORD[r8],xmm4 + xorps xmm2,xmm3 + pxor xmm3,xmm3 + movups XMMWORD[rsi],xmm2 + pxor xmm2,xmm2 + jmp NEAR $L$cbc_ret +ALIGN 16 +$L$cbc_decrypt_bulk: lea rax,[rsp] push rbp sub rsp,176 @@ -2911,7 +3084,7 @@ DB 102,69,15,56,223,202 movaps xmm2,xmm9 lea rcx,[((-112))+rcx] add rdx,0x70 - jle NEAR $L$cbc_dec_tail_collected + jle NEAR $L$cbc_dec_clear_tail_collected movups XMMWORD[rsi],xmm9 lea rsi,[16+rsi] cmp rdx,0x50 @@ -2930,14 +3103,19 @@ $L$cbc_dec_six_or_seven: movdqu XMMWORD[rsi],xmm2 pxor xmm4,xmm12 movdqu XMMWORD[16+rsi],xmm3 + pxor xmm3,xmm3 pxor xmm5,xmm13 movdqu XMMWORD[32+rsi],xmm4 + pxor xmm4,xmm4 pxor xmm6,xmm14 movdqu XMMWORD[48+rsi],xmm5 + pxor xmm5,xmm5 pxor xmm7,xmm15 movdqu XMMWORD[64+rsi],xmm6 + pxor xmm6,xmm6 lea rsi,[80+rsi] movdqa xmm2,xmm7 + pxor xmm7,xmm7 jmp NEAR $L$cbc_dec_tail_collected ALIGN 16 @@ -2952,16 +3130,23 @@ $L$cbc_dec_seven: movdqu XMMWORD[rsi],xmm2 pxor xmm4,xmm12 movdqu XMMWORD[16+rsi],xmm3 + pxor xmm3,xmm3 pxor xmm5,xmm13 movdqu XMMWORD[32+rsi],xmm4 + pxor xmm4,xmm4 pxor xmm6,xmm14 movdqu XMMWORD[48+rsi],xmm5 + pxor xmm5,xmm5 pxor xmm7,xmm15 movdqu XMMWORD[64+rsi],xmm6 + pxor xmm6,xmm6 pxor xmm8,xmm9 movdqu XMMWORD[80+rsi],xmm7 + pxor xmm7,xmm7 lea rsi,[96+rsi] movdqa xmm2,xmm8 + pxor xmm8,xmm8 + pxor xmm9,xmm9 jmp NEAR $L$cbc_dec_tail_collected ALIGN 16 @@ -3005,7 +3190,7 @@ $L$cbc_dec_loop6_enter: movdqa xmm2,xmm7 add rdx,0x50 - jle NEAR $L$cbc_dec_tail_collected + jle NEAR $L$cbc_dec_clear_tail_collected movups XMMWORD[rsi],xmm7 lea rsi,[16+rsi] @@ -3040,12 +3225,17 @@ $L$cbc_dec_tail: movdqu XMMWORD[rsi],xmm2 pxor xmm4,xmm12 movdqu XMMWORD[16+rsi],xmm3 + pxor xmm3,xmm3 pxor xmm5,xmm13 movdqu XMMWORD[32+rsi],xmm4 + pxor xmm4,xmm4 pxor xmm6,xmm14 movdqu XMMWORD[48+rsi],xmm5 + pxor xmm5,xmm5 lea rsi,[64+rsi] movdqa xmm2,xmm6 + pxor xmm6,xmm6 + pxor xmm7,xmm7 sub rdx,0x10 jmp NEAR $L$cbc_dec_tail_collected @@ -3056,12 +3246,12 @@ $L$cbc_dec_one: movups xmm1,XMMWORD[16+rcx] lea rcx,[32+rcx] xorps xmm2,xmm0 -$L$oop_dec1_16: +$L$oop_dec1_17: DB 102,15,56,222,209 dec eax movups xmm1,XMMWORD[rcx] lea rcx,[16+rcx] - jnz NEAR $L$oop_dec1_16 + jnz NEAR $L$oop_dec1_17 DB 102,15,56,223,209 xorps xmm2,xmm10 movaps xmm10,xmm11 @@ -3075,6 +3265,7 @@ $L$cbc_dec_two: pxor xmm3,xmm11 movdqu XMMWORD[rsi],xmm2 movdqa xmm2,xmm3 + pxor xmm3,xmm3 lea rsi,[16+rsi] jmp NEAR $L$cbc_dec_tail_collected ALIGN 16 @@ -3087,7 +3278,9 @@ $L$cbc_dec_three: movdqu XMMWORD[rsi],xmm2 pxor xmm4,xmm12 movdqu XMMWORD[16+rsi],xmm3 + pxor xmm3,xmm3 movdqa xmm2,xmm4 + pxor xmm4,xmm4 lea rsi,[32+rsi] jmp NEAR $L$cbc_dec_tail_collected ALIGN 16 @@ -3100,39 +3293,61 @@ $L$cbc_dec_four: movdqu XMMWORD[rsi],xmm2 pxor xmm4,xmm12 movdqu XMMWORD[16+rsi],xmm3 + pxor xmm3,xmm3 pxor xmm5,xmm13 movdqu XMMWORD[32+rsi],xmm4 + pxor xmm4,xmm4 movdqa xmm2,xmm5 + pxor xmm5,xmm5 lea rsi,[48+rsi] jmp NEAR $L$cbc_dec_tail_collected ALIGN 16 +$L$cbc_dec_clear_tail_collected: + pxor xmm3,xmm3 + pxor xmm4,xmm4 + pxor xmm5,xmm5 $L$cbc_dec_tail_collected: movups XMMWORD[r8],xmm10 and rdx,15 jnz NEAR $L$cbc_dec_tail_partial movups XMMWORD[rsi],xmm2 + pxor xmm2,xmm2 jmp NEAR $L$cbc_dec_ret ALIGN 16 $L$cbc_dec_tail_partial: movaps XMMWORD[rsp],xmm2 + pxor xmm2,xmm2 mov rcx,16 mov rdi,rsi sub rcx,rdx lea rsi,[rsp] DD 0x9066A4F3 + movdqa XMMWORD[rsp],xmm2 $L$cbc_dec_ret: + xorps xmm0,xmm0 + pxor xmm1,xmm1 movaps xmm6,XMMWORD[16+rsp] + movaps XMMWORD[16+rsp],xmm0 movaps xmm7,XMMWORD[32+rsp] + movaps XMMWORD[32+rsp],xmm0 movaps xmm8,XMMWORD[48+rsp] + movaps XMMWORD[48+rsp],xmm0 movaps xmm9,XMMWORD[64+rsp] + movaps XMMWORD[64+rsp],xmm0 movaps xmm10,XMMWORD[80+rsp] + movaps XMMWORD[80+rsp],xmm0 movaps xmm11,XMMWORD[96+rsp] + movaps XMMWORD[96+rsp],xmm0 movaps xmm12,XMMWORD[112+rsp] + movaps XMMWORD[112+rsp],xmm0 movaps xmm13,XMMWORD[128+rsp] + movaps XMMWORD[128+rsp],xmm0 movaps xmm14,XMMWORD[144+rsp] + movaps XMMWORD[144+rsp],xmm0 movaps xmm15,XMMWORD[160+rsp] + movaps XMMWORD[160+rsp],xmm0 lea rsp,[rbp] pop rbp $L$cbc_ret: @@ -3172,7 +3387,9 @@ DB 102,15,56,219,201 movups xmm0,XMMWORD[r8] DB 102,15,56,219,192 + pxor xmm1,xmm1 movups XMMWORD[rcx],xmm0 + pxor xmm0,xmm0 $L$dec_key_ret: add rsp,8 DB 0F3h,0C3h ;repret @@ -3190,8 +3407,10 @@ DB 0x48,0x83,0xEC,0x08 test r8,r8 jz NEAR $L$enc_key_ret + mov r10d,268437504 movups xmm0,XMMWORD[rcx] xorps xmm4,xmm4 + and r10d,DWORD[((OPENSSL_ia32cap_P+4))] lea rax,[16+r8] cmp edx,256 je NEAR $L$14rounds @@ -3202,6 +3421,9 @@ DB 0x48,0x83,0xEC,0x08 $L$10rounds: mov edx,9 + cmp r10d,268435456 + je NEAR $L$10rounds_alt + movups XMMWORD[r8],xmm0 DB 102,15,58,223,200,1 call $L$key_expansion_128_cold @@ -3228,10 +3450,80 @@ DB 102,15,58,223,200,54 xor eax,eax jmp NEAR $L$enc_key_ret +ALIGN 16 +$L$10rounds_alt: + movdqa xmm5,XMMWORD[$L$key_rotate] + mov r10d,8 + movdqa xmm4,XMMWORD[$L$key_rcon1] + movdqa xmm2,xmm0 + movdqu XMMWORD[r8],xmm0 + jmp NEAR $L$oop_key128 + +ALIGN 16 +$L$oop_key128: +DB 102,15,56,0,197 +DB 102,15,56,221,196 + pslld xmm4,1 + lea rax,[16+rax] + + movdqa xmm3,xmm2 + pslldq xmm2,4 + pxor xmm3,xmm2 + pslldq xmm2,4 + pxor xmm3,xmm2 + pslldq xmm2,4 + pxor xmm2,xmm3 + + pxor xmm0,xmm2 + movdqu XMMWORD[(-16)+rax],xmm0 + movdqa xmm2,xmm0 + + dec r10d + jnz NEAR $L$oop_key128 + + movdqa xmm4,XMMWORD[$L$key_rcon1b] + +DB 102,15,56,0,197 +DB 102,15,56,221,196 + pslld xmm4,1 + + movdqa xmm3,xmm2 + pslldq xmm2,4 + pxor xmm3,xmm2 + pslldq xmm2,4 + pxor xmm3,xmm2 + pslldq xmm2,4 + pxor xmm2,xmm3 + + pxor xmm0,xmm2 + movdqu XMMWORD[rax],xmm0 + + movdqa xmm2,xmm0 +DB 102,15,56,0,197 +DB 102,15,56,221,196 + + movdqa xmm3,xmm2 + pslldq xmm2,4 + pxor xmm3,xmm2 + pslldq xmm2,4 + pxor xmm3,xmm2 + pslldq xmm2,4 + pxor xmm2,xmm3 + + pxor xmm0,xmm2 + movdqu XMMWORD[16+rax],xmm0 + + mov DWORD[96+rax],edx + xor eax,eax + jmp NEAR $L$enc_key_ret + ALIGN 16 $L$12rounds: movq xmm2,QWORD[16+rcx] mov edx,11 + cmp r10d,268435456 + je NEAR $L$12rounds_alt + movups XMMWORD[r8],xmm0 DB 102,15,58,223,202,1 call $L$key_expansion_192a_cold @@ -3254,11 +3546,55 @@ DB 102,15,58,223,202,128 xor rax,rax jmp NEAR $L$enc_key_ret +ALIGN 16 +$L$12rounds_alt: + movdqa xmm5,XMMWORD[$L$key_rotate192] + movdqa xmm4,XMMWORD[$L$key_rcon1] + mov r10d,8 + movdqu XMMWORD[r8],xmm0 + jmp NEAR $L$oop_key192 + +ALIGN 16 +$L$oop_key192: + movq QWORD[rax],xmm2 + movdqa xmm1,xmm2 +DB 102,15,56,0,213 +DB 102,15,56,221,212 + pslld xmm4,1 + lea rax,[24+rax] + + movdqa xmm3,xmm0 + pslldq xmm0,4 + pxor xmm3,xmm0 + pslldq xmm0,4 + pxor xmm3,xmm0 + pslldq xmm0,4 + pxor xmm0,xmm3 + + pshufd xmm3,xmm0,0xff + pxor xmm3,xmm1 + pslldq xmm1,4 + pxor xmm3,xmm1 + + pxor xmm0,xmm2 + pxor xmm2,xmm3 + movdqu XMMWORD[(-16)+rax],xmm0 + + dec r10d + jnz NEAR $L$oop_key192 + + mov DWORD[32+rax],edx + xor eax,eax + jmp NEAR $L$enc_key_ret + ALIGN 16 $L$14rounds: movups xmm2,XMMWORD[16+rcx] mov edx,13 lea rax,[16+rax] + cmp r10d,268435456 + je NEAR $L$14rounds_alt + movups XMMWORD[r8],xmm0 movups XMMWORD[16+r8],xmm2 DB 102,15,58,223,202,1 @@ -3292,10 +3628,70 @@ DB 102,15,58,223,202,64 xor rax,rax jmp NEAR $L$enc_key_ret +ALIGN 16 +$L$14rounds_alt: + movdqa xmm5,XMMWORD[$L$key_rotate] + movdqa xmm4,XMMWORD[$L$key_rcon1] + mov r10d,7 + movdqu XMMWORD[r8],xmm0 + movdqa xmm1,xmm2 + movdqu XMMWORD[16+r8],xmm2 + jmp NEAR $L$oop_key256 + +ALIGN 16 +$L$oop_key256: +DB 102,15,56,0,213 +DB 102,15,56,221,212 + + movdqa xmm3,xmm0 + pslldq xmm0,4 + pxor xmm3,xmm0 + pslldq xmm0,4 + pxor xmm3,xmm0 + pslldq xmm0,4 + pxor xmm0,xmm3 + pslld xmm4,1 + + pxor xmm0,xmm2 + movdqu XMMWORD[rax],xmm0 + + dec r10d + jz NEAR $L$done_key256 + + pshufd xmm2,xmm0,0xff + pxor xmm3,xmm3 +DB 102,15,56,221,211 + + movdqa xmm3,xmm1 + pslldq xmm1,4 + pxor xmm3,xmm1 + pslldq xmm1,4 + pxor xmm3,xmm1 + pslldq xmm1,4 + pxor xmm1,xmm3 + + pxor xmm2,xmm1 + movdqu XMMWORD[16+rax],xmm2 + lea rax,[32+rax] + movdqa xmm1,xmm2 + + jmp NEAR $L$oop_key256 + +$L$done_key256: + mov DWORD[16+rax],edx + xor eax,eax + jmp NEAR $L$enc_key_ret + ALIGN 16 $L$bad_keybits: mov rax,-2 $L$enc_key_ret: + pxor xmm0,xmm0 + pxor xmm1,xmm1 + pxor xmm2,xmm2 + pxor xmm3,xmm3 + pxor xmm4,xmm4 + pxor xmm5,xmm5 add rsp,8 DB 0F3h,0C3h ;repret $L$SEH_end_set_encrypt_key: @@ -3381,6 +3777,14 @@ $L$xts_magic: DD 0x87,0,1,0 $L$increment1: DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 +$L$key_rotate: + DD 0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d +$L$key_rotate192: + DD 0x04070605,0x04070605,0x04070605,0x04070605 +$L$key_rcon1: + DD 1,1,1,1 +$L$key_rcon1b: + DD 0x1b,0x1b,0x1b,0x1b DB 65,69,83,32,102,111,114,32,73,110,116,101,108,32,65,69 DB 83,45,78,73,44,32,67,82,89,80,84,79,71,65,77,83 @@ -3486,7 +3890,7 @@ cbc_se_handler: mov rax,QWORD[152+r8] mov rbx,QWORD[248+r8] - lea r10,[$L$cbc_decrypt] + lea r10,[$L$cbc_decrypt_bulk] cmp rbx,r10 jb NEAR $L$common_seh_tail diff --git a/third_party/boringssl/win-x86_64/crypto/rand/rdrand-x86_64.asm b/third_party/boringssl/win-x86_64/crypto/rand/rdrand-x86_64.asm new file mode 100644 index 0000000000000..4c03791b48efe --- /dev/null +++ b/third_party/boringssl/win-x86_64/crypto/rand/rdrand-x86_64.asm @@ -0,0 +1,70 @@ +default rel +%define XMMWORD +%define YMMWORD +%define ZMMWORD +section .text code align=64 + + + + + +global CRYPTO_rdrand + +ALIGN 16 +CRYPTO_rdrand: + mov QWORD[8+rsp],rdi ;WIN64 prologue + mov QWORD[16+rsp],rsi + mov rax,rsp +$L$SEH_begin_CRYPTO_rdrand: + mov rdi,rcx + + + xor rax,rax + + +DB 0x48,0x0f,0xc7,0xf1 + + adc rax,rax + mov QWORD[rdi],rcx + mov rdi,QWORD[8+rsp] ;WIN64 epilogue + mov rsi,QWORD[16+rsp] + DB 0F3h,0C3h ;repret + + + + + +global CRYPTO_rdrand_multiple8_buf + +ALIGN 16 +CRYPTO_rdrand_multiple8_buf: + mov QWORD[8+rsp],rdi ;WIN64 prologue + mov QWORD[16+rsp],rsi + mov rax,rsp +$L$SEH_begin_CRYPTO_rdrand_multiple8_buf: + mov rdi,rcx + mov rsi,rdx + + + test rsi,rsi + jz NEAR $L$out + mov rdx,8 +$L$loop: + + +DB 0x48,0x0f,0xc7,0xf1 + jnc NEAR $L$err + mov QWORD[rdi],rcx + add rdi,rdx + sub rsi,rdx + jnz NEAR $L$loop +$L$out: + mov rax,1 + mov rdi,QWORD[8+rsp] ;WIN64 epilogue + mov rsi,QWORD[16+rsp] + DB 0F3h,0C3h ;repret +$L$err: + xor rax,rax + mov rdi,QWORD[8+rsp] ;WIN64 epilogue + mov rsi,QWORD[16+rsp] + DB 0F3h,0C3h ;repret diff --git a/third_party/brotli/BUILD.gn b/third_party/brotli/BUILD.gn index 11f2871e9d430..8e1c111260ed1 100644 --- a/third_party/brotli/BUILD.gn +++ b/third_party/brotli/BUILD.gn @@ -15,6 +15,8 @@ source_set("brotli") { "dec/prefix.h", "dec/safe_malloc.c", "dec/safe_malloc.h", + "dec/state.c", + "dec/state.h", "dec/streams.c", "dec/streams.h", "dec/transform.h", @@ -24,5 +26,13 @@ source_set("brotli") { configs -= [ "//build/config/compiler:chromium_code" ] configs += [ "//build/config/compiler:no_chromium_code" ] + # Since we are never debug brotli, freeze the optimizations to -O2. + if (is_debug) { + configs -= [ "//build/config/compiler:no_optimize" ] + } else { + configs -= [ "//build/config/compiler:optimize" ] + } + configs += [ "//build/config/compiler:optimize_max" ] + include_dirs = [ "dec" ] } diff --git a/third_party/brotli/README.chromium b/third_party/brotli/README.chromium index 855ec12735611..2a2fe66d756be 100644 --- a/third_party/brotli/README.chromium +++ b/third_party/brotli/README.chromium @@ -1,6 +1,6 @@ Name: Brotli URL: https://github.com/google/brotli -Version: 35cd3db9c1728ad26a2e46cb401e7a14424cb481 +Version: ec03509d6d5d18a57afe1254e713b6787ef1c516 License: Apache 2.0 License File: LICENSE Security Critical: yes diff --git a/third_party/brotli/brotli.gyp b/third_party/brotli/brotli.gyp index e09f0c6cdbad6..9c47b1fa607e0 100644 --- a/third_party/brotli/brotli.gyp +++ b/third_party/brotli/brotli.gyp @@ -22,11 +22,19 @@ 'dec/prefix.h', 'dec/safe_malloc.c', 'dec/safe_malloc.h', + 'dec/state.c', + 'dec/state.h', 'dec/streams.c', 'dec/streams.h', 'dec/transform.h', 'dec/types.h', ], + 'conditions': [ + ['os_posix==1 and (target_arch=="arm" or target_arch=="armv7" or target_arch=="arm64")', { + 'cflags!': ['-Os'], + 'cflags': ['-O2'], + }], + ], }, ], } diff --git a/third_party/brotli/dec/Makefile b/third_party/brotli/dec/Makefile index 0b85c654e8aeb..5a1fcd05c3336 100644 --- a/third_party/brotli/dec/Makefile +++ b/third_party/brotli/dec/Makefile @@ -2,9 +2,9 @@ include ../shared.mk -CPPFLAGS += -Wall +CFLAGS += -Wall -OBJS = bit_reader.o decode.o huffman.o safe_malloc.o streams.o +OBJS = bit_reader.o decode.o huffman.o safe_malloc.o state.o streams.o all : $(OBJS) diff --git a/third_party/brotli/dec/bit_reader.c b/third_party/brotli/dec/bit_reader.c index 981dccf5e6723..8369397e6a927 100644 --- a/third_party/brotli/dec/bit_reader.c +++ b/third_party/brotli/dec/bit_reader.c @@ -11,10 +11,10 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - - Bit reading helpers */ +/* Bit reading helpers */ + #include #include @@ -24,10 +24,13 @@ extern "C" { #endif -int BrotliInitBitReader(BrotliBitReader* const br, BrotliInput input) { - size_t i; +void BrotliInitBitReader(BrotliBitReader* const br, + BrotliInput input, int finish) { assert(br != NULL); + br->finish_ = finish; + br->tmp_bytes_read_ = 0; + br->buf_ptr_ = br->buf_; br->input_ = input; br->val_ = 0; @@ -35,6 +38,12 @@ int BrotliInitBitReader(BrotliBitReader* const br, BrotliInput input) { br->bit_pos_ = 0; br->bit_end_pos_ = 0; br->eos_ = 0; +} + + +int BrotliWarmupBitReader(BrotliBitReader* const br) { + size_t i; + if (!BrotliReadMoreInput(br)) { return 0; } diff --git a/third_party/brotli/dec/bit_reader.h b/third_party/brotli/dec/bit_reader.h index 4b2a199c2c324..84cddb4ff8920 100644 --- a/third_party/brotli/dec/bit_reader.h +++ b/third_party/brotli/dec/bit_reader.h @@ -11,10 +11,10 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - - Bit reading helpers */ +/* Bit reading helpers */ + #ifndef BROTLI_DEC_BIT_READER_H_ #define BROTLI_DEC_BIT_READER_H_ @@ -26,6 +26,12 @@ extern "C" { #endif +#if (defined(__x86_64__) || defined(_M_X64)) +/* This should be set to 1 only on little-endian machines. */ +#define BROTLI_USE_64_BITS 1 +#else +#define BROTLI_USE_64_BITS 0 +#endif #define BROTLI_MAX_NUM_BIT_READ 25 #define BROTLI_READ_SIZE 4096 #define BROTLI_IBUF_SIZE (2 * BROTLI_READ_SIZE + 32) @@ -45,14 +51,32 @@ typedef struct { uint8_t buf_[BROTLI_IBUF_SIZE]; uint8_t* buf_ptr_; /* next input will write here */ BrotliInput input_; /* input callback */ +#if (BROTLI_USE_64_BITS) uint64_t val_; /* pre-fetched bits */ +#else + uint32_t val_; /* pre-fetched bits */ +#endif uint32_t pos_; /* byte position in stream */ uint32_t bit_pos_; /* current bit-reading position in val_ */ uint32_t bit_end_pos_; /* bit-reading end position from LSB of val_ */ int eos_; /* input stream is finished */ + + /* Set to 0 to support partial data streaming. Set to 1 to expect full data or + for the last chunk of partial data. */ + int finish_; + /* indicates how much bytes already read when reading partial data */ + int tmp_bytes_read_; } BrotliBitReader; -int BrotliInitBitReader(BrotliBitReader* const br, BrotliInput input); +/* Initializes the bitreader fields. After this, BrotliWarmupBitReader must + be used. */ +void BrotliInitBitReader(BrotliBitReader* const br, + BrotliInput input, int finish); + +/* Fetches data to fill up internal buffers. Returns 0 if there wasn't enough */ +/* data to read. It then buffers the read data and can be called again with */ +/* more data. If br->finish_ is 1, never fails. */ +int BrotliWarmupBitReader(BrotliBitReader* const br); /* Return the prefetched bits, so they can be looked up. */ static BROTLI_INLINE uint32_t BrotliPrefetchBits(BrotliBitReader* const br) { @@ -72,11 +96,14 @@ static BROTLI_INLINE void BrotliSetBitPos(BrotliBitReader* const br, br->bit_pos_ = val; } -/* Reload up to 64 bits byte-by-byte */ -static BROTLI_INLINE void ShiftBytes(BrotliBitReader* const br) { +/* + * Reload up to 32 bits byte-by-byte. + * This function works on both little and big endian. + */ +static BROTLI_INLINE void ShiftBytes32(BrotliBitReader* const br) { while (br->bit_pos_ >= 8) { br->val_ >>= 8; - br->val_ |= ((uint64_t)br->buf_[br->pos_ & BROTLI_IBUF_MASK]) << 56; + br->val_ |= ((uint32_t)br->buf_[br->pos_ & BROTLI_IBUF_MASK]) << 24; ++br->pos_; br->bit_pos_ -= 8; br->bit_end_pos_ -= 8; @@ -87,9 +114,12 @@ static BROTLI_INLINE void ShiftBytes(BrotliBitReader* const br) { Does nothing if there are at least 32 bytes present after current position. - Returns 0 if either: + Returns 0 if one of: - the input callback returned an error, or - there is no more input and the position is past the end of the stream. + - finish is false and less than BROTLI_READ_SIZE are available - a next call + when more data is available makes it continue including the partially read + data After encountering the end of the input stream, 32 additional zero bytes are copied to the ringbuffer, therefore it is safe to call this function after @@ -102,14 +132,21 @@ static BROTLI_INLINE int BrotliReadMoreInput(BrotliBitReader* const br) { return br->bit_pos_ <= br->bit_end_pos_; } else { uint8_t* dst = br->buf_ptr_; - int bytes_read = BrotliRead(br->input_, dst, BROTLI_READ_SIZE); + int bytes_read = BrotliRead(br->input_, dst + br->tmp_bytes_read_, + (size_t) (BROTLI_READ_SIZE - br->tmp_bytes_read_)); if (bytes_read < 0) { return 0; } + bytes_read += br->tmp_bytes_read_; + br->tmp_bytes_read_ = 0; if (bytes_read < BROTLI_READ_SIZE) { + if (!br->finish_) { + br->tmp_bytes_read_ = bytes_read; + return 0; + } br->eos_ = 1; /* Store 32 bytes of zero after the stream end. */ -#if (defined(__x86_64__) || defined(_M_X64)) +#if (BROTLI_USE_64_BITS) *(uint64_t*)(dst + bytes_read) = 0; *(uint64_t*)(dst + bytes_read + 8) = 0; *(uint64_t*)(dst + bytes_read + 16) = 0; @@ -120,7 +157,7 @@ static BROTLI_INLINE int BrotliReadMoreInput(BrotliBitReader* const br) { } if (dst == br->buf_) { /* Copy the head of the ringbuffer to the slack region. */ -#if (defined(__x86_64__) || defined(_M_X64)) +#if (BROTLI_USE_64_BITS) UNALIGNED_COPY64(br->buf_ + BROTLI_IBUF_SIZE - 32, br->buf_); UNALIGNED_COPY64(br->buf_ + BROTLI_IBUF_SIZE - 24, br->buf_ + 8); UNALIGNED_COPY64(br->buf_ + BROTLI_IBUF_SIZE - 16, br->buf_ + 16); @@ -137,30 +174,45 @@ static BROTLI_INLINE int BrotliReadMoreInput(BrotliBitReader* const br) { } } -/* Advances the Read buffer by 5 bytes to make room for reading next 24 bits. */ +/* Guarantees that there are at least 24 bits in the buffer. */ static BROTLI_INLINE void BrotliFillBitWindow(BrotliBitReader* const br) { +#if (BROTLI_USE_64_BITS) if (br->bit_pos_ >= 40) { -#if (defined(__x86_64__) || defined(_M_X64)) + /* + * Advances the Read buffer by 5 bytes to make room for reading next + * 24 bits. + * The expression below needs a little-endian arch to work correctly. + * This gives a large speedup for decoding speed. + */ br->val_ >>= 40; - /* The expression below needs a little-endian arch to work correctly. */ - /* This gives a large speedup for decoding speed. */ br->val_ |= *(const uint64_t*)( br->buf_ + (br->pos_ & BROTLI_IBUF_MASK)) << 24; br->pos_ += 5; br->bit_pos_ -= 40; br->bit_end_pos_ -= 40; + } #else - ShiftBytes(br); + ShiftBytes32(br); #endif - } } /* Reads the specified number of bits from Read Buffer. */ static BROTLI_INLINE uint32_t BrotliReadBits( BrotliBitReader* const br, int n_bits) { uint32_t val; +#if (BROTLI_USE_64_BITS) BrotliFillBitWindow(br); val = (uint32_t)(br->val_ >> br->bit_pos_) & kBitMask[n_bits]; +#else + /* + * The if statement gives 2-4% speed boost on Canterbury data set with + * asm.js/firefox/x86-64. + */ + if ((32 - br->bit_pos_) < ((uint32_t) n_bits)) { + BrotliFillBitWindow(br); + } + val = (br->val_ >> br->bit_pos_) & kBitMask[n_bits]; +#endif #ifdef BROTLI_DECODE_DEBUG printf("[BrotliReadBits] %010d %2d val: %6x\n", (br->pos_ << 3) + br->bit_pos_ - 64, n_bits, val); diff --git a/third_party/brotli/dec/context.h b/third_party/brotli/dec/context.h index dbc0c3649dbb7..c0e4bbc7dfc8a 100644 --- a/third_party/brotli/dec/context.h +++ b/third_party/brotli/dec/context.h @@ -11,8 +11,9 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +*/ - Lookup table to map the previous two bytes to a context id. +/* Lookup table to map the previous two bytes to a context id. There are four different context modeling modes defined here: CONTEXT_LSB6: context id is the least significant 6 bits of the last byte, diff --git a/third_party/brotli/dec/decode.c b/third_party/brotli/dec/decode.c index ca114c61c1905..674dbfb5667f1 100644 --- a/third_party/brotli/dec/decode.c +++ b/third_party/brotli/dec/decode.c @@ -50,9 +50,6 @@ static const int kDistanceContextBits = 2; #define HUFFMAN_TABLE_BITS 8 #define HUFFMAN_TABLE_MASK 0xff -/* Maximum possible Huffman table size for an alphabet size of 704, max code - * length 15 and root table bits 8. */ -#define HUFFMAN_MAX_TABLE_SIZE 1080 #define CODE_LENGTH_CODES 18 static const uint8_t kCodeLengthCodeOrder[CODE_LENGTH_CODES] = { @@ -89,26 +86,61 @@ static BROTLI_INLINE int DecodeVarLenUint8(BrotliBitReader* br) { return 0; } -static void DecodeMetaBlockLength(BrotliBitReader* br, - int* meta_block_length, - int* input_end, - int* is_uncompressed) { +/* Advances the bit reader position to the next byte boundary and verifies + that any skipped bits are set to zero. */ +static BROTLI_INLINE int JumpToByteBoundary(BrotliBitReader* br) { + uint32_t new_bit_pos = (br->bit_pos_ + 7) & (uint32_t)(~7UL); + uint32_t pad_bits = BrotliReadBits(br, (int)(new_bit_pos - br->bit_pos_)); + return pad_bits == 0; +} + +static int DecodeMetaBlockLength(BrotliBitReader* br, + int* meta_block_length, + int* input_end, + int* is_metadata, + int* is_uncompressed) { int size_nibbles; + int size_bytes; int i; *input_end = (int)BrotliReadBits(br, 1); *meta_block_length = 0; *is_uncompressed = 0; + *is_metadata = 0; if (*input_end && BrotliReadBits(br, 1)) { - return; + return 1; } size_nibbles = (int)BrotliReadBits(br, 2) + 4; - for (i = 0; i < size_nibbles; ++i) { - *meta_block_length |= (int)BrotliReadBits(br, 4) << (i * 4); + if (size_nibbles == 7) { + *is_metadata = 1; + /* Verify reserved bit. */ + if (BrotliReadBits(br, 1) != 0) { + return 0; + } + size_bytes = (int)BrotliReadBits(br, 2); + if (size_bytes == 0) { + return 1; + } + for (i = 0; i < size_bytes; ++i) { + int next_byte = (int)BrotliReadBits(br, 8); + if (i + 1 == size_bytes && size_bytes > 1 && next_byte == 0) { + return 0; + } + *meta_block_length |= next_byte << (i * 8); + } + } else { + for (i = 0; i < size_nibbles; ++i) { + int next_nibble = (int)BrotliReadBits(br, 4); + if (i + 1 == size_nibbles && size_nibbles > 4 && next_nibble == 0) { + return 0; + } + *meta_block_length |= next_nibble << (i * 4); + } } ++(*meta_block_length); - if (!*input_end) { + if (!*input_end && !*is_metadata) { *is_uncompressed = (int)BrotliReadBits(br, 1); } + return 1; } /* Decodes the next Huffman code from bit-stream. */ @@ -132,187 +164,232 @@ static void PrintUcharVector(const uint8_t* v, int len) { printf("\n"); } -static int ReadHuffmanCodeLengths( +static BrotliResult ReadHuffmanCodeLengths( const uint8_t* code_length_code_lengths, int num_symbols, uint8_t* code_lengths, - BrotliBitReader* br) { - int symbol = 0; - uint8_t prev_code_len = kDefaultCodeLength; - int repeat = 0; - uint8_t repeat_code_len = 0; - int space = 32768; - HuffmanCode table[32]; - - if (!BrotliBuildHuffmanTable(table, 5, - code_length_code_lengths, - CODE_LENGTH_CODES)) { - printf("[ReadHuffmanCodeLengths] Building code length tree failed: "); - PrintUcharVector(code_length_code_lengths, CODE_LENGTH_CODES); - return 0; - } - - while (symbol < num_symbols && space > 0) { - const HuffmanCode* p = table; - uint8_t code_len; - if (!BrotliReadMoreInput(br)) { - printf("[ReadHuffmanCodeLengths] Unexpected end of input.\n"); - return 0; - } - BrotliFillBitWindow(br); - p += (br->val_ >> br->bit_pos_) & 31; - br->bit_pos_ += p->bits; - code_len = (uint8_t)p->value; - if (code_len < kCodeLengthRepeatCode) { - repeat = 0; - code_lengths[symbol++] = code_len; - if (code_len != 0) { - prev_code_len = code_len; - space -= 32768 >> code_len; - } - } else { - const int extra_bits = code_len - 14; - int old_repeat; - int repeat_delta; - uint8_t new_len = 0; - if (code_len == kCodeLengthRepeatCode) { - new_len = prev_code_len; - } - if (repeat_code_len != new_len) { - repeat = 0; - repeat_code_len = new_len; - } - old_repeat = repeat; - if (repeat > 0) { - repeat -= 2; - repeat <<= extra_bits; + BrotliState* s) { + BrotliBitReader* br = &s->br; + switch (s->sub_state[1]) { + case BROTLI_STATE_SUB_HUFFMAN_LENGTH_BEGIN: + s->symbol = 0; + s->prev_code_len = kDefaultCodeLength; + s->repeat = 0; + s->repeat_code_len = 0; + s->space = 32768; + + if (!BrotliBuildHuffmanTable(s->table, 5, + code_length_code_lengths, + CODE_LENGTH_CODES)) { + printf("[ReadHuffmanCodeLengths] Building code length tree failed: "); + PrintUcharVector(code_length_code_lengths, CODE_LENGTH_CODES); + return BROTLI_RESULT_ERROR; } - repeat += (int)BrotliReadBits(br, extra_bits) + 3; - repeat_delta = repeat - old_repeat; - if (symbol + repeat_delta > num_symbols) { - return 0; + s->sub_state[1] = BROTLI_STATE_SUB_HUFFMAN_LENGTH_SYMBOLS; + /* No break, continue to next state. */ + case BROTLI_STATE_SUB_HUFFMAN_LENGTH_SYMBOLS: + while (s->symbol < num_symbols && s->space > 0) { + const HuffmanCode* p = s->table; + uint8_t code_len; + if (!BrotliReadMoreInput(br)) { + return BROTLI_RESULT_NEEDS_MORE_INPUT; + } + BrotliFillBitWindow(br); + p += (br->val_ >> br->bit_pos_) & 31; + br->bit_pos_ += p->bits; + code_len = (uint8_t)p->value; + if (code_len < kCodeLengthRepeatCode) { + s->repeat = 0; + code_lengths[s->symbol++] = code_len; + if (code_len != 0) { + s->prev_code_len = code_len; + s->space -= 32768 >> code_len; + } + } else { + const int extra_bits = code_len - 14; + int old_repeat; + int repeat_delta; + uint8_t new_len = 0; + if (code_len == kCodeLengthRepeatCode) { + new_len = s->prev_code_len; + } + if (s->repeat_code_len != new_len) { + s->repeat = 0; + s->repeat_code_len = new_len; + } + old_repeat = s->repeat; + if (s->repeat > 0) { + s->repeat -= 2; + s->repeat <<= extra_bits; + } + s->repeat += (int)BrotliReadBits(br, extra_bits) + 3; + repeat_delta = s->repeat - old_repeat; + if (s->symbol + repeat_delta > num_symbols) { + return BROTLI_RESULT_ERROR; + } + memset(&code_lengths[s->symbol], s->repeat_code_len, + (size_t)repeat_delta); + s->symbol += repeat_delta; + if (s->repeat_code_len != 0) { + s->space -= repeat_delta << (15 - s->repeat_code_len); + } + } } - memset(&code_lengths[symbol], repeat_code_len, (size_t)repeat_delta); - symbol += repeat_delta; - if (repeat_code_len != 0) { - space -= repeat_delta << (15 - repeat_code_len); + if (s->space != 0) { + printf("[ReadHuffmanCodeLengths] s->space = %d\n", s->space); + return BROTLI_RESULT_ERROR; } - } - } - if (space != 0) { - printf("[ReadHuffmanCodeLengths] space = %d\n", space); - return 0; + memset(&code_lengths[s->symbol], 0, (size_t)(num_symbols - s->symbol)); + s->sub_state[1] = BROTLI_STATE_SUB_NONE; + return BROTLI_RESULT_SUCCESS; + default: + return BROTLI_RESULT_ERROR; } - memset(&code_lengths[symbol], 0, (size_t)(num_symbols - symbol)); - return 1; + return BROTLI_RESULT_ERROR; } -static int ReadHuffmanCode(int alphabet_size, - HuffmanCode* table, - BrotliBitReader* br) { - int ok = 1; +static BrotliResult ReadHuffmanCode(int alphabet_size, + HuffmanCode* table, + int* opt_table_size, + BrotliState* s) { + BrotliBitReader* br = &s->br; + BrotliResult result = BROTLI_RESULT_SUCCESS; int table_size = 0; - int simple_code_or_skip; - uint8_t* code_lengths = NULL; - - code_lengths = - (uint8_t*)BrotliSafeMalloc((uint64_t)alphabet_size, - sizeof(*code_lengths)); - if (code_lengths == NULL) { - return 0; - } - if (!BrotliReadMoreInput(br)) { - printf("[ReadHuffmanCode] Unexpected end of input.\n"); - return 0; - } - /* simple_code_or_skip is used as follows: - 1 for simple code; - 0 for no skipping, 2 skips 2 code lengths, 3 skips 3 code lengths */ - simple_code_or_skip = (int)BrotliReadBits(br, 2); - BROTLI_LOG_UINT(simple_code_or_skip); - if (simple_code_or_skip == 1) { - /* Read symbols, codes & code lengths directly. */ - int i; - int max_bits_counter = alphabet_size - 1; - int max_bits = 0; - int symbols[4] = { 0 }; - const int num_symbols = (int)BrotliReadBits(br, 2) + 1; - while (max_bits_counter) { - max_bits_counter >>= 1; - ++max_bits; - } - memset(code_lengths, 0, (size_t)alphabet_size); - for (i = 0; i < num_symbols; ++i) { - symbols[i] = (int)BrotliReadBits(br, max_bits) % alphabet_size; - code_lengths[symbols[i]] = 2; - } - code_lengths[symbols[0]] = 1; - switch (num_symbols) { - case 1: - break; - case 3: - ok = ((symbols[0] != symbols[1]) && - (symbols[0] != symbols[2]) && - (symbols[1] != symbols[2])); - break; - case 2: - ok = (symbols[0] != symbols[1]); - code_lengths[symbols[1]] = 1; - break; - case 4: - ok = ((symbols[0] != symbols[1]) && - (symbols[0] != symbols[2]) && - (symbols[0] != symbols[3]) && - (symbols[1] != symbols[2]) && - (symbols[1] != symbols[3]) && - (symbols[2] != symbols[3])); - if (BrotliReadBits(br, 1)) { - code_lengths[symbols[2]] = 3; - code_lengths[symbols[3]] = 3; - } else { - code_lengths[symbols[0]] = 2; + /* State machine */ + for (;;) { + switch(s->sub_state[1]) { + case BROTLI_STATE_SUB_NONE: + if (!BrotliReadMoreInput(br)) { + return BROTLI_RESULT_NEEDS_MORE_INPUT; } - break; - } - BROTLI_LOG_UINT(num_symbols); - } else { /* Decode Huffman-coded code lengths. */ - int i; - uint8_t code_length_code_lengths[CODE_LENGTH_CODES] = { 0 }; - int space = 32; - int num_codes = 0; - /* Static Huffman code for the code length code lengths */ - static const HuffmanCode huff[16] = { - {2, 0}, {2, 4}, {2, 3}, {3, 2}, {2, 0}, {2, 4}, {2, 3}, {4, 1}, - {2, 0}, {2, 4}, {2, 3}, {3, 2}, {2, 0}, {2, 4}, {2, 3}, {4, 5}, - }; - for (i = simple_code_or_skip; i < CODE_LENGTH_CODES && space > 0; ++i) { - const int code_len_idx = kCodeLengthCodeOrder[i]; - const HuffmanCode* p = huff; - uint8_t v; - BrotliFillBitWindow(br); - p += (br->val_ >> br->bit_pos_) & 15; - br->bit_pos_ += p->bits; - v = (uint8_t)p->value; - code_length_code_lengths[code_len_idx] = v; - BROTLI_LOG_ARRAY_INDEX(code_length_code_lengths, code_len_idx); - if (v != 0) { - space -= (32 >> v); - ++num_codes; - } - } - ok = (num_codes == 1 || space == 0) && - ReadHuffmanCodeLengths(code_length_code_lengths, - alphabet_size, code_lengths, br); - } - if (ok) { - table_size = BrotliBuildHuffmanTable(table, HUFFMAN_TABLE_BITS, - code_lengths, alphabet_size); - if (table_size == 0) { - printf("[ReadHuffmanCode] BuildHuffmanTable failed: "); - PrintUcharVector(code_lengths, alphabet_size); + s->code_lengths = + (uint8_t*)BrotliSafeMalloc((uint64_t)alphabet_size, + sizeof(*s->code_lengths)); + if (s->code_lengths == NULL) { + return BROTLI_RESULT_ERROR; + } + /* simple_code_or_skip is used as follows: + 1 for simple code; + 0 for no skipping, 2 skips 2 code lengths, 3 skips 3 code lengths */ + s->simple_code_or_skip = (int)BrotliReadBits(br, 2); + BROTLI_LOG_UINT(s->simple_code_or_skip); + if (s->simple_code_or_skip == 1) { + /* Read symbols, codes & code lengths directly. */ + int i; + int max_bits_counter = alphabet_size - 1; + int max_bits = 0; + int symbols[4] = { 0 }; + const int num_symbols = (int)BrotliReadBits(br, 2) + 1; + while (max_bits_counter) { + max_bits_counter >>= 1; + ++max_bits; + } + memset(s->code_lengths, 0, (size_t)alphabet_size); + for (i = 0; i < num_symbols; ++i) { + symbols[i] = (int)BrotliReadBits(br, max_bits); + if (symbols[i] >= alphabet_size) { + return BROTLI_RESULT_ERROR; + } + s->code_lengths[symbols[i]] = 2; + } + s->code_lengths[symbols[0]] = 1; + switch (num_symbols) { + case 1: + break; + case 3: + if ((symbols[0] == symbols[1]) || + (symbols[0] == symbols[2]) || + (symbols[1] == symbols[2])) { + return BROTLI_RESULT_ERROR; + } + break; + case 2: + if (symbols[0] == symbols[1]) { + return BROTLI_RESULT_ERROR; + } + s->code_lengths[symbols[1]] = 1; + break; + case 4: + if ((symbols[0] == symbols[1]) || + (symbols[0] == symbols[2]) || + (symbols[0] == symbols[3]) || + (symbols[1] == symbols[2]) || + (symbols[1] == symbols[3]) || + (symbols[2] == symbols[3])) { + return BROTLI_RESULT_ERROR; + } + if (BrotliReadBits(br, 1)) { + s->code_lengths[symbols[2]] = 3; + s->code_lengths[symbols[3]] = 3; + } else { + s->code_lengths[symbols[0]] = 2; + } + break; + } + BROTLI_LOG_UINT(num_symbols); + s->sub_state[1] = BROTLI_STATE_SUB_HUFFMAN_DONE; + break; + } else { /* Decode Huffman-coded code lengths. */ + int i; + int space = 32; + int num_codes = 0; + /* Static Huffman code for the code length code lengths */ + static const HuffmanCode huff[16] = { + {2, 0}, {2, 4}, {2, 3}, {3, 2}, {2, 0}, {2, 4}, {2, 3}, {4, 1}, + {2, 0}, {2, 4}, {2, 3}, {3, 2}, {2, 0}, {2, 4}, {2, 3}, {4, 5}, + }; + for (i = 0; i < CODE_LENGTH_CODES; i++) { + s->code_length_code_lengths[i] = 0; + } + for (i = s->simple_code_or_skip; + i < CODE_LENGTH_CODES && space > 0; ++i) { + const int code_len_idx = kCodeLengthCodeOrder[i]; + const HuffmanCode* p = huff; + uint8_t v; + BrotliFillBitWindow(br); + p += (br->val_ >> br->bit_pos_) & 15; + br->bit_pos_ += p->bits; + v = (uint8_t)p->value; + s->code_length_code_lengths[code_len_idx] = v; + BROTLI_LOG_ARRAY_INDEX(s->code_length_code_lengths, code_len_idx); + if (v != 0) { + space -= (32 >> v); + ++num_codes; + } + } + if (!(num_codes == 1 || space == 0)) { + return BROTLI_RESULT_ERROR; + } + s->sub_state[1] = BROTLI_STATE_SUB_HUFFMAN_LENGTH_BEGIN; + } + /* No break, go to next state */ + case BROTLI_STATE_SUB_HUFFMAN_LENGTH_BEGIN: + case BROTLI_STATE_SUB_HUFFMAN_LENGTH_SYMBOLS: + result = ReadHuffmanCodeLengths(s->code_length_code_lengths, + alphabet_size, s->code_lengths, s); + if (result != BROTLI_RESULT_SUCCESS) return result; + s->sub_state[1] = BROTLI_STATE_SUB_HUFFMAN_DONE; + /* No break, go to next state */ + case BROTLI_STATE_SUB_HUFFMAN_DONE: + table_size = BrotliBuildHuffmanTable(table, HUFFMAN_TABLE_BITS, + s->code_lengths, alphabet_size); + if (table_size == 0) { + printf("[ReadHuffmanCode] BuildHuffmanTable failed: "); + PrintUcharVector(s->code_lengths, alphabet_size); + return BROTLI_RESULT_ERROR; + } + free(s->code_lengths); + s->code_lengths = NULL; + if (opt_table_size) { + *opt_table_size = table_size; + } + s->sub_state[1] = BROTLI_STATE_SUB_NONE; + return result; + default: + return BROTLI_RESULT_ERROR; /* unknown state */ } } - free(code_lengths); - return table_size; + + return BROTLI_RESULT_ERROR; } static BROTLI_INLINE int ReadBlockLength(const HuffmanCode* table, @@ -336,13 +413,6 @@ static int TranslateShortCodes(int code, int* ringbuffer, int index) { return val; } -static void MoveToFront(uint8_t* v, uint8_t index) { - uint8_t value = v[index]; - uint8_t i = index; - for (; i; --i) v[i] = v[i - 1]; - v[0] = value; -} - static void InverseMoveToFrontTransform(uint8_t* v, int v_len) { uint8_t mtf[256]; int i; @@ -351,124 +421,130 @@ static void InverseMoveToFrontTransform(uint8_t* v, int v_len) { } for (i = 0; i < v_len; ++i) { uint8_t index = v[i]; - v[i] = mtf[index]; - if (index) MoveToFront(mtf, index); + uint8_t value = mtf[index]; + v[i] = value; + for (; index; --index) { + mtf[index] = mtf[index - 1]; + } + mtf[0] = value; } } -/* Contains a collection of huffman trees with the same alphabet size. */ -typedef struct { - int alphabet_size; - int num_htrees; - HuffmanCode* codes; - HuffmanCode** htrees; -} HuffmanTreeGroup; - -static void HuffmanTreeGroupInit(HuffmanTreeGroup* group, int alphabet_size, - int ntrees) { - group->alphabet_size = alphabet_size; - group->num_htrees = ntrees; - group->codes = (HuffmanCode*)malloc( - sizeof(HuffmanCode) * (size_t)(ntrees * HUFFMAN_MAX_TABLE_SIZE)); - group->htrees = (HuffmanCode**)malloc(sizeof(HuffmanCode*) * (size_t)ntrees); -} - -static void HuffmanTreeGroupRelease(HuffmanTreeGroup* group) { - if (group->codes) { - free(group->codes); - } - if (group->htrees) { - free(group->htrees); +static BrotliResult HuffmanTreeGroupDecode(HuffmanTreeGroup* group, + BrotliState* s) { + switch (s->sub_state[0]) { + case BROTLI_STATE_SUB_NONE: + s->next = group->codes; + s->htree_index = 0; + s->sub_state[0] = BROTLI_STATE_SUB_TREE_GROUP; + /* No break, continue to next state. */ + case BROTLI_STATE_SUB_TREE_GROUP: + while (s->htree_index < group->num_htrees) { + int table_size; + BrotliResult result = + ReadHuffmanCode(group->alphabet_size, s->next, &table_size, s); + if (result != BROTLI_RESULT_SUCCESS) return result; + group->htrees[s->htree_index] = s->next; + s->next += table_size; + if (table_size == 0) { + return BROTLI_RESULT_ERROR; + } + ++s->htree_index; + } + s->sub_state[0] = BROTLI_STATE_SUB_NONE; + return BROTLI_RESULT_SUCCESS; + default: + return BROTLI_RESULT_ERROR; /* unknown state */ } -} -static int HuffmanTreeGroupDecode(HuffmanTreeGroup* group, - BrotliBitReader* br) { - int i; - int table_size; - HuffmanCode* next = group->codes; - for (i = 0; i < group->num_htrees; ++i) { - group->htrees[i] = next; - table_size = ReadHuffmanCode(group->alphabet_size, next, br); - next += table_size; - if (table_size == 0) { - return 0; - } - } - return 1; + return BROTLI_RESULT_ERROR; } -static int DecodeContextMap(int context_map_size, - int* num_htrees, - uint8_t** context_map, - BrotliBitReader* br) { - int ok = 1; +static BrotliResult DecodeContextMap(int context_map_size, + int* num_htrees, + uint8_t** context_map, + BrotliState* s) { + BrotliBitReader* br = &s->br; + BrotliResult result = BROTLI_RESULT_SUCCESS; int use_rle_for_zeros; - int max_run_length_prefix = 0; - HuffmanCode* table; - int i; - if (!BrotliReadMoreInput(br)) { - printf("[DecodeContextMap] Unexpected end of input.\n"); - return 0; - } - *num_htrees = DecodeVarLenUint8(br) + 1; - BROTLI_LOG_UINT(context_map_size); - BROTLI_LOG_UINT(*num_htrees); + switch(s->sub_state[0]) { + case BROTLI_STATE_SUB_NONE: + if (!BrotliReadMoreInput(br)) { + return BROTLI_RESULT_NEEDS_MORE_INPUT; + } + *num_htrees = DecodeVarLenUint8(br) + 1; - *context_map = (uint8_t*)malloc((size_t)context_map_size); - if (*context_map == 0) { - return 0; - } - if (*num_htrees <= 1) { - memset(*context_map, 0, (size_t)context_map_size); - return 1; - } + s->context_index = 0; - use_rle_for_zeros = (int)BrotliReadBits(br, 1); - if (use_rle_for_zeros) { - max_run_length_prefix = (int)BrotliReadBits(br, 4) + 1; - } - table = (HuffmanCode*)malloc(HUFFMAN_MAX_TABLE_SIZE * sizeof(*table)); - if (table == NULL) { - return 0; - } - if (!ReadHuffmanCode(*num_htrees + max_run_length_prefix, table, br)) { - ok = 0; - goto End; - } - for (i = 0; i < context_map_size;) { - int code; - if (!BrotliReadMoreInput(br)) { - printf("[DecodeContextMap] Unexpected end of input.\n"); - ok = 0; - goto End; - } - code = ReadSymbol(table, br); - if (code == 0) { - (*context_map)[i] = 0; - ++i; - } else if (code <= max_run_length_prefix) { - int reps = 1 + (1 << code) + (int)BrotliReadBits(br, code); - while (--reps) { - if (i >= context_map_size) { - ok = 0; - goto End; - } - (*context_map)[i] = 0; - ++i; + BROTLI_LOG_UINT(context_map_size); + BROTLI_LOG_UINT(*num_htrees); + + *context_map = (uint8_t*)malloc((size_t)context_map_size); + if (*context_map == 0) { + return BROTLI_RESULT_ERROR; } - } else { - (*context_map)[i] = (uint8_t)(code - max_run_length_prefix); - ++i; - } - } - if (BrotliReadBits(br, 1)) { - InverseMoveToFrontTransform(*context_map, context_map_size); + if (*num_htrees <= 1) { + memset(*context_map, 0, (size_t)context_map_size); + return BROTLI_RESULT_SUCCESS; + } + + use_rle_for_zeros = (int)BrotliReadBits(br, 1); + if (use_rle_for_zeros) { + s->max_run_length_prefix = (int)BrotliReadBits(br, 4) + 1; + } else { + s->max_run_length_prefix = 0; + } + s->context_map_table = (HuffmanCode*)malloc( + BROTLI_HUFFMAN_MAX_TABLE_SIZE * sizeof(*s->context_map_table)); + if (s->context_map_table == NULL) { + return BROTLI_RESULT_ERROR; + } + s->sub_state[0] = BROTLI_STATE_SUB_CONTEXT_MAP_HUFFMAN; + /* No break, continue to next state. */ + case BROTLI_STATE_SUB_CONTEXT_MAP_HUFFMAN: + result = ReadHuffmanCode(*num_htrees + s->max_run_length_prefix, + s->context_map_table, NULL, s); + if (result != BROTLI_RESULT_SUCCESS) return result; + s->sub_state[0] = BROTLI_STATE_SUB_CONTEXT_MAPS; + /* No break, continue to next state. */ + case BROTLI_STATE_SUB_CONTEXT_MAPS: + while (s->context_index < context_map_size) { + int code; + if (!BrotliReadMoreInput(br)) { + return BROTLI_RESULT_NEEDS_MORE_INPUT; + } + code = ReadSymbol(s->context_map_table, br); + if (code == 0) { + (*context_map)[s->context_index] = 0; + ++s->context_index; + } else if (code <= s->max_run_length_prefix) { + int reps = 1 + (1 << code) + (int)BrotliReadBits(br, code); + while (--reps) { + if (s->context_index >= context_map_size) { + return BROTLI_RESULT_ERROR; + } + (*context_map)[s->context_index] = 0; + ++s->context_index; + } + } else { + (*context_map)[s->context_index] = + (uint8_t)(code - s->max_run_length_prefix); + ++s->context_index; + } + } + if (BrotliReadBits(br, 1)) { + InverseMoveToFrontTransform(*context_map, context_map_size); + } + free(s->context_map_table); + s->context_map_table = NULL; + s->sub_state[0] = BROTLI_STATE_SUB_NONE; + return BROTLI_RESULT_SUCCESS; + default: + return BROTLI_RESULT_ERROR; /* unknown state */ } -End: - free(table); - return ok; + + return BROTLI_RESULT_ERROR; } static BROTLI_INLINE void DecodeBlockType(const int max_block_type, @@ -480,7 +556,8 @@ static BROTLI_INLINE void DecodeBlockType(const int max_block_type, BrotliBitReader* br) { int* ringbuffer = ringbuffers + tree_type * 2; int* index = indexes + tree_type; - int type_code = ReadSymbol(&trees[tree_type * HUFFMAN_MAX_TABLE_SIZE], br); + int type_code = + ReadSymbol(&trees[tree_type * BROTLI_HUFFMAN_MAX_TABLE_SIZE], br); int block_type; if (type_code == 0) { block_type = ringbuffer[*index & 1]; @@ -497,6 +574,22 @@ static BROTLI_INLINE void DecodeBlockType(const int max_block_type, ++(*index); } +/* Decodes the block type and updates the state for literal context. */ +static BROTLI_INLINE void DecodeBlockTypeWithContext(BrotliState* s, + BrotliBitReader* br) { + DecodeBlockType(s->num_block_types[0], + s->block_type_trees, 0, + s->block_type, s->block_type_rb, + s->block_type_rb_index, br); + s->block_length[0] = ReadBlockLength(s->block_len_trees, br); + s->context_offset = s->block_type[0] << kLiteralContextBits; + s->context_map_slice = s->context_map + s->context_offset; + s->literal_htree_index = s->context_map_slice[0]; + s->context_mode = s->context_modes[s->block_type[0]]; + s->context_lookup_offset1 = kContextLookupOffsets[s->context_mode]; + s->context_lookup_offset2 = kContextLookupOffsets[s->context_mode + 1]; +} + /* Copy len bytes from src to dst. It can write up to ten extra bytes after the end of the copy. @@ -545,95 +638,178 @@ static BROTLI_INLINE void IncrementalCopyFastPath( } } -int CopyUncompressedBlockToOutput(BrotliOutput output, int len, int pos, - uint8_t* ringbuffer, int ringbuffer_mask, - BrotliBitReader* br) { - const int rb_size = ringbuffer_mask + 1; - uint8_t* ringbuffer_end = ringbuffer + rb_size; - int rb_pos = pos & ringbuffer_mask; - int br_pos = br->pos_ & BROTLI_IBUF_MASK; - int nbytes; - - /* For short lengths copy byte-by-byte */ - if (len < 8 || br->bit_pos_ + (uint32_t)(len << 3) < br->bit_end_pos_) { - while (len-- > 0) { - if (!BrotliReadMoreInput(br)) { - return 0; - } - ringbuffer[rb_pos++]= (uint8_t)BrotliReadBits(br, 8); - if (rb_pos == rb_size) { - if (BrotliWrite(output, ringbuffer, (size_t)rb_size) < rb_size) { - return 0; +BrotliResult CopyUncompressedBlockToOutput(BrotliOutput output, + int pos, + BrotliState* s) { + const int rb_size = s->ringbuffer_mask + 1; + uint8_t* ringbuffer_end = s->ringbuffer + rb_size; + int rb_pos = pos & s->ringbuffer_mask; + int br_pos = s->br.pos_ & BROTLI_IBUF_MASK; + uint32_t remaining_bits; + int num_read; + int num_written; + + /* State machine */ + for (;;) { + switch (s->sub_state[0]) { + case BROTLI_STATE_SUB_NONE: + /* For short lengths copy byte-by-byte */ + if (s->meta_block_remaining_len < 8 || s->br.bit_pos_ + + (uint32_t)(s->meta_block_remaining_len << 3) < s->br.bit_end_pos_) { + s->sub_state[0] = BROTLI_STATE_SUB_UNCOMPRESSED_SHORT; + break; + } + if (s->br.bit_end_pos_ < 64) { + return BROTLI_RESULT_ERROR; + } + /* + * Copy remaining 0-4 in 32-bit case or 0-8 bytes in the 64-bit case + * from s->br.val_ to ringbuffer. + */ +#if (BROTLI_USE_64_BITS) + remaining_bits = 64; +#else + remaining_bits = 32; +#endif + while (s->br.bit_pos_ < remaining_bits) { + s->ringbuffer[rb_pos] = (uint8_t)(s->br.val_ >> s->br.bit_pos_); + s->br.bit_pos_ += 8; + ++rb_pos; + --s->meta_block_remaining_len; } - rb_pos = 0; - } - } - return 1; - } - - if (br->bit_end_pos_ < 64) { - return 0; - } - - /* Copy remaining 0-8 bytes from br->val_ to ringbuffer. */ - while (br->bit_pos_ < 64) { - ringbuffer[rb_pos] = (uint8_t)(br->val_ >> br->bit_pos_); - br->bit_pos_ += 8; - ++rb_pos; - --len; - } - /* Copy remaining bytes from br->buf_ to ringbuffer. */ - nbytes = (int)(br->bit_end_pos_ - br->bit_pos_) >> 3; - if (br_pos + nbytes > BROTLI_IBUF_MASK) { - int tail = BROTLI_IBUF_MASK + 1 - br_pos; - memcpy(&ringbuffer[rb_pos], &br->buf_[br_pos], (size_t)tail); - nbytes -= tail; - rb_pos += tail; - len -= tail; - br_pos = 0; - } - memcpy(&ringbuffer[rb_pos], &br->buf_[br_pos], (size_t)nbytes); - rb_pos += nbytes; - len -= nbytes; - - /* If we wrote past the logical end of the ringbuffer, copy the tail of the - ringbuffer to its beginning and flush the ringbuffer to the output. */ - if (rb_pos >= rb_size) { - if (BrotliWrite(output, ringbuffer, (size_t)rb_size) < rb_size) { - return 0; - } - rb_pos -= rb_size; - memcpy(ringbuffer, ringbuffer_end, (size_t)rb_pos); - } + /* Copy remaining bytes from s->br.buf_ to ringbuffer. */ + s->nbytes = (int)(s->br.bit_end_pos_ - s->br.bit_pos_) >> 3; + if (br_pos + s->nbytes > BROTLI_IBUF_MASK) { + int tail = BROTLI_IBUF_MASK + 1 - br_pos; + memcpy(&s->ringbuffer[rb_pos], &s->br.buf_[br_pos], (size_t)tail); + s->nbytes -= tail; + rb_pos += tail; + s->meta_block_remaining_len -= tail; + br_pos = 0; + } + memcpy(&s->ringbuffer[rb_pos], &s->br.buf_[br_pos], (size_t)s->nbytes); + rb_pos += s->nbytes; + s->meta_block_remaining_len -= s->nbytes; + + s->partially_written = 0; + s->sub_state[0] = BROTLI_STATE_SUB_UNCOMPRESSED_WRITE_1; + /* No break, continue to next state */ + case BROTLI_STATE_SUB_UNCOMPRESSED_WRITE_1: + /* If we wrote past the logical end of the ringbuffer, copy the tail of + the ringbuffer to its beginning and flush the ringbuffer to the + output. */ + if (rb_pos >= rb_size) { + num_written = BrotliWrite(output, + s->ringbuffer + s->partially_written, + (size_t)(rb_size - s->partially_written)); + if (num_written < 0) { + return BROTLI_RESULT_ERROR; + } + s->partially_written += num_written; + if (s->partially_written < rb_size) { + return BROTLI_RESULT_NEEDS_MORE_OUTPUT; + } + rb_pos -= rb_size; + s->meta_block_remaining_len += rb_size; + memcpy(s->ringbuffer, ringbuffer_end, (size_t)rb_pos); + } + s->sub_state[0] = BROTLI_STATE_SUB_UNCOMPRESSED_FILL; + break; + case BROTLI_STATE_SUB_UNCOMPRESSED_SHORT: + while (s->meta_block_remaining_len > 0) { + if (!BrotliReadMoreInput(&s->br)) { + return BROTLI_RESULT_NEEDS_MORE_INPUT; + } + s->ringbuffer[rb_pos++] = (uint8_t)BrotliReadBits(&s->br, 8); + if (rb_pos == rb_size) { + s->partially_written = 0; + s->sub_state[0] = BROTLI_STATE_SUB_UNCOMPRESSED_WRITE_2; + break; + } + s->meta_block_remaining_len--; + } + if (s->sub_state[0] == BROTLI_STATE_SUB_UNCOMPRESSED_SHORT) { + s->sub_state[0] = BROTLI_STATE_SUB_NONE; + return BROTLI_RESULT_SUCCESS; + } + /* No break, if state is updated, continue to next state */ + case BROTLI_STATE_SUB_UNCOMPRESSED_WRITE_2: + num_written = BrotliWrite(output, s->ringbuffer + s->partially_written, + (size_t)(rb_size - s->partially_written)); + if (num_written < 0) { + return BROTLI_RESULT_ERROR; + } + s->partially_written += num_written; + if (s->partially_written < rb_size) { + return BROTLI_RESULT_NEEDS_MORE_OUTPUT; + } + rb_pos = 0; + s->meta_block_remaining_len--; + s->sub_state[0] = BROTLI_STATE_SUB_UNCOMPRESSED_SHORT; + break; + case BROTLI_STATE_SUB_UNCOMPRESSED_FILL: + /* If we have more to copy than the remaining size of the ringbuffer, + then we first fill the ringbuffer from the input and then flush the + ringbuffer to the output */ + if (rb_pos + s->meta_block_remaining_len >= rb_size) { + s->nbytes = rb_size - rb_pos; + if (BrotliRead(s->br.input_, &s->ringbuffer[rb_pos], + (size_t)s->nbytes) < s->nbytes) { + return BROTLI_RESULT_NEEDS_MORE_INPUT; + } + s->partially_written = 0; + s->sub_state[0] = BROTLI_STATE_SUB_UNCOMPRESSED_WRITE_3; + } else { + s->sub_state[0] = BROTLI_STATE_SUB_UNCOMPRESSED_COPY; + break; + } + /* No break, continue to next state */ + case BROTLI_STATE_SUB_UNCOMPRESSED_WRITE_3: + num_written = BrotliWrite(output, s->ringbuffer + s->partially_written, + (size_t)(rb_size - s->partially_written)); + if (num_written < 0) { + return BROTLI_RESULT_ERROR; + } + s->partially_written += num_written; + if (s->partially_written < rb_size) { + return BROTLI_RESULT_NEEDS_MORE_OUTPUT; + } + s->meta_block_remaining_len -= s->nbytes; + rb_pos = 0; + s->sub_state[0] = BROTLI_STATE_SUB_UNCOMPRESSED_FILL; + break; + case BROTLI_STATE_SUB_UNCOMPRESSED_COPY: + /* Copy straight from the input onto the ringbuffer. The ringbuffer will + be flushed to the output at a later time. */ + num_read = BrotliRead(s->br.input_, &s->ringbuffer[rb_pos], + (size_t)s->meta_block_remaining_len); + s->meta_block_remaining_len -= num_read; + if (s->meta_block_remaining_len > 0) { + return BROTLI_RESULT_NEEDS_MORE_INPUT; + } - /* If we have more to copy than the remaining size of the ringbuffer, then we - first fill the ringbuffer from the input and then flush the ringbuffer to - the output */ - while (rb_pos + len >= rb_size) { - nbytes = rb_size - rb_pos; - if (BrotliRead(br->input_, &ringbuffer[rb_pos], (size_t)nbytes) < nbytes || - BrotliWrite(output, ringbuffer, (size_t)rb_size) < nbytes) { - return 0; + /* Restore the state of the bit reader. */ + BrotliInitBitReader(&s->br, s->br.input_, s->br.finish_); + s->sub_state[0] = BROTLI_STATE_SUB_UNCOMPRESSED_WARMUP; + /* No break, continue to next state */ + case BROTLI_STATE_SUB_UNCOMPRESSED_WARMUP: + if (!BrotliWarmupBitReader(&s->br)) { + return BROTLI_RESULT_NEEDS_MORE_INPUT; + } + s->sub_state[0] = BROTLI_STATE_SUB_NONE; + return BROTLI_RESULT_SUCCESS; + break; + default: + return BROTLI_RESULT_ERROR; /* Unknown state */ } - len -= nbytes; - rb_pos = 0; } - - /* Copy straight from the input onto the ringbuffer. The ringbuffer will be - flushed to the output at a later time. */ - if (BrotliRead(br->input_, &ringbuffer[rb_pos], (size_t)len) < len) { - return 0; - } - - /* Restore the state of the bit reader. */ - BrotliInitBitReader(br, br->input_); - return 1; + return BROTLI_RESULT_ERROR; } -int BrotliDecompressedSize(size_t encoded_size, - const uint8_t* encoded_buffer, - size_t* decoded_size) { +BrotliResult BrotliDecompressedSize(size_t encoded_size, + const uint8_t* encoded_buffer, + size_t* decoded_size) { int i; uint64_t val = 0; int bit_pos = 0; @@ -642,7 +818,7 @@ int BrotliDecompressedSize(size_t encoded_size, int size_nibbles; int meta_block_len = 0; if (encoded_size == 0) { - return 0; + return BROTLI_RESULT_ERROR; } /* Look at the first 8 bytes, it is enough to decode the length of the first meta-block. */ @@ -658,7 +834,7 @@ int BrotliDecompressedSize(size_t encoded_size, /* Decode the ISEMPTY bit, if it is set to 1, we are done. */ if ((val >> bit_pos) & 1) { *decoded_size = 0; - return 1; + return BROTLI_RESULT_SUCCESS; } ++bit_pos; } @@ -673,7 +849,7 @@ int BrotliDecompressedSize(size_t encoded_size, if (is_last) { /* If this meta-block is the only one, we are done. */ *decoded_size = (size_t)meta_block_len; - return 1; + return BROTLI_RESULT_SUCCESS; } is_uncompressed = (val >> bit_pos) & 1; ++bit_pos; @@ -683,472 +859,773 @@ int BrotliDecompressedSize(size_t encoded_size, both are set to 1, we have a stream with an uncompressed meta-block followed by an empty one, so the decompressed size is the size of the first meta-block. */ - size_t offset = ((bit_pos + 7) >> 3) + meta_block_len; + size_t offset = (size_t)((bit_pos + 7) >> 3) + (size_t)meta_block_len; if (offset < encoded_size && ((encoded_buffer[offset] & 3) == 3)) { *decoded_size = (size_t)meta_block_len; - return 1; + return BROTLI_RESULT_SUCCESS; } } - return 0; + return BROTLI_RESULT_ERROR; } -int BrotliDecompressBuffer(size_t encoded_size, - const uint8_t* encoded_buffer, - size_t* decoded_size, - uint8_t* decoded_buffer) { +BrotliResult BrotliDecompressBuffer(size_t encoded_size, + const uint8_t* encoded_buffer, + size_t* decoded_size, + uint8_t* decoded_buffer) { BrotliMemInput memin; BrotliInput in = BrotliInitMemInput(encoded_buffer, encoded_size, &memin); BrotliMemOutput mout; BrotliOutput out = BrotliInitMemOutput(decoded_buffer, *decoded_size, &mout); - int success = BrotliDecompress(in, out); + BrotliResult success = BrotliDecompress(in, out); *decoded_size = mout.pos; return success; } -int BrotliDecompress(BrotliInput input, BrotliOutput output) { - int ok = 1; - int i; - int pos = 0; - int input_end = 0; - int window_bits = 0; - int max_backward_distance; - int max_distance = 0; - int ringbuffer_size; - int ringbuffer_mask; - uint8_t* ringbuffer; - uint8_t* ringbuffer_end; - /* This ring buffer holds a few past copy distances that will be used by */ - /* some special distance codes. */ - int dist_rb[4] = { 16, 15, 11, 4 }; - int dist_rb_idx = 0; - /* The previous 2 bytes used for context. */ - uint8_t prev_byte1 = 0; - uint8_t prev_byte2 = 0; - HuffmanTreeGroup hgroup[3]; - HuffmanCode* block_type_trees = NULL; - HuffmanCode* block_len_trees = NULL; - BrotliBitReader br; +BrotliResult BrotliDecompress(BrotliInput input, BrotliOutput output) { + BrotliState s; + BrotliResult result; + BrotliStateInit(&s); + result = BrotliDecompressStreaming(input, output, 1, &s); + if (result == BROTLI_RESULT_NEEDS_MORE_INPUT) { + /* Not ok: it didn't finish even though this is a non-streaming function. */ + result = BROTLI_RESULT_ERROR; + } + BrotliStateCleanup(&s); + return result; +} + +BrotliResult BrotliDecompressBufferStreaming(size_t* available_in, + const uint8_t** next_in, + int finish, + size_t* available_out, + uint8_t** next_out, + size_t* total_out, + BrotliState* s) { + BrotliResult result; + BrotliMemInput memin; + BrotliInput in = BrotliInitMemInput(*next_in, *available_in, &memin); + BrotliMemOutput memout; + BrotliOutput out = BrotliInitMemOutput(*next_out, *available_out, &memout); + + result = BrotliDecompressStreaming(in, out, finish, s); + + /* The current implementation reads everything, so 0 bytes are available. */ + *next_in += memin.pos; + *available_in -= memin.pos; + + /* Update the output position to where we write next. */ + *next_out += memout.pos; + *available_out -= memout.pos; + *total_out += memout.pos; + + return result; +} + +BrotliResult BrotliDecompressStreaming(BrotliInput input, BrotliOutput output, + int finish, BrotliState* s) { + uint8_t context; + int pos = s->pos; + int i = s->loop_counter; + BrotliResult result = BROTLI_RESULT_SUCCESS; + BrotliBitReader* br = &s->br; + int initial_remaining_len; + int bytes_copied; + int num_written; /* We need the slack region for the following reasons: - always doing two 8-byte copies for fast backward copying - transforms - - flushing the input ringbuffer when decoding uncompressed blocks */ + - flushing the input s->ringbuffer when decoding uncompressed blocks */ static const int kRingBufferWriteAheadSlack = 128 + BROTLI_READ_SIZE; - if (!BrotliInitBitReader(&br, input)) { - return 0; - } + s->br.finish_ = finish; - /* Decode window size. */ - window_bits = DecodeWindowBits(&br); - max_backward_distance = (1 << window_bits) - 16; - - ringbuffer_size = 1 << window_bits; - ringbuffer_mask = ringbuffer_size - 1; - ringbuffer = (uint8_t*)malloc((size_t)(ringbuffer_size + - kRingBufferWriteAheadSlack + - kMaxDictionaryWordLength)); - if (!ringbuffer) { - ok = 0; - } - ringbuffer_end = ringbuffer + ringbuffer_size; - - if (ok) { - block_type_trees = (HuffmanCode*)malloc( - 3 * HUFFMAN_MAX_TABLE_SIZE * sizeof(HuffmanCode)); - block_len_trees = (HuffmanCode*)malloc( - 3 * HUFFMAN_MAX_TABLE_SIZE * sizeof(HuffmanCode)); - if (block_type_trees == NULL || block_len_trees == NULL) { - ok = 0; + /* State machine */ + for (;;) { + if (result != BROTLI_RESULT_SUCCESS) { + if (result == BROTLI_RESULT_NEEDS_MORE_INPUT && finish) { + printf("Unexpected end of input. State: %d\n", s->state); + result = BROTLI_RESULT_ERROR; + } + break; /* Fail, or partial data. */ } - } - while (!input_end && ok) { - int meta_block_remaining_len = 0; - int is_uncompressed; - int block_length[3] = { 1 << 28, 1 << 28, 1 << 28 }; - int block_type[3] = { 0 }; - int num_block_types[3] = { 1, 1, 1 }; - int block_type_rb[6] = { 0, 1, 0, 1, 0, 1 }; - int block_type_rb_index[3] = { 0 }; - int distance_postfix_bits; - int num_direct_distance_codes; - int distance_postfix_mask; - int num_distance_codes; - uint8_t* context_map = NULL; - uint8_t* context_modes = NULL; - int num_literal_htrees; - uint8_t* dist_context_map = NULL; - int num_dist_htrees; - int context_offset = 0; - uint8_t* context_map_slice = NULL; - uint8_t literal_htree_index = 0; - int dist_context_offset = 0; - uint8_t* dist_context_map_slice = NULL; - uint8_t dist_htree_index = 0; - int context_lookup_offset1 = 0; - int context_lookup_offset2 = 0; - uint8_t context_mode; - HuffmanCode* htree_command; - - for (i = 0; i < 3; ++i) { - hgroup[i].codes = NULL; - hgroup[i].htrees = NULL; - } + switch (s->state) { + case BROTLI_STATE_UNINITED: + pos = 0; + s->input_end = 0; + s->window_bits = 0; + s->max_distance = 0; + s->dist_rb[0] = 16; + s->dist_rb[1] = 15; + s->dist_rb[2] = 11; + s->dist_rb[3] = 4; + s->dist_rb_idx = 0; + s->prev_byte1 = 0; + s->prev_byte2 = 0; + s->block_type_trees = NULL; + s->block_len_trees = NULL; + + BrotliInitBitReader(br, input, finish); + + s->state = BROTLI_STATE_BITREADER_WARMUP; + /* No break, continue to next state */ + case BROTLI_STATE_BITREADER_WARMUP: + if (!BrotliWarmupBitReader(br)) { + result = BROTLI_RESULT_NEEDS_MORE_INPUT; + break; + } + /* Decode window size. */ + s->window_bits = DecodeWindowBits(br); + s->max_backward_distance = (1 << s->window_bits) - 16; + + s->ringbuffer_size = 1 << s->window_bits; + s->ringbuffer_mask = s->ringbuffer_size - 1; + s->ringbuffer = (uint8_t*)malloc((size_t)(s->ringbuffer_size + + kRingBufferWriteAheadSlack + + kMaxDictionaryWordLength)); + if (!s->ringbuffer) { + result = BROTLI_RESULT_ERROR; + break; + } + s->ringbuffer_end = s->ringbuffer + s->ringbuffer_size; + + s->block_type_trees = (HuffmanCode*)malloc( + 3 * BROTLI_HUFFMAN_MAX_TABLE_SIZE * sizeof(HuffmanCode)); + s->block_len_trees = (HuffmanCode*)malloc( + 3 * BROTLI_HUFFMAN_MAX_TABLE_SIZE * sizeof(HuffmanCode)); + if (s->block_type_trees == NULL || s->block_len_trees == NULL) { + result = BROTLI_RESULT_ERROR; + break; + } - if (!BrotliReadMoreInput(&br)) { - printf("[BrotliDecompress] Unexpected end of input.\n"); - ok = 0; - goto End; - } - BROTLI_LOG_UINT(pos); - DecodeMetaBlockLength(&br, &meta_block_remaining_len, - &input_end, &is_uncompressed); - BROTLI_LOG_UINT(meta_block_remaining_len); - if (meta_block_remaining_len == 0) { - goto End; - } - if (is_uncompressed) { - BrotliSetBitPos(&br, (br.bit_pos_ + 7) & (uint32_t)(~7UL)); - ok = CopyUncompressedBlockToOutput(output, meta_block_remaining_len, pos, - ringbuffer, ringbuffer_mask, &br); - pos += meta_block_remaining_len; - goto End; - } - for (i = 0; i < 3; ++i) { - num_block_types[i] = DecodeVarLenUint8(&br) + 1; - if (num_block_types[i] >= 2) { - if (!ReadHuffmanCode(num_block_types[i] + 2, - &block_type_trees[i * HUFFMAN_MAX_TABLE_SIZE], - &br) || - !ReadHuffmanCode(kNumBlockLengthCodes, - &block_len_trees[i * HUFFMAN_MAX_TABLE_SIZE], - &br)) { - ok = 0; - goto End; - } - block_length[i] = ReadBlockLength( - &block_len_trees[i * HUFFMAN_MAX_TABLE_SIZE], &br); - block_type_rb_index[i] = 1; - } - } + s->state = BROTLI_STATE_METABLOCK_BEGIN; + /* No break, continue to next state */ + case BROTLI_STATE_METABLOCK_BEGIN: + if (!BrotliReadMoreInput(br)) { + result = BROTLI_RESULT_NEEDS_MORE_INPUT; + break; + } + if (s->input_end) { + s->partially_written = 0; + s->state = BROTLI_STATE_DONE; + break; + } + s->meta_block_remaining_len = 0; + s->block_length[0] = 1 << 28; + s->block_length[1] = 1 << 28; + s->block_length[2] = 1 << 28; + s->block_type[0] = 0; + s->num_block_types[0] = 1; + s->num_block_types[1] = 1; + s->num_block_types[2] = 1; + s->block_type_rb[0] = 0; + s->block_type_rb[1] = 1; + s->block_type_rb[2] = 0; + s->block_type_rb[3] = 1; + s->block_type_rb[4] = 0; + s->block_type_rb[5] = 1; + s->block_type_rb_index[0] = 0; + s->context_map = NULL; + s->context_modes = NULL; + s->dist_context_map = NULL; + s->context_offset = 0; + s->context_map_slice = NULL; + s->literal_htree_index = 0; + s->dist_context_offset = 0; + s->dist_context_map_slice = NULL; + s->dist_htree_index = 0; + s->context_lookup_offset1 = 0; + s->context_lookup_offset2 = 0; + for (i = 0; i < 3; ++i) { + s->hgroup[i].codes = NULL; + s->hgroup[i].htrees = NULL; + } + s->state = BROTLI_STATE_METABLOCK_HEADER_1; + /* No break, continue to next state */ + case BROTLI_STATE_METABLOCK_HEADER_1: + if (!BrotliReadMoreInput(br)) { + result = BROTLI_RESULT_NEEDS_MORE_INPUT; + break; + } + BROTLI_LOG_UINT(pos); + if (!DecodeMetaBlockLength(br, + &s->meta_block_remaining_len, + &s->input_end, + &s->is_metadata, + &s->is_uncompressed)) { + result = BROTLI_RESULT_ERROR; + break; + } + BROTLI_LOG_UINT(s->meta_block_remaining_len); + if (s->is_metadata) { + if (!JumpToByteBoundary(&s->br)) { + result = BROTLI_RESULT_ERROR; + break; + } + s->state = BROTLI_STATE_METADATA; + break; + } + if (s->meta_block_remaining_len == 0) { + s->state = BROTLI_STATE_METABLOCK_DONE; + break; + } + if (s->is_uncompressed) { + if (!JumpToByteBoundary(&s->br)) { + result = BROTLI_RESULT_ERROR; + break; + } + s->state = BROTLI_STATE_UNCOMPRESSED; + break; + } + i = 0; + s->state = BROTLI_STATE_HUFFMAN_CODE_0; + break; + case BROTLI_STATE_UNCOMPRESSED: + initial_remaining_len = s->meta_block_remaining_len; + /* pos is given as argument since s->pos is only updated at the end. */ + result = CopyUncompressedBlockToOutput(output, pos, s); + if (result == BROTLI_RESULT_NEEDS_MORE_OUTPUT) { + break; + } + bytes_copied = initial_remaining_len - s->meta_block_remaining_len; + pos += bytes_copied; + if (bytes_copied > 0) { + s->prev_byte2 = bytes_copied == 1 ? s->prev_byte1 : + s->ringbuffer[(pos - 2) & s->ringbuffer_mask]; + s->prev_byte1 = s->ringbuffer[(pos - 1) & s->ringbuffer_mask]; + } + if (result != BROTLI_RESULT_SUCCESS) break; + s->state = BROTLI_STATE_METABLOCK_DONE; + break; + case BROTLI_STATE_METADATA: + for (; s->meta_block_remaining_len > 0; --s->meta_block_remaining_len) { + if (!BrotliReadMoreInput(&s->br)) { + result = BROTLI_RESULT_NEEDS_MORE_INPUT; + break; + } + /* Read one byte and ignore it. */ + BrotliReadBits(&s->br, 8); + } + s->state = BROTLI_STATE_METABLOCK_DONE; + break; + case BROTLI_STATE_HUFFMAN_CODE_0: + if (i >= 3) { + BROTLI_LOG_UINT(s->num_block_types[0]); + BROTLI_LOG_UINT(s->num_block_types[1]); + BROTLI_LOG_UINT(s->num_block_types[2]); + BROTLI_LOG_UINT(s->block_length[0]); + BROTLI_LOG_UINT(s->block_length[1]); + BROTLI_LOG_UINT(s->block_length[2]); + + s->state = BROTLI_STATE_METABLOCK_HEADER_2; + break; + } + s->num_block_types[i] = DecodeVarLenUint8(br) + 1; + s->state = BROTLI_STATE_HUFFMAN_CODE_1; + /* No break, continue to next state */ + case BROTLI_STATE_HUFFMAN_CODE_1: + if (s->num_block_types[i] >= 2) { + result = ReadHuffmanCode(s->num_block_types[i] + 2, + &s->block_type_trees[i * BROTLI_HUFFMAN_MAX_TABLE_SIZE], + NULL, s); + if (result != BROTLI_RESULT_SUCCESS) break; + s->state = BROTLI_STATE_HUFFMAN_CODE_2; + } else { + i++; + s->state = BROTLI_STATE_HUFFMAN_CODE_0; + break; + } + /* No break, continue to next state */ + case BROTLI_STATE_HUFFMAN_CODE_2: + result = ReadHuffmanCode(kNumBlockLengthCodes, + &s->block_len_trees[i * BROTLI_HUFFMAN_MAX_TABLE_SIZE], + NULL, s); + if (result != BROTLI_RESULT_SUCCESS) break; + s->block_length[i] = ReadBlockLength( + &s->block_len_trees[i * BROTLI_HUFFMAN_MAX_TABLE_SIZE], br); + s->block_type_rb_index[i] = 1; + i++; + s->state = BROTLI_STATE_HUFFMAN_CODE_0; + break; + case BROTLI_STATE_METABLOCK_HEADER_2: + if (!BrotliReadMoreInput(br)) { + result = BROTLI_RESULT_NEEDS_MORE_INPUT; + break; + } + s->distance_postfix_bits = (int)BrotliReadBits(br, 2); + s->num_direct_distance_codes = NUM_DISTANCE_SHORT_CODES + + ((int)BrotliReadBits(br, 4) << s->distance_postfix_bits); + s->distance_postfix_mask = (1 << s->distance_postfix_bits) - 1; + s->num_distance_codes = (s->num_direct_distance_codes + + (48 << s->distance_postfix_bits)); + s->context_modes = (uint8_t*)malloc((size_t)s->num_block_types[0]); + if (s->context_modes == 0) { + result = BROTLI_RESULT_ERROR; + break; + } + for (i = 0; i < s->num_block_types[0]; ++i) { + s->context_modes[i] = (uint8_t)(BrotliReadBits(br, 2) << 1); + BROTLI_LOG_ARRAY_INDEX(s->context_modes, i); + } + BROTLI_LOG_UINT(s->num_direct_distance_codes); + BROTLI_LOG_UINT(s->distance_postfix_bits); + s->state = BROTLI_STATE_CONTEXT_MAP_1; + /* No break, continue to next state */ + case BROTLI_STATE_CONTEXT_MAP_1: + result = DecodeContextMap(s->num_block_types[0] << kLiteralContextBits, + &s->num_literal_htrees, &s->context_map, s); + + s->trivial_literal_context = 1; + for (i = 0; i < s->num_block_types[0] << kLiteralContextBits; i++) { + if (s->context_map[i] != i >> kLiteralContextBits) { + s->trivial_literal_context = 0; + break; + } + } - BROTLI_LOG_UINT(num_block_types[0]); - BROTLI_LOG_UINT(num_block_types[1]); - BROTLI_LOG_UINT(num_block_types[2]); - BROTLI_LOG_UINT(block_length[0]); - BROTLI_LOG_UINT(block_length[1]); - BROTLI_LOG_UINT(block_length[2]); - - if (!BrotliReadMoreInput(&br)) { - printf("[BrotliDecompress] Unexpected end of input.\n"); - ok = 0; - goto End; - } - distance_postfix_bits = (int)BrotliReadBits(&br, 2); - num_direct_distance_codes = NUM_DISTANCE_SHORT_CODES + - ((int)BrotliReadBits(&br, 4) << distance_postfix_bits); - distance_postfix_mask = (1 << distance_postfix_bits) - 1; - num_distance_codes = (num_direct_distance_codes + - (48 << distance_postfix_bits)); - context_modes = (uint8_t*)malloc((size_t)num_block_types[0]); - if (context_modes == 0) { - ok = 0; - goto End; - } - for (i = 0; i < num_block_types[0]; ++i) { - context_modes[i] = (uint8_t)(BrotliReadBits(&br, 2) << 1); - BROTLI_LOG_ARRAY_INDEX(context_modes, i); - } - BROTLI_LOG_UINT(num_direct_distance_codes); - BROTLI_LOG_UINT(distance_postfix_bits); - - if (!DecodeContextMap(num_block_types[0] << kLiteralContextBits, - &num_literal_htrees, &context_map, &br) || - !DecodeContextMap(num_block_types[2] << kDistanceContextBits, - &num_dist_htrees, &dist_context_map, &br)) { - ok = 0; - goto End; - } + if (result != BROTLI_RESULT_SUCCESS) break; + s->state = BROTLI_STATE_CONTEXT_MAP_2; + /* No break, continue to next state */ + case BROTLI_STATE_CONTEXT_MAP_2: + result = DecodeContextMap(s->num_block_types[2] << kDistanceContextBits, + &s->num_dist_htrees, &s->dist_context_map, s); + if (result != BROTLI_RESULT_SUCCESS) break; + + BrotliHuffmanTreeGroupInit(&s->hgroup[0], kNumLiteralCodes, + s->num_literal_htrees); + BrotliHuffmanTreeGroupInit(&s->hgroup[1], kNumInsertAndCopyCodes, + s->num_block_types[1]); + BrotliHuffmanTreeGroupInit(&s->hgroup[2], s->num_distance_codes, + s->num_dist_htrees); + i = 0; + s->state = BROTLI_STATE_TREE_GROUP; + /* No break, continue to next state */ + case BROTLI_STATE_TREE_GROUP: + result = HuffmanTreeGroupDecode(&s->hgroup[i], s); + if (result != BROTLI_RESULT_SUCCESS) break; + i++; + + if (i >= 3) { + s->context_map_slice = s->context_map; + s->dist_context_map_slice = s->dist_context_map; + s->context_mode = s->context_modes[s->block_type[0]]; + s->context_lookup_offset1 = kContextLookupOffsets[s->context_mode]; + s->context_lookup_offset2 = + kContextLookupOffsets[s->context_mode + 1]; + s->htree_command = s->hgroup[1].htrees[0]; + + s->state = BROTLI_STATE_BLOCK_BEGIN; + break; + } - HuffmanTreeGroupInit(&hgroup[0], kNumLiteralCodes, num_literal_htrees); - HuffmanTreeGroupInit(&hgroup[1], kNumInsertAndCopyCodes, - num_block_types[1]); - HuffmanTreeGroupInit(&hgroup[2], num_distance_codes, num_dist_htrees); + break; + case BROTLI_STATE_BLOCK_BEGIN: + /* Block decoding is the inner loop, jumping with goto makes it 3% faster */ + BlockBegin: + if (!BrotliReadMoreInput(br)) { + result = BROTLI_RESULT_NEEDS_MORE_INPUT; + break; + } + if (s->meta_block_remaining_len <= 0) { + /* Protect pos from overflow, wrap it around at every GB of input. */ + pos &= 0x3fffffff; - for (i = 0; i < 3; ++i) { - if (!HuffmanTreeGroupDecode(&hgroup[i], &br)) { - ok = 0; - goto End; - } - } + /* Next metablock, if any */ + s->state = BROTLI_STATE_METABLOCK_DONE; + break; + } - context_map_slice = context_map; - dist_context_map_slice = dist_context_map; - context_mode = context_modes[block_type[0]]; - context_lookup_offset1 = kContextLookupOffsets[context_mode]; - context_lookup_offset2 = kContextLookupOffsets[context_mode + 1]; - htree_command = hgroup[1].htrees[0]; - - while (meta_block_remaining_len > 0) { - int cmd_code; - int range_idx; - int insert_code; - int copy_code; - int insert_length; - int copy_length; - int distance_code; - int distance; - uint8_t context; - int j; - const uint8_t* copy_src; - uint8_t* copy_dst; - if (!BrotliReadMoreInput(&br)) { - printf("[BrotliDecompress] Unexpected end of input.\n"); - ok = 0; - goto End; - } - if (block_length[1] == 0) { - DecodeBlockType(num_block_types[1], - block_type_trees, 1, block_type, block_type_rb, - block_type_rb_index, &br); - block_length[1] = ReadBlockLength( - &block_len_trees[HUFFMAN_MAX_TABLE_SIZE], &br); - htree_command = hgroup[1].htrees[block_type[1]]; - } - --block_length[1]; - cmd_code = ReadSymbol(htree_command, &br); - range_idx = cmd_code >> 6; - if (range_idx >= 2) { - range_idx -= 2; - distance_code = -1; - } else { - distance_code = 0; - } - insert_code = kInsertRangeLut[range_idx] + ((cmd_code >> 3) & 7); - copy_code = kCopyRangeLut[range_idx] + (cmd_code & 7); - insert_length = kInsertLengthPrefixCode[insert_code].offset + - (int)BrotliReadBits(&br, kInsertLengthPrefixCode[insert_code].nbits); - copy_length = kCopyLengthPrefixCode[copy_code].offset + - (int)BrotliReadBits(&br, kCopyLengthPrefixCode[copy_code].nbits); - BROTLI_LOG_UINT(insert_length); - BROTLI_LOG_UINT(copy_length); - BROTLI_LOG_UINT(distance_code); - for (j = 0; j < insert_length; ++j) { - if (!BrotliReadMoreInput(&br)) { - printf("[BrotliDecompress] Unexpected end of input.\n"); - ok = 0; - goto End; - } - if (block_length[0] == 0) { - DecodeBlockType(num_block_types[0], - block_type_trees, 0, block_type, block_type_rb, - block_type_rb_index, &br); - block_length[0] = ReadBlockLength(block_len_trees, &br); - context_offset = block_type[0] << kLiteralContextBits; - context_map_slice = context_map + context_offset; - context_mode = context_modes[block_type[0]]; - context_lookup_offset1 = kContextLookupOffsets[context_mode]; - context_lookup_offset2 = kContextLookupOffsets[context_mode + 1]; - } - context = (kContextLookup[context_lookup_offset1 + prev_byte1] | - kContextLookup[context_lookup_offset2 + prev_byte2]); - BROTLI_LOG_UINT(context); - literal_htree_index = context_map_slice[context]; - --block_length[0]; - prev_byte2 = prev_byte1; - prev_byte1 = (uint8_t)ReadSymbol(hgroup[0].htrees[literal_htree_index], - &br); - ringbuffer[pos & ringbuffer_mask] = prev_byte1; - BROTLI_LOG_UINT(literal_htree_index); - BROTLI_LOG_ARRAY_INDEX(ringbuffer, pos & ringbuffer_mask); - if ((pos & ringbuffer_mask) == ringbuffer_mask) { - if (BrotliWrite(output, ringbuffer, (size_t)ringbuffer_size) < 0) { - ok = 0; - goto End; + if (s->block_length[1] == 0) { + DecodeBlockType(s->num_block_types[1], + s->block_type_trees, 1, + s->block_type, s->block_type_rb, + s->block_type_rb_index, br); + s->block_length[1] = ReadBlockLength( + &s->block_len_trees[BROTLI_HUFFMAN_MAX_TABLE_SIZE], br); + s->htree_command = s->hgroup[1].htrees[s->block_type[1]]; + } + --s->block_length[1]; + s->cmd_code = ReadSymbol(s->htree_command, br); + s->range_idx = s->cmd_code >> 6; + if (s->range_idx >= 2) { + s->range_idx -= 2; + s->distance_code = -1; + } else { + s->distance_code = 0; + } + s->insert_code = + kInsertRangeLut[s->range_idx] + ((s->cmd_code >> 3) & 7); + s->copy_code = kCopyRangeLut[s->range_idx] + (s->cmd_code & 7); + s->insert_length = kInsertLengthPrefixCode[s->insert_code].offset + + (int)BrotliReadBits(br, + kInsertLengthPrefixCode[s->insert_code].nbits); + s->copy_length = kCopyLengthPrefixCode[s->copy_code].offset + + (int)BrotliReadBits(br, kCopyLengthPrefixCode[s->copy_code].nbits); + BROTLI_LOG_UINT(s->insert_length); + BROTLI_LOG_UINT(s->copy_length); + BROTLI_LOG_UINT(s->distance_code); + + i = 0; + s->state = BROTLI_STATE_BLOCK_INNER; + /* No break, go to next state */ + case BROTLI_STATE_BLOCK_INNER: + if (s->trivial_literal_context) { + while (i < s->insert_length) { + if (!BrotliReadMoreInput(br)) { + result = BROTLI_RESULT_NEEDS_MORE_INPUT; + break; + } + if (s->block_length[0] == 0) { + DecodeBlockTypeWithContext(s, br); + } + + s->ringbuffer[pos & s->ringbuffer_mask] = (uint8_t)ReadSymbol( + s->hgroup[0].htrees[s->literal_htree_index], br); + + --s->block_length[0]; + BROTLI_LOG_UINT(s->literal_htree_index); + BROTLI_LOG_ARRAY_INDEX(s->ringbuffer, pos & s->ringbuffer_mask); + if ((pos & s->ringbuffer_mask) == s->ringbuffer_mask) { + s->partially_written = 0; + s->state = BROTLI_STATE_BLOCK_INNER_WRITE; + break; + } + /* Modifications to this code shold be reflected in + BROTLI_STATE_BLOCK_INNER_WRITE case */ + ++pos; + ++i; + } + } else { + while (i < s->insert_length) { + if (!BrotliReadMoreInput(br)) { + result = BROTLI_RESULT_NEEDS_MORE_INPUT; + break; + } + if (s->block_length[0] == 0) { + DecodeBlockTypeWithContext(s, br); + } + + context = + (kContextLookup[s->context_lookup_offset1 + s->prev_byte1] | + kContextLookup[s->context_lookup_offset2 + s->prev_byte2]); + BROTLI_LOG_UINT(context); + s->literal_htree_index = s->context_map_slice[context]; + --s->block_length[0]; + s->prev_byte2 = s->prev_byte1; + s->prev_byte1 = (uint8_t)ReadSymbol( + s->hgroup[0].htrees[s->literal_htree_index], br); + s->ringbuffer[pos & s->ringbuffer_mask] = s->prev_byte1; + BROTLI_LOG_UINT(s->literal_htree_index); + BROTLI_LOG_ARRAY_INDEX(s->ringbuffer, pos & s->ringbuffer_mask); + if ((pos & s->ringbuffer_mask) == s->ringbuffer_mask) { + s->partially_written = 0; + s->state = BROTLI_STATE_BLOCK_INNER_WRITE; + break; + } + /* Modifications to this code shold be reflected in + BROTLI_STATE_BLOCK_INNER_WRITE case */ + ++pos; + ++i; } } - ++pos; - } - meta_block_remaining_len -= insert_length; - if (meta_block_remaining_len <= 0) break; - - if (distance_code < 0) { - uint8_t context; - if (!BrotliReadMoreInput(&br)) { - printf("[BrotliDecompress] Unexpected end of input.\n"); - ok = 0; - goto End; - } - if (block_length[2] == 0) { - DecodeBlockType(num_block_types[2], - block_type_trees, 2, block_type, block_type_rb, - block_type_rb_index, &br); - block_length[2] = ReadBlockLength( - &block_len_trees[2 * HUFFMAN_MAX_TABLE_SIZE], &br); - dist_context_offset = block_type[2] << kDistanceContextBits; - dist_context_map_slice = dist_context_map + dist_context_offset; - } - --block_length[2]; - context = (uint8_t)(copy_length > 4 ? 3 : copy_length - 2); - dist_htree_index = dist_context_map_slice[context]; - distance_code = ReadSymbol(hgroup[2].htrees[dist_htree_index], &br); - if (distance_code >= num_direct_distance_codes) { + if (result != BROTLI_RESULT_SUCCESS || + s->state == BROTLI_STATE_BLOCK_INNER_WRITE) break; + + s->meta_block_remaining_len -= s->insert_length; + if (s->meta_block_remaining_len <= 0) { + s->state = BROTLI_STATE_METABLOCK_DONE; + break; + } else if (s->distance_code < 0) { + s->state = BROTLI_STATE_BLOCK_DISTANCE; + } else { + s->state = BROTLI_STATE_BLOCK_POST; + break; + } + /* No break, go to next state */ + case BROTLI_STATE_BLOCK_DISTANCE: + if (!BrotliReadMoreInput(br)) { + result = BROTLI_RESULT_NEEDS_MORE_INPUT; + break; + } + assert(s->distance_code < 0); + + if (s->block_length[2] == 0) { + DecodeBlockType(s->num_block_types[2], + s->block_type_trees, 2, + s->block_type, s->block_type_rb, + s->block_type_rb_index, br); + s->block_length[2] = ReadBlockLength( + &s->block_len_trees[2 * BROTLI_HUFFMAN_MAX_TABLE_SIZE], br); + s->dist_context_offset = s->block_type[2] << kDistanceContextBits; + s->dist_context_map_slice = + s->dist_context_map + s->dist_context_offset; + } + --s->block_length[2]; + context = (uint8_t)(s->copy_length > 4 ? 3 : s->copy_length - 2); + s->dist_htree_index = s->dist_context_map_slice[context]; + s->distance_code = + ReadSymbol(s->hgroup[2].htrees[s->dist_htree_index], br); + if (s->distance_code >= s->num_direct_distance_codes) { int nbits; int postfix; int offset; - distance_code -= num_direct_distance_codes; - postfix = distance_code & distance_postfix_mask; - distance_code >>= distance_postfix_bits; - nbits = (distance_code >> 1) + 1; - offset = ((2 + (distance_code & 1)) << nbits) - 4; - distance_code = num_direct_distance_codes + - ((offset + (int)BrotliReadBits(&br, nbits)) << - distance_postfix_bits) + postfix; + s->distance_code -= s->num_direct_distance_codes; + postfix = s->distance_code & s->distance_postfix_mask; + s->distance_code >>= s->distance_postfix_bits; + nbits = (s->distance_code >> 1) + 1; + offset = ((2 + (s->distance_code & 1)) << nbits) - 4; + s->distance_code = s->num_direct_distance_codes + + ((offset + (int)BrotliReadBits(br, nbits)) << + s->distance_postfix_bits) + postfix; } - } - - /* Convert the distance code to the actual distance by possibly looking */ - /* up past distnaces from the ringbuffer. */ - distance = TranslateShortCodes(distance_code, dist_rb, dist_rb_idx); - if (distance < 0) { - ok = 0; - goto End; - } - BROTLI_LOG_UINT(distance); + s->state = BROTLI_STATE_BLOCK_POST; + /* No break, go to next state */ + case BROTLI_STATE_BLOCK_POST: + if (!BrotliReadMoreInput(br)) { + result = BROTLI_RESULT_NEEDS_MORE_INPUT; + break; + } + /* Convert the distance code to the actual distance by possibly */ + /* looking up past distnaces from the s->ringbuffer. */ + s->distance = + TranslateShortCodes(s->distance_code, s->dist_rb, s->dist_rb_idx); + if (s->distance < 0) { + result = BROTLI_RESULT_ERROR; + break; + } + BROTLI_LOG_UINT(s->distance); - if (pos < max_backward_distance && - max_distance != max_backward_distance) { - max_distance = pos; - } else { - max_distance = max_backward_distance; - } + if (pos < s->max_backward_distance && + s->max_distance != s->max_backward_distance) { + s->max_distance = pos; + } else { + s->max_distance = s->max_backward_distance; + } - copy_dst = &ringbuffer[pos & ringbuffer_mask]; - - if (distance > max_distance) { - if (copy_length >= kMinDictionaryWordLength && - copy_length <= kMaxDictionaryWordLength) { - int offset = kBrotliDictionaryOffsetsByLength[copy_length]; - int word_id = distance - max_distance - 1; - int shift = kBrotliDictionarySizeBitsByLength[copy_length]; - int mask = (1 << shift) - 1; - int word_idx = word_id & mask; - int transform_idx = word_id >> shift; - offset += word_idx * copy_length; - if (transform_idx < kNumTransforms) { - const uint8_t* word = &kBrotliDictionary[offset]; - int len = TransformDictionaryWord( - copy_dst, word, copy_length, transform_idx); - copy_dst += len; - pos += len; - meta_block_remaining_len -= len; - if (copy_dst >= ringbuffer_end) { - if (BrotliWrite(output, ringbuffer, - (size_t)ringbuffer_size) < 0) { - ok = 0; - goto End; + s->copy_dst = &s->ringbuffer[pos & s->ringbuffer_mask]; + + if (s->distance > s->max_distance) { + if (s->copy_length >= kMinDictionaryWordLength && + s->copy_length <= kMaxDictionaryWordLength) { + int offset = kBrotliDictionaryOffsetsByLength[s->copy_length]; + int word_id = s->distance - s->max_distance - 1; + int shift = kBrotliDictionarySizeBitsByLength[s->copy_length]; + int mask = (1 << shift) - 1; + int word_idx = word_id & mask; + int transform_idx = word_id >> shift; + offset += word_idx * s->copy_length; + if (transform_idx < kNumTransforms) { + const uint8_t* word = &kBrotliDictionary[offset]; + int len = TransformDictionaryWord( + s->copy_dst, word, s->copy_length, transform_idx); + s->copy_dst += len; + pos += len; + s->meta_block_remaining_len -= len; + if (s->copy_dst >= s->ringbuffer_end) { + s->partially_written = 0; + num_written = BrotliWrite(output, s->ringbuffer, + (size_t)s->ringbuffer_size); + if (num_written < 0) { + result = BROTLI_RESULT_ERROR; + break; + } + s->partially_written += num_written; + if (s->partially_written < s->ringbuffer_size) { + result = BROTLI_RESULT_NEEDS_MORE_OUTPUT; + s->state = BROTLI_STATE_BLOCK_POST_WRITE_1; + break; + } + /* Modifications to this code shold be reflected in + BROTLI_STATE_BLOCK_POST_WRITE_1 case */ + memcpy(s->ringbuffer, s->ringbuffer_end, + (size_t)(s->copy_dst - s->ringbuffer_end)); } - memcpy(ringbuffer, ringbuffer_end, - (size_t)(copy_dst - ringbuffer_end)); + } else { + printf("Invalid backward reference. pos: %d distance: %d " + "len: %d bytes left: %d\n", + pos, s->distance, s->copy_length, + s->meta_block_remaining_len); + result = BROTLI_RESULT_ERROR; + break; } } else { printf("Invalid backward reference. pos: %d distance: %d " - "len: %d bytes left: %d\n", pos, distance, copy_length, - meta_block_remaining_len); - ok = 0; - goto End; + "len: %d bytes left: %d\n", pos, s->distance, s->copy_length, + s->meta_block_remaining_len); + result = BROTLI_RESULT_ERROR; + break; } } else { - printf("Invalid backward reference. pos: %d distance: %d " - "len: %d bytes left: %d\n", pos, distance, copy_length, - meta_block_remaining_len); - ok = 0; - goto End; - } - } else { - if (distance_code > 0) { - dist_rb[dist_rb_idx & 3] = distance; - ++dist_rb_idx; - } + if (s->distance_code > 0) { + s->dist_rb[s->dist_rb_idx & 3] = s->distance; + ++s->dist_rb_idx; + } - if (copy_length > meta_block_remaining_len) { - printf("Invalid backward reference. pos: %d distance: %d " - "len: %d bytes left: %d\n", pos, distance, copy_length, - meta_block_remaining_len); - ok = 0; - goto End; - } + if (s->copy_length > s->meta_block_remaining_len) { + printf("Invalid backward reference. pos: %d distance: %d " + "len: %d bytes left: %d\n", pos, s->distance, s->copy_length, + s->meta_block_remaining_len); + result = BROTLI_RESULT_ERROR; + break; + } - copy_src = &ringbuffer[(pos - distance) & ringbuffer_mask]; + s->copy_src = + &s->ringbuffer[(pos - s->distance) & s->ringbuffer_mask]; #if (defined(__x86_64__) || defined(_M_X64)) - if (copy_src + copy_length <= ringbuffer_end && - copy_dst + copy_length < ringbuffer_end) { - if (copy_length <= 16 && distance >= 8) { - UNALIGNED_COPY64(copy_dst, copy_src); - UNALIGNED_COPY64(copy_dst + 8, copy_src + 8); - } else { - IncrementalCopyFastPath(copy_dst, copy_src, copy_length); + if (s->copy_src + s->copy_length <= s->ringbuffer_end && + s->copy_dst + s->copy_length < s->ringbuffer_end) { + if (s->copy_length <= 16 && s->distance >= 8) { + UNALIGNED_COPY64(s->copy_dst, s->copy_src); + UNALIGNED_COPY64(s->copy_dst + 8, s->copy_src + 8); + } else { + IncrementalCopyFastPath(s->copy_dst, s->copy_src, s->copy_length); + } + pos += s->copy_length; + s->meta_block_remaining_len -= s->copy_length; + s->copy_length = 0; } - pos += copy_length; - meta_block_remaining_len -= copy_length; - copy_length = 0; - } #endif - - for (j = 0; j < copy_length; ++j) { - ringbuffer[pos & ringbuffer_mask] = - ringbuffer[(pos - distance) & ringbuffer_mask]; - if ((pos & ringbuffer_mask) == ringbuffer_mask) { - if (BrotliWrite(output, ringbuffer, (size_t)ringbuffer_size) < 0) { - ok = 0; - goto End; + /* Modifications to this loop shold be reflected in + BROTLI_STATE_BLOCK_POST_WRITE_2 case */ + for (i = 0; i < s->copy_length; ++i) { + s->ringbuffer[pos & s->ringbuffer_mask] = + s->ringbuffer[(pos - s->distance) & s->ringbuffer_mask]; + if ((pos & s->ringbuffer_mask) == s->ringbuffer_mask) { + s->partially_written = 0; + num_written = BrotliWrite(output, s->ringbuffer, + (size_t)s->ringbuffer_size); + if (num_written < 0) { + result = BROTLI_RESULT_ERROR; + break; + } + s->partially_written += num_written; + if (s->partially_written < s->ringbuffer_size) { + result = BROTLI_RESULT_NEEDS_MORE_OUTPUT; + s->state = BROTLI_STATE_BLOCK_POST_WRITE_2; + break; + } } + ++pos; + --s->meta_block_remaining_len; } + if (result == BROTLI_RESULT_NEEDS_MORE_OUTPUT) { + break; + } + } + /* No break, continue to next state */ + case BROTLI_STATE_BLOCK_POST_CONTINUE: + /* When we get here, we must have inserted at least one literal and */ + /* made a copy of at least length two, therefore accessing the last 2 */ + /* bytes is valid. */ + s->prev_byte1 = s->ringbuffer[(pos - 1) & s->ringbuffer_mask]; + s->prev_byte2 = s->ringbuffer[(pos - 2) & s->ringbuffer_mask]; + s->state = BROTLI_STATE_BLOCK_BEGIN; + goto BlockBegin; + case BROTLI_STATE_BLOCK_INNER_WRITE: + case BROTLI_STATE_BLOCK_POST_WRITE_1: + case BROTLI_STATE_BLOCK_POST_WRITE_2: + num_written = BrotliWrite( + output, s->ringbuffer + s->partially_written, + (size_t)(s->ringbuffer_size - s->partially_written)); + if (num_written < 0) { + result = BROTLI_RESULT_ERROR; + break; + } + s->partially_written += num_written; + if (s->partially_written < s->ringbuffer_size) { + result = BROTLI_RESULT_NEEDS_MORE_OUTPUT; + break; + } + if (s->state == BROTLI_STATE_BLOCK_POST_WRITE_1) { + memcpy(s->ringbuffer, s->ringbuffer_end, + (size_t)(s->copy_dst - s->ringbuffer_end)); + s->state = BROTLI_STATE_BLOCK_POST_CONTINUE; + } else if (s->state == BROTLI_STATE_BLOCK_POST_WRITE_2) { + /* The tail of "i < s->copy_length" loop. */ ++pos; - --meta_block_remaining_len; + --s->meta_block_remaining_len; + ++i; + /* Reenter the loop. */ + for (; i < s->copy_length; ++i) { + s->ringbuffer[pos & s->ringbuffer_mask] = + s->ringbuffer[(pos - s->distance) & s->ringbuffer_mask]; + if ((pos & s->ringbuffer_mask) == s->ringbuffer_mask) { + s->partially_written = 0; + num_written = BrotliWrite(output, s->ringbuffer, + (size_t)s->ringbuffer_size); + if (num_written < 0) { + result = BROTLI_RESULT_ERROR; + break; + } + s->partially_written += num_written; + if (s->partially_written < s->ringbuffer_size) { + result = BROTLI_RESULT_NEEDS_MORE_OUTPUT; + break; + } + } + ++pos; + --s->meta_block_remaining_len; + } + if (result == BROTLI_RESULT_NEEDS_MORE_OUTPUT) { + break; + } + s->state = BROTLI_STATE_BLOCK_POST_CONTINUE; + } else { /* BROTLI_STATE_BLOCK_INNER_WRITE */ + /* The tail of "i < s->insert_length" loop. */ + ++pos; + ++i; + s->state = BROTLI_STATE_BLOCK_INNER; } - } - - /* When we get here, we must have inserted at least one literal and */ - /* made a copy of at least length two, therefore accessing the last 2 */ - /* bytes is valid. */ - prev_byte1 = ringbuffer[(pos - 1) & ringbuffer_mask]; - prev_byte2 = ringbuffer[(pos - 2) & ringbuffer_mask]; - } - - /* Protect pos from overflow, wrap it around at every GB of input data */ - pos &= 0x3fffffff; - - End: - if (context_modes != 0) { - free(context_modes); - } - if (context_map != 0) { - free(context_map); - } - if (dist_context_map != 0) { - free(dist_context_map); - } - for (i = 0; i < 3; ++i) { - HuffmanTreeGroupRelease(&hgroup[i]); + break; + case BROTLI_STATE_METABLOCK_DONE: + if (s->context_modes != 0) { + free(s->context_modes); + s->context_modes = NULL; + } + if (s->context_map != 0) { + free(s->context_map); + s->context_map = NULL; + } + if (s->dist_context_map != 0) { + free(s->dist_context_map); + s->dist_context_map = NULL; + } + for (i = 0; i < 3; ++i) { + BrotliHuffmanTreeGroupRelease(&s->hgroup[i]); + s->hgroup[i].codes = NULL; + s->hgroup[i].htrees = NULL; + } + s->state = BROTLI_STATE_METABLOCK_BEGIN; + break; + case BROTLI_STATE_DONE: + if (s->ringbuffer != 0) { + num_written = BrotliWrite( + output, s->ringbuffer + s->partially_written, + (size_t)((pos & s->ringbuffer_mask) - s->partially_written)); + if (num_written < 0) { + result = BROTLI_RESULT_ERROR; + } + s->partially_written += num_written; + if (s->partially_written < (pos & s->ringbuffer_mask)) { + result = BROTLI_RESULT_NEEDS_MORE_OUTPUT; + break; + } + } + if (!JumpToByteBoundary(&s->br)) { + result = BROTLI_RESULT_ERROR; + } + return result; + default: + printf("Unknown state %d\n", s->state); + result = BROTLI_RESULT_ERROR; } } - if (ringbuffer != 0) { - if (BrotliWrite(output, ringbuffer, (size_t)(pos & ringbuffer_mask)) < 0) { - ok = 0; - } - free(ringbuffer); - } - if (block_type_trees != 0) { - free(block_type_trees); - } - if (block_len_trees != 0) { - free(block_len_trees); - } - return ok; + s->pos = pos; + s->loop_counter = i; + return result; } #if defined(__cplusplus) || defined(c_plusplus) diff --git a/third_party/brotli/dec/decode.h b/third_party/brotli/dec/decode.h index d0490a2706cbb..834a7b5485a45 100644 --- a/third_party/brotli/dec/decode.h +++ b/third_party/brotli/dec/decode.h @@ -11,13 +11,14 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - - API for Brotli decompression */ +/* API for Brotli decompression */ + #ifndef BROTLI_DEC_DECODE_H_ #define BROTLI_DEC_DECODE_H_ +#include "./state.h" #include "./streams.h" #include "./types.h" @@ -25,31 +26,105 @@ extern "C" { #endif +typedef enum { + /* Decoding error, e.g. corrupt input or no memory */ + BROTLI_RESULT_ERROR = 0, + /* Successfully completely done */ + BROTLI_RESULT_SUCCESS = 1, + /* Partially done, but must be called again with more input */ + BROTLI_RESULT_NEEDS_MORE_INPUT = 2, + /* Partially done, but must be called again with more output */ + BROTLI_RESULT_NEEDS_MORE_OUTPUT = 3 +} BrotliResult; + /* Sets *decoded_size to the decompressed size of the given encoded stream. */ /* This function only works if the encoded buffer has a single meta block, */ /* or if it has two meta-blocks, where the first is uncompressed and the */ /* second is empty. */ /* Returns 1 on success, 0 on failure. */ -int BrotliDecompressedSize(size_t encoded_size, - const uint8_t* encoded_buffer, - size_t* decoded_size); +BrotliResult BrotliDecompressedSize(size_t encoded_size, + const uint8_t* encoded_buffer, + size_t* decoded_size); /* Decompresses the data in encoded_buffer into decoded_buffer, and sets */ /* *decoded_size to the decompressed length. */ /* Returns 0 if there was either a bit stream error or memory allocation */ /* error, and 1 otherwise. */ /* If decoded size is zero, returns 1 and keeps decoded_buffer unchanged. */ -int BrotliDecompressBuffer(size_t encoded_size, - const uint8_t* encoded_buffer, - size_t* decoded_size, - uint8_t* decoded_buffer); +BrotliResult BrotliDecompressBuffer(size_t encoded_size, + const uint8_t* encoded_buffer, + size_t* decoded_size, + uint8_t* decoded_buffer); /* Same as above, but uses the specified input and output callbacks instead */ /* of reading from and writing to pre-allocated memory buffers. */ -int BrotliDecompress(BrotliInput input, BrotliOutput output); +BrotliResult BrotliDecompress(BrotliInput input, BrotliOutput output); + +/* Same as above, but supports the caller to call the decoder repeatedly with + partial data to support streaming. The state must be initialized with + BrotliStateInit and reused with every call for the same stream. + Return values: + 0: failure. + 1: success, and done. + 2: success so far, end not reached so should call again with more input. + The finish parameter is used as follows, for a series of calls with the + same state: + 0: Every call except the last one must be called with finish set to 0. The + last call may have finish set to either 0 or 1. Only if finish is 0, can + the function return 2. It may also return 0 or 1, in that case no more + calls (even with finish 1) may be made. + 1: Only the last call may have finish set to 1. It's ok to give empty input + if all input was already given to previous calls. It is also ok to have + only one single call in total, with finish 1, and with all input + available immediately. That matches the non-streaming case. If finish is + 1, the function can only return 0 or 1, never 2. After a finish, no more + calls may be done. + After everything is done, the state must be cleaned with BrotliStateCleanup + to free allocated resources. + The given BrotliOutput must always accept all output and make enough space, + it returning a smaller value than the amount of bytes to write always results + in an error. +*/ +BrotliResult BrotliDecompressStreaming(BrotliInput input, BrotliOutput output, + int finish, BrotliState* s); + +/* Same as above, but with memory buffers. + Must be called with an allocated input buffer in *next_in and an allocated + output buffer in *next_out. The values *available_in and *available_out + must specify the allocated size in *next_in and *next_out respectively. + The value *total_out must be 0 initially, and will be summed with the + amount of output bytes written after each call, so that at the end it + gives the complete decoded size. + After each call, *available_in will be decremented by the amount of input + bytes consumed, and the *next_in pointer will be incremented by that amount. + Similarly, *available_out will be decremented by the amount of output + bytes written, and the *next_out pointer will be incremented by that + amount. + + The input may be partial. With each next function call, *next_in and + *available_in must be updated to point to a next part of the compressed + input. The current implementation will always consume all input unless + an error occurs, so normally *available_in will always be 0 after + calling this function and the next adjacent part of input is desired. + + In the current implementation, the function requires that there is enough + output buffer size to write all currently processed input, so + *available_out must be large enough. Since the function updates *next_out + each time, as long as the output buffer is large enough you can keep + reusing this variable. It is also possible to update *next_out and + *available_out yourself before a next call, e.g. to point to a new larger + buffer. +*/ +BrotliResult BrotliDecompressBufferStreaming(size_t* available_in, + const uint8_t** next_in, + int finish, + size_t* available_out, + uint8_t** next_out, + size_t* total_out, + BrotliState* s); #if defined(__cplusplus) || defined(c_plusplus) -} /* extern "C" */ +} /* extern "C" */ #endif #endif /* BROTLI_DEC_DECODE_H_ */ diff --git a/third_party/brotli/dec/dictionary.h b/third_party/brotli/dec/dictionary.h index 9ca83e8af042c..cbfebdf63eb61 100644 --- a/third_party/brotli/dec/dictionary.h +++ b/third_party/brotli/dec/dictionary.h @@ -11,10 +11,10 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - - Collection of static dictionary words. */ +/* Collection of static dictionary words. */ + #ifndef BROTLI_DEC_DICTIONARY_H_ #define BROTLI_DEC_DICTIONARY_H_ diff --git a/third_party/brotli/dec/huffman.c b/third_party/brotli/dec/huffman.c index 12493a9969946..9590c761a07f7 100644 --- a/third_party/brotli/dec/huffman.c +++ b/third_party/brotli/dec/huffman.c @@ -11,10 +11,10 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - - Utilities for building Huffman decoding tables. */ +/* Utilities for building Huffman decoding tables. */ + #include #include #include @@ -159,6 +159,24 @@ int BrotliBuildHuffmanTable(HuffmanCode* root_table, return total_size; } +void BrotliHuffmanTreeGroupInit(HuffmanTreeGroup* group, int alphabet_size, + int ntrees) { + group->alphabet_size = alphabet_size; + group->num_htrees = ntrees; + group->codes = (HuffmanCode*)malloc( + sizeof(HuffmanCode) * (size_t)(ntrees * BROTLI_HUFFMAN_MAX_TABLE_SIZE)); + group->htrees = (HuffmanCode**)malloc(sizeof(HuffmanCode*) * (size_t)ntrees); +} + +void BrotliHuffmanTreeGroupRelease(HuffmanTreeGroup* group) { + if (group->codes) { + free(group->codes); + } + if (group->htrees) { + free(group->htrees); + } +} + #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif diff --git a/third_party/brotli/dec/huffman.h b/third_party/brotli/dec/huffman.h index 834b316c36000..edadac3b4439e 100644 --- a/third_party/brotli/dec/huffman.h +++ b/third_party/brotli/dec/huffman.h @@ -11,10 +11,10 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - - Utilities for building Huffman decoding tables. */ +/* Utilities for building Huffman decoding tables. */ + #ifndef BROTLI_DEC_HUFFMAN_H_ #define BROTLI_DEC_HUFFMAN_H_ @@ -25,6 +25,10 @@ extern "C" { #endif +/* Maximum possible Huffman table size for an alphabet size of 704, max code + * length 15 and root table bits 8. */ +#define BROTLI_HUFFMAN_MAX_TABLE_SIZE 1080 + typedef struct { uint8_t bits; /* number of bits used for this symbol */ uint16_t value; /* symbol value or table offset */ @@ -37,6 +41,18 @@ int BrotliBuildHuffmanTable(HuffmanCode* root_table, const uint8_t* const code_lengths, int code_lengths_size); +/* Contains a collection of huffman trees with the same alphabet size. */ +typedef struct { + int alphabet_size; + int num_htrees; + HuffmanCode* codes; + HuffmanCode** htrees; +} HuffmanTreeGroup; + +void BrotliHuffmanTreeGroupInit(HuffmanTreeGroup* group, + int alphabet_size, int ntrees); +void BrotliHuffmanTreeGroupRelease(HuffmanTreeGroup* group); + #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif diff --git a/third_party/brotli/dec/prefix.h b/third_party/brotli/dec/prefix.h index 06afe4df36b62..d2b1f9a985676 100644 --- a/third_party/brotli/dec/prefix.h +++ b/third_party/brotli/dec/prefix.h @@ -11,8 +11,9 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +*/ - Lookup tables to map prefix codes to value ranges. This is used during +/* Lookup tables to map prefix codes to value ranges. This is used during decoding of the block lengths, literal insertion lengths and copy lengths. */ diff --git a/third_party/brotli/dec/safe_malloc.c b/third_party/brotli/dec/safe_malloc.c index ef1624c72223b..a2ee50465bb35 100644 --- a/third_party/brotli/dec/safe_malloc.c +++ b/third_party/brotli/dec/safe_malloc.c @@ -11,10 +11,10 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - - Size-checked memory allocation. */ +/* Size-checked memory allocation. */ + #include #include "./safe_malloc.h" diff --git a/third_party/brotli/dec/safe_malloc.h b/third_party/brotli/dec/safe_malloc.h index 065f93084a2e7..0698239feb855 100644 --- a/third_party/brotli/dec/safe_malloc.h +++ b/third_party/brotli/dec/safe_malloc.h @@ -11,10 +11,10 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - - Size-checked memory allocation. */ +/* Size-checked memory allocation. */ + #ifndef BROTLI_DEC_SAFE_MALLOC_H_ #define BROTLI_DEC_SAFE_MALLOC_H_ diff --git a/third_party/brotli/dec/state.c b/third_party/brotli/dec/state.c new file mode 100644 index 0000000000000..7ad64be7a782f --- /dev/null +++ b/third_party/brotli/dec/state.c @@ -0,0 +1,87 @@ +/* Copyright 2015 Google Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include "./state.h" + +#include +#include + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + +void BrotliStateInit(BrotliState* s) { + int i; + + s->state = BROTLI_STATE_UNINITED; + s->sub_state[0] = BROTLI_STATE_SUB_NONE; + s->sub_state[1] = BROTLI_STATE_SUB_NONE; + + s->block_type_trees = NULL; + s->block_len_trees = NULL; + s->ringbuffer = NULL; + + s->context_map = NULL; + s->context_modes = NULL; + s->dist_context_map = NULL; + s->context_map_slice = NULL; + s->dist_context_map_slice = NULL; + + for (i = 0; i < 3; ++i) { + s->hgroup[i].codes = NULL; + s->hgroup[i].htrees = NULL; + } + + s->code_lengths = NULL; + s->context_map_table = NULL; +} + +void BrotliStateCleanup(BrotliState* s) { + int i; + + if (s->context_map_table != 0) { + free(s->context_map_table); + } + if (s->code_lengths != 0) { + free(s->code_lengths); + } + + if (s->context_modes != 0) { + free(s->context_modes); + } + if (s->context_map != 0) { + free(s->context_map); + } + if (s->dist_context_map != 0) { + free(s->dist_context_map); + } + for (i = 0; i < 3; ++i) { + BrotliHuffmanTreeGroupRelease(&s->hgroup[i]); + } + + if (s->ringbuffer != 0) { + free(s->ringbuffer); + } + if (s->block_type_trees != 0) { + free(s->block_type_trees); + } + if (s->block_len_trees != 0) { + free(s->block_len_trees); + } +} + +#if defined(__cplusplus) || defined(c_plusplus) +} /* extern "C" */ +#endif diff --git a/third_party/brotli/dec/state.h b/third_party/brotli/dec/state.h new file mode 100644 index 0000000000000..e5d6b5a5d0a52 --- /dev/null +++ b/third_party/brotli/dec/state.h @@ -0,0 +1,179 @@ +/* Copyright 2015 Google Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/* Brotli state for partial streaming decoding. */ + +#ifndef BROTLI_DEC_STATE_H_ +#define BROTLI_DEC_STATE_H_ + +#include +#include "./bit_reader.h" +#include "./huffman.h" +#include "./streams.h" +#include "./types.h" + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + +typedef enum { + BROTLI_STATE_UNINITED = 0, + BROTLI_STATE_BITREADER_WARMUP = 1, + BROTLI_STATE_METABLOCK_BEGIN = 10, + BROTLI_STATE_METABLOCK_HEADER_1 = 11, + BROTLI_STATE_METABLOCK_HEADER_2 = 12, + BROTLI_STATE_BLOCK_BEGIN = 13, + BROTLI_STATE_BLOCK_INNER = 14, + BROTLI_STATE_BLOCK_DISTANCE = 15, + BROTLI_STATE_BLOCK_POST = 16, + BROTLI_STATE_UNCOMPRESSED = 17, + BROTLI_STATE_METADATA = 18, + BROTLI_STATE_BLOCK_INNER_WRITE = 19, + BROTLI_STATE_METABLOCK_DONE = 20, + BROTLI_STATE_BLOCK_POST_WRITE_1 = 21, + BROTLI_STATE_BLOCK_POST_WRITE_2 = 22, + BROTLI_STATE_BLOCK_POST_CONTINUE = 23, + BROTLI_STATE_HUFFMAN_CODE_0 = 30, + BROTLI_STATE_HUFFMAN_CODE_1 = 31, + BROTLI_STATE_HUFFMAN_CODE_2 = 32, + BROTLI_STATE_CONTEXT_MAP_1 = 33, + BROTLI_STATE_CONTEXT_MAP_2 = 34, + BROTLI_STATE_TREE_GROUP = 35, + BROTLI_STATE_SUB_NONE = 50, + BROTLI_STATE_SUB_UNCOMPRESSED_SHORT = 51, + BROTLI_STATE_SUB_UNCOMPRESSED_FILL = 52, + BROTLI_STATE_SUB_UNCOMPRESSED_COPY = 53, + BROTLI_STATE_SUB_UNCOMPRESSED_WARMUP = 54, + BROTLI_STATE_SUB_UNCOMPRESSED_WRITE_1 = 55, + BROTLI_STATE_SUB_UNCOMPRESSED_WRITE_2 = 56, + BROTLI_STATE_SUB_UNCOMPRESSED_WRITE_3 = 57, + BROTLI_STATE_SUB_HUFFMAN_LENGTH_BEGIN = 60, + BROTLI_STATE_SUB_HUFFMAN_LENGTH_SYMBOLS = 61, + BROTLI_STATE_SUB_HUFFMAN_DONE = 62, + BROTLI_STATE_SUB_TREE_GROUP = 70, + BROTLI_STATE_SUB_CONTEXT_MAP_HUFFMAN = 80, + BROTLI_STATE_SUB_CONTEXT_MAPS = 81, + BROTLI_STATE_DONE = 100 +} BrotliRunningState; + +typedef struct { + BrotliRunningState state; + BrotliRunningState sub_state[2]; /* State inside function call */ + + int pos; + int input_end; + int window_bits; + int max_backward_distance; + int max_distance; + int ringbuffer_size; + int ringbuffer_mask; + uint8_t* ringbuffer; + uint8_t* ringbuffer_end; + /* This ring buffer holds a few past copy distances that will be used by */ + /* some special distance codes. */ + int dist_rb[4]; + int dist_rb_idx; + /* The previous 2 bytes used for context. */ + uint8_t prev_byte1; + uint8_t prev_byte2; + HuffmanTreeGroup hgroup[3]; + HuffmanCode* block_type_trees; + HuffmanCode* block_len_trees; + BrotliBitReader br; + /* This counter is reused for several disjoint loops. */ + int loop_counter; + /* This is true if the literal context map histogram type always matches the + block type. It is then not needed to keep the context (faster decoding). */ + int trivial_literal_context; + + int meta_block_remaining_len; + int is_metadata; + int is_uncompressed; + int block_length[3]; + int block_type[3]; + int num_block_types[3]; + int block_type_rb[6]; + int block_type_rb_index[3]; + int distance_postfix_bits; + int num_direct_distance_codes; + int distance_postfix_mask; + int num_distance_codes; + uint8_t* context_map; + uint8_t* context_modes; + int num_literal_htrees; + uint8_t* dist_context_map; + int num_dist_htrees; + int context_offset; + uint8_t* context_map_slice; + uint8_t literal_htree_index; + int dist_context_offset; + uint8_t* dist_context_map_slice; + uint8_t dist_htree_index; + int context_lookup_offset1; + int context_lookup_offset2; + uint8_t context_mode; + HuffmanCode* htree_command; + + int cmd_code; + int range_idx; + int insert_code; + int copy_code; + int insert_length; + int copy_length; + int distance_code; + int distance; + const uint8_t* copy_src; + uint8_t* copy_dst; + + /* For CopyUncompressedBlockToOutput */ + int nbytes; + + /* For partial write operations */ + int partially_written; + + /* For HuffmanTreeGroupDecode */ + int htrees_decoded; + + /* For ReadHuffmanCodeLengths */ + int symbol; + uint8_t prev_code_len; + int repeat; + uint8_t repeat_code_len; + int space; + HuffmanCode table[32]; + uint8_t code_length_code_lengths[18]; + + /* For ReadHuffmanCode */ + int simple_code_or_skip; + uint8_t* code_lengths; + + /* For HuffmanTreeGroupDecode */ + int htree_index; + HuffmanCode* next; + + /* For DecodeContextMap */ + int context_index; + int max_run_length_prefix; + HuffmanCode* context_map_table; +} BrotliState; + +void BrotliStateInit(BrotliState* s); +void BrotliStateCleanup(BrotliState* s); + +#if defined(__cplusplus) || defined(c_plusplus) +} /* extern "C" */ +#endif + +#endif /* BROTLI_DEC_STATE_H_ */ diff --git a/third_party/brotli/dec/streams.c b/third_party/brotli/dec/streams.c index 6147252535f3e..b33f7a46e9e26 100644 --- a/third_party/brotli/dec/streams.c +++ b/third_party/brotli/dec/streams.c @@ -11,10 +11,10 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - - Functions for streaming input and output. */ +/* Functions for streaming input and output. */ + #include #ifndef _WIN32 #include @@ -51,8 +51,9 @@ BrotliInput BrotliInitMemInput(const uint8_t* buffer, size_t length, int BrotliMemOutputFunction(void* data, const uint8_t* buf, size_t count) { BrotliMemOutput* output = (BrotliMemOutput*)data; - if (output->pos + count > output->length) { - return -1; + size_t limit = output->length - output->pos; + if (count > limit) { + count = limit; } memcpy(output->buffer + output->pos, buf, count); output->pos += count; @@ -71,6 +72,7 @@ BrotliOutput BrotliInitMemOutput(uint8_t* buffer, size_t length, } int BrotliStdinInputFunction(void* data, uint8_t* buf, size_t count) { + (void) data; /* Shut up LLVM */ #ifndef _WIN32 return (int)read(STDIN_FILENO, buf, count); #else @@ -86,6 +88,7 @@ BrotliInput BrotliStdinInput() { } int BrotliStdoutOutputFunction(void* data, const uint8_t* buf, size_t count) { + (void) data; /* Shut up LLVM */ #ifndef _WIN32 return (int)write(STDOUT_FILENO, buf, count); #else diff --git a/third_party/brotli/dec/streams.h b/third_party/brotli/dec/streams.h index 40fe3ef026ac7..71301a930a8e2 100644 --- a/third_party/brotli/dec/streams.h +++ b/third_party/brotli/dec/streams.h @@ -11,10 +11,10 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - - Functions for streaming input and output. */ +/* Functions for streaming input and output. */ + #ifndef BROTLI_DEC_STREAMS_H_ #define BROTLI_DEC_STREAMS_H_ diff --git a/third_party/brotli/dec/transform.h b/third_party/brotli/dec/transform.h index cd9e1b5b72a2c..011e787d082a3 100644 --- a/third_party/brotli/dec/transform.h +++ b/third_party/brotli/dec/transform.h @@ -11,10 +11,10 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - - Transformations on dictionary words. */ +/* Transformations on dictionary words. */ + #ifndef BROTLI_DEC_TRANSFORM_H_ #define BROTLI_DEC_TRANSFORM_H_ diff --git a/third_party/brotli/dec/types.h b/third_party/brotli/dec/types.h index 2f79b2a5d75c3..0aed3ef990bad 100644 --- a/third_party/brotli/dec/types.h +++ b/third_party/brotli/dec/types.h @@ -11,10 +11,10 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - - Common types */ +/* Common types */ + #ifndef BROTLI_DEC_TYPES_H_ #define BROTLI_DEC_TYPES_H_ diff --git a/third_party/expat/README.chromium b/third_party/expat/README.chromium index 7b47f5f7f1dda..a0af1e2d310fd 100644 --- a/third_party/expat/README.chromium +++ b/third_party/expat/README.chromium @@ -4,7 +4,7 @@ URL: http://sourceforge.net/projects/expat/ Version: 2.1.0 License: MIT License File: files/COPYING -Security Critical: no +Security Critical: yes Description: This is Expat XML parser - very lightweight C library for parsing XML. @@ -38,5 +38,8 @@ Local Modifications: lib/xmltok_impl.c (see xmltok_imp.c.original for unmodified version) * Prevent a compiler warning when compiling with WIN32_LEAN_AND_MEAN predefined. + lib/xmlparse.c (see xmlparse.c.original for unmodified version) + * Apply https://hg.mozilla.org/releases/mozilla-esr31/rev/2f3e78643f5c + to prevent an integer overflow. Added files: lib/expat_config.h (a generated config file) diff --git a/third_party/expat/files/lib/xmlparse.c b/third_party/expat/files/lib/xmlparse.c index f35aa36ba8a7f..ede7b5bb6673e 100644 --- a/third_party/expat/files/lib/xmlparse.c +++ b/third_party/expat/files/lib/xmlparse.c @@ -1678,6 +1678,12 @@ XML_ParseBuffer(XML_Parser parser, int len, int isFinal) void * XMLCALL XML_GetBuffer(XML_Parser parser, int len) { +/* BEGIN MOZILLA CHANGE (sanity check len) */ + if (len < 0) { + errorCode = XML_ERROR_NO_MEMORY; + return NULL; + } +/* END MOZILLA CHANGE */ switch (ps_parsing) { case XML_SUSPENDED: errorCode = XML_ERROR_SUSPENDED; @@ -1689,8 +1695,13 @@ XML_GetBuffer(XML_Parser parser, int len) } if (len > bufferLim - bufferEnd) { - /* FIXME avoid integer overflow */ int neededSize = len + (int)(bufferEnd - bufferPtr); +/* BEGIN MOZILLA CHANGE (sanity check neededSize) */ + if (neededSize < 0) { + errorCode = XML_ERROR_NO_MEMORY; + return NULL; + } +/* END MOZILLA CHANGE */ #ifdef XML_CONTEXT_BYTES int keep = (int)(bufferPtr - buffer); @@ -1719,7 +1730,15 @@ XML_GetBuffer(XML_Parser parser, int len) bufferSize = INIT_BUFFER_SIZE; do { bufferSize *= 2; - } while (bufferSize < neededSize); +/* BEGIN MOZILLA CHANGE (prevent infinite loop on overflow) */ + } while (bufferSize < neededSize && bufferSize > 0); +/* END MOZILLA CHANGE */ +/* BEGIN MOZILLA CHANGE (sanity check bufferSize) */ + if (bufferSize <= 0) { + errorCode = XML_ERROR_NO_MEMORY; + return NULL; + } +/* END MOZILLA CHANGE */ newBuf = (char *)MALLOC(bufferSize); if (newBuf == 0) { errorCode = XML_ERROR_NO_MEMORY; diff --git a/third_party/expat/files/lib/xmlparse.c.original b/third_party/expat/files/lib/xmlparse.c.original new file mode 100644 index 0000000000000..f35aa36ba8a7f --- /dev/null +++ b/third_party/expat/files/lib/xmlparse.c.original @@ -0,0 +1,6403 @@ +/* Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd + See the file COPYING for copying permission. +*/ + +#include +#include /* memset(), memcpy() */ +#include +#include /* UINT_MAX */ +#include /* time() */ + +#define XML_BUILDING_EXPAT 1 + +#ifdef COMPILED_FROM_DSP +#include "winconfig.h" +#elif defined(MACOS_CLASSIC) +#include "macconfig.h" +#elif defined(__amigaos__) +#include "amigaconfig.h" +#elif defined(__WATCOMC__) +#include "watcomconfig.h" +#elif defined(HAVE_EXPAT_CONFIG_H) +#include +#endif /* ndef COMPILED_FROM_DSP */ + +#include "ascii.h" +#include "expat.h" + +#ifdef XML_UNICODE +#define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX +#define XmlConvert XmlUtf16Convert +#define XmlGetInternalEncoding XmlGetUtf16InternalEncoding +#define XmlGetInternalEncodingNS XmlGetUtf16InternalEncodingNS +#define XmlEncode XmlUtf16Encode +/* Using pointer subtraction to convert to integer type. */ +#define MUST_CONVERT(enc, s) (!(enc)->isUtf16 || (((char *)(s) - (char *)NULL) & 1)) +typedef unsigned short ICHAR; +#else +#define XML_ENCODE_MAX XML_UTF8_ENCODE_MAX +#define XmlConvert XmlUtf8Convert +#define XmlGetInternalEncoding XmlGetUtf8InternalEncoding +#define XmlGetInternalEncodingNS XmlGetUtf8InternalEncodingNS +#define XmlEncode XmlUtf8Encode +#define MUST_CONVERT(enc, s) (!(enc)->isUtf8) +typedef char ICHAR; +#endif + + +#ifndef XML_NS + +#define XmlInitEncodingNS XmlInitEncoding +#define XmlInitUnknownEncodingNS XmlInitUnknownEncoding +#undef XmlGetInternalEncodingNS +#define XmlGetInternalEncodingNS XmlGetInternalEncoding +#define XmlParseXmlDeclNS XmlParseXmlDecl + +#endif + +#ifdef XML_UNICODE + +#ifdef XML_UNICODE_WCHAR_T +#define XML_T(x) (const wchar_t)x +#define XML_L(x) L ## x +#else +#define XML_T(x) (const unsigned short)x +#define XML_L(x) x +#endif + +#else + +#define XML_T(x) x +#define XML_L(x) x + +#endif + +/* Round up n to be a multiple of sz, where sz is a power of 2. */ +#define ROUND_UP(n, sz) (((n) + ((sz) - 1)) & ~((sz) - 1)) + +/* Handle the case where memmove() doesn't exist. */ +#ifndef HAVE_MEMMOVE +#ifdef HAVE_BCOPY +#define memmove(d,s,l) bcopy((s),(d),(l)) +#else +#error memmove does not exist on this platform, nor is a substitute available +#endif /* HAVE_BCOPY */ +#endif /* HAVE_MEMMOVE */ + +#include "internal.h" +#include "xmltok.h" +#include "xmlrole.h" + +typedef const XML_Char *KEY; + +typedef struct { + KEY name; +} NAMED; + +typedef struct { + NAMED **v; + unsigned char power; + size_t size; + size_t used; + const XML_Memory_Handling_Suite *mem; +} HASH_TABLE; + +/* Basic character hash algorithm, taken from Python's string hash: + h = h * 1000003 ^ character, the constant being a prime number. + +*/ +#ifdef XML_UNICODE +#define CHAR_HASH(h, c) \ + (((h) * 0xF4243) ^ (unsigned short)(c)) +#else +#define CHAR_HASH(h, c) \ + (((h) * 0xF4243) ^ (unsigned char)(c)) +#endif + +/* For probing (after a collision) we need a step size relative prime + to the hash table size, which is a power of 2. We use double-hashing, + since we can calculate a second hash value cheaply by taking those bits + of the first hash value that were discarded (masked out) when the table + index was calculated: index = hash & mask, where mask = table->size - 1. + We limit the maximum step size to table->size / 4 (mask >> 2) and make + it odd, since odd numbers are always relative prime to a power of 2. +*/ +#define SECOND_HASH(hash, mask, power) \ + ((((hash) & ~(mask)) >> ((power) - 1)) & ((mask) >> 2)) +#define PROBE_STEP(hash, mask, power) \ + ((unsigned char)((SECOND_HASH(hash, mask, power)) | 1)) + +typedef struct { + NAMED **p; + NAMED **end; +} HASH_TABLE_ITER; + +#define INIT_TAG_BUF_SIZE 32 /* must be a multiple of sizeof(XML_Char) */ +#define INIT_DATA_BUF_SIZE 1024 +#define INIT_ATTS_SIZE 16 +#define INIT_ATTS_VERSION 0xFFFFFFFF +#define INIT_BLOCK_SIZE 1024 +#define INIT_BUFFER_SIZE 1024 + +#define EXPAND_SPARE 24 + +typedef struct binding { + struct prefix *prefix; + struct binding *nextTagBinding; + struct binding *prevPrefixBinding; + const struct attribute_id *attId; + XML_Char *uri; + int uriLen; + int uriAlloc; +} BINDING; + +typedef struct prefix { + const XML_Char *name; + BINDING *binding; +} PREFIX; + +typedef struct { + const XML_Char *str; + const XML_Char *localPart; + const XML_Char *prefix; + int strLen; + int uriLen; + int prefixLen; +} TAG_NAME; + +/* TAG represents an open element. + The name of the element is stored in both the document and API + encodings. The memory buffer 'buf' is a separately-allocated + memory area which stores the name. During the XML_Parse()/ + XMLParseBuffer() when the element is open, the memory for the 'raw' + version of the name (in the document encoding) is shared with the + document buffer. If the element is open across calls to + XML_Parse()/XML_ParseBuffer(), the buffer is re-allocated to + contain the 'raw' name as well. + + A parser re-uses these structures, maintaining a list of allocated + TAG objects in a free list. +*/ +typedef struct tag { + struct tag *parent; /* parent of this element */ + const char *rawName; /* tagName in the original encoding */ + int rawNameLength; + TAG_NAME name; /* tagName in the API encoding */ + char *buf; /* buffer for name components */ + char *bufEnd; /* end of the buffer */ + BINDING *bindings; +} TAG; + +typedef struct { + const XML_Char *name; + const XML_Char *textPtr; + int textLen; /* length in XML_Chars */ + int processed; /* # of processed bytes - when suspended */ + const XML_Char *systemId; + const XML_Char *base; + const XML_Char *publicId; + const XML_Char *notation; + XML_Bool open; + XML_Bool is_param; + XML_Bool is_internal; /* true if declared in internal subset outside PE */ +} ENTITY; + +typedef struct { + enum XML_Content_Type type; + enum XML_Content_Quant quant; + const XML_Char * name; + int firstchild; + int lastchild; + int childcnt; + int nextsib; +} CONTENT_SCAFFOLD; + +#define INIT_SCAFFOLD_ELEMENTS 32 + +typedef struct block { + struct block *next; + int size; + XML_Char s[1]; +} BLOCK; + +typedef struct { + BLOCK *blocks; + BLOCK *freeBlocks; + const XML_Char *end; + XML_Char *ptr; + XML_Char *start; + const XML_Memory_Handling_Suite *mem; +} STRING_POOL; + +/* The XML_Char before the name is used to determine whether + an attribute has been specified. */ +typedef struct attribute_id { + XML_Char *name; + PREFIX *prefix; + XML_Bool maybeTokenized; + XML_Bool xmlns; +} ATTRIBUTE_ID; + +typedef struct { + const ATTRIBUTE_ID *id; + XML_Bool isCdata; + const XML_Char *value; +} DEFAULT_ATTRIBUTE; + +typedef struct { + unsigned long version; + unsigned long hash; + const XML_Char *uriName; +} NS_ATT; + +typedef struct { + const XML_Char *name; + PREFIX *prefix; + const ATTRIBUTE_ID *idAtt; + int nDefaultAtts; + int allocDefaultAtts; + DEFAULT_ATTRIBUTE *defaultAtts; +} ELEMENT_TYPE; + +typedef struct { + HASH_TABLE generalEntities; + HASH_TABLE elementTypes; + HASH_TABLE attributeIds; + HASH_TABLE prefixes; + STRING_POOL pool; + STRING_POOL entityValuePool; + /* false once a parameter entity reference has been skipped */ + XML_Bool keepProcessing; + /* true once an internal or external PE reference has been encountered; + this includes the reference to an external subset */ + XML_Bool hasParamEntityRefs; + XML_Bool standalone; +#ifdef XML_DTD + /* indicates if external PE has been read */ + XML_Bool paramEntityRead; + HASH_TABLE paramEntities; +#endif /* XML_DTD */ + PREFIX defaultPrefix; + /* === scaffolding for building content model === */ + XML_Bool in_eldecl; + CONTENT_SCAFFOLD *scaffold; + unsigned contentStringLen; + unsigned scaffSize; + unsigned scaffCount; + int scaffLevel; + int *scaffIndex; +} DTD; + +typedef struct open_internal_entity { + const char *internalEventPtr; + const char *internalEventEndPtr; + struct open_internal_entity *next; + ENTITY *entity; + int startTagLevel; + XML_Bool betweenDecl; /* WFC: PE Between Declarations */ +} OPEN_INTERNAL_ENTITY; + +typedef enum XML_Error PTRCALL Processor(XML_Parser parser, + const char *start, + const char *end, + const char **endPtr); + +static Processor prologProcessor; +static Processor prologInitProcessor; +static Processor contentProcessor; +static Processor cdataSectionProcessor; +#ifdef XML_DTD +static Processor ignoreSectionProcessor; +static Processor externalParEntProcessor; +static Processor externalParEntInitProcessor; +static Processor entityValueProcessor; +static Processor entityValueInitProcessor; +#endif /* XML_DTD */ +static Processor epilogProcessor; +static Processor errorProcessor; +static Processor externalEntityInitProcessor; +static Processor externalEntityInitProcessor2; +static Processor externalEntityInitProcessor3; +static Processor externalEntityContentProcessor; +static Processor internalEntityProcessor; + +static enum XML_Error +handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName); +static enum XML_Error +processXmlDecl(XML_Parser parser, int isGeneralTextEntity, + const char *s, const char *next); +static enum XML_Error +initializeEncoding(XML_Parser parser); +static enum XML_Error +doProlog(XML_Parser parser, const ENCODING *enc, const char *s, + const char *end, int tok, const char *next, const char **nextPtr, + XML_Bool haveMore); +static enum XML_Error +processInternalEntity(XML_Parser parser, ENTITY *entity, + XML_Bool betweenDecl); +static enum XML_Error +doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc, + const char *start, const char *end, const char **endPtr, + XML_Bool haveMore); +static enum XML_Error +doCdataSection(XML_Parser parser, const ENCODING *, const char **startPtr, + const char *end, const char **nextPtr, XML_Bool haveMore); +#ifdef XML_DTD +static enum XML_Error +doIgnoreSection(XML_Parser parser, const ENCODING *, const char **startPtr, + const char *end, const char **nextPtr, XML_Bool haveMore); +#endif /* XML_DTD */ + +static enum XML_Error +storeAtts(XML_Parser parser, const ENCODING *, const char *s, + TAG_NAME *tagNamePtr, BINDING **bindingsPtr); +static enum XML_Error +addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, + const XML_Char *uri, BINDING **bindingsPtr); +static int +defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, XML_Bool isCdata, + XML_Bool isId, const XML_Char *dfltValue, XML_Parser parser); +static enum XML_Error +storeAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata, + const char *, const char *, STRING_POOL *); +static enum XML_Error +appendAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata, + const char *, const char *, STRING_POOL *); +static ATTRIBUTE_ID * +getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start, + const char *end); +static int +setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *); +static enum XML_Error +storeEntityValue(XML_Parser parser, const ENCODING *enc, const char *start, + const char *end); +static int +reportProcessingInstruction(XML_Parser parser, const ENCODING *enc, + const char *start, const char *end); +static int +reportComment(XML_Parser parser, const ENCODING *enc, const char *start, + const char *end); +static void +reportDefault(XML_Parser parser, const ENCODING *enc, const char *start, + const char *end); + +static const XML_Char * getContext(XML_Parser parser); +static XML_Bool +setContext(XML_Parser parser, const XML_Char *context); + +static void FASTCALL normalizePublicId(XML_Char *s); + +static DTD * dtdCreate(const XML_Memory_Handling_Suite *ms); +/* do not call if parentParser != NULL */ +static void dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms); +static void +dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms); +static int +dtdCopy(XML_Parser oldParser, + DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms); +static int +copyEntityTable(XML_Parser oldParser, + HASH_TABLE *, STRING_POOL *, const HASH_TABLE *); +static NAMED * +lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize); +static void FASTCALL +hashTableInit(HASH_TABLE *, const XML_Memory_Handling_Suite *ms); +static void FASTCALL hashTableClear(HASH_TABLE *); +static void FASTCALL hashTableDestroy(HASH_TABLE *); +static void FASTCALL +hashTableIterInit(HASH_TABLE_ITER *, const HASH_TABLE *); +static NAMED * FASTCALL hashTableIterNext(HASH_TABLE_ITER *); + +static void FASTCALL +poolInit(STRING_POOL *, const XML_Memory_Handling_Suite *ms); +static void FASTCALL poolClear(STRING_POOL *); +static void FASTCALL poolDestroy(STRING_POOL *); +static XML_Char * +poolAppend(STRING_POOL *pool, const ENCODING *enc, + const char *ptr, const char *end); +static XML_Char * +poolStoreString(STRING_POOL *pool, const ENCODING *enc, + const char *ptr, const char *end); +static XML_Bool FASTCALL poolGrow(STRING_POOL *pool); +static const XML_Char * FASTCALL +poolCopyString(STRING_POOL *pool, const XML_Char *s); +static const XML_Char * +poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n); +static const XML_Char * FASTCALL +poolAppendString(STRING_POOL *pool, const XML_Char *s); + +static int FASTCALL nextScaffoldPart(XML_Parser parser); +static XML_Content * build_model(XML_Parser parser); +static ELEMENT_TYPE * +getElementType(XML_Parser parser, const ENCODING *enc, + const char *ptr, const char *end); + +static unsigned long generate_hash_secret_salt(void); +static XML_Bool startParsing(XML_Parser parser); + +static XML_Parser +parserCreate(const XML_Char *encodingName, + const XML_Memory_Handling_Suite *memsuite, + const XML_Char *nameSep, + DTD *dtd); + +static void +parserInit(XML_Parser parser, const XML_Char *encodingName); + +#define poolStart(pool) ((pool)->start) +#define poolEnd(pool) ((pool)->ptr) +#define poolLength(pool) ((pool)->ptr - (pool)->start) +#define poolChop(pool) ((void)--(pool->ptr)) +#define poolLastChar(pool) (((pool)->ptr)[-1]) +#define poolDiscard(pool) ((pool)->ptr = (pool)->start) +#define poolFinish(pool) ((pool)->start = (pool)->ptr) +#define poolAppendChar(pool, c) \ + (((pool)->ptr == (pool)->end && !poolGrow(pool)) \ + ? 0 \ + : ((*((pool)->ptr)++ = c), 1)) + +struct XML_ParserStruct { + /* The first member must be userData so that the XML_GetUserData + macro works. */ + void *m_userData; + void *m_handlerArg; + char *m_buffer; + const XML_Memory_Handling_Suite m_mem; + /* first character to be parsed */ + const char *m_bufferPtr; + /* past last character to be parsed */ + char *m_bufferEnd; + /* allocated end of buffer */ + const char *m_bufferLim; + XML_Index m_parseEndByteIndex; + const char *m_parseEndPtr; + XML_Char *m_dataBuf; + XML_Char *m_dataBufEnd; + XML_StartElementHandler m_startElementHandler; + XML_EndElementHandler m_endElementHandler; + XML_CharacterDataHandler m_characterDataHandler; + XML_ProcessingInstructionHandler m_processingInstructionHandler; + XML_CommentHandler m_commentHandler; + XML_StartCdataSectionHandler m_startCdataSectionHandler; + XML_EndCdataSectionHandler m_endCdataSectionHandler; + XML_DefaultHandler m_defaultHandler; + XML_StartDoctypeDeclHandler m_startDoctypeDeclHandler; + XML_EndDoctypeDeclHandler m_endDoctypeDeclHandler; + XML_UnparsedEntityDeclHandler m_unparsedEntityDeclHandler; + XML_NotationDeclHandler m_notationDeclHandler; + XML_StartNamespaceDeclHandler m_startNamespaceDeclHandler; + XML_EndNamespaceDeclHandler m_endNamespaceDeclHandler; + XML_NotStandaloneHandler m_notStandaloneHandler; + XML_ExternalEntityRefHandler m_externalEntityRefHandler; + XML_Parser m_externalEntityRefHandlerArg; + XML_SkippedEntityHandler m_skippedEntityHandler; + XML_UnknownEncodingHandler m_unknownEncodingHandler; + XML_ElementDeclHandler m_elementDeclHandler; + XML_AttlistDeclHandler m_attlistDeclHandler; + XML_EntityDeclHandler m_entityDeclHandler; + XML_XmlDeclHandler m_xmlDeclHandler; + const ENCODING *m_encoding; + INIT_ENCODING m_initEncoding; + const ENCODING *m_internalEncoding; + const XML_Char *m_protocolEncodingName; + XML_Bool m_ns; + XML_Bool m_ns_triplets; + void *m_unknownEncodingMem; + void *m_unknownEncodingData; + void *m_unknownEncodingHandlerData; + void (XMLCALL *m_unknownEncodingRelease)(void *); + PROLOG_STATE m_prologState; + Processor *m_processor; + enum XML_Error m_errorCode; + const char *m_eventPtr; + const char *m_eventEndPtr; + const char *m_positionPtr; + OPEN_INTERNAL_ENTITY *m_openInternalEntities; + OPEN_INTERNAL_ENTITY *m_freeInternalEntities; + XML_Bool m_defaultExpandInternalEntities; + int m_tagLevel; + ENTITY *m_declEntity; + const XML_Char *m_doctypeName; + const XML_Char *m_doctypeSysid; + const XML_Char *m_doctypePubid; + const XML_Char *m_declAttributeType; + const XML_Char *m_declNotationName; + const XML_Char *m_declNotationPublicId; + ELEMENT_TYPE *m_declElementType; + ATTRIBUTE_ID *m_declAttributeId; + XML_Bool m_declAttributeIsCdata; + XML_Bool m_declAttributeIsId; + DTD *m_dtd; + const XML_Char *m_curBase; + TAG *m_tagStack; + TAG *m_freeTagList; + BINDING *m_inheritedBindings; + BINDING *m_freeBindingList; + int m_attsSize; + int m_nSpecifiedAtts; + int m_idAttIndex; + ATTRIBUTE *m_atts; + NS_ATT *m_nsAtts; + unsigned long m_nsAttsVersion; + unsigned char m_nsAttsPower; +#ifdef XML_ATTR_INFO + XML_AttrInfo *m_attInfo; +#endif + POSITION m_position; + STRING_POOL m_tempPool; + STRING_POOL m_temp2Pool; + char *m_groupConnector; + unsigned int m_groupSize; + XML_Char m_namespaceSeparator; + XML_Parser m_parentParser; + XML_ParsingStatus m_parsingStatus; +#ifdef XML_DTD + XML_Bool m_isParamEntity; + XML_Bool m_useForeignDTD; + enum XML_ParamEntityParsing m_paramEntityParsing; +#endif + unsigned long m_hash_secret_salt; +}; + +#define MALLOC(s) (parser->m_mem.malloc_fcn((s))) +#define REALLOC(p,s) (parser->m_mem.realloc_fcn((p),(s))) +#define FREE(p) (parser->m_mem.free_fcn((p))) + +#define userData (parser->m_userData) +#define handlerArg (parser->m_handlerArg) +#define startElementHandler (parser->m_startElementHandler) +#define endElementHandler (parser->m_endElementHandler) +#define characterDataHandler (parser->m_characterDataHandler) +#define processingInstructionHandler \ + (parser->m_processingInstructionHandler) +#define commentHandler (parser->m_commentHandler) +#define startCdataSectionHandler \ + (parser->m_startCdataSectionHandler) +#define endCdataSectionHandler (parser->m_endCdataSectionHandler) +#define defaultHandler (parser->m_defaultHandler) +#define startDoctypeDeclHandler (parser->m_startDoctypeDeclHandler) +#define endDoctypeDeclHandler (parser->m_endDoctypeDeclHandler) +#define unparsedEntityDeclHandler \ + (parser->m_unparsedEntityDeclHandler) +#define notationDeclHandler (parser->m_notationDeclHandler) +#define startNamespaceDeclHandler \ + (parser->m_startNamespaceDeclHandler) +#define endNamespaceDeclHandler (parser->m_endNamespaceDeclHandler) +#define notStandaloneHandler (parser->m_notStandaloneHandler) +#define externalEntityRefHandler \ + (parser->m_externalEntityRefHandler) +#define externalEntityRefHandlerArg \ + (parser->m_externalEntityRefHandlerArg) +#define internalEntityRefHandler \ + (parser->m_internalEntityRefHandler) +#define skippedEntityHandler (parser->m_skippedEntityHandler) +#define unknownEncodingHandler (parser->m_unknownEncodingHandler) +#define elementDeclHandler (parser->m_elementDeclHandler) +#define attlistDeclHandler (parser->m_attlistDeclHandler) +#define entityDeclHandler (parser->m_entityDeclHandler) +#define xmlDeclHandler (parser->m_xmlDeclHandler) +#define encoding (parser->m_encoding) +#define initEncoding (parser->m_initEncoding) +#define internalEncoding (parser->m_internalEncoding) +#define unknownEncodingMem (parser->m_unknownEncodingMem) +#define unknownEncodingData (parser->m_unknownEncodingData) +#define unknownEncodingHandlerData \ + (parser->m_unknownEncodingHandlerData) +#define unknownEncodingRelease (parser->m_unknownEncodingRelease) +#define protocolEncodingName (parser->m_protocolEncodingName) +#define ns (parser->m_ns) +#define ns_triplets (parser->m_ns_triplets) +#define prologState (parser->m_prologState) +#define processor (parser->m_processor) +#define errorCode (parser->m_errorCode) +#define eventPtr (parser->m_eventPtr) +#define eventEndPtr (parser->m_eventEndPtr) +#define positionPtr (parser->m_positionPtr) +#define position (parser->m_position) +#define openInternalEntities (parser->m_openInternalEntities) +#define freeInternalEntities (parser->m_freeInternalEntities) +#define defaultExpandInternalEntities \ + (parser->m_defaultExpandInternalEntities) +#define tagLevel (parser->m_tagLevel) +#define buffer (parser->m_buffer) +#define bufferPtr (parser->m_bufferPtr) +#define bufferEnd (parser->m_bufferEnd) +#define parseEndByteIndex (parser->m_parseEndByteIndex) +#define parseEndPtr (parser->m_parseEndPtr) +#define bufferLim (parser->m_bufferLim) +#define dataBuf (parser->m_dataBuf) +#define dataBufEnd (parser->m_dataBufEnd) +#define _dtd (parser->m_dtd) +#define curBase (parser->m_curBase) +#define declEntity (parser->m_declEntity) +#define doctypeName (parser->m_doctypeName) +#define doctypeSysid (parser->m_doctypeSysid) +#define doctypePubid (parser->m_doctypePubid) +#define declAttributeType (parser->m_declAttributeType) +#define declNotationName (parser->m_declNotationName) +#define declNotationPublicId (parser->m_declNotationPublicId) +#define declElementType (parser->m_declElementType) +#define declAttributeId (parser->m_declAttributeId) +#define declAttributeIsCdata (parser->m_declAttributeIsCdata) +#define declAttributeIsId (parser->m_declAttributeIsId) +#define freeTagList (parser->m_freeTagList) +#define freeBindingList (parser->m_freeBindingList) +#define inheritedBindings (parser->m_inheritedBindings) +#define tagStack (parser->m_tagStack) +#define atts (parser->m_atts) +#define attsSize (parser->m_attsSize) +#define nSpecifiedAtts (parser->m_nSpecifiedAtts) +#define idAttIndex (parser->m_idAttIndex) +#define nsAtts (parser->m_nsAtts) +#define nsAttsVersion (parser->m_nsAttsVersion) +#define nsAttsPower (parser->m_nsAttsPower) +#define attInfo (parser->m_attInfo) +#define tempPool (parser->m_tempPool) +#define temp2Pool (parser->m_temp2Pool) +#define groupConnector (parser->m_groupConnector) +#define groupSize (parser->m_groupSize) +#define namespaceSeparator (parser->m_namespaceSeparator) +#define parentParser (parser->m_parentParser) +#define ps_parsing (parser->m_parsingStatus.parsing) +#define ps_finalBuffer (parser->m_parsingStatus.finalBuffer) +#ifdef XML_DTD +#define isParamEntity (parser->m_isParamEntity) +#define useForeignDTD (parser->m_useForeignDTD) +#define paramEntityParsing (parser->m_paramEntityParsing) +#endif /* XML_DTD */ +#define hash_secret_salt (parser->m_hash_secret_salt) + +XML_Parser XMLCALL +XML_ParserCreate(const XML_Char *encodingName) +{ + return XML_ParserCreate_MM(encodingName, NULL, NULL); +} + +XML_Parser XMLCALL +XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep) +{ + XML_Char tmp[2]; + *tmp = nsSep; + return XML_ParserCreate_MM(encodingName, NULL, tmp); +} + +static const XML_Char implicitContext[] = { + ASCII_x, ASCII_m, ASCII_l, ASCII_EQUALS, ASCII_h, ASCII_t, ASCII_t, ASCII_p, + ASCII_COLON, ASCII_SLASH, ASCII_SLASH, ASCII_w, ASCII_w, ASCII_w, + ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD, ASCII_o, ASCII_r, ASCII_g, + ASCII_SLASH, ASCII_X, ASCII_M, ASCII_L, ASCII_SLASH, ASCII_1, ASCII_9, + ASCII_9, ASCII_8, ASCII_SLASH, ASCII_n, ASCII_a, ASCII_m, ASCII_e, + ASCII_s, ASCII_p, ASCII_a, ASCII_c, ASCII_e, '\0' +}; + +static unsigned long +generate_hash_secret_salt(void) +{ + unsigned int seed = time(NULL) % UINT_MAX; + srand(seed); + return rand(); +} + +static XML_Bool /* only valid for root parser */ +startParsing(XML_Parser parser) +{ + /* hash functions must be initialized before setContext() is called */ + if (hash_secret_salt == 0) + hash_secret_salt = generate_hash_secret_salt(); + if (ns) { + /* implicit context only set for root parser, since child + parsers (i.e. external entity parsers) will inherit it + */ + return setContext(parser, implicitContext); + } + return XML_TRUE; +} + +XML_Parser XMLCALL +XML_ParserCreate_MM(const XML_Char *encodingName, + const XML_Memory_Handling_Suite *memsuite, + const XML_Char *nameSep) +{ + return parserCreate(encodingName, memsuite, nameSep, NULL); +} + +static XML_Parser +parserCreate(const XML_Char *encodingName, + const XML_Memory_Handling_Suite *memsuite, + const XML_Char *nameSep, + DTD *dtd) +{ + XML_Parser parser; + + if (memsuite) { + XML_Memory_Handling_Suite *mtemp; + parser = (XML_Parser) + memsuite->malloc_fcn(sizeof(struct XML_ParserStruct)); + if (parser != NULL) { + mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem); + mtemp->malloc_fcn = memsuite->malloc_fcn; + mtemp->realloc_fcn = memsuite->realloc_fcn; + mtemp->free_fcn = memsuite->free_fcn; + } + } + else { + XML_Memory_Handling_Suite *mtemp; + parser = (XML_Parser)malloc(sizeof(struct XML_ParserStruct)); + if (parser != NULL) { + mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem); + mtemp->malloc_fcn = malloc; + mtemp->realloc_fcn = realloc; + mtemp->free_fcn = free; + } + } + + if (!parser) + return parser; + + buffer = NULL; + bufferLim = NULL; + + attsSize = INIT_ATTS_SIZE; + atts = (ATTRIBUTE *)MALLOC(attsSize * sizeof(ATTRIBUTE)); + if (atts == NULL) { + FREE(parser); + return NULL; + } +#ifdef XML_ATTR_INFO + attInfo = (XML_AttrInfo*)MALLOC(attsSize * sizeof(XML_AttrInfo)); + if (attInfo == NULL) { + FREE(atts); + FREE(parser); + return NULL; + } +#endif + dataBuf = (XML_Char *)MALLOC(INIT_DATA_BUF_SIZE * sizeof(XML_Char)); + if (dataBuf == NULL) { + FREE(atts); +#ifdef XML_ATTR_INFO + FREE(attInfo); +#endif + FREE(parser); + return NULL; + } + dataBufEnd = dataBuf + INIT_DATA_BUF_SIZE; + + if (dtd) + _dtd = dtd; + else { + _dtd = dtdCreate(&parser->m_mem); + if (_dtd == NULL) { + FREE(dataBuf); + FREE(atts); +#ifdef XML_ATTR_INFO + FREE(attInfo); +#endif + FREE(parser); + return NULL; + } + } + + freeBindingList = NULL; + freeTagList = NULL; + freeInternalEntities = NULL; + + groupSize = 0; + groupConnector = NULL; + + unknownEncodingHandler = NULL; + unknownEncodingHandlerData = NULL; + + namespaceSeparator = ASCII_EXCL; + ns = XML_FALSE; + ns_triplets = XML_FALSE; + + nsAtts = NULL; + nsAttsVersion = 0; + nsAttsPower = 0; + + poolInit(&tempPool, &(parser->m_mem)); + poolInit(&temp2Pool, &(parser->m_mem)); + parserInit(parser, encodingName); + + if (encodingName && !protocolEncodingName) { + XML_ParserFree(parser); + return NULL; + } + + if (nameSep) { + ns = XML_TRUE; + internalEncoding = XmlGetInternalEncodingNS(); + namespaceSeparator = *nameSep; + } + else { + internalEncoding = XmlGetInternalEncoding(); + } + + return parser; +} + +static void +parserInit(XML_Parser parser, const XML_Char *encodingName) +{ + processor = prologInitProcessor; + XmlPrologStateInit(&prologState); + protocolEncodingName = (encodingName != NULL + ? poolCopyString(&tempPool, encodingName) + : NULL); + curBase = NULL; + XmlInitEncoding(&initEncoding, &encoding, 0); + userData = NULL; + handlerArg = NULL; + startElementHandler = NULL; + endElementHandler = NULL; + characterDataHandler = NULL; + processingInstructionHandler = NULL; + commentHandler = NULL; + startCdataSectionHandler = NULL; + endCdataSectionHandler = NULL; + defaultHandler = NULL; + startDoctypeDeclHandler = NULL; + endDoctypeDeclHandler = NULL; + unparsedEntityDeclHandler = NULL; + notationDeclHandler = NULL; + startNamespaceDeclHandler = NULL; + endNamespaceDeclHandler = NULL; + notStandaloneHandler = NULL; + externalEntityRefHandler = NULL; + externalEntityRefHandlerArg = parser; + skippedEntityHandler = NULL; + elementDeclHandler = NULL; + attlistDeclHandler = NULL; + entityDeclHandler = NULL; + xmlDeclHandler = NULL; + bufferPtr = buffer; + bufferEnd = buffer; + parseEndByteIndex = 0; + parseEndPtr = NULL; + declElementType = NULL; + declAttributeId = NULL; + declEntity = NULL; + doctypeName = NULL; + doctypeSysid = NULL; + doctypePubid = NULL; + declAttributeType = NULL; + declNotationName = NULL; + declNotationPublicId = NULL; + declAttributeIsCdata = XML_FALSE; + declAttributeIsId = XML_FALSE; + memset(&position, 0, sizeof(POSITION)); + errorCode = XML_ERROR_NONE; + eventPtr = NULL; + eventEndPtr = NULL; + positionPtr = NULL; + openInternalEntities = NULL; + defaultExpandInternalEntities = XML_TRUE; + tagLevel = 0; + tagStack = NULL; + inheritedBindings = NULL; + nSpecifiedAtts = 0; + unknownEncodingMem = NULL; + unknownEncodingRelease = NULL; + unknownEncodingData = NULL; + parentParser = NULL; + ps_parsing = XML_INITIALIZED; +#ifdef XML_DTD + isParamEntity = XML_FALSE; + useForeignDTD = XML_FALSE; + paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER; +#endif + hash_secret_salt = 0; +} + +/* moves list of bindings to freeBindingList */ +static void FASTCALL +moveToFreeBindingList(XML_Parser parser, BINDING *bindings) +{ + while (bindings) { + BINDING *b = bindings; + bindings = bindings->nextTagBinding; + b->nextTagBinding = freeBindingList; + freeBindingList = b; + } +} + +XML_Bool XMLCALL +XML_ParserReset(XML_Parser parser, const XML_Char *encodingName) +{ + TAG *tStk; + OPEN_INTERNAL_ENTITY *openEntityList; + if (parentParser) + return XML_FALSE; + /* move tagStack to freeTagList */ + tStk = tagStack; + while (tStk) { + TAG *tag = tStk; + tStk = tStk->parent; + tag->parent = freeTagList; + moveToFreeBindingList(parser, tag->bindings); + tag->bindings = NULL; + freeTagList = tag; + } + /* move openInternalEntities to freeInternalEntities */ + openEntityList = openInternalEntities; + while (openEntityList) { + OPEN_INTERNAL_ENTITY *openEntity = openEntityList; + openEntityList = openEntity->next; + openEntity->next = freeInternalEntities; + freeInternalEntities = openEntity; + } + moveToFreeBindingList(parser, inheritedBindings); + FREE(unknownEncodingMem); + if (unknownEncodingRelease) + unknownEncodingRelease(unknownEncodingData); + poolClear(&tempPool); + poolClear(&temp2Pool); + parserInit(parser, encodingName); + dtdReset(_dtd, &parser->m_mem); + return XML_TRUE; +} + +enum XML_Status XMLCALL +XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName) +{ + /* Block after XML_Parse()/XML_ParseBuffer() has been called. + XXX There's no way for the caller to determine which of the + XXX possible error cases caused the XML_STATUS_ERROR return. + */ + if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED) + return XML_STATUS_ERROR; + if (encodingName == NULL) + protocolEncodingName = NULL; + else { + protocolEncodingName = poolCopyString(&tempPool, encodingName); + if (!protocolEncodingName) + return XML_STATUS_ERROR; + } + return XML_STATUS_OK; +} + +XML_Parser XMLCALL +XML_ExternalEntityParserCreate(XML_Parser oldParser, + const XML_Char *context, + const XML_Char *encodingName) +{ + XML_Parser parser = oldParser; + DTD *newDtd = NULL; + DTD *oldDtd = _dtd; + XML_StartElementHandler oldStartElementHandler = startElementHandler; + XML_EndElementHandler oldEndElementHandler = endElementHandler; + XML_CharacterDataHandler oldCharacterDataHandler = characterDataHandler; + XML_ProcessingInstructionHandler oldProcessingInstructionHandler + = processingInstructionHandler; + XML_CommentHandler oldCommentHandler = commentHandler; + XML_StartCdataSectionHandler oldStartCdataSectionHandler + = startCdataSectionHandler; + XML_EndCdataSectionHandler oldEndCdataSectionHandler + = endCdataSectionHandler; + XML_DefaultHandler oldDefaultHandler = defaultHandler; + XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler + = unparsedEntityDeclHandler; + XML_NotationDeclHandler oldNotationDeclHandler = notationDeclHandler; + XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler + = startNamespaceDeclHandler; + XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler + = endNamespaceDeclHandler; + XML_NotStandaloneHandler oldNotStandaloneHandler = notStandaloneHandler; + XML_ExternalEntityRefHandler oldExternalEntityRefHandler + = externalEntityRefHandler; + XML_SkippedEntityHandler oldSkippedEntityHandler = skippedEntityHandler; + XML_UnknownEncodingHandler oldUnknownEncodingHandler + = unknownEncodingHandler; + XML_ElementDeclHandler oldElementDeclHandler = elementDeclHandler; + XML_AttlistDeclHandler oldAttlistDeclHandler = attlistDeclHandler; + XML_EntityDeclHandler oldEntityDeclHandler = entityDeclHandler; + XML_XmlDeclHandler oldXmlDeclHandler = xmlDeclHandler; + ELEMENT_TYPE * oldDeclElementType = declElementType; + + void *oldUserData = userData; + void *oldHandlerArg = handlerArg; + XML_Bool oldDefaultExpandInternalEntities = defaultExpandInternalEntities; + XML_Parser oldExternalEntityRefHandlerArg = externalEntityRefHandlerArg; +#ifdef XML_DTD + enum XML_ParamEntityParsing oldParamEntityParsing = paramEntityParsing; + int oldInEntityValue = prologState.inEntityValue; +#endif + XML_Bool oldns_triplets = ns_triplets; + /* Note that the new parser shares the same hash secret as the old + parser, so that dtdCopy and copyEntityTable can lookup values + from hash tables associated with either parser without us having + to worry which hash secrets each table has. + */ + unsigned long oldhash_secret_salt = hash_secret_salt; + +#ifdef XML_DTD + if (!context) + newDtd = oldDtd; +#endif /* XML_DTD */ + + /* Note that the magical uses of the pre-processor to make field + access look more like C++ require that `parser' be overwritten + here. This makes this function more painful to follow than it + would be otherwise. + */ + if (ns) { + XML_Char tmp[2]; + *tmp = namespaceSeparator; + parser = parserCreate(encodingName, &parser->m_mem, tmp, newDtd); + } + else { + parser = parserCreate(encodingName, &parser->m_mem, NULL, newDtd); + } + + if (!parser) + return NULL; + + startElementHandler = oldStartElementHandler; + endElementHandler = oldEndElementHandler; + characterDataHandler = oldCharacterDataHandler; + processingInstructionHandler = oldProcessingInstructionHandler; + commentHandler = oldCommentHandler; + startCdataSectionHandler = oldStartCdataSectionHandler; + endCdataSectionHandler = oldEndCdataSectionHandler; + defaultHandler = oldDefaultHandler; + unparsedEntityDeclHandler = oldUnparsedEntityDeclHandler; + notationDeclHandler = oldNotationDeclHandler; + startNamespaceDeclHandler = oldStartNamespaceDeclHandler; + endNamespaceDeclHandler = oldEndNamespaceDeclHandler; + notStandaloneHandler = oldNotStandaloneHandler; + externalEntityRefHandler = oldExternalEntityRefHandler; + skippedEntityHandler = oldSkippedEntityHandler; + unknownEncodingHandler = oldUnknownEncodingHandler; + elementDeclHandler = oldElementDeclHandler; + attlistDeclHandler = oldAttlistDeclHandler; + entityDeclHandler = oldEntityDeclHandler; + xmlDeclHandler = oldXmlDeclHandler; + declElementType = oldDeclElementType; + userData = oldUserData; + if (oldUserData == oldHandlerArg) + handlerArg = userData; + else + handlerArg = parser; + if (oldExternalEntityRefHandlerArg != oldParser) + externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg; + defaultExpandInternalEntities = oldDefaultExpandInternalEntities; + ns_triplets = oldns_triplets; + hash_secret_salt = oldhash_secret_salt; + parentParser = oldParser; +#ifdef XML_DTD + paramEntityParsing = oldParamEntityParsing; + prologState.inEntityValue = oldInEntityValue; + if (context) { +#endif /* XML_DTD */ + if (!dtdCopy(oldParser, _dtd, oldDtd, &parser->m_mem) + || !setContext(parser, context)) { + XML_ParserFree(parser); + return NULL; + } + processor = externalEntityInitProcessor; +#ifdef XML_DTD + } + else { + /* The DTD instance referenced by _dtd is shared between the document's + root parser and external PE parsers, therefore one does not need to + call setContext. In addition, one also *must* not call setContext, + because this would overwrite existing prefix->binding pointers in + _dtd with ones that get destroyed with the external PE parser. + This would leave those prefixes with dangling pointers. + */ + isParamEntity = XML_TRUE; + XmlPrologStateInitExternalEntity(&prologState); + processor = externalParEntInitProcessor; + } +#endif /* XML_DTD */ + return parser; +} + +static void FASTCALL +destroyBindings(BINDING *bindings, XML_Parser parser) +{ + for (;;) { + BINDING *b = bindings; + if (!b) + break; + bindings = b->nextTagBinding; + FREE(b->uri); + FREE(b); + } +} + +void XMLCALL +XML_ParserFree(XML_Parser parser) +{ + TAG *tagList; + OPEN_INTERNAL_ENTITY *entityList; + if (parser == NULL) + return; + /* free tagStack and freeTagList */ + tagList = tagStack; + for (;;) { + TAG *p; + if (tagList == NULL) { + if (freeTagList == NULL) + break; + tagList = freeTagList; + freeTagList = NULL; + } + p = tagList; + tagList = tagList->parent; + FREE(p->buf); + destroyBindings(p->bindings, parser); + FREE(p); + } + /* free openInternalEntities and freeInternalEntities */ + entityList = openInternalEntities; + for (;;) { + OPEN_INTERNAL_ENTITY *openEntity; + if (entityList == NULL) { + if (freeInternalEntities == NULL) + break; + entityList = freeInternalEntities; + freeInternalEntities = NULL; + } + openEntity = entityList; + entityList = entityList->next; + FREE(openEntity); + } + + destroyBindings(freeBindingList, parser); + destroyBindings(inheritedBindings, parser); + poolDestroy(&tempPool); + poolDestroy(&temp2Pool); +#ifdef XML_DTD + /* external parameter entity parsers share the DTD structure + parser->m_dtd with the root parser, so we must not destroy it + */ + if (!isParamEntity && _dtd) +#else + if (_dtd) +#endif /* XML_DTD */ + dtdDestroy(_dtd, (XML_Bool)!parentParser, &parser->m_mem); + FREE((void *)atts); +#ifdef XML_ATTR_INFO + FREE((void *)attInfo); +#endif + FREE(groupConnector); + FREE(buffer); + FREE(dataBuf); + FREE(nsAtts); + FREE(unknownEncodingMem); + if (unknownEncodingRelease) + unknownEncodingRelease(unknownEncodingData); + FREE(parser); +} + +void XMLCALL +XML_UseParserAsHandlerArg(XML_Parser parser) +{ + handlerArg = parser; +} + +enum XML_Error XMLCALL +XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD) +{ +#ifdef XML_DTD + /* block after XML_Parse()/XML_ParseBuffer() has been called */ + if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED) + return XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING; + useForeignDTD = useDTD; + return XML_ERROR_NONE; +#else + return XML_ERROR_FEATURE_REQUIRES_XML_DTD; +#endif +} + +void XMLCALL +XML_SetReturnNSTriplet(XML_Parser parser, int do_nst) +{ + /* block after XML_Parse()/XML_ParseBuffer() has been called */ + if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED) + return; + ns_triplets = do_nst ? XML_TRUE : XML_FALSE; +} + +void XMLCALL +XML_SetUserData(XML_Parser parser, void *p) +{ + if (handlerArg == userData) + handlerArg = userData = p; + else + userData = p; +} + +enum XML_Status XMLCALL +XML_SetBase(XML_Parser parser, const XML_Char *p) +{ + if (p) { + p = poolCopyString(&_dtd->pool, p); + if (!p) + return XML_STATUS_ERROR; + curBase = p; + } + else + curBase = NULL; + return XML_STATUS_OK; +} + +const XML_Char * XMLCALL +XML_GetBase(XML_Parser parser) +{ + return curBase; +} + +int XMLCALL +XML_GetSpecifiedAttributeCount(XML_Parser parser) +{ + return nSpecifiedAtts; +} + +int XMLCALL +XML_GetIdAttributeIndex(XML_Parser parser) +{ + return idAttIndex; +} + +#ifdef XML_ATTR_INFO +const XML_AttrInfo * XMLCALL +XML_GetAttributeInfo(XML_Parser parser) +{ + return attInfo; +} +#endif + +void XMLCALL +XML_SetElementHandler(XML_Parser parser, + XML_StartElementHandler start, + XML_EndElementHandler end) +{ + startElementHandler = start; + endElementHandler = end; +} + +void XMLCALL +XML_SetStartElementHandler(XML_Parser parser, + XML_StartElementHandler start) { + startElementHandler = start; +} + +void XMLCALL +XML_SetEndElementHandler(XML_Parser parser, + XML_EndElementHandler end) { + endElementHandler = end; +} + +void XMLCALL +XML_SetCharacterDataHandler(XML_Parser parser, + XML_CharacterDataHandler handler) +{ + characterDataHandler = handler; +} + +void XMLCALL +XML_SetProcessingInstructionHandler(XML_Parser parser, + XML_ProcessingInstructionHandler handler) +{ + processingInstructionHandler = handler; +} + +void XMLCALL +XML_SetCommentHandler(XML_Parser parser, + XML_CommentHandler handler) +{ + commentHandler = handler; +} + +void XMLCALL +XML_SetCdataSectionHandler(XML_Parser parser, + XML_StartCdataSectionHandler start, + XML_EndCdataSectionHandler end) +{ + startCdataSectionHandler = start; + endCdataSectionHandler = end; +} + +void XMLCALL +XML_SetStartCdataSectionHandler(XML_Parser parser, + XML_StartCdataSectionHandler start) { + startCdataSectionHandler = start; +} + +void XMLCALL +XML_SetEndCdataSectionHandler(XML_Parser parser, + XML_EndCdataSectionHandler end) { + endCdataSectionHandler = end; +} + +void XMLCALL +XML_SetDefaultHandler(XML_Parser parser, + XML_DefaultHandler handler) +{ + defaultHandler = handler; + defaultExpandInternalEntities = XML_FALSE; +} + +void XMLCALL +XML_SetDefaultHandlerExpand(XML_Parser parser, + XML_DefaultHandler handler) +{ + defaultHandler = handler; + defaultExpandInternalEntities = XML_TRUE; +} + +void XMLCALL +XML_SetDoctypeDeclHandler(XML_Parser parser, + XML_StartDoctypeDeclHandler start, + XML_EndDoctypeDeclHandler end) +{ + startDoctypeDeclHandler = start; + endDoctypeDeclHandler = end; +} + +void XMLCALL +XML_SetStartDoctypeDeclHandler(XML_Parser parser, + XML_StartDoctypeDeclHandler start) { + startDoctypeDeclHandler = start; +} + +void XMLCALL +XML_SetEndDoctypeDeclHandler(XML_Parser parser, + XML_EndDoctypeDeclHandler end) { + endDoctypeDeclHandler = end; +} + +void XMLCALL +XML_SetUnparsedEntityDeclHandler(XML_Parser parser, + XML_UnparsedEntityDeclHandler handler) +{ + unparsedEntityDeclHandler = handler; +} + +void XMLCALL +XML_SetNotationDeclHandler(XML_Parser parser, + XML_NotationDeclHandler handler) +{ + notationDeclHandler = handler; +} + +void XMLCALL +XML_SetNamespaceDeclHandler(XML_Parser parser, + XML_StartNamespaceDeclHandler start, + XML_EndNamespaceDeclHandler end) +{ + startNamespaceDeclHandler = start; + endNamespaceDeclHandler = end; +} + +void XMLCALL +XML_SetStartNamespaceDeclHandler(XML_Parser parser, + XML_StartNamespaceDeclHandler start) { + startNamespaceDeclHandler = start; +} + +void XMLCALL +XML_SetEndNamespaceDeclHandler(XML_Parser parser, + XML_EndNamespaceDeclHandler end) { + endNamespaceDeclHandler = end; +} + +void XMLCALL +XML_SetNotStandaloneHandler(XML_Parser parser, + XML_NotStandaloneHandler handler) +{ + notStandaloneHandler = handler; +} + +void XMLCALL +XML_SetExternalEntityRefHandler(XML_Parser parser, + XML_ExternalEntityRefHandler handler) +{ + externalEntityRefHandler = handler; +} + +void XMLCALL +XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg) +{ + if (arg) + externalEntityRefHandlerArg = (XML_Parser)arg; + else + externalEntityRefHandlerArg = parser; +} + +void XMLCALL +XML_SetSkippedEntityHandler(XML_Parser parser, + XML_SkippedEntityHandler handler) +{ + skippedEntityHandler = handler; +} + +void XMLCALL +XML_SetUnknownEncodingHandler(XML_Parser parser, + XML_UnknownEncodingHandler handler, + void *data) +{ + unknownEncodingHandler = handler; + unknownEncodingHandlerData = data; +} + +void XMLCALL +XML_SetElementDeclHandler(XML_Parser parser, + XML_ElementDeclHandler eldecl) +{ + elementDeclHandler = eldecl; +} + +void XMLCALL +XML_SetAttlistDeclHandler(XML_Parser parser, + XML_AttlistDeclHandler attdecl) +{ + attlistDeclHandler = attdecl; +} + +void XMLCALL +XML_SetEntityDeclHandler(XML_Parser parser, + XML_EntityDeclHandler handler) +{ + entityDeclHandler = handler; +} + +void XMLCALL +XML_SetXmlDeclHandler(XML_Parser parser, + XML_XmlDeclHandler handler) { + xmlDeclHandler = handler; +} + +int XMLCALL +XML_SetParamEntityParsing(XML_Parser parser, + enum XML_ParamEntityParsing peParsing) +{ + /* block after XML_Parse()/XML_ParseBuffer() has been called */ + if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED) + return 0; +#ifdef XML_DTD + paramEntityParsing = peParsing; + return 1; +#else + return peParsing == XML_PARAM_ENTITY_PARSING_NEVER; +#endif +} + +int XMLCALL +XML_SetHashSalt(XML_Parser parser, + unsigned long hash_salt) +{ + /* block after XML_Parse()/XML_ParseBuffer() has been called */ + if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED) + return 0; + hash_secret_salt = hash_salt; + return 1; +} + +enum XML_Status XMLCALL +XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) +{ + switch (ps_parsing) { + case XML_SUSPENDED: + errorCode = XML_ERROR_SUSPENDED; + return XML_STATUS_ERROR; + case XML_FINISHED: + errorCode = XML_ERROR_FINISHED; + return XML_STATUS_ERROR; + case XML_INITIALIZED: + if (parentParser == NULL && !startParsing(parser)) { + errorCode = XML_ERROR_NO_MEMORY; + return XML_STATUS_ERROR; + } + default: + ps_parsing = XML_PARSING; + } + + if (len == 0) { + ps_finalBuffer = (XML_Bool)isFinal; + if (!isFinal) + return XML_STATUS_OK; + positionPtr = bufferPtr; + parseEndPtr = bufferEnd; + + /* If data are left over from last buffer, and we now know that these + data are the final chunk of input, then we have to check them again + to detect errors based on that fact. + */ + errorCode = processor(parser, bufferPtr, parseEndPtr, &bufferPtr); + + if (errorCode == XML_ERROR_NONE) { + switch (ps_parsing) { + case XML_SUSPENDED: + XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position); + positionPtr = bufferPtr; + return XML_STATUS_SUSPENDED; + case XML_INITIALIZED: + case XML_PARSING: + ps_parsing = XML_FINISHED; + /* fall through */ + default: + return XML_STATUS_OK; + } + } + eventEndPtr = eventPtr; + processor = errorProcessor; + return XML_STATUS_ERROR; + } +#ifndef XML_CONTEXT_BYTES + else if (bufferPtr == bufferEnd) { + const char *end; + int nLeftOver; + enum XML_Error result; + parseEndByteIndex += len; + positionPtr = s; + ps_finalBuffer = (XML_Bool)isFinal; + + errorCode = processor(parser, s, parseEndPtr = s + len, &end); + + if (errorCode != XML_ERROR_NONE) { + eventEndPtr = eventPtr; + processor = errorProcessor; + return XML_STATUS_ERROR; + } + else { + switch (ps_parsing) { + case XML_SUSPENDED: + result = XML_STATUS_SUSPENDED; + break; + case XML_INITIALIZED: + case XML_PARSING: + if (isFinal) { + ps_parsing = XML_FINISHED; + return XML_STATUS_OK; + } + /* fall through */ + default: + result = XML_STATUS_OK; + } + } + + XmlUpdatePosition(encoding, positionPtr, end, &position); + nLeftOver = s + len - end; + if (nLeftOver) { + if (buffer == NULL || nLeftOver > bufferLim - buffer) { + /* FIXME avoid integer overflow */ + char *temp; + temp = (buffer == NULL + ? (char *)MALLOC(len * 2) + : (char *)REALLOC(buffer, len * 2)); + if (temp == NULL) { + errorCode = XML_ERROR_NO_MEMORY; + eventPtr = eventEndPtr = NULL; + processor = errorProcessor; + return XML_STATUS_ERROR; + } + buffer = temp; + bufferLim = buffer + len * 2; + } + memcpy(buffer, end, nLeftOver); + } + bufferPtr = buffer; + bufferEnd = buffer + nLeftOver; + positionPtr = bufferPtr; + parseEndPtr = bufferEnd; + eventPtr = bufferPtr; + eventEndPtr = bufferPtr; + return result; + } +#endif /* not defined XML_CONTEXT_BYTES */ + else { + void *buff = XML_GetBuffer(parser, len); + if (buff == NULL) + return XML_STATUS_ERROR; + else { + memcpy(buff, s, len); + return XML_ParseBuffer(parser, len, isFinal); + } + } +} + +enum XML_Status XMLCALL +XML_ParseBuffer(XML_Parser parser, int len, int isFinal) +{ + const char *start; + enum XML_Status result = XML_STATUS_OK; + + switch (ps_parsing) { + case XML_SUSPENDED: + errorCode = XML_ERROR_SUSPENDED; + return XML_STATUS_ERROR; + case XML_FINISHED: + errorCode = XML_ERROR_FINISHED; + return XML_STATUS_ERROR; + case XML_INITIALIZED: + if (parentParser == NULL && !startParsing(parser)) { + errorCode = XML_ERROR_NO_MEMORY; + return XML_STATUS_ERROR; + } + default: + ps_parsing = XML_PARSING; + } + + start = bufferPtr; + positionPtr = start; + bufferEnd += len; + parseEndPtr = bufferEnd; + parseEndByteIndex += len; + ps_finalBuffer = (XML_Bool)isFinal; + + errorCode = processor(parser, start, parseEndPtr, &bufferPtr); + + if (errorCode != XML_ERROR_NONE) { + eventEndPtr = eventPtr; + processor = errorProcessor; + return XML_STATUS_ERROR; + } + else { + switch (ps_parsing) { + case XML_SUSPENDED: + result = XML_STATUS_SUSPENDED; + break; + case XML_INITIALIZED: + case XML_PARSING: + if (isFinal) { + ps_parsing = XML_FINISHED; + return result; + } + default: ; /* should not happen */ + } + } + + XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position); + positionPtr = bufferPtr; + return result; +} + +void * XMLCALL +XML_GetBuffer(XML_Parser parser, int len) +{ + switch (ps_parsing) { + case XML_SUSPENDED: + errorCode = XML_ERROR_SUSPENDED; + return NULL; + case XML_FINISHED: + errorCode = XML_ERROR_FINISHED; + return NULL; + default: ; + } + + if (len > bufferLim - bufferEnd) { + /* FIXME avoid integer overflow */ + int neededSize = len + (int)(bufferEnd - bufferPtr); +#ifdef XML_CONTEXT_BYTES + int keep = (int)(bufferPtr - buffer); + + if (keep > XML_CONTEXT_BYTES) + keep = XML_CONTEXT_BYTES; + neededSize += keep; +#endif /* defined XML_CONTEXT_BYTES */ + if (neededSize <= bufferLim - buffer) { +#ifdef XML_CONTEXT_BYTES + if (keep < bufferPtr - buffer) { + int offset = (int)(bufferPtr - buffer) - keep; + memmove(buffer, &buffer[offset], bufferEnd - bufferPtr + keep); + bufferEnd -= offset; + bufferPtr -= offset; + } +#else + memmove(buffer, bufferPtr, bufferEnd - bufferPtr); + bufferEnd = buffer + (bufferEnd - bufferPtr); + bufferPtr = buffer; +#endif /* not defined XML_CONTEXT_BYTES */ + } + else { + char *newBuf; + int bufferSize = (int)(bufferLim - bufferPtr); + if (bufferSize == 0) + bufferSize = INIT_BUFFER_SIZE; + do { + bufferSize *= 2; + } while (bufferSize < neededSize); + newBuf = (char *)MALLOC(bufferSize); + if (newBuf == 0) { + errorCode = XML_ERROR_NO_MEMORY; + return NULL; + } + bufferLim = newBuf + bufferSize; +#ifdef XML_CONTEXT_BYTES + if (bufferPtr) { + int keep = (int)(bufferPtr - buffer); + if (keep > XML_CONTEXT_BYTES) + keep = XML_CONTEXT_BYTES; + memcpy(newBuf, &bufferPtr[-keep], bufferEnd - bufferPtr + keep); + FREE(buffer); + buffer = newBuf; + bufferEnd = buffer + (bufferEnd - bufferPtr) + keep; + bufferPtr = buffer + keep; + } + else { + bufferEnd = newBuf + (bufferEnd - bufferPtr); + bufferPtr = buffer = newBuf; + } +#else + if (bufferPtr) { + memcpy(newBuf, bufferPtr, bufferEnd - bufferPtr); + FREE(buffer); + } + bufferEnd = newBuf + (bufferEnd - bufferPtr); + bufferPtr = buffer = newBuf; +#endif /* not defined XML_CONTEXT_BYTES */ + } + eventPtr = eventEndPtr = NULL; + positionPtr = NULL; + } + return bufferEnd; +} + +enum XML_Status XMLCALL +XML_StopParser(XML_Parser parser, XML_Bool resumable) +{ + switch (ps_parsing) { + case XML_SUSPENDED: + if (resumable) { + errorCode = XML_ERROR_SUSPENDED; + return XML_STATUS_ERROR; + } + ps_parsing = XML_FINISHED; + break; + case XML_FINISHED: + errorCode = XML_ERROR_FINISHED; + return XML_STATUS_ERROR; + default: + if (resumable) { +#ifdef XML_DTD + if (isParamEntity) { + errorCode = XML_ERROR_SUSPEND_PE; + return XML_STATUS_ERROR; + } +#endif + ps_parsing = XML_SUSPENDED; + } + else + ps_parsing = XML_FINISHED; + } + return XML_STATUS_OK; +} + +enum XML_Status XMLCALL +XML_ResumeParser(XML_Parser parser) +{ + enum XML_Status result = XML_STATUS_OK; + + if (ps_parsing != XML_SUSPENDED) { + errorCode = XML_ERROR_NOT_SUSPENDED; + return XML_STATUS_ERROR; + } + ps_parsing = XML_PARSING; + + errorCode = processor(parser, bufferPtr, parseEndPtr, &bufferPtr); + + if (errorCode != XML_ERROR_NONE) { + eventEndPtr = eventPtr; + processor = errorProcessor; + return XML_STATUS_ERROR; + } + else { + switch (ps_parsing) { + case XML_SUSPENDED: + result = XML_STATUS_SUSPENDED; + break; + case XML_INITIALIZED: + case XML_PARSING: + if (ps_finalBuffer) { + ps_parsing = XML_FINISHED; + return result; + } + default: ; + } + } + + XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position); + positionPtr = bufferPtr; + return result; +} + +void XMLCALL +XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status) +{ + assert(status != NULL); + *status = parser->m_parsingStatus; +} + +enum XML_Error XMLCALL +XML_GetErrorCode(XML_Parser parser) +{ + return errorCode; +} + +XML_Index XMLCALL +XML_GetCurrentByteIndex(XML_Parser parser) +{ + if (eventPtr) + return parseEndByteIndex - (parseEndPtr - eventPtr); + return -1; +} + +int XMLCALL +XML_GetCurrentByteCount(XML_Parser parser) +{ + if (eventEndPtr && eventPtr) + return (int)(eventEndPtr - eventPtr); + return 0; +} + +const char * XMLCALL +XML_GetInputContext(XML_Parser parser, int *offset, int *size) +{ +#ifdef XML_CONTEXT_BYTES + if (eventPtr && buffer) { + *offset = (int)(eventPtr - buffer); + *size = (int)(bufferEnd - buffer); + return buffer; + } +#endif /* defined XML_CONTEXT_BYTES */ + return (char *) 0; +} + +XML_Size XMLCALL +XML_GetCurrentLineNumber(XML_Parser parser) +{ + if (eventPtr && eventPtr >= positionPtr) { + XmlUpdatePosition(encoding, positionPtr, eventPtr, &position); + positionPtr = eventPtr; + } + return position.lineNumber + 1; +} + +XML_Size XMLCALL +XML_GetCurrentColumnNumber(XML_Parser parser) +{ + if (eventPtr && eventPtr >= positionPtr) { + XmlUpdatePosition(encoding, positionPtr, eventPtr, &position); + positionPtr = eventPtr; + } + return position.columnNumber; +} + +void XMLCALL +XML_FreeContentModel(XML_Parser parser, XML_Content *model) +{ + FREE(model); +} + +void * XMLCALL +XML_MemMalloc(XML_Parser parser, size_t size) +{ + return MALLOC(size); +} + +void * XMLCALL +XML_MemRealloc(XML_Parser parser, void *ptr, size_t size) +{ + return REALLOC(ptr, size); +} + +void XMLCALL +XML_MemFree(XML_Parser parser, void *ptr) +{ + FREE(ptr); +} + +void XMLCALL +XML_DefaultCurrent(XML_Parser parser) +{ + if (defaultHandler) { + if (openInternalEntities) + reportDefault(parser, + internalEncoding, + openInternalEntities->internalEventPtr, + openInternalEntities->internalEventEndPtr); + else + reportDefault(parser, encoding, eventPtr, eventEndPtr); + } +} + +const XML_LChar * XMLCALL +XML_ErrorString(enum XML_Error code) +{ + static const XML_LChar* const message[] = { + 0, + XML_L("out of memory"), + XML_L("syntax error"), + XML_L("no element found"), + XML_L("not well-formed (invalid token)"), + XML_L("unclosed token"), + XML_L("partial character"), + XML_L("mismatched tag"), + XML_L("duplicate attribute"), + XML_L("junk after document element"), + XML_L("illegal parameter entity reference"), + XML_L("undefined entity"), + XML_L("recursive entity reference"), + XML_L("asynchronous entity"), + XML_L("reference to invalid character number"), + XML_L("reference to binary entity"), + XML_L("reference to external entity in attribute"), + XML_L("XML or text declaration not at start of entity"), + XML_L("unknown encoding"), + XML_L("encoding specified in XML declaration is incorrect"), + XML_L("unclosed CDATA section"), + XML_L("error in processing external entity reference"), + XML_L("document is not standalone"), + XML_L("unexpected parser state - please send a bug report"), + XML_L("entity declared in parameter entity"), + XML_L("requested feature requires XML_DTD support in Expat"), + XML_L("cannot change setting once parsing has begun"), + XML_L("unbound prefix"), + XML_L("must not undeclare prefix"), + XML_L("incomplete markup in parameter entity"), + XML_L("XML declaration not well-formed"), + XML_L("text declaration not well-formed"), + XML_L("illegal character(s) in public id"), + XML_L("parser suspended"), + XML_L("parser not suspended"), + XML_L("parsing aborted"), + XML_L("parsing finished"), + XML_L("cannot suspend in external parameter entity"), + XML_L("reserved prefix (xml) must not be undeclared or bound to another namespace name"), + XML_L("reserved prefix (xmlns) must not be declared or undeclared"), + XML_L("prefix must not be bound to one of the reserved namespace names") + }; + if (code > 0 && code < sizeof(message)/sizeof(message[0])) + return message[code]; + return NULL; +} + +const XML_LChar * XMLCALL +XML_ExpatVersion(void) { + + /* V1 is used to string-ize the version number. However, it would + string-ize the actual version macro *names* unless we get them + substituted before being passed to V1. CPP is defined to expand + a macro, then rescan for more expansions. Thus, we use V2 to expand + the version macros, then CPP will expand the resulting V1() macro + with the correct numerals. */ + /* ### I'm assuming cpp is portable in this respect... */ + +#define V1(a,b,c) XML_L(#a)XML_L(".")XML_L(#b)XML_L(".")XML_L(#c) +#define V2(a,b,c) XML_L("expat_")V1(a,b,c) + + return V2(XML_MAJOR_VERSION, XML_MINOR_VERSION, XML_MICRO_VERSION); + +#undef V1 +#undef V2 +} + +XML_Expat_Version XMLCALL +XML_ExpatVersionInfo(void) +{ + XML_Expat_Version version; + + version.major = XML_MAJOR_VERSION; + version.minor = XML_MINOR_VERSION; + version.micro = XML_MICRO_VERSION; + + return version; +} + +const XML_Feature * XMLCALL +XML_GetFeatureList(void) +{ + static const XML_Feature features[] = { + {XML_FEATURE_SIZEOF_XML_CHAR, XML_L("sizeof(XML_Char)"), + sizeof(XML_Char)}, + {XML_FEATURE_SIZEOF_XML_LCHAR, XML_L("sizeof(XML_LChar)"), + sizeof(XML_LChar)}, +#ifdef XML_UNICODE + {XML_FEATURE_UNICODE, XML_L("XML_UNICODE"), 0}, +#endif +#ifdef XML_UNICODE_WCHAR_T + {XML_FEATURE_UNICODE_WCHAR_T, XML_L("XML_UNICODE_WCHAR_T"), 0}, +#endif +#ifdef XML_DTD + {XML_FEATURE_DTD, XML_L("XML_DTD"), 0}, +#endif +#ifdef XML_CONTEXT_BYTES + {XML_FEATURE_CONTEXT_BYTES, XML_L("XML_CONTEXT_BYTES"), + XML_CONTEXT_BYTES}, +#endif +#ifdef XML_MIN_SIZE + {XML_FEATURE_MIN_SIZE, XML_L("XML_MIN_SIZE"), 0}, +#endif +#ifdef XML_NS + {XML_FEATURE_NS, XML_L("XML_NS"), 0}, +#endif +#ifdef XML_LARGE_SIZE + {XML_FEATURE_LARGE_SIZE, XML_L("XML_LARGE_SIZE"), 0}, +#endif +#ifdef XML_ATTR_INFO + {XML_FEATURE_ATTR_INFO, XML_L("XML_ATTR_INFO"), 0}, +#endif + {XML_FEATURE_END, NULL, 0} + }; + + return features; +} + +/* Initially tag->rawName always points into the parse buffer; + for those TAG instances opened while the current parse buffer was + processed, and not yet closed, we need to store tag->rawName in a more + permanent location, since the parse buffer is about to be discarded. +*/ +static XML_Bool +storeRawNames(XML_Parser parser) +{ + TAG *tag = tagStack; + while (tag) { + int bufSize; + int nameLen = sizeof(XML_Char) * (tag->name.strLen + 1); + char *rawNameBuf = tag->buf + nameLen; + /* Stop if already stored. Since tagStack is a stack, we can stop + at the first entry that has already been copied; everything + below it in the stack is already been accounted for in a + previous call to this function. + */ + if (tag->rawName == rawNameBuf) + break; + /* For re-use purposes we need to ensure that the + size of tag->buf is a multiple of sizeof(XML_Char). + */ + bufSize = nameLen + ROUND_UP(tag->rawNameLength, sizeof(XML_Char)); + if (bufSize > tag->bufEnd - tag->buf) { + char *temp = (char *)REALLOC(tag->buf, bufSize); + if (temp == NULL) + return XML_FALSE; + /* if tag->name.str points to tag->buf (only when namespace + processing is off) then we have to update it + */ + if (tag->name.str == (XML_Char *)tag->buf) + tag->name.str = (XML_Char *)temp; + /* if tag->name.localPart is set (when namespace processing is on) + then update it as well, since it will always point into tag->buf + */ + if (tag->name.localPart) + tag->name.localPart = (XML_Char *)temp + (tag->name.localPart - + (XML_Char *)tag->buf); + tag->buf = temp; + tag->bufEnd = temp + bufSize; + rawNameBuf = temp + nameLen; + } + memcpy(rawNameBuf, tag->rawName, tag->rawNameLength); + tag->rawName = rawNameBuf; + tag = tag->parent; + } + return XML_TRUE; +} + +static enum XML_Error PTRCALL +contentProcessor(XML_Parser parser, + const char *start, + const char *end, + const char **endPtr) +{ + enum XML_Error result = doContent(parser, 0, encoding, start, end, + endPtr, (XML_Bool)!ps_finalBuffer); + if (result == XML_ERROR_NONE) { + if (!storeRawNames(parser)) + return XML_ERROR_NO_MEMORY; + } + return result; +} + +static enum XML_Error PTRCALL +externalEntityInitProcessor(XML_Parser parser, + const char *start, + const char *end, + const char **endPtr) +{ + enum XML_Error result = initializeEncoding(parser); + if (result != XML_ERROR_NONE) + return result; + processor = externalEntityInitProcessor2; + return externalEntityInitProcessor2(parser, start, end, endPtr); +} + +static enum XML_Error PTRCALL +externalEntityInitProcessor2(XML_Parser parser, + const char *start, + const char *end, + const char **endPtr) +{ + const char *next = start; /* XmlContentTok doesn't always set the last arg */ + int tok = XmlContentTok(encoding, start, end, &next); + switch (tok) { + case XML_TOK_BOM: + /* If we are at the end of the buffer, this would cause the next stage, + i.e. externalEntityInitProcessor3, to pass control directly to + doContent (by detecting XML_TOK_NONE) without processing any xml text + declaration - causing the error XML_ERROR_MISPLACED_XML_PI in doContent. + */ + if (next == end && !ps_finalBuffer) { + *endPtr = next; + return XML_ERROR_NONE; + } + start = next; + break; + case XML_TOK_PARTIAL: + if (!ps_finalBuffer) { + *endPtr = start; + return XML_ERROR_NONE; + } + eventPtr = start; + return XML_ERROR_UNCLOSED_TOKEN; + case XML_TOK_PARTIAL_CHAR: + if (!ps_finalBuffer) { + *endPtr = start; + return XML_ERROR_NONE; + } + eventPtr = start; + return XML_ERROR_PARTIAL_CHAR; + } + processor = externalEntityInitProcessor3; + return externalEntityInitProcessor3(parser, start, end, endPtr); +} + +static enum XML_Error PTRCALL +externalEntityInitProcessor3(XML_Parser parser, + const char *start, + const char *end, + const char **endPtr) +{ + int tok; + const char *next = start; /* XmlContentTok doesn't always set the last arg */ + eventPtr = start; + tok = XmlContentTok(encoding, start, end, &next); + eventEndPtr = next; + + switch (tok) { + case XML_TOK_XML_DECL: + { + enum XML_Error result; + result = processXmlDecl(parser, 1, start, next); + if (result != XML_ERROR_NONE) + return result; + switch (ps_parsing) { + case XML_SUSPENDED: + *endPtr = next; + return XML_ERROR_NONE; + case XML_FINISHED: + return XML_ERROR_ABORTED; + default: + start = next; + } + } + break; + case XML_TOK_PARTIAL: + if (!ps_finalBuffer) { + *endPtr = start; + return XML_ERROR_NONE; + } + return XML_ERROR_UNCLOSED_TOKEN; + case XML_TOK_PARTIAL_CHAR: + if (!ps_finalBuffer) { + *endPtr = start; + return XML_ERROR_NONE; + } + return XML_ERROR_PARTIAL_CHAR; + } + processor = externalEntityContentProcessor; + tagLevel = 1; + return externalEntityContentProcessor(parser, start, end, endPtr); +} + +static enum XML_Error PTRCALL +externalEntityContentProcessor(XML_Parser parser, + const char *start, + const char *end, + const char **endPtr) +{ + enum XML_Error result = doContent(parser, 1, encoding, start, end, + endPtr, (XML_Bool)!ps_finalBuffer); + if (result == XML_ERROR_NONE) { + if (!storeRawNames(parser)) + return XML_ERROR_NO_MEMORY; + } + return result; +} + +static enum XML_Error +doContent(XML_Parser parser, + int startTagLevel, + const ENCODING *enc, + const char *s, + const char *end, + const char **nextPtr, + XML_Bool haveMore) +{ + /* save one level of indirection */ + DTD * const dtd = _dtd; + + const char **eventPP; + const char **eventEndPP; + if (enc == encoding) { + eventPP = &eventPtr; + eventEndPP = &eventEndPtr; + } + else { + eventPP = &(openInternalEntities->internalEventPtr); + eventEndPP = &(openInternalEntities->internalEventEndPtr); + } + *eventPP = s; + + for (;;) { + const char *next = s; /* XmlContentTok doesn't always set the last arg */ + int tok = XmlContentTok(enc, s, end, &next); + *eventEndPP = next; + switch (tok) { + case XML_TOK_TRAILING_CR: + if (haveMore) { + *nextPtr = s; + return XML_ERROR_NONE; + } + *eventEndPP = end; + if (characterDataHandler) { + XML_Char c = 0xA; + characterDataHandler(handlerArg, &c, 1); + } + else if (defaultHandler) + reportDefault(parser, enc, s, end); + /* We are at the end of the final buffer, should we check for + XML_SUSPENDED, XML_FINISHED? + */ + if (startTagLevel == 0) + return XML_ERROR_NO_ELEMENTS; + if (tagLevel != startTagLevel) + return XML_ERROR_ASYNC_ENTITY; + *nextPtr = end; + return XML_ERROR_NONE; + case XML_TOK_NONE: + if (haveMore) { + *nextPtr = s; + return XML_ERROR_NONE; + } + if (startTagLevel > 0) { + if (tagLevel != startTagLevel) + return XML_ERROR_ASYNC_ENTITY; + *nextPtr = s; + return XML_ERROR_NONE; + } + return XML_ERROR_NO_ELEMENTS; + case XML_TOK_INVALID: + *eventPP = next; + return XML_ERROR_INVALID_TOKEN; + case XML_TOK_PARTIAL: + if (haveMore) { + *nextPtr = s; + return XML_ERROR_NONE; + } + return XML_ERROR_UNCLOSED_TOKEN; + case XML_TOK_PARTIAL_CHAR: + if (haveMore) { + *nextPtr = s; + return XML_ERROR_NONE; + } + return XML_ERROR_PARTIAL_CHAR; + case XML_TOK_ENTITY_REF: + { + const XML_Char *name; + ENTITY *entity; + XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (ch) { + if (characterDataHandler) + characterDataHandler(handlerArg, &ch, 1); + else if (defaultHandler) + reportDefault(parser, enc, s, next); + break; + } + name = poolStoreString(&dtd->pool, enc, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (!name) + return XML_ERROR_NO_MEMORY; + entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0); + poolDiscard(&dtd->pool); + /* First, determine if a check for an existing declaration is needed; + if yes, check that the entity exists, and that it is internal, + otherwise call the skipped entity or default handler. + */ + if (!dtd->hasParamEntityRefs || dtd->standalone) { + if (!entity) + return XML_ERROR_UNDEFINED_ENTITY; + else if (!entity->is_internal) + return XML_ERROR_ENTITY_DECLARED_IN_PE; + } + else if (!entity) { + if (skippedEntityHandler) + skippedEntityHandler(handlerArg, name, 0); + else if (defaultHandler) + reportDefault(parser, enc, s, next); + break; + } + if (entity->open) + return XML_ERROR_RECURSIVE_ENTITY_REF; + if (entity->notation) + return XML_ERROR_BINARY_ENTITY_REF; + if (entity->textPtr) { + enum XML_Error result; + if (!defaultExpandInternalEntities) { + if (skippedEntityHandler) + skippedEntityHandler(handlerArg, entity->name, 0); + else if (defaultHandler) + reportDefault(parser, enc, s, next); + break; + } + result = processInternalEntity(parser, entity, XML_FALSE); + if (result != XML_ERROR_NONE) + return result; + } + else if (externalEntityRefHandler) { + const XML_Char *context; + entity->open = XML_TRUE; + context = getContext(parser); + entity->open = XML_FALSE; + if (!context) + return XML_ERROR_NO_MEMORY; + if (!externalEntityRefHandler(externalEntityRefHandlerArg, + context, + entity->base, + entity->systemId, + entity->publicId)) + return XML_ERROR_EXTERNAL_ENTITY_HANDLING; + poolDiscard(&tempPool); + } + else if (defaultHandler) + reportDefault(parser, enc, s, next); + break; + } + case XML_TOK_START_TAG_NO_ATTS: + /* fall through */ + case XML_TOK_START_TAG_WITH_ATTS: + { + TAG *tag; + enum XML_Error result; + XML_Char *toPtr; + if (freeTagList) { + tag = freeTagList; + freeTagList = freeTagList->parent; + } + else { + tag = (TAG *)MALLOC(sizeof(TAG)); + if (!tag) + return XML_ERROR_NO_MEMORY; + tag->buf = (char *)MALLOC(INIT_TAG_BUF_SIZE); + if (!tag->buf) { + FREE(tag); + return XML_ERROR_NO_MEMORY; + } + tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE; + } + tag->bindings = NULL; + tag->parent = tagStack; + tagStack = tag; + tag->name.localPart = NULL; + tag->name.prefix = NULL; + tag->rawName = s + enc->minBytesPerChar; + tag->rawNameLength = XmlNameLength(enc, tag->rawName); + ++tagLevel; + { + const char *rawNameEnd = tag->rawName + tag->rawNameLength; + const char *fromPtr = tag->rawName; + toPtr = (XML_Char *)tag->buf; + for (;;) { + int bufSize; + int convLen; + XmlConvert(enc, + &fromPtr, rawNameEnd, + (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1); + convLen = (int)(toPtr - (XML_Char *)tag->buf); + if (fromPtr == rawNameEnd) { + tag->name.strLen = convLen; + break; + } + bufSize = (int)(tag->bufEnd - tag->buf) << 1; + { + char *temp = (char *)REALLOC(tag->buf, bufSize); + if (temp == NULL) + return XML_ERROR_NO_MEMORY; + tag->buf = temp; + tag->bufEnd = temp + bufSize; + toPtr = (XML_Char *)temp + convLen; + } + } + } + tag->name.str = (XML_Char *)tag->buf; + *toPtr = XML_T('\0'); + result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings)); + if (result) + return result; + if (startElementHandler) + startElementHandler(handlerArg, tag->name.str, + (const XML_Char **)atts); + else if (defaultHandler) + reportDefault(parser, enc, s, next); + poolClear(&tempPool); + break; + } + case XML_TOK_EMPTY_ELEMENT_NO_ATTS: + /* fall through */ + case XML_TOK_EMPTY_ELEMENT_WITH_ATTS: + { + const char *rawName = s + enc->minBytesPerChar; + enum XML_Error result; + BINDING *bindings = NULL; + XML_Bool noElmHandlers = XML_TRUE; + TAG_NAME name; + name.str = poolStoreString(&tempPool, enc, rawName, + rawName + XmlNameLength(enc, rawName)); + if (!name.str) + return XML_ERROR_NO_MEMORY; + poolFinish(&tempPool); + result = storeAtts(parser, enc, s, &name, &bindings); + if (result) + return result; + poolFinish(&tempPool); + if (startElementHandler) { + startElementHandler(handlerArg, name.str, (const XML_Char **)atts); + noElmHandlers = XML_FALSE; + } + if (endElementHandler) { + if (startElementHandler) + *eventPP = *eventEndPP; + endElementHandler(handlerArg, name.str); + noElmHandlers = XML_FALSE; + } + if (noElmHandlers && defaultHandler) + reportDefault(parser, enc, s, next); + poolClear(&tempPool); + while (bindings) { + BINDING *b = bindings; + if (endNamespaceDeclHandler) + endNamespaceDeclHandler(handlerArg, b->prefix->name); + bindings = bindings->nextTagBinding; + b->nextTagBinding = freeBindingList; + freeBindingList = b; + b->prefix->binding = b->prevPrefixBinding; + } + } + if (tagLevel == 0) + return epilogProcessor(parser, next, end, nextPtr); + break; + case XML_TOK_END_TAG: + if (tagLevel == startTagLevel) + return XML_ERROR_ASYNC_ENTITY; + else { + int len; + const char *rawName; + TAG *tag = tagStack; + tagStack = tag->parent; + tag->parent = freeTagList; + freeTagList = tag; + rawName = s + enc->minBytesPerChar*2; + len = XmlNameLength(enc, rawName); + if (len != tag->rawNameLength + || memcmp(tag->rawName, rawName, len) != 0) { + *eventPP = rawName; + return XML_ERROR_TAG_MISMATCH; + } + --tagLevel; + if (endElementHandler) { + const XML_Char *localPart; + const XML_Char *prefix; + XML_Char *uri; + localPart = tag->name.localPart; + if (ns && localPart) { + /* localPart and prefix may have been overwritten in + tag->name.str, since this points to the binding->uri + buffer which gets re-used; so we have to add them again + */ + uri = (XML_Char *)tag->name.str + tag->name.uriLen; + /* don't need to check for space - already done in storeAtts() */ + while (*localPart) *uri++ = *localPart++; + prefix = (XML_Char *)tag->name.prefix; + if (ns_triplets && prefix) { + *uri++ = namespaceSeparator; + while (*prefix) *uri++ = *prefix++; + } + *uri = XML_T('\0'); + } + endElementHandler(handlerArg, tag->name.str); + } + else if (defaultHandler) + reportDefault(parser, enc, s, next); + while (tag->bindings) { + BINDING *b = tag->bindings; + if (endNamespaceDeclHandler) + endNamespaceDeclHandler(handlerArg, b->prefix->name); + tag->bindings = tag->bindings->nextTagBinding; + b->nextTagBinding = freeBindingList; + freeBindingList = b; + b->prefix->binding = b->prevPrefixBinding; + } + if (tagLevel == 0) + return epilogProcessor(parser, next, end, nextPtr); + } + break; + case XML_TOK_CHAR_REF: + { + int n = XmlCharRefNumber(enc, s); + if (n < 0) + return XML_ERROR_BAD_CHAR_REF; + if (characterDataHandler) { + XML_Char buf[XML_ENCODE_MAX]; + characterDataHandler(handlerArg, buf, XmlEncode(n, (ICHAR *)buf)); + } + else if (defaultHandler) + reportDefault(parser, enc, s, next); + } + break; + case XML_TOK_XML_DECL: + return XML_ERROR_MISPLACED_XML_PI; + case XML_TOK_DATA_NEWLINE: + if (characterDataHandler) { + XML_Char c = 0xA; + characterDataHandler(handlerArg, &c, 1); + } + else if (defaultHandler) + reportDefault(parser, enc, s, next); + break; + case XML_TOK_CDATA_SECT_OPEN: + { + enum XML_Error result; + if (startCdataSectionHandler) + startCdataSectionHandler(handlerArg); +#if 0 + /* Suppose you doing a transformation on a document that involves + changing only the character data. You set up a defaultHandler + and a characterDataHandler. The defaultHandler simply copies + characters through. The characterDataHandler does the + transformation and writes the characters out escaping them as + necessary. This case will fail to work if we leave out the + following two lines (because & and < inside CDATA sections will + be incorrectly escaped). + + However, now we have a start/endCdataSectionHandler, so it seems + easier to let the user deal with this. + */ + else if (characterDataHandler) + characterDataHandler(handlerArg, dataBuf, 0); +#endif + else if (defaultHandler) + reportDefault(parser, enc, s, next); + result = doCdataSection(parser, enc, &next, end, nextPtr, haveMore); + if (result != XML_ERROR_NONE) + return result; + else if (!next) { + processor = cdataSectionProcessor; + return result; + } + } + break; + case XML_TOK_TRAILING_RSQB: + if (haveMore) { + *nextPtr = s; + return XML_ERROR_NONE; + } + if (characterDataHandler) { + if (MUST_CONVERT(enc, s)) { + ICHAR *dataPtr = (ICHAR *)dataBuf; + XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd); + characterDataHandler(handlerArg, dataBuf, + (int)(dataPtr - (ICHAR *)dataBuf)); + } + else + characterDataHandler(handlerArg, + (XML_Char *)s, + (int)((XML_Char *)end - (XML_Char *)s)); + } + else if (defaultHandler) + reportDefault(parser, enc, s, end); + /* We are at the end of the final buffer, should we check for + XML_SUSPENDED, XML_FINISHED? + */ + if (startTagLevel == 0) { + *eventPP = end; + return XML_ERROR_NO_ELEMENTS; + } + if (tagLevel != startTagLevel) { + *eventPP = end; + return XML_ERROR_ASYNC_ENTITY; + } + *nextPtr = end; + return XML_ERROR_NONE; + case XML_TOK_DATA_CHARS: + { + XML_CharacterDataHandler charDataHandler = characterDataHandler; + if (charDataHandler) { + if (MUST_CONVERT(enc, s)) { + for (;;) { + ICHAR *dataPtr = (ICHAR *)dataBuf; + XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd); + *eventEndPP = s; + charDataHandler(handlerArg, dataBuf, + (int)(dataPtr - (ICHAR *)dataBuf)); + if (s == next) + break; + *eventPP = s; + } + } + else + charDataHandler(handlerArg, + (XML_Char *)s, + (int)((XML_Char *)next - (XML_Char *)s)); + } + else if (defaultHandler) + reportDefault(parser, enc, s, next); + } + break; + case XML_TOK_PI: + if (!reportProcessingInstruction(parser, enc, s, next)) + return XML_ERROR_NO_MEMORY; + break; + case XML_TOK_COMMENT: + if (!reportComment(parser, enc, s, next)) + return XML_ERROR_NO_MEMORY; + break; + default: + if (defaultHandler) + reportDefault(parser, enc, s, next); + break; + } + *eventPP = s = next; + switch (ps_parsing) { + case XML_SUSPENDED: + *nextPtr = next; + return XML_ERROR_NONE; + case XML_FINISHED: + return XML_ERROR_ABORTED; + default: ; + } + } + /* not reached */ +} + +/* Precondition: all arguments must be non-NULL; + Purpose: + - normalize attributes + - check attributes for well-formedness + - generate namespace aware attribute names (URI, prefix) + - build list of attributes for startElementHandler + - default attributes + - process namespace declarations (check and report them) + - generate namespace aware element name (URI, prefix) +*/ +static enum XML_Error +storeAtts(XML_Parser parser, const ENCODING *enc, + const char *attStr, TAG_NAME *tagNamePtr, + BINDING **bindingsPtr) +{ + DTD * const dtd = _dtd; /* save one level of indirection */ + ELEMENT_TYPE *elementType; + int nDefaultAtts; + const XML_Char **appAtts; /* the attribute list for the application */ + int attIndex = 0; + int prefixLen; + int i; + int n; + XML_Char *uri; + int nPrefixes = 0; + BINDING *binding; + const XML_Char *localPart; + + /* lookup the element type name */ + elementType = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, tagNamePtr->str,0); + if (!elementType) { + const XML_Char *name = poolCopyString(&dtd->pool, tagNamePtr->str); + if (!name) + return XML_ERROR_NO_MEMORY; + elementType = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, name, + sizeof(ELEMENT_TYPE)); + if (!elementType) + return XML_ERROR_NO_MEMORY; + if (ns && !setElementTypePrefix(parser, elementType)) + return XML_ERROR_NO_MEMORY; + } + nDefaultAtts = elementType->nDefaultAtts; + + /* get the attributes from the tokenizer */ + n = XmlGetAttributes(enc, attStr, attsSize, atts); + if (n + nDefaultAtts > attsSize) { + int oldAttsSize = attsSize; + ATTRIBUTE *temp; +#ifdef XML_ATTR_INFO + XML_AttrInfo *temp2; +#endif + attsSize = n + nDefaultAtts + INIT_ATTS_SIZE; + temp = (ATTRIBUTE *)REALLOC((void *)atts, attsSize * sizeof(ATTRIBUTE)); + if (temp == NULL) + return XML_ERROR_NO_MEMORY; + atts = temp; +#ifdef XML_ATTR_INFO + temp2 = (XML_AttrInfo *)REALLOC((void *)attInfo, attsSize * sizeof(XML_AttrInfo)); + if (temp2 == NULL) + return XML_ERROR_NO_MEMORY; + attInfo = temp2; +#endif + if (n > oldAttsSize) + XmlGetAttributes(enc, attStr, n, atts); + } + + appAtts = (const XML_Char **)atts; + for (i = 0; i < n; i++) { + ATTRIBUTE *currAtt = &atts[i]; +#ifdef XML_ATTR_INFO + XML_AttrInfo *currAttInfo = &attInfo[i]; +#endif + /* add the name and value to the attribute list */ + ATTRIBUTE_ID *attId = getAttributeId(parser, enc, currAtt->name, + currAtt->name + + XmlNameLength(enc, currAtt->name)); + if (!attId) + return XML_ERROR_NO_MEMORY; +#ifdef XML_ATTR_INFO + currAttInfo->nameStart = parseEndByteIndex - (parseEndPtr - currAtt->name); + currAttInfo->nameEnd = currAttInfo->nameStart + + XmlNameLength(enc, currAtt->name); + currAttInfo->valueStart = parseEndByteIndex - + (parseEndPtr - currAtt->valuePtr); + currAttInfo->valueEnd = parseEndByteIndex - (parseEndPtr - currAtt->valueEnd); +#endif + /* Detect duplicate attributes by their QNames. This does not work when + namespace processing is turned on and different prefixes for the same + namespace are used. For this case we have a check further down. + */ + if ((attId->name)[-1]) { + if (enc == encoding) + eventPtr = atts[i].name; + return XML_ERROR_DUPLICATE_ATTRIBUTE; + } + (attId->name)[-1] = 1; + appAtts[attIndex++] = attId->name; + if (!atts[i].normalized) { + enum XML_Error result; + XML_Bool isCdata = XML_TRUE; + + /* figure out whether declared as other than CDATA */ + if (attId->maybeTokenized) { + int j; + for (j = 0; j < nDefaultAtts; j++) { + if (attId == elementType->defaultAtts[j].id) { + isCdata = elementType->defaultAtts[j].isCdata; + break; + } + } + } + + /* normalize the attribute value */ + result = storeAttributeValue(parser, enc, isCdata, + atts[i].valuePtr, atts[i].valueEnd, + &tempPool); + if (result) + return result; + appAtts[attIndex] = poolStart(&tempPool); + poolFinish(&tempPool); + } + else { + /* the value did not need normalizing */ + appAtts[attIndex] = poolStoreString(&tempPool, enc, atts[i].valuePtr, + atts[i].valueEnd); + if (appAtts[attIndex] == 0) + return XML_ERROR_NO_MEMORY; + poolFinish(&tempPool); + } + /* handle prefixed attribute names */ + if (attId->prefix) { + if (attId->xmlns) { + /* deal with namespace declarations here */ + enum XML_Error result = addBinding(parser, attId->prefix, attId, + appAtts[attIndex], bindingsPtr); + if (result) + return result; + --attIndex; + } + else { + /* deal with other prefixed names later */ + attIndex++; + nPrefixes++; + (attId->name)[-1] = 2; + } + } + else + attIndex++; + } + + /* set-up for XML_GetSpecifiedAttributeCount and XML_GetIdAttributeIndex */ + nSpecifiedAtts = attIndex; + if (elementType->idAtt && (elementType->idAtt->name)[-1]) { + for (i = 0; i < attIndex; i += 2) + if (appAtts[i] == elementType->idAtt->name) { + idAttIndex = i; + break; + } + } + else + idAttIndex = -1; + + /* do attribute defaulting */ + for (i = 0; i < nDefaultAtts; i++) { + const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + i; + if (!(da->id->name)[-1] && da->value) { + if (da->id->prefix) { + if (da->id->xmlns) { + enum XML_Error result = addBinding(parser, da->id->prefix, da->id, + da->value, bindingsPtr); + if (result) + return result; + } + else { + (da->id->name)[-1] = 2; + nPrefixes++; + appAtts[attIndex++] = da->id->name; + appAtts[attIndex++] = da->value; + } + } + else { + (da->id->name)[-1] = 1; + appAtts[attIndex++] = da->id->name; + appAtts[attIndex++] = da->value; + } + } + } + appAtts[attIndex] = 0; + + /* expand prefixed attribute names, check for duplicates, + and clear flags that say whether attributes were specified */ + i = 0; + if (nPrefixes) { + int j; /* hash table index */ + unsigned long version = nsAttsVersion; + int nsAttsSize = (int)1 << nsAttsPower; + /* size of hash table must be at least 2 * (# of prefixed attributes) */ + if ((nPrefixes << 1) >> nsAttsPower) { /* true for nsAttsPower = 0 */ + NS_ATT *temp; + /* hash table size must also be a power of 2 and >= 8 */ + while (nPrefixes >> nsAttsPower++); + if (nsAttsPower < 3) + nsAttsPower = 3; + nsAttsSize = (int)1 << nsAttsPower; + temp = (NS_ATT *)REALLOC(nsAtts, nsAttsSize * sizeof(NS_ATT)); + if (!temp) + return XML_ERROR_NO_MEMORY; + nsAtts = temp; + version = 0; /* force re-initialization of nsAtts hash table */ + } + /* using a version flag saves us from initializing nsAtts every time */ + if (!version) { /* initialize version flags when version wraps around */ + version = INIT_ATTS_VERSION; + for (j = nsAttsSize; j != 0; ) + nsAtts[--j].version = version; + } + nsAttsVersion = --version; + + /* expand prefixed names and check for duplicates */ + for (; i < attIndex; i += 2) { + const XML_Char *s = appAtts[i]; + if (s[-1] == 2) { /* prefixed */ + ATTRIBUTE_ID *id; + const BINDING *b; + unsigned long uriHash = hash_secret_salt; + ((XML_Char *)s)[-1] = 0; /* clear flag */ + id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, s, 0); + b = id->prefix->binding; + if (!b) + return XML_ERROR_UNBOUND_PREFIX; + + /* as we expand the name we also calculate its hash value */ + for (j = 0; j < b->uriLen; j++) { + const XML_Char c = b->uri[j]; + if (!poolAppendChar(&tempPool, c)) + return XML_ERROR_NO_MEMORY; + uriHash = CHAR_HASH(uriHash, c); + } + while (*s++ != XML_T(ASCII_COLON)) + ; + do { /* copies null terminator */ + const XML_Char c = *s; + if (!poolAppendChar(&tempPool, *s)) + return XML_ERROR_NO_MEMORY; + uriHash = CHAR_HASH(uriHash, c); + } while (*s++); + + { /* Check hash table for duplicate of expanded name (uriName). + Derived from code in lookup(parser, HASH_TABLE *table, ...). + */ + unsigned char step = 0; + unsigned long mask = nsAttsSize - 1; + j = uriHash & mask; /* index into hash table */ + while (nsAtts[j].version == version) { + /* for speed we compare stored hash values first */ + if (uriHash == nsAtts[j].hash) { + const XML_Char *s1 = poolStart(&tempPool); + const XML_Char *s2 = nsAtts[j].uriName; + /* s1 is null terminated, but not s2 */ + for (; *s1 == *s2 && *s1 != 0; s1++, s2++); + if (*s1 == 0) + return XML_ERROR_DUPLICATE_ATTRIBUTE; + } + if (!step) + step = PROBE_STEP(uriHash, mask, nsAttsPower); + j < step ? (j += nsAttsSize - step) : (j -= step); + } + } + + if (ns_triplets) { /* append namespace separator and prefix */ + tempPool.ptr[-1] = namespaceSeparator; + s = b->prefix->name; + do { + if (!poolAppendChar(&tempPool, *s)) + return XML_ERROR_NO_MEMORY; + } while (*s++); + } + + /* store expanded name in attribute list */ + s = poolStart(&tempPool); + poolFinish(&tempPool); + appAtts[i] = s; + + /* fill empty slot with new version, uriName and hash value */ + nsAtts[j].version = version; + nsAtts[j].hash = uriHash; + nsAtts[j].uriName = s; + + if (!--nPrefixes) { + i += 2; + break; + } + } + else /* not prefixed */ + ((XML_Char *)s)[-1] = 0; /* clear flag */ + } + } + /* clear flags for the remaining attributes */ + for (; i < attIndex; i += 2) + ((XML_Char *)(appAtts[i]))[-1] = 0; + for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding) + binding->attId->name[-1] = 0; + + if (!ns) + return XML_ERROR_NONE; + + /* expand the element type name */ + if (elementType->prefix) { + binding = elementType->prefix->binding; + if (!binding) + return XML_ERROR_UNBOUND_PREFIX; + localPart = tagNamePtr->str; + while (*localPart++ != XML_T(ASCII_COLON)) + ; + } + else if (dtd->defaultPrefix.binding) { + binding = dtd->defaultPrefix.binding; + localPart = tagNamePtr->str; + } + else + return XML_ERROR_NONE; + prefixLen = 0; + if (ns_triplets && binding->prefix->name) { + for (; binding->prefix->name[prefixLen++];) + ; /* prefixLen includes null terminator */ + } + tagNamePtr->localPart = localPart; + tagNamePtr->uriLen = binding->uriLen; + tagNamePtr->prefix = binding->prefix->name; + tagNamePtr->prefixLen = prefixLen; + for (i = 0; localPart[i++];) + ; /* i includes null terminator */ + n = i + binding->uriLen + prefixLen; + if (n > binding->uriAlloc) { + TAG *p; + uri = (XML_Char *)MALLOC((n + EXPAND_SPARE) * sizeof(XML_Char)); + if (!uri) + return XML_ERROR_NO_MEMORY; + binding->uriAlloc = n + EXPAND_SPARE; + memcpy(uri, binding->uri, binding->uriLen * sizeof(XML_Char)); + for (p = tagStack; p; p = p->parent) + if (p->name.str == binding->uri) + p->name.str = uri; + FREE(binding->uri); + binding->uri = uri; + } + /* if namespaceSeparator != '\0' then uri includes it already */ + uri = binding->uri + binding->uriLen; + memcpy(uri, localPart, i * sizeof(XML_Char)); + /* we always have a namespace separator between localPart and prefix */ + if (prefixLen) { + uri += i - 1; + *uri = namespaceSeparator; /* replace null terminator */ + memcpy(uri + 1, binding->prefix->name, prefixLen * sizeof(XML_Char)); + } + tagNamePtr->str = binding->uri; + return XML_ERROR_NONE; +} + +/* addBinding() overwrites the value of prefix->binding without checking. + Therefore one must keep track of the old value outside of addBinding(). +*/ +static enum XML_Error +addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, + const XML_Char *uri, BINDING **bindingsPtr) +{ + static const XML_Char xmlNamespace[] = { + ASCII_h, ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH, ASCII_SLASH, + ASCII_w, ASCII_w, ASCII_w, ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD, + ASCII_o, ASCII_r, ASCII_g, ASCII_SLASH, ASCII_X, ASCII_M, ASCII_L, + ASCII_SLASH, ASCII_1, ASCII_9, ASCII_9, ASCII_8, ASCII_SLASH, + ASCII_n, ASCII_a, ASCII_m, ASCII_e, ASCII_s, ASCII_p, ASCII_a, ASCII_c, + ASCII_e, '\0' + }; + static const int xmlLen = + (int)sizeof(xmlNamespace)/sizeof(XML_Char) - 1; + static const XML_Char xmlnsNamespace[] = { + ASCII_h, ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH, ASCII_SLASH, + ASCII_w, ASCII_w, ASCII_w, ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD, + ASCII_o, ASCII_r, ASCII_g, ASCII_SLASH, ASCII_2, ASCII_0, ASCII_0, + ASCII_0, ASCII_SLASH, ASCII_x, ASCII_m, ASCII_l, ASCII_n, ASCII_s, + ASCII_SLASH, '\0' + }; + static const int xmlnsLen = + (int)sizeof(xmlnsNamespace)/sizeof(XML_Char) - 1; + + XML_Bool mustBeXML = XML_FALSE; + XML_Bool isXML = XML_TRUE; + XML_Bool isXMLNS = XML_TRUE; + + BINDING *b; + int len; + + /* empty URI is only valid for default namespace per XML NS 1.0 (not 1.1) */ + if (*uri == XML_T('\0') && prefix->name) + return XML_ERROR_UNDECLARING_PREFIX; + + if (prefix->name + && prefix->name[0] == XML_T(ASCII_x) + && prefix->name[1] == XML_T(ASCII_m) + && prefix->name[2] == XML_T(ASCII_l)) { + + /* Not allowed to bind xmlns */ + if (prefix->name[3] == XML_T(ASCII_n) + && prefix->name[4] == XML_T(ASCII_s) + && prefix->name[5] == XML_T('\0')) + return XML_ERROR_RESERVED_PREFIX_XMLNS; + + if (prefix->name[3] == XML_T('\0')) + mustBeXML = XML_TRUE; + } + + for (len = 0; uri[len]; len++) { + if (isXML && (len > xmlLen || uri[len] != xmlNamespace[len])) + isXML = XML_FALSE; + + if (!mustBeXML && isXMLNS + && (len > xmlnsLen || uri[len] != xmlnsNamespace[len])) + isXMLNS = XML_FALSE; + } + isXML = isXML && len == xmlLen; + isXMLNS = isXMLNS && len == xmlnsLen; + + if (mustBeXML != isXML) + return mustBeXML ? XML_ERROR_RESERVED_PREFIX_XML + : XML_ERROR_RESERVED_NAMESPACE_URI; + + if (isXMLNS) + return XML_ERROR_RESERVED_NAMESPACE_URI; + + if (namespaceSeparator) + len++; + if (freeBindingList) { + b = freeBindingList; + if (len > b->uriAlloc) { + XML_Char *temp = (XML_Char *)REALLOC(b->uri, + sizeof(XML_Char) * (len + EXPAND_SPARE)); + if (temp == NULL) + return XML_ERROR_NO_MEMORY; + b->uri = temp; + b->uriAlloc = len + EXPAND_SPARE; + } + freeBindingList = b->nextTagBinding; + } + else { + b = (BINDING *)MALLOC(sizeof(BINDING)); + if (!b) + return XML_ERROR_NO_MEMORY; + b->uri = (XML_Char *)MALLOC(sizeof(XML_Char) * (len + EXPAND_SPARE)); + if (!b->uri) { + FREE(b); + return XML_ERROR_NO_MEMORY; + } + b->uriAlloc = len + EXPAND_SPARE; + } + b->uriLen = len; + memcpy(b->uri, uri, len * sizeof(XML_Char)); + if (namespaceSeparator) + b->uri[len - 1] = namespaceSeparator; + b->prefix = prefix; + b->attId = attId; + b->prevPrefixBinding = prefix->binding; + /* NULL binding when default namespace undeclared */ + if (*uri == XML_T('\0') && prefix == &_dtd->defaultPrefix) + prefix->binding = NULL; + else + prefix->binding = b; + b->nextTagBinding = *bindingsPtr; + *bindingsPtr = b; + /* if attId == NULL then we are not starting a namespace scope */ + if (attId && startNamespaceDeclHandler) + startNamespaceDeclHandler(handlerArg, prefix->name, + prefix->binding ? uri : 0); + return XML_ERROR_NONE; +} + +/* The idea here is to avoid using stack for each CDATA section when + the whole file is parsed with one call. +*/ +static enum XML_Error PTRCALL +cdataSectionProcessor(XML_Parser parser, + const char *start, + const char *end, + const char **endPtr) +{ + enum XML_Error result = doCdataSection(parser, encoding, &start, end, + endPtr, (XML_Bool)!ps_finalBuffer); + if (result != XML_ERROR_NONE) + return result; + if (start) { + if (parentParser) { /* we are parsing an external entity */ + processor = externalEntityContentProcessor; + return externalEntityContentProcessor(parser, start, end, endPtr); + } + else { + processor = contentProcessor; + return contentProcessor(parser, start, end, endPtr); + } + } + return result; +} + +/* startPtr gets set to non-null if the section is closed, and to null if + the section is not yet closed. +*/ +static enum XML_Error +doCdataSection(XML_Parser parser, + const ENCODING *enc, + const char **startPtr, + const char *end, + const char **nextPtr, + XML_Bool haveMore) +{ + const char *s = *startPtr; + const char **eventPP; + const char **eventEndPP; + if (enc == encoding) { + eventPP = &eventPtr; + *eventPP = s; + eventEndPP = &eventEndPtr; + } + else { + eventPP = &(openInternalEntities->internalEventPtr); + eventEndPP = &(openInternalEntities->internalEventEndPtr); + } + *eventPP = s; + *startPtr = NULL; + + for (;;) { + const char *next; + int tok = XmlCdataSectionTok(enc, s, end, &next); + *eventEndPP = next; + switch (tok) { + case XML_TOK_CDATA_SECT_CLOSE: + if (endCdataSectionHandler) + endCdataSectionHandler(handlerArg); +#if 0 + /* see comment under XML_TOK_CDATA_SECT_OPEN */ + else if (characterDataHandler) + characterDataHandler(handlerArg, dataBuf, 0); +#endif + else if (defaultHandler) + reportDefault(parser, enc, s, next); + *startPtr = next; + *nextPtr = next; + if (ps_parsing == XML_FINISHED) + return XML_ERROR_ABORTED; + else + return XML_ERROR_NONE; + case XML_TOK_DATA_NEWLINE: + if (characterDataHandler) { + XML_Char c = 0xA; + characterDataHandler(handlerArg, &c, 1); + } + else if (defaultHandler) + reportDefault(parser, enc, s, next); + break; + case XML_TOK_DATA_CHARS: + { + XML_CharacterDataHandler charDataHandler = characterDataHandler; + if (charDataHandler) { + if (MUST_CONVERT(enc, s)) { + for (;;) { + ICHAR *dataPtr = (ICHAR *)dataBuf; + XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd); + *eventEndPP = next; + charDataHandler(handlerArg, dataBuf, + (int)(dataPtr - (ICHAR *)dataBuf)); + if (s == next) + break; + *eventPP = s; + } + } + else + charDataHandler(handlerArg, + (XML_Char *)s, + (int)((XML_Char *)next - (XML_Char *)s)); + } + else if (defaultHandler) + reportDefault(parser, enc, s, next); + } + break; + case XML_TOK_INVALID: + *eventPP = next; + return XML_ERROR_INVALID_TOKEN; + case XML_TOK_PARTIAL_CHAR: + if (haveMore) { + *nextPtr = s; + return XML_ERROR_NONE; + } + return XML_ERROR_PARTIAL_CHAR; + case XML_TOK_PARTIAL: + case XML_TOK_NONE: + if (haveMore) { + *nextPtr = s; + return XML_ERROR_NONE; + } + return XML_ERROR_UNCLOSED_CDATA_SECTION; + default: + *eventPP = next; + return XML_ERROR_UNEXPECTED_STATE; + } + + *eventPP = s = next; + switch (ps_parsing) { + case XML_SUSPENDED: + *nextPtr = next; + return XML_ERROR_NONE; + case XML_FINISHED: + return XML_ERROR_ABORTED; + default: ; + } + } + /* not reached */ +} + +#ifdef XML_DTD + +/* The idea here is to avoid using stack for each IGNORE section when + the whole file is parsed with one call. +*/ +static enum XML_Error PTRCALL +ignoreSectionProcessor(XML_Parser parser, + const char *start, + const char *end, + const char **endPtr) +{ + enum XML_Error result = doIgnoreSection(parser, encoding, &start, end, + endPtr, (XML_Bool)!ps_finalBuffer); + if (result != XML_ERROR_NONE) + return result; + if (start) { + processor = prologProcessor; + return prologProcessor(parser, start, end, endPtr); + } + return result; +} + +/* startPtr gets set to non-null is the section is closed, and to null + if the section is not yet closed. +*/ +static enum XML_Error +doIgnoreSection(XML_Parser parser, + const ENCODING *enc, + const char **startPtr, + const char *end, + const char **nextPtr, + XML_Bool haveMore) +{ + const char *next; + int tok; + const char *s = *startPtr; + const char **eventPP; + const char **eventEndPP; + if (enc == encoding) { + eventPP = &eventPtr; + *eventPP = s; + eventEndPP = &eventEndPtr; + } + else { + eventPP = &(openInternalEntities->internalEventPtr); + eventEndPP = &(openInternalEntities->internalEventEndPtr); + } + *eventPP = s; + *startPtr = NULL; + tok = XmlIgnoreSectionTok(enc, s, end, &next); + *eventEndPP = next; + switch (tok) { + case XML_TOK_IGNORE_SECT: + if (defaultHandler) + reportDefault(parser, enc, s, next); + *startPtr = next; + *nextPtr = next; + if (ps_parsing == XML_FINISHED) + return XML_ERROR_ABORTED; + else + return XML_ERROR_NONE; + case XML_TOK_INVALID: + *eventPP = next; + return XML_ERROR_INVALID_TOKEN; + case XML_TOK_PARTIAL_CHAR: + if (haveMore) { + *nextPtr = s; + return XML_ERROR_NONE; + } + return XML_ERROR_PARTIAL_CHAR; + case XML_TOK_PARTIAL: + case XML_TOK_NONE: + if (haveMore) { + *nextPtr = s; + return XML_ERROR_NONE; + } + return XML_ERROR_SYNTAX; /* XML_ERROR_UNCLOSED_IGNORE_SECTION */ + default: + *eventPP = next; + return XML_ERROR_UNEXPECTED_STATE; + } + /* not reached */ +} + +#endif /* XML_DTD */ + +static enum XML_Error +initializeEncoding(XML_Parser parser) +{ + const char *s; +#ifdef XML_UNICODE + char encodingBuf[128]; + if (!protocolEncodingName) + s = NULL; + else { + int i; + for (i = 0; protocolEncodingName[i]; i++) { + if (i == sizeof(encodingBuf) - 1 + || (protocolEncodingName[i] & ~0x7f) != 0) { + encodingBuf[0] = '\0'; + break; + } + encodingBuf[i] = (char)protocolEncodingName[i]; + } + encodingBuf[i] = '\0'; + s = encodingBuf; + } +#else + s = protocolEncodingName; +#endif + if ((ns ? XmlInitEncodingNS : XmlInitEncoding)(&initEncoding, &encoding, s)) + return XML_ERROR_NONE; + return handleUnknownEncoding(parser, protocolEncodingName); +} + +static enum XML_Error +processXmlDecl(XML_Parser parser, int isGeneralTextEntity, + const char *s, const char *next) +{ + const char *encodingName = NULL; + const XML_Char *storedEncName = NULL; + const ENCODING *newEncoding = NULL; + const char *version = NULL; + const char *versionend; + const XML_Char *storedversion = NULL; + int standalone = -1; + if (!(ns + ? XmlParseXmlDeclNS + : XmlParseXmlDecl)(isGeneralTextEntity, + encoding, + s, + next, + &eventPtr, + &version, + &versionend, + &encodingName, + &newEncoding, + &standalone)) { + if (isGeneralTextEntity) + return XML_ERROR_TEXT_DECL; + else + return XML_ERROR_XML_DECL; + } + if (!isGeneralTextEntity && standalone == 1) { + _dtd->standalone = XML_TRUE; +#ifdef XML_DTD + if (paramEntityParsing == XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE) + paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER; +#endif /* XML_DTD */ + } + if (xmlDeclHandler) { + if (encodingName != NULL) { + storedEncName = poolStoreString(&temp2Pool, + encoding, + encodingName, + encodingName + + XmlNameLength(encoding, encodingName)); + if (!storedEncName) + return XML_ERROR_NO_MEMORY; + poolFinish(&temp2Pool); + } + if (version) { + storedversion = poolStoreString(&temp2Pool, + encoding, + version, + versionend - encoding->minBytesPerChar); + if (!storedversion) + return XML_ERROR_NO_MEMORY; + } + xmlDeclHandler(handlerArg, storedversion, storedEncName, standalone); + } + else if (defaultHandler) + reportDefault(parser, encoding, s, next); + if (protocolEncodingName == NULL) { + if (newEncoding) { + if (newEncoding->minBytesPerChar != encoding->minBytesPerChar) { + eventPtr = encodingName; + return XML_ERROR_INCORRECT_ENCODING; + } + encoding = newEncoding; + } + else if (encodingName) { + enum XML_Error result; + if (!storedEncName) { + storedEncName = poolStoreString( + &temp2Pool, encoding, encodingName, + encodingName + XmlNameLength(encoding, encodingName)); + if (!storedEncName) + return XML_ERROR_NO_MEMORY; + } + result = handleUnknownEncoding(parser, storedEncName); + poolClear(&temp2Pool); + if (result == XML_ERROR_UNKNOWN_ENCODING) + eventPtr = encodingName; + return result; + } + } + + if (storedEncName || storedversion) + poolClear(&temp2Pool); + + return XML_ERROR_NONE; +} + +static enum XML_Error +handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName) +{ + if (unknownEncodingHandler) { + XML_Encoding info; + int i; + for (i = 0; i < 256; i++) + info.map[i] = -1; + info.convert = NULL; + info.data = NULL; + info.release = NULL; + if (unknownEncodingHandler(unknownEncodingHandlerData, encodingName, + &info)) { + ENCODING *enc; + unknownEncodingMem = MALLOC(XmlSizeOfUnknownEncoding()); + if (!unknownEncodingMem) { + if (info.release) + info.release(info.data); + return XML_ERROR_NO_MEMORY; + } + enc = (ns + ? XmlInitUnknownEncodingNS + : XmlInitUnknownEncoding)(unknownEncodingMem, + info.map, + info.convert, + info.data); + if (enc) { + unknownEncodingData = info.data; + unknownEncodingRelease = info.release; + encoding = enc; + return XML_ERROR_NONE; + } + } + if (info.release != NULL) + info.release(info.data); + } + return XML_ERROR_UNKNOWN_ENCODING; +} + +static enum XML_Error PTRCALL +prologInitProcessor(XML_Parser parser, + const char *s, + const char *end, + const char **nextPtr) +{ + enum XML_Error result = initializeEncoding(parser); + if (result != XML_ERROR_NONE) + return result; + processor = prologProcessor; + return prologProcessor(parser, s, end, nextPtr); +} + +#ifdef XML_DTD + +static enum XML_Error PTRCALL +externalParEntInitProcessor(XML_Parser parser, + const char *s, + const char *end, + const char **nextPtr) +{ + enum XML_Error result = initializeEncoding(parser); + if (result != XML_ERROR_NONE) + return result; + + /* we know now that XML_Parse(Buffer) has been called, + so we consider the external parameter entity read */ + _dtd->paramEntityRead = XML_TRUE; + + if (prologState.inEntityValue) { + processor = entityValueInitProcessor; + return entityValueInitProcessor(parser, s, end, nextPtr); + } + else { + processor = externalParEntProcessor; + return externalParEntProcessor(parser, s, end, nextPtr); + } +} + +static enum XML_Error PTRCALL +entityValueInitProcessor(XML_Parser parser, + const char *s, + const char *end, + const char **nextPtr) +{ + int tok; + const char *start = s; + const char *next = start; + eventPtr = start; + + for (;;) { + tok = XmlPrologTok(encoding, start, end, &next); + eventEndPtr = next; + if (tok <= 0) { + if (!ps_finalBuffer && tok != XML_TOK_INVALID) { + *nextPtr = s; + return XML_ERROR_NONE; + } + switch (tok) { + case XML_TOK_INVALID: + return XML_ERROR_INVALID_TOKEN; + case XML_TOK_PARTIAL: + return XML_ERROR_UNCLOSED_TOKEN; + case XML_TOK_PARTIAL_CHAR: + return XML_ERROR_PARTIAL_CHAR; + case XML_TOK_NONE: /* start == end */ + default: + break; + } + /* found end of entity value - can store it now */ + return storeEntityValue(parser, encoding, s, end); + } + else if (tok == XML_TOK_XML_DECL) { + enum XML_Error result; + result = processXmlDecl(parser, 0, start, next); + if (result != XML_ERROR_NONE) + return result; + switch (ps_parsing) { + case XML_SUSPENDED: + *nextPtr = next; + return XML_ERROR_NONE; + case XML_FINISHED: + return XML_ERROR_ABORTED; + default: + *nextPtr = next; + } + /* stop scanning for text declaration - we found one */ + processor = entityValueProcessor; + return entityValueProcessor(parser, next, end, nextPtr); + } + /* If we are at the end of the buffer, this would cause XmlPrologTok to + return XML_TOK_NONE on the next call, which would then cause the + function to exit with *nextPtr set to s - that is what we want for other + tokens, but not for the BOM - we would rather like to skip it; + then, when this routine is entered the next time, XmlPrologTok will + return XML_TOK_INVALID, since the BOM is still in the buffer + */ + else if (tok == XML_TOK_BOM && next == end && !ps_finalBuffer) { + *nextPtr = next; + return XML_ERROR_NONE; + } + start = next; + eventPtr = start; + } +} + +static enum XML_Error PTRCALL +externalParEntProcessor(XML_Parser parser, + const char *s, + const char *end, + const char **nextPtr) +{ + const char *next = s; + int tok; + + tok = XmlPrologTok(encoding, s, end, &next); + if (tok <= 0) { + if (!ps_finalBuffer && tok != XML_TOK_INVALID) { + *nextPtr = s; + return XML_ERROR_NONE; + } + switch (tok) { + case XML_TOK_INVALID: + return XML_ERROR_INVALID_TOKEN; + case XML_TOK_PARTIAL: + return XML_ERROR_UNCLOSED_TOKEN; + case XML_TOK_PARTIAL_CHAR: + return XML_ERROR_PARTIAL_CHAR; + case XML_TOK_NONE: /* start == end */ + default: + break; + } + } + /* This would cause the next stage, i.e. doProlog to be passed XML_TOK_BOM. + However, when parsing an external subset, doProlog will not accept a BOM + as valid, and report a syntax error, so we have to skip the BOM + */ + else if (tok == XML_TOK_BOM) { + s = next; + tok = XmlPrologTok(encoding, s, end, &next); + } + + processor = prologProcessor; + return doProlog(parser, encoding, s, end, tok, next, + nextPtr, (XML_Bool)!ps_finalBuffer); +} + +static enum XML_Error PTRCALL +entityValueProcessor(XML_Parser parser, + const char *s, + const char *end, + const char **nextPtr) +{ + const char *start = s; + const char *next = s; + const ENCODING *enc = encoding; + int tok; + + for (;;) { + tok = XmlPrologTok(enc, start, end, &next); + if (tok <= 0) { + if (!ps_finalBuffer && tok != XML_TOK_INVALID) { + *nextPtr = s; + return XML_ERROR_NONE; + } + switch (tok) { + case XML_TOK_INVALID: + return XML_ERROR_INVALID_TOKEN; + case XML_TOK_PARTIAL: + return XML_ERROR_UNCLOSED_TOKEN; + case XML_TOK_PARTIAL_CHAR: + return XML_ERROR_PARTIAL_CHAR; + case XML_TOK_NONE: /* start == end */ + default: + break; + } + /* found end of entity value - can store it now */ + return storeEntityValue(parser, enc, s, end); + } + start = next; + } +} + +#endif /* XML_DTD */ + +static enum XML_Error PTRCALL +prologProcessor(XML_Parser parser, + const char *s, + const char *end, + const char **nextPtr) +{ + const char *next = s; + int tok = XmlPrologTok(encoding, s, end, &next); + return doProlog(parser, encoding, s, end, tok, next, + nextPtr, (XML_Bool)!ps_finalBuffer); +} + +static enum XML_Error +doProlog(XML_Parser parser, + const ENCODING *enc, + const char *s, + const char *end, + int tok, + const char *next, + const char **nextPtr, + XML_Bool haveMore) +{ +#ifdef XML_DTD + static const XML_Char externalSubsetName[] = { ASCII_HASH , '\0' }; +#endif /* XML_DTD */ + static const XML_Char atypeCDATA[] = + { ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' }; + static const XML_Char atypeID[] = { ASCII_I, ASCII_D, '\0' }; + static const XML_Char atypeIDREF[] = + { ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, '\0' }; + static const XML_Char atypeIDREFS[] = + { ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, ASCII_S, '\0' }; + static const XML_Char atypeENTITY[] = + { ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_Y, '\0' }; + static const XML_Char atypeENTITIES[] = { ASCII_E, ASCII_N, + ASCII_T, ASCII_I, ASCII_T, ASCII_I, ASCII_E, ASCII_S, '\0' }; + static const XML_Char atypeNMTOKEN[] = { + ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, '\0' }; + static const XML_Char atypeNMTOKENS[] = { ASCII_N, ASCII_M, ASCII_T, + ASCII_O, ASCII_K, ASCII_E, ASCII_N, ASCII_S, '\0' }; + static const XML_Char notationPrefix[] = { ASCII_N, ASCII_O, ASCII_T, + ASCII_A, ASCII_T, ASCII_I, ASCII_O, ASCII_N, ASCII_LPAREN, '\0' }; + static const XML_Char enumValueSep[] = { ASCII_PIPE, '\0' }; + static const XML_Char enumValueStart[] = { ASCII_LPAREN, '\0' }; + + /* save one level of indirection */ + DTD * const dtd = _dtd; + + const char **eventPP; + const char **eventEndPP; + enum XML_Content_Quant quant; + + if (enc == encoding) { + eventPP = &eventPtr; + eventEndPP = &eventEndPtr; + } + else { + eventPP = &(openInternalEntities->internalEventPtr); + eventEndPP = &(openInternalEntities->internalEventEndPtr); + } + + for (;;) { + int role; + XML_Bool handleDefault = XML_TRUE; + *eventPP = s; + *eventEndPP = next; + if (tok <= 0) { + if (haveMore && tok != XML_TOK_INVALID) { + *nextPtr = s; + return XML_ERROR_NONE; + } + switch (tok) { + case XML_TOK_INVALID: + *eventPP = next; + return XML_ERROR_INVALID_TOKEN; + case XML_TOK_PARTIAL: + return XML_ERROR_UNCLOSED_TOKEN; + case XML_TOK_PARTIAL_CHAR: + return XML_ERROR_PARTIAL_CHAR; + case -XML_TOK_PROLOG_S: + tok = -tok; + break; + case XML_TOK_NONE: +#ifdef XML_DTD + /* for internal PE NOT referenced between declarations */ + if (enc != encoding && !openInternalEntities->betweenDecl) { + *nextPtr = s; + return XML_ERROR_NONE; + } + /* WFC: PE Between Declarations - must check that PE contains + complete markup, not only for external PEs, but also for + internal PEs if the reference occurs between declarations. + */ + if (isParamEntity || enc != encoding) { + if (XmlTokenRole(&prologState, XML_TOK_NONE, end, end, enc) + == XML_ROLE_ERROR) + return XML_ERROR_INCOMPLETE_PE; + *nextPtr = s; + return XML_ERROR_NONE; + } +#endif /* XML_DTD */ + return XML_ERROR_NO_ELEMENTS; + default: + tok = -tok; + next = end; + break; + } + } + role = XmlTokenRole(&prologState, tok, s, next, enc); + switch (role) { + case XML_ROLE_XML_DECL: + { + enum XML_Error result = processXmlDecl(parser, 0, s, next); + if (result != XML_ERROR_NONE) + return result; + enc = encoding; + handleDefault = XML_FALSE; + } + break; + case XML_ROLE_DOCTYPE_NAME: + if (startDoctypeDeclHandler) { + doctypeName = poolStoreString(&tempPool, enc, s, next); + if (!doctypeName) + return XML_ERROR_NO_MEMORY; + poolFinish(&tempPool); + doctypePubid = NULL; + handleDefault = XML_FALSE; + } + doctypeSysid = NULL; /* always initialize to NULL */ + break; + case XML_ROLE_DOCTYPE_INTERNAL_SUBSET: + if (startDoctypeDeclHandler) { + startDoctypeDeclHandler(handlerArg, doctypeName, doctypeSysid, + doctypePubid, 1); + doctypeName = NULL; + poolClear(&tempPool); + handleDefault = XML_FALSE; + } + break; +#ifdef XML_DTD + case XML_ROLE_TEXT_DECL: + { + enum XML_Error result = processXmlDecl(parser, 1, s, next); + if (result != XML_ERROR_NONE) + return result; + enc = encoding; + handleDefault = XML_FALSE; + } + break; +#endif /* XML_DTD */ + case XML_ROLE_DOCTYPE_PUBLIC_ID: +#ifdef XML_DTD + useForeignDTD = XML_FALSE; + declEntity = (ENTITY *)lookup(parser, + &dtd->paramEntities, + externalSubsetName, + sizeof(ENTITY)); + if (!declEntity) + return XML_ERROR_NO_MEMORY; +#endif /* XML_DTD */ + dtd->hasParamEntityRefs = XML_TRUE; + if (startDoctypeDeclHandler) { + XML_Char *pubId; + if (!XmlIsPublicId(enc, s, next, eventPP)) + return XML_ERROR_PUBLICID; + pubId = poolStoreString(&tempPool, enc, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (!pubId) + return XML_ERROR_NO_MEMORY; + normalizePublicId(pubId); + poolFinish(&tempPool); + doctypePubid = pubId; + handleDefault = XML_FALSE; + goto alreadyChecked; + } + /* fall through */ + case XML_ROLE_ENTITY_PUBLIC_ID: + if (!XmlIsPublicId(enc, s, next, eventPP)) + return XML_ERROR_PUBLICID; + alreadyChecked: + if (dtd->keepProcessing && declEntity) { + XML_Char *tem = poolStoreString(&dtd->pool, + enc, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (!tem) + return XML_ERROR_NO_MEMORY; + normalizePublicId(tem); + declEntity->publicId = tem; + poolFinish(&dtd->pool); + if (entityDeclHandler) + handleDefault = XML_FALSE; + } + break; + case XML_ROLE_DOCTYPE_CLOSE: + if (doctypeName) { + startDoctypeDeclHandler(handlerArg, doctypeName, + doctypeSysid, doctypePubid, 0); + poolClear(&tempPool); + handleDefault = XML_FALSE; + } + /* doctypeSysid will be non-NULL in the case of a previous + XML_ROLE_DOCTYPE_SYSTEM_ID, even if startDoctypeDeclHandler + was not set, indicating an external subset + */ +#ifdef XML_DTD + if (doctypeSysid || useForeignDTD) { + XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs; + dtd->hasParamEntityRefs = XML_TRUE; + if (paramEntityParsing && externalEntityRefHandler) { + ENTITY *entity = (ENTITY *)lookup(parser, + &dtd->paramEntities, + externalSubsetName, + sizeof(ENTITY)); + if (!entity) + return XML_ERROR_NO_MEMORY; + if (useForeignDTD) + entity->base = curBase; + dtd->paramEntityRead = XML_FALSE; + if (!externalEntityRefHandler(externalEntityRefHandlerArg, + 0, + entity->base, + entity->systemId, + entity->publicId)) + return XML_ERROR_EXTERNAL_ENTITY_HANDLING; + if (dtd->paramEntityRead) { + if (!dtd->standalone && + notStandaloneHandler && + !notStandaloneHandler(handlerArg)) + return XML_ERROR_NOT_STANDALONE; + } + /* if we didn't read the foreign DTD then this means that there + is no external subset and we must reset dtd->hasParamEntityRefs + */ + else if (!doctypeSysid) + dtd->hasParamEntityRefs = hadParamEntityRefs; + /* end of DTD - no need to update dtd->keepProcessing */ + } + useForeignDTD = XML_FALSE; + } +#endif /* XML_DTD */ + if (endDoctypeDeclHandler) { + endDoctypeDeclHandler(handlerArg); + handleDefault = XML_FALSE; + } + break; + case XML_ROLE_INSTANCE_START: +#ifdef XML_DTD + /* if there is no DOCTYPE declaration then now is the + last chance to read the foreign DTD + */ + if (useForeignDTD) { + XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs; + dtd->hasParamEntityRefs = XML_TRUE; + if (paramEntityParsing && externalEntityRefHandler) { + ENTITY *entity = (ENTITY *)lookup(parser, &dtd->paramEntities, + externalSubsetName, + sizeof(ENTITY)); + if (!entity) + return XML_ERROR_NO_MEMORY; + entity->base = curBase; + dtd->paramEntityRead = XML_FALSE; + if (!externalEntityRefHandler(externalEntityRefHandlerArg, + 0, + entity->base, + entity->systemId, + entity->publicId)) + return XML_ERROR_EXTERNAL_ENTITY_HANDLING; + if (dtd->paramEntityRead) { + if (!dtd->standalone && + notStandaloneHandler && + !notStandaloneHandler(handlerArg)) + return XML_ERROR_NOT_STANDALONE; + } + /* if we didn't read the foreign DTD then this means that there + is no external subset and we must reset dtd->hasParamEntityRefs + */ + else + dtd->hasParamEntityRefs = hadParamEntityRefs; + /* end of DTD - no need to update dtd->keepProcessing */ + } + } +#endif /* XML_DTD */ + processor = contentProcessor; + return contentProcessor(parser, s, end, nextPtr); + case XML_ROLE_ATTLIST_ELEMENT_NAME: + declElementType = getElementType(parser, enc, s, next); + if (!declElementType) + return XML_ERROR_NO_MEMORY; + goto checkAttListDeclHandler; + case XML_ROLE_ATTRIBUTE_NAME: + declAttributeId = getAttributeId(parser, enc, s, next); + if (!declAttributeId) + return XML_ERROR_NO_MEMORY; + declAttributeIsCdata = XML_FALSE; + declAttributeType = NULL; + declAttributeIsId = XML_FALSE; + goto checkAttListDeclHandler; + case XML_ROLE_ATTRIBUTE_TYPE_CDATA: + declAttributeIsCdata = XML_TRUE; + declAttributeType = atypeCDATA; + goto checkAttListDeclHandler; + case XML_ROLE_ATTRIBUTE_TYPE_ID: + declAttributeIsId = XML_TRUE; + declAttributeType = atypeID; + goto checkAttListDeclHandler; + case XML_ROLE_ATTRIBUTE_TYPE_IDREF: + declAttributeType = atypeIDREF; + goto checkAttListDeclHandler; + case XML_ROLE_ATTRIBUTE_TYPE_IDREFS: + declAttributeType = atypeIDREFS; + goto checkAttListDeclHandler; + case XML_ROLE_ATTRIBUTE_TYPE_ENTITY: + declAttributeType = atypeENTITY; + goto checkAttListDeclHandler; + case XML_ROLE_ATTRIBUTE_TYPE_ENTITIES: + declAttributeType = atypeENTITIES; + goto checkAttListDeclHandler; + case XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN: + declAttributeType = atypeNMTOKEN; + goto checkAttListDeclHandler; + case XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS: + declAttributeType = atypeNMTOKENS; + checkAttListDeclHandler: + if (dtd->keepProcessing && attlistDeclHandler) + handleDefault = XML_FALSE; + break; + case XML_ROLE_ATTRIBUTE_ENUM_VALUE: + case XML_ROLE_ATTRIBUTE_NOTATION_VALUE: + if (dtd->keepProcessing && attlistDeclHandler) { + const XML_Char *prefix; + if (declAttributeType) { + prefix = enumValueSep; + } + else { + prefix = (role == XML_ROLE_ATTRIBUTE_NOTATION_VALUE + ? notationPrefix + : enumValueStart); + } + if (!poolAppendString(&tempPool, prefix)) + return XML_ERROR_NO_MEMORY; + if (!poolAppend(&tempPool, enc, s, next)) + return XML_ERROR_NO_MEMORY; + declAttributeType = tempPool.start; + handleDefault = XML_FALSE; + } + break; + case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE: + case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE: + if (dtd->keepProcessing) { + if (!defineAttribute(declElementType, declAttributeId, + declAttributeIsCdata, declAttributeIsId, + 0, parser)) + return XML_ERROR_NO_MEMORY; + if (attlistDeclHandler && declAttributeType) { + if (*declAttributeType == XML_T(ASCII_LPAREN) + || (*declAttributeType == XML_T(ASCII_N) + && declAttributeType[1] == XML_T(ASCII_O))) { + /* Enumerated or Notation type */ + if (!poolAppendChar(&tempPool, XML_T(ASCII_RPAREN)) + || !poolAppendChar(&tempPool, XML_T('\0'))) + return XML_ERROR_NO_MEMORY; + declAttributeType = tempPool.start; + poolFinish(&tempPool); + } + *eventEndPP = s; + attlistDeclHandler(handlerArg, declElementType->name, + declAttributeId->name, declAttributeType, + 0, role == XML_ROLE_REQUIRED_ATTRIBUTE_VALUE); + poolClear(&tempPool); + handleDefault = XML_FALSE; + } + } + break; + case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE: + case XML_ROLE_FIXED_ATTRIBUTE_VALUE: + if (dtd->keepProcessing) { + const XML_Char *attVal; + enum XML_Error result = + storeAttributeValue(parser, enc, declAttributeIsCdata, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar, + &dtd->pool); + if (result) + return result; + attVal = poolStart(&dtd->pool); + poolFinish(&dtd->pool); + /* ID attributes aren't allowed to have a default */ + if (!defineAttribute(declElementType, declAttributeId, + declAttributeIsCdata, XML_FALSE, attVal, parser)) + return XML_ERROR_NO_MEMORY; + if (attlistDeclHandler && declAttributeType) { + if (*declAttributeType == XML_T(ASCII_LPAREN) + || (*declAttributeType == XML_T(ASCII_N) + && declAttributeType[1] == XML_T(ASCII_O))) { + /* Enumerated or Notation type */ + if (!poolAppendChar(&tempPool, XML_T(ASCII_RPAREN)) + || !poolAppendChar(&tempPool, XML_T('\0'))) + return XML_ERROR_NO_MEMORY; + declAttributeType = tempPool.start; + poolFinish(&tempPool); + } + *eventEndPP = s; + attlistDeclHandler(handlerArg, declElementType->name, + declAttributeId->name, declAttributeType, + attVal, + role == XML_ROLE_FIXED_ATTRIBUTE_VALUE); + poolClear(&tempPool); + handleDefault = XML_FALSE; + } + } + break; + case XML_ROLE_ENTITY_VALUE: + if (dtd->keepProcessing) { + enum XML_Error result = storeEntityValue(parser, enc, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (declEntity) { + declEntity->textPtr = poolStart(&dtd->entityValuePool); + declEntity->textLen = (int)(poolLength(&dtd->entityValuePool)); + poolFinish(&dtd->entityValuePool); + if (entityDeclHandler) { + *eventEndPP = s; + entityDeclHandler(handlerArg, + declEntity->name, + declEntity->is_param, + declEntity->textPtr, + declEntity->textLen, + curBase, 0, 0, 0); + handleDefault = XML_FALSE; + } + } + else + poolDiscard(&dtd->entityValuePool); + if (result != XML_ERROR_NONE) + return result; + } + break; + case XML_ROLE_DOCTYPE_SYSTEM_ID: +#ifdef XML_DTD + useForeignDTD = XML_FALSE; +#endif /* XML_DTD */ + dtd->hasParamEntityRefs = XML_TRUE; + if (startDoctypeDeclHandler) { + doctypeSysid = poolStoreString(&tempPool, enc, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (doctypeSysid == NULL) + return XML_ERROR_NO_MEMORY; + poolFinish(&tempPool); + handleDefault = XML_FALSE; + } +#ifdef XML_DTD + else + /* use externalSubsetName to make doctypeSysid non-NULL + for the case where no startDoctypeDeclHandler is set */ + doctypeSysid = externalSubsetName; +#endif /* XML_DTD */ + if (!dtd->standalone +#ifdef XML_DTD + && !paramEntityParsing +#endif /* XML_DTD */ + && notStandaloneHandler + && !notStandaloneHandler(handlerArg)) + return XML_ERROR_NOT_STANDALONE; +#ifndef XML_DTD + break; +#else /* XML_DTD */ + if (!declEntity) { + declEntity = (ENTITY *)lookup(parser, + &dtd->paramEntities, + externalSubsetName, + sizeof(ENTITY)); + if (!declEntity) + return XML_ERROR_NO_MEMORY; + declEntity->publicId = NULL; + } + /* fall through */ +#endif /* XML_DTD */ + case XML_ROLE_ENTITY_SYSTEM_ID: + if (dtd->keepProcessing && declEntity) { + declEntity->systemId = poolStoreString(&dtd->pool, enc, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (!declEntity->systemId) + return XML_ERROR_NO_MEMORY; + declEntity->base = curBase; + poolFinish(&dtd->pool); + if (entityDeclHandler) + handleDefault = XML_FALSE; + } + break; + case XML_ROLE_ENTITY_COMPLETE: + if (dtd->keepProcessing && declEntity && entityDeclHandler) { + *eventEndPP = s; + entityDeclHandler(handlerArg, + declEntity->name, + declEntity->is_param, + 0,0, + declEntity->base, + declEntity->systemId, + declEntity->publicId, + 0); + handleDefault = XML_FALSE; + } + break; + case XML_ROLE_ENTITY_NOTATION_NAME: + if (dtd->keepProcessing && declEntity) { + declEntity->notation = poolStoreString(&dtd->pool, enc, s, next); + if (!declEntity->notation) + return XML_ERROR_NO_MEMORY; + poolFinish(&dtd->pool); + if (unparsedEntityDeclHandler) { + *eventEndPP = s; + unparsedEntityDeclHandler(handlerArg, + declEntity->name, + declEntity->base, + declEntity->systemId, + declEntity->publicId, + declEntity->notation); + handleDefault = XML_FALSE; + } + else if (entityDeclHandler) { + *eventEndPP = s; + entityDeclHandler(handlerArg, + declEntity->name, + 0,0,0, + declEntity->base, + declEntity->systemId, + declEntity->publicId, + declEntity->notation); + handleDefault = XML_FALSE; + } + } + break; + case XML_ROLE_GENERAL_ENTITY_NAME: + { + if (XmlPredefinedEntityName(enc, s, next)) { + declEntity = NULL; + break; + } + if (dtd->keepProcessing) { + const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next); + if (!name) + return XML_ERROR_NO_MEMORY; + declEntity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, + sizeof(ENTITY)); + if (!declEntity) + return XML_ERROR_NO_MEMORY; + if (declEntity->name != name) { + poolDiscard(&dtd->pool); + declEntity = NULL; + } + else { + poolFinish(&dtd->pool); + declEntity->publicId = NULL; + declEntity->is_param = XML_FALSE; + /* if we have a parent parser or are reading an internal parameter + entity, then the entity declaration is not considered "internal" + */ + declEntity->is_internal = !(parentParser || openInternalEntities); + if (entityDeclHandler) + handleDefault = XML_FALSE; + } + } + else { + poolDiscard(&dtd->pool); + declEntity = NULL; + } + } + break; + case XML_ROLE_PARAM_ENTITY_NAME: +#ifdef XML_DTD + if (dtd->keepProcessing) { + const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next); + if (!name) + return XML_ERROR_NO_MEMORY; + declEntity = (ENTITY *)lookup(parser, &dtd->paramEntities, + name, sizeof(ENTITY)); + if (!declEntity) + return XML_ERROR_NO_MEMORY; + if (declEntity->name != name) { + poolDiscard(&dtd->pool); + declEntity = NULL; + } + else { + poolFinish(&dtd->pool); + declEntity->publicId = NULL; + declEntity->is_param = XML_TRUE; + /* if we have a parent parser or are reading an internal parameter + entity, then the entity declaration is not considered "internal" + */ + declEntity->is_internal = !(parentParser || openInternalEntities); + if (entityDeclHandler) + handleDefault = XML_FALSE; + } + } + else { + poolDiscard(&dtd->pool); + declEntity = NULL; + } +#else /* not XML_DTD */ + declEntity = NULL; +#endif /* XML_DTD */ + break; + case XML_ROLE_NOTATION_NAME: + declNotationPublicId = NULL; + declNotationName = NULL; + if (notationDeclHandler) { + declNotationName = poolStoreString(&tempPool, enc, s, next); + if (!declNotationName) + return XML_ERROR_NO_MEMORY; + poolFinish(&tempPool); + handleDefault = XML_FALSE; + } + break; + case XML_ROLE_NOTATION_PUBLIC_ID: + if (!XmlIsPublicId(enc, s, next, eventPP)) + return XML_ERROR_PUBLICID; + if (declNotationName) { /* means notationDeclHandler != NULL */ + XML_Char *tem = poolStoreString(&tempPool, + enc, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (!tem) + return XML_ERROR_NO_MEMORY; + normalizePublicId(tem); + declNotationPublicId = tem; + poolFinish(&tempPool); + handleDefault = XML_FALSE; + } + break; + case XML_ROLE_NOTATION_SYSTEM_ID: + if (declNotationName && notationDeclHandler) { + const XML_Char *systemId + = poolStoreString(&tempPool, enc, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (!systemId) + return XML_ERROR_NO_MEMORY; + *eventEndPP = s; + notationDeclHandler(handlerArg, + declNotationName, + curBase, + systemId, + declNotationPublicId); + handleDefault = XML_FALSE; + } + poolClear(&tempPool); + break; + case XML_ROLE_NOTATION_NO_SYSTEM_ID: + if (declNotationPublicId && notationDeclHandler) { + *eventEndPP = s; + notationDeclHandler(handlerArg, + declNotationName, + curBase, + 0, + declNotationPublicId); + handleDefault = XML_FALSE; + } + poolClear(&tempPool); + break; + case XML_ROLE_ERROR: + switch (tok) { + case XML_TOK_PARAM_ENTITY_REF: + /* PE references in internal subset are + not allowed within declarations. */ + return XML_ERROR_PARAM_ENTITY_REF; + case XML_TOK_XML_DECL: + return XML_ERROR_MISPLACED_XML_PI; + default: + return XML_ERROR_SYNTAX; + } +#ifdef XML_DTD + case XML_ROLE_IGNORE_SECT: + { + enum XML_Error result; + if (defaultHandler) + reportDefault(parser, enc, s, next); + handleDefault = XML_FALSE; + result = doIgnoreSection(parser, enc, &next, end, nextPtr, haveMore); + if (result != XML_ERROR_NONE) + return result; + else if (!next) { + processor = ignoreSectionProcessor; + return result; + } + } + break; +#endif /* XML_DTD */ + case XML_ROLE_GROUP_OPEN: + if (prologState.level >= groupSize) { + if (groupSize) { + char *temp = (char *)REALLOC(groupConnector, groupSize *= 2); + if (temp == NULL) + return XML_ERROR_NO_MEMORY; + groupConnector = temp; + if (dtd->scaffIndex) { + int *temp = (int *)REALLOC(dtd->scaffIndex, + groupSize * sizeof(int)); + if (temp == NULL) + return XML_ERROR_NO_MEMORY; + dtd->scaffIndex = temp; + } + } + else { + groupConnector = (char *)MALLOC(groupSize = 32); + if (!groupConnector) + return XML_ERROR_NO_MEMORY; + } + } + groupConnector[prologState.level] = 0; + if (dtd->in_eldecl) { + int myindex = nextScaffoldPart(parser); + if (myindex < 0) + return XML_ERROR_NO_MEMORY; + dtd->scaffIndex[dtd->scaffLevel] = myindex; + dtd->scaffLevel++; + dtd->scaffold[myindex].type = XML_CTYPE_SEQ; + if (elementDeclHandler) + handleDefault = XML_FALSE; + } + break; + case XML_ROLE_GROUP_SEQUENCE: + if (groupConnector[prologState.level] == ASCII_PIPE) + return XML_ERROR_SYNTAX; + groupConnector[prologState.level] = ASCII_COMMA; + if (dtd->in_eldecl && elementDeclHandler) + handleDefault = XML_FALSE; + break; + case XML_ROLE_GROUP_CHOICE: + if (groupConnector[prologState.level] == ASCII_COMMA) + return XML_ERROR_SYNTAX; + if (dtd->in_eldecl + && !groupConnector[prologState.level] + && (dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type + != XML_CTYPE_MIXED) + ) { + dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type + = XML_CTYPE_CHOICE; + if (elementDeclHandler) + handleDefault = XML_FALSE; + } + groupConnector[prologState.level] = ASCII_PIPE; + break; + case XML_ROLE_PARAM_ENTITY_REF: +#ifdef XML_DTD + case XML_ROLE_INNER_PARAM_ENTITY_REF: + dtd->hasParamEntityRefs = XML_TRUE; + if (!paramEntityParsing) + dtd->keepProcessing = dtd->standalone; + else { + const XML_Char *name; + ENTITY *entity; + name = poolStoreString(&dtd->pool, enc, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (!name) + return XML_ERROR_NO_MEMORY; + entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0); + poolDiscard(&dtd->pool); + /* first, determine if a check for an existing declaration is needed; + if yes, check that the entity exists, and that it is internal, + otherwise call the skipped entity handler + */ + if (prologState.documentEntity && + (dtd->standalone + ? !openInternalEntities + : !dtd->hasParamEntityRefs)) { + if (!entity) + return XML_ERROR_UNDEFINED_ENTITY; + else if (!entity->is_internal) + return XML_ERROR_ENTITY_DECLARED_IN_PE; + } + else if (!entity) { + dtd->keepProcessing = dtd->standalone; + /* cannot report skipped entities in declarations */ + if ((role == XML_ROLE_PARAM_ENTITY_REF) && skippedEntityHandler) { + skippedEntityHandler(handlerArg, name, 1); + handleDefault = XML_FALSE; + } + break; + } + if (entity->open) + return XML_ERROR_RECURSIVE_ENTITY_REF; + if (entity->textPtr) { + enum XML_Error result; + XML_Bool betweenDecl = + (role == XML_ROLE_PARAM_ENTITY_REF ? XML_TRUE : XML_FALSE); + result = processInternalEntity(parser, entity, betweenDecl); + if (result != XML_ERROR_NONE) + return result; + handleDefault = XML_FALSE; + break; + } + if (externalEntityRefHandler) { + dtd->paramEntityRead = XML_FALSE; + entity->open = XML_TRUE; + if (!externalEntityRefHandler(externalEntityRefHandlerArg, + 0, + entity->base, + entity->systemId, + entity->publicId)) { + entity->open = XML_FALSE; + return XML_ERROR_EXTERNAL_ENTITY_HANDLING; + } + entity->open = XML_FALSE; + handleDefault = XML_FALSE; + if (!dtd->paramEntityRead) { + dtd->keepProcessing = dtd->standalone; + break; + } + } + else { + dtd->keepProcessing = dtd->standalone; + break; + } + } +#endif /* XML_DTD */ + if (!dtd->standalone && + notStandaloneHandler && + !notStandaloneHandler(handlerArg)) + return XML_ERROR_NOT_STANDALONE; + break; + + /* Element declaration stuff */ + + case XML_ROLE_ELEMENT_NAME: + if (elementDeclHandler) { + declElementType = getElementType(parser, enc, s, next); + if (!declElementType) + return XML_ERROR_NO_MEMORY; + dtd->scaffLevel = 0; + dtd->scaffCount = 0; + dtd->in_eldecl = XML_TRUE; + handleDefault = XML_FALSE; + } + break; + + case XML_ROLE_CONTENT_ANY: + case XML_ROLE_CONTENT_EMPTY: + if (dtd->in_eldecl) { + if (elementDeclHandler) { + XML_Content * content = (XML_Content *) MALLOC(sizeof(XML_Content)); + if (!content) + return XML_ERROR_NO_MEMORY; + content->quant = XML_CQUANT_NONE; + content->name = NULL; + content->numchildren = 0; + content->children = NULL; + content->type = ((role == XML_ROLE_CONTENT_ANY) ? + XML_CTYPE_ANY : + XML_CTYPE_EMPTY); + *eventEndPP = s; + elementDeclHandler(handlerArg, declElementType->name, content); + handleDefault = XML_FALSE; + } + dtd->in_eldecl = XML_FALSE; + } + break; + + case XML_ROLE_CONTENT_PCDATA: + if (dtd->in_eldecl) { + dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type + = XML_CTYPE_MIXED; + if (elementDeclHandler) + handleDefault = XML_FALSE; + } + break; + + case XML_ROLE_CONTENT_ELEMENT: + quant = XML_CQUANT_NONE; + goto elementContent; + case XML_ROLE_CONTENT_ELEMENT_OPT: + quant = XML_CQUANT_OPT; + goto elementContent; + case XML_ROLE_CONTENT_ELEMENT_REP: + quant = XML_CQUANT_REP; + goto elementContent; + case XML_ROLE_CONTENT_ELEMENT_PLUS: + quant = XML_CQUANT_PLUS; + elementContent: + if (dtd->in_eldecl) { + ELEMENT_TYPE *el; + const XML_Char *name; + int nameLen; + const char *nxt = (quant == XML_CQUANT_NONE + ? next + : next - enc->minBytesPerChar); + int myindex = nextScaffoldPart(parser); + if (myindex < 0) + return XML_ERROR_NO_MEMORY; + dtd->scaffold[myindex].type = XML_CTYPE_NAME; + dtd->scaffold[myindex].quant = quant; + el = getElementType(parser, enc, s, nxt); + if (!el) + return XML_ERROR_NO_MEMORY; + name = el->name; + dtd->scaffold[myindex].name = name; + nameLen = 0; + for (; name[nameLen++]; ); + dtd->contentStringLen += nameLen; + if (elementDeclHandler) + handleDefault = XML_FALSE; + } + break; + + case XML_ROLE_GROUP_CLOSE: + quant = XML_CQUANT_NONE; + goto closeGroup; + case XML_ROLE_GROUP_CLOSE_OPT: + quant = XML_CQUANT_OPT; + goto closeGroup; + case XML_ROLE_GROUP_CLOSE_REP: + quant = XML_CQUANT_REP; + goto closeGroup; + case XML_ROLE_GROUP_CLOSE_PLUS: + quant = XML_CQUANT_PLUS; + closeGroup: + if (dtd->in_eldecl) { + if (elementDeclHandler) + handleDefault = XML_FALSE; + dtd->scaffLevel--; + dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel]].quant = quant; + if (dtd->scaffLevel == 0) { + if (!handleDefault) { + XML_Content *model = build_model(parser); + if (!model) + return XML_ERROR_NO_MEMORY; + *eventEndPP = s; + elementDeclHandler(handlerArg, declElementType->name, model); + } + dtd->in_eldecl = XML_FALSE; + dtd->contentStringLen = 0; + } + } + break; + /* End element declaration stuff */ + + case XML_ROLE_PI: + if (!reportProcessingInstruction(parser, enc, s, next)) + return XML_ERROR_NO_MEMORY; + handleDefault = XML_FALSE; + break; + case XML_ROLE_COMMENT: + if (!reportComment(parser, enc, s, next)) + return XML_ERROR_NO_MEMORY; + handleDefault = XML_FALSE; + break; + case XML_ROLE_NONE: + switch (tok) { + case XML_TOK_BOM: + handleDefault = XML_FALSE; + break; + } + break; + case XML_ROLE_DOCTYPE_NONE: + if (startDoctypeDeclHandler) + handleDefault = XML_FALSE; + break; + case XML_ROLE_ENTITY_NONE: + if (dtd->keepProcessing && entityDeclHandler) + handleDefault = XML_FALSE; + break; + case XML_ROLE_NOTATION_NONE: + if (notationDeclHandler) + handleDefault = XML_FALSE; + break; + case XML_ROLE_ATTLIST_NONE: + if (dtd->keepProcessing && attlistDeclHandler) + handleDefault = XML_FALSE; + break; + case XML_ROLE_ELEMENT_NONE: + if (elementDeclHandler) + handleDefault = XML_FALSE; + break; + } /* end of big switch */ + + if (handleDefault && defaultHandler) + reportDefault(parser, enc, s, next); + + switch (ps_parsing) { + case XML_SUSPENDED: + *nextPtr = next; + return XML_ERROR_NONE; + case XML_FINISHED: + return XML_ERROR_ABORTED; + default: + s = next; + tok = XmlPrologTok(enc, s, end, &next); + } + } + /* not reached */ +} + +static enum XML_Error PTRCALL +epilogProcessor(XML_Parser parser, + const char *s, + const char *end, + const char **nextPtr) +{ + processor = epilogProcessor; + eventPtr = s; + for (;;) { + const char *next = NULL; + int tok = XmlPrologTok(encoding, s, end, &next); + eventEndPtr = next; + switch (tok) { + /* report partial linebreak - it might be the last token */ + case -XML_TOK_PROLOG_S: + if (defaultHandler) { + reportDefault(parser, encoding, s, next); + if (ps_parsing == XML_FINISHED) + return XML_ERROR_ABORTED; + } + *nextPtr = next; + return XML_ERROR_NONE; + case XML_TOK_NONE: + *nextPtr = s; + return XML_ERROR_NONE; + case XML_TOK_PROLOG_S: + if (defaultHandler) + reportDefault(parser, encoding, s, next); + break; + case XML_TOK_PI: + if (!reportProcessingInstruction(parser, encoding, s, next)) + return XML_ERROR_NO_MEMORY; + break; + case XML_TOK_COMMENT: + if (!reportComment(parser, encoding, s, next)) + return XML_ERROR_NO_MEMORY; + break; + case XML_TOK_INVALID: + eventPtr = next; + return XML_ERROR_INVALID_TOKEN; + case XML_TOK_PARTIAL: + if (!ps_finalBuffer) { + *nextPtr = s; + return XML_ERROR_NONE; + } + return XML_ERROR_UNCLOSED_TOKEN; + case XML_TOK_PARTIAL_CHAR: + if (!ps_finalBuffer) { + *nextPtr = s; + return XML_ERROR_NONE; + } + return XML_ERROR_PARTIAL_CHAR; + default: + return XML_ERROR_JUNK_AFTER_DOC_ELEMENT; + } + eventPtr = s = next; + switch (ps_parsing) { + case XML_SUSPENDED: + *nextPtr = next; + return XML_ERROR_NONE; + case XML_FINISHED: + return XML_ERROR_ABORTED; + default: ; + } + } +} + +static enum XML_Error +processInternalEntity(XML_Parser parser, ENTITY *entity, + XML_Bool betweenDecl) +{ + const char *textStart, *textEnd; + const char *next; + enum XML_Error result; + OPEN_INTERNAL_ENTITY *openEntity; + + if (freeInternalEntities) { + openEntity = freeInternalEntities; + freeInternalEntities = openEntity->next; + } + else { + openEntity = (OPEN_INTERNAL_ENTITY *)MALLOC(sizeof(OPEN_INTERNAL_ENTITY)); + if (!openEntity) + return XML_ERROR_NO_MEMORY; + } + entity->open = XML_TRUE; + entity->processed = 0; + openEntity->next = openInternalEntities; + openInternalEntities = openEntity; + openEntity->entity = entity; + openEntity->startTagLevel = tagLevel; + openEntity->betweenDecl = betweenDecl; + openEntity->internalEventPtr = NULL; + openEntity->internalEventEndPtr = NULL; + textStart = (char *)entity->textPtr; + textEnd = (char *)(entity->textPtr + entity->textLen); + +#ifdef XML_DTD + if (entity->is_param) { + int tok = XmlPrologTok(internalEncoding, textStart, textEnd, &next); + result = doProlog(parser, internalEncoding, textStart, textEnd, tok, + next, &next, XML_FALSE); + } + else +#endif /* XML_DTD */ + result = doContent(parser, tagLevel, internalEncoding, textStart, + textEnd, &next, XML_FALSE); + + if (result == XML_ERROR_NONE) { + if (textEnd != next && ps_parsing == XML_SUSPENDED) { + entity->processed = (int)(next - textStart); + processor = internalEntityProcessor; + } + else { + entity->open = XML_FALSE; + openInternalEntities = openEntity->next; + /* put openEntity back in list of free instances */ + openEntity->next = freeInternalEntities; + freeInternalEntities = openEntity; + } + } + return result; +} + +static enum XML_Error PTRCALL +internalEntityProcessor(XML_Parser parser, + const char *s, + const char *end, + const char **nextPtr) +{ + ENTITY *entity; + const char *textStart, *textEnd; + const char *next; + enum XML_Error result; + OPEN_INTERNAL_ENTITY *openEntity = openInternalEntities; + if (!openEntity) + return XML_ERROR_UNEXPECTED_STATE; + + entity = openEntity->entity; + textStart = ((char *)entity->textPtr) + entity->processed; + textEnd = (char *)(entity->textPtr + entity->textLen); + +#ifdef XML_DTD + if (entity->is_param) { + int tok = XmlPrologTok(internalEncoding, textStart, textEnd, &next); + result = doProlog(parser, internalEncoding, textStart, textEnd, tok, + next, &next, XML_FALSE); + } + else +#endif /* XML_DTD */ + result = doContent(parser, openEntity->startTagLevel, internalEncoding, + textStart, textEnd, &next, XML_FALSE); + + if (result != XML_ERROR_NONE) + return result; + else if (textEnd != next && ps_parsing == XML_SUSPENDED) { + entity->processed = (int)(next - (char *)entity->textPtr); + return result; + } + else { + entity->open = XML_FALSE; + openInternalEntities = openEntity->next; + /* put openEntity back in list of free instances */ + openEntity->next = freeInternalEntities; + freeInternalEntities = openEntity; + } + +#ifdef XML_DTD + if (entity->is_param) { + int tok; + processor = prologProcessor; + tok = XmlPrologTok(encoding, s, end, &next); + return doProlog(parser, encoding, s, end, tok, next, nextPtr, + (XML_Bool)!ps_finalBuffer); + } + else +#endif /* XML_DTD */ + { + processor = contentProcessor; + /* see externalEntityContentProcessor vs contentProcessor */ + return doContent(parser, parentParser ? 1 : 0, encoding, s, end, + nextPtr, (XML_Bool)!ps_finalBuffer); + } +} + +static enum XML_Error PTRCALL +errorProcessor(XML_Parser parser, + const char *s, + const char *end, + const char **nextPtr) +{ + return errorCode; +} + +static enum XML_Error +storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata, + const char *ptr, const char *end, + STRING_POOL *pool) +{ + enum XML_Error result = appendAttributeValue(parser, enc, isCdata, ptr, + end, pool); + if (result) + return result; + if (!isCdata && poolLength(pool) && poolLastChar(pool) == 0x20) + poolChop(pool); + if (!poolAppendChar(pool, XML_T('\0'))) + return XML_ERROR_NO_MEMORY; + return XML_ERROR_NONE; +} + +static enum XML_Error +appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata, + const char *ptr, const char *end, + STRING_POOL *pool) +{ + DTD * const dtd = _dtd; /* save one level of indirection */ + for (;;) { + const char *next; + int tok = XmlAttributeValueTok(enc, ptr, end, &next); + switch (tok) { + case XML_TOK_NONE: + return XML_ERROR_NONE; + case XML_TOK_INVALID: + if (enc == encoding) + eventPtr = next; + return XML_ERROR_INVALID_TOKEN; + case XML_TOK_PARTIAL: + if (enc == encoding) + eventPtr = ptr; + return XML_ERROR_INVALID_TOKEN; + case XML_TOK_CHAR_REF: + { + XML_Char buf[XML_ENCODE_MAX]; + int i; + int n = XmlCharRefNumber(enc, ptr); + if (n < 0) { + if (enc == encoding) + eventPtr = ptr; + return XML_ERROR_BAD_CHAR_REF; + } + if (!isCdata + && n == 0x20 /* space */ + && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20)) + break; + n = XmlEncode(n, (ICHAR *)buf); + if (!n) { + if (enc == encoding) + eventPtr = ptr; + return XML_ERROR_BAD_CHAR_REF; + } + for (i = 0; i < n; i++) { + if (!poolAppendChar(pool, buf[i])) + return XML_ERROR_NO_MEMORY; + } + } + break; + case XML_TOK_DATA_CHARS: + if (!poolAppend(pool, enc, ptr, next)) + return XML_ERROR_NO_MEMORY; + break; + case XML_TOK_TRAILING_CR: + next = ptr + enc->minBytesPerChar; + /* fall through */ + case XML_TOK_ATTRIBUTE_VALUE_S: + case XML_TOK_DATA_NEWLINE: + if (!isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20)) + break; + if (!poolAppendChar(pool, 0x20)) + return XML_ERROR_NO_MEMORY; + break; + case XML_TOK_ENTITY_REF: + { + const XML_Char *name; + ENTITY *entity; + char checkEntityDecl; + XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc, + ptr + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (ch) { + if (!poolAppendChar(pool, ch)) + return XML_ERROR_NO_MEMORY; + break; + } + name = poolStoreString(&temp2Pool, enc, + ptr + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (!name) + return XML_ERROR_NO_MEMORY; + entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0); + poolDiscard(&temp2Pool); + /* First, determine if a check for an existing declaration is needed; + if yes, check that the entity exists, and that it is internal. + */ + if (pool == &dtd->pool) /* are we called from prolog? */ + checkEntityDecl = +#ifdef XML_DTD + prologState.documentEntity && +#endif /* XML_DTD */ + (dtd->standalone + ? !openInternalEntities + : !dtd->hasParamEntityRefs); + else /* if (pool == &tempPool): we are called from content */ + checkEntityDecl = !dtd->hasParamEntityRefs || dtd->standalone; + if (checkEntityDecl) { + if (!entity) + return XML_ERROR_UNDEFINED_ENTITY; + else if (!entity->is_internal) + return XML_ERROR_ENTITY_DECLARED_IN_PE; + } + else if (!entity) { + /* Cannot report skipped entity here - see comments on + skippedEntityHandler. + if (skippedEntityHandler) + skippedEntityHandler(handlerArg, name, 0); + */ + /* Cannot call the default handler because this would be + out of sync with the call to the startElementHandler. + if ((pool == &tempPool) && defaultHandler) + reportDefault(parser, enc, ptr, next); + */ + break; + } + if (entity->open) { + if (enc == encoding) + eventPtr = ptr; + return XML_ERROR_RECURSIVE_ENTITY_REF; + } + if (entity->notation) { + if (enc == encoding) + eventPtr = ptr; + return XML_ERROR_BINARY_ENTITY_REF; + } + if (!entity->textPtr) { + if (enc == encoding) + eventPtr = ptr; + return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF; + } + else { + enum XML_Error result; + const XML_Char *textEnd = entity->textPtr + entity->textLen; + entity->open = XML_TRUE; + result = appendAttributeValue(parser, internalEncoding, isCdata, + (char *)entity->textPtr, + (char *)textEnd, pool); + entity->open = XML_FALSE; + if (result) + return result; + } + } + break; + default: + if (enc == encoding) + eventPtr = ptr; + return XML_ERROR_UNEXPECTED_STATE; + } + ptr = next; + } + /* not reached */ +} + +static enum XML_Error +storeEntityValue(XML_Parser parser, + const ENCODING *enc, + const char *entityTextPtr, + const char *entityTextEnd) +{ + DTD * const dtd = _dtd; /* save one level of indirection */ + STRING_POOL *pool = &(dtd->entityValuePool); + enum XML_Error result = XML_ERROR_NONE; +#ifdef XML_DTD + int oldInEntityValue = prologState.inEntityValue; + prologState.inEntityValue = 1; +#endif /* XML_DTD */ + /* never return Null for the value argument in EntityDeclHandler, + since this would indicate an external entity; therefore we + have to make sure that entityValuePool.start is not null */ + if (!pool->blocks) { + if (!poolGrow(pool)) + return XML_ERROR_NO_MEMORY; + } + + for (;;) { + const char *next; + int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next); + switch (tok) { + case XML_TOK_PARAM_ENTITY_REF: +#ifdef XML_DTD + if (isParamEntity || enc != encoding) { + const XML_Char *name; + ENTITY *entity; + name = poolStoreString(&tempPool, enc, + entityTextPtr + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (!name) { + result = XML_ERROR_NO_MEMORY; + goto endEntityValue; + } + entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0); + poolDiscard(&tempPool); + if (!entity) { + /* not a well-formedness error - see XML 1.0: WFC Entity Declared */ + /* cannot report skipped entity here - see comments on + skippedEntityHandler + if (skippedEntityHandler) + skippedEntityHandler(handlerArg, name, 0); + */ + dtd->keepProcessing = dtd->standalone; + goto endEntityValue; + } + if (entity->open) { + if (enc == encoding) + eventPtr = entityTextPtr; + result = XML_ERROR_RECURSIVE_ENTITY_REF; + goto endEntityValue; + } + if (entity->systemId) { + if (externalEntityRefHandler) { + dtd->paramEntityRead = XML_FALSE; + entity->open = XML_TRUE; + if (!externalEntityRefHandler(externalEntityRefHandlerArg, + 0, + entity->base, + entity->systemId, + entity->publicId)) { + entity->open = XML_FALSE; + result = XML_ERROR_EXTERNAL_ENTITY_HANDLING; + goto endEntityValue; + } + entity->open = XML_FALSE; + if (!dtd->paramEntityRead) + dtd->keepProcessing = dtd->standalone; + } + else + dtd->keepProcessing = dtd->standalone; + } + else { + entity->open = XML_TRUE; + result = storeEntityValue(parser, + internalEncoding, + (char *)entity->textPtr, + (char *)(entity->textPtr + + entity->textLen)); + entity->open = XML_FALSE; + if (result) + goto endEntityValue; + } + break; + } +#endif /* XML_DTD */ + /* In the internal subset, PE references are not legal + within markup declarations, e.g entity values in this case. */ + eventPtr = entityTextPtr; + result = XML_ERROR_PARAM_ENTITY_REF; + goto endEntityValue; + case XML_TOK_NONE: + result = XML_ERROR_NONE; + goto endEntityValue; + case XML_TOK_ENTITY_REF: + case XML_TOK_DATA_CHARS: + if (!poolAppend(pool, enc, entityTextPtr, next)) { + result = XML_ERROR_NO_MEMORY; + goto endEntityValue; + } + break; + case XML_TOK_TRAILING_CR: + next = entityTextPtr + enc->minBytesPerChar; + /* fall through */ + case XML_TOK_DATA_NEWLINE: + if (pool->end == pool->ptr && !poolGrow(pool)) { + result = XML_ERROR_NO_MEMORY; + goto endEntityValue; + } + *(pool->ptr)++ = 0xA; + break; + case XML_TOK_CHAR_REF: + { + XML_Char buf[XML_ENCODE_MAX]; + int i; + int n = XmlCharRefNumber(enc, entityTextPtr); + if (n < 0) { + if (enc == encoding) + eventPtr = entityTextPtr; + result = XML_ERROR_BAD_CHAR_REF; + goto endEntityValue; + } + n = XmlEncode(n, (ICHAR *)buf); + if (!n) { + if (enc == encoding) + eventPtr = entityTextPtr; + result = XML_ERROR_BAD_CHAR_REF; + goto endEntityValue; + } + for (i = 0; i < n; i++) { + if (pool->end == pool->ptr && !poolGrow(pool)) { + result = XML_ERROR_NO_MEMORY; + goto endEntityValue; + } + *(pool->ptr)++ = buf[i]; + } + } + break; + case XML_TOK_PARTIAL: + if (enc == encoding) + eventPtr = entityTextPtr; + result = XML_ERROR_INVALID_TOKEN; + goto endEntityValue; + case XML_TOK_INVALID: + if (enc == encoding) + eventPtr = next; + result = XML_ERROR_INVALID_TOKEN; + goto endEntityValue; + default: + if (enc == encoding) + eventPtr = entityTextPtr; + result = XML_ERROR_UNEXPECTED_STATE; + goto endEntityValue; + } + entityTextPtr = next; + } +endEntityValue: +#ifdef XML_DTD + prologState.inEntityValue = oldInEntityValue; +#endif /* XML_DTD */ + return result; +} + +static void FASTCALL +normalizeLines(XML_Char *s) +{ + XML_Char *p; + for (;; s++) { + if (*s == XML_T('\0')) + return; + if (*s == 0xD) + break; + } + p = s; + do { + if (*s == 0xD) { + *p++ = 0xA; + if (*++s == 0xA) + s++; + } + else + *p++ = *s++; + } while (*s); + *p = XML_T('\0'); +} + +static int +reportProcessingInstruction(XML_Parser parser, const ENCODING *enc, + const char *start, const char *end) +{ + const XML_Char *target; + XML_Char *data; + const char *tem; + if (!processingInstructionHandler) { + if (defaultHandler) + reportDefault(parser, enc, start, end); + return 1; + } + start += enc->minBytesPerChar * 2; + tem = start + XmlNameLength(enc, start); + target = poolStoreString(&tempPool, enc, start, tem); + if (!target) + return 0; + poolFinish(&tempPool); + data = poolStoreString(&tempPool, enc, + XmlSkipS(enc, tem), + end - enc->minBytesPerChar*2); + if (!data) + return 0; + normalizeLines(data); + processingInstructionHandler(handlerArg, target, data); + poolClear(&tempPool); + return 1; +} + +static int +reportComment(XML_Parser parser, const ENCODING *enc, + const char *start, const char *end) +{ + XML_Char *data; + if (!commentHandler) { + if (defaultHandler) + reportDefault(parser, enc, start, end); + return 1; + } + data = poolStoreString(&tempPool, + enc, + start + enc->minBytesPerChar * 4, + end - enc->minBytesPerChar * 3); + if (!data) + return 0; + normalizeLines(data); + commentHandler(handlerArg, data); + poolClear(&tempPool); + return 1; +} + +static void +reportDefault(XML_Parser parser, const ENCODING *enc, + const char *s, const char *end) +{ + if (MUST_CONVERT(enc, s)) { + const char **eventPP; + const char **eventEndPP; + if (enc == encoding) { + eventPP = &eventPtr; + eventEndPP = &eventEndPtr; + } + else { + eventPP = &(openInternalEntities->internalEventPtr); + eventEndPP = &(openInternalEntities->internalEventEndPtr); + } + do { + ICHAR *dataPtr = (ICHAR *)dataBuf; + XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd); + *eventEndPP = s; + defaultHandler(handlerArg, dataBuf, (int)(dataPtr - (ICHAR *)dataBuf)); + *eventPP = s; + } while (s != end); + } + else + defaultHandler(handlerArg, (XML_Char *)s, (int)((XML_Char *)end - (XML_Char *)s)); +} + + +static int +defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata, + XML_Bool isId, const XML_Char *value, XML_Parser parser) +{ + DEFAULT_ATTRIBUTE *att; + if (value || isId) { + /* The handling of default attributes gets messed up if we have + a default which duplicates a non-default. */ + int i; + for (i = 0; i < type->nDefaultAtts; i++) + if (attId == type->defaultAtts[i].id) + return 1; + if (isId && !type->idAtt && !attId->xmlns) + type->idAtt = attId; + } + if (type->nDefaultAtts == type->allocDefaultAtts) { + if (type->allocDefaultAtts == 0) { + type->allocDefaultAtts = 8; + type->defaultAtts = (DEFAULT_ATTRIBUTE *)MALLOC(type->allocDefaultAtts + * sizeof(DEFAULT_ATTRIBUTE)); + if (!type->defaultAtts) + return 0; + } + else { + DEFAULT_ATTRIBUTE *temp; + int count = type->allocDefaultAtts * 2; + temp = (DEFAULT_ATTRIBUTE *) + REALLOC(type->defaultAtts, (count * sizeof(DEFAULT_ATTRIBUTE))); + if (temp == NULL) + return 0; + type->allocDefaultAtts = count; + type->defaultAtts = temp; + } + } + att = type->defaultAtts + type->nDefaultAtts; + att->id = attId; + att->value = value; + att->isCdata = isCdata; + if (!isCdata) + attId->maybeTokenized = XML_TRUE; + type->nDefaultAtts += 1; + return 1; +} + +static int +setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType) +{ + DTD * const dtd = _dtd; /* save one level of indirection */ + const XML_Char *name; + for (name = elementType->name; *name; name++) { + if (*name == XML_T(ASCII_COLON)) { + PREFIX *prefix; + const XML_Char *s; + for (s = elementType->name; s != name; s++) { + if (!poolAppendChar(&dtd->pool, *s)) + return 0; + } + if (!poolAppendChar(&dtd->pool, XML_T('\0'))) + return 0; + prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&dtd->pool), + sizeof(PREFIX)); + if (!prefix) + return 0; + if (prefix->name == poolStart(&dtd->pool)) + poolFinish(&dtd->pool); + else + poolDiscard(&dtd->pool); + elementType->prefix = prefix; + + } + } + return 1; +} + +static ATTRIBUTE_ID * +getAttributeId(XML_Parser parser, const ENCODING *enc, + const char *start, const char *end) +{ + DTD * const dtd = _dtd; /* save one level of indirection */ + ATTRIBUTE_ID *id; + const XML_Char *name; + if (!poolAppendChar(&dtd->pool, XML_T('\0'))) + return NULL; + name = poolStoreString(&dtd->pool, enc, start, end); + if (!name) + return NULL; + /* skip quotation mark - its storage will be re-used (like in name[-1]) */ + ++name; + id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, name, sizeof(ATTRIBUTE_ID)); + if (!id) + return NULL; + if (id->name != name) + poolDiscard(&dtd->pool); + else { + poolFinish(&dtd->pool); + if (!ns) + ; + else if (name[0] == XML_T(ASCII_x) + && name[1] == XML_T(ASCII_m) + && name[2] == XML_T(ASCII_l) + && name[3] == XML_T(ASCII_n) + && name[4] == XML_T(ASCII_s) + && (name[5] == XML_T('\0') || name[5] == XML_T(ASCII_COLON))) { + if (name[5] == XML_T('\0')) + id->prefix = &dtd->defaultPrefix; + else + id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, name + 6, sizeof(PREFIX)); + id->xmlns = XML_TRUE; + } + else { + int i; + for (i = 0; name[i]; i++) { + /* attributes without prefix are *not* in the default namespace */ + if (name[i] == XML_T(ASCII_COLON)) { + int j; + for (j = 0; j < i; j++) { + if (!poolAppendChar(&dtd->pool, name[j])) + return NULL; + } + if (!poolAppendChar(&dtd->pool, XML_T('\0'))) + return NULL; + id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&dtd->pool), + sizeof(PREFIX)); + if (id->prefix->name == poolStart(&dtd->pool)) + poolFinish(&dtd->pool); + else + poolDiscard(&dtd->pool); + break; + } + } + } + } + return id; +} + +#define CONTEXT_SEP XML_T(ASCII_FF) + +static const XML_Char * +getContext(XML_Parser parser) +{ + DTD * const dtd = _dtd; /* save one level of indirection */ + HASH_TABLE_ITER iter; + XML_Bool needSep = XML_FALSE; + + if (dtd->defaultPrefix.binding) { + int i; + int len; + if (!poolAppendChar(&tempPool, XML_T(ASCII_EQUALS))) + return NULL; + len = dtd->defaultPrefix.binding->uriLen; + if (namespaceSeparator) + len--; + for (i = 0; i < len; i++) + if (!poolAppendChar(&tempPool, dtd->defaultPrefix.binding->uri[i])) + return NULL; + needSep = XML_TRUE; + } + + hashTableIterInit(&iter, &(dtd->prefixes)); + for (;;) { + int i; + int len; + const XML_Char *s; + PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter); + if (!prefix) + break; + if (!prefix->binding) + continue; + if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP)) + return NULL; + for (s = prefix->name; *s; s++) + if (!poolAppendChar(&tempPool, *s)) + return NULL; + if (!poolAppendChar(&tempPool, XML_T(ASCII_EQUALS))) + return NULL; + len = prefix->binding->uriLen; + if (namespaceSeparator) + len--; + for (i = 0; i < len; i++) + if (!poolAppendChar(&tempPool, prefix->binding->uri[i])) + return NULL; + needSep = XML_TRUE; + } + + + hashTableIterInit(&iter, &(dtd->generalEntities)); + for (;;) { + const XML_Char *s; + ENTITY *e = (ENTITY *)hashTableIterNext(&iter); + if (!e) + break; + if (!e->open) + continue; + if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP)) + return NULL; + for (s = e->name; *s; s++) + if (!poolAppendChar(&tempPool, *s)) + return 0; + needSep = XML_TRUE; + } + + if (!poolAppendChar(&tempPool, XML_T('\0'))) + return NULL; + return tempPool.start; +} + +static XML_Bool +setContext(XML_Parser parser, const XML_Char *context) +{ + DTD * const dtd = _dtd; /* save one level of indirection */ + const XML_Char *s = context; + + while (*context != XML_T('\0')) { + if (*s == CONTEXT_SEP || *s == XML_T('\0')) { + ENTITY *e; + if (!poolAppendChar(&tempPool, XML_T('\0'))) + return XML_FALSE; + e = (ENTITY *)lookup(parser, &dtd->generalEntities, poolStart(&tempPool), 0); + if (e) + e->open = XML_TRUE; + if (*s != XML_T('\0')) + s++; + context = s; + poolDiscard(&tempPool); + } + else if (*s == XML_T(ASCII_EQUALS)) { + PREFIX *prefix; + if (poolLength(&tempPool) == 0) + prefix = &dtd->defaultPrefix; + else { + if (!poolAppendChar(&tempPool, XML_T('\0'))) + return XML_FALSE; + prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&tempPool), + sizeof(PREFIX)); + if (!prefix) + return XML_FALSE; + if (prefix->name == poolStart(&tempPool)) { + prefix->name = poolCopyString(&dtd->pool, prefix->name); + if (!prefix->name) + return XML_FALSE; + } + poolDiscard(&tempPool); + } + for (context = s + 1; + *context != CONTEXT_SEP && *context != XML_T('\0'); + context++) + if (!poolAppendChar(&tempPool, *context)) + return XML_FALSE; + if (!poolAppendChar(&tempPool, XML_T('\0'))) + return XML_FALSE; + if (addBinding(parser, prefix, NULL, poolStart(&tempPool), + &inheritedBindings) != XML_ERROR_NONE) + return XML_FALSE; + poolDiscard(&tempPool); + if (*context != XML_T('\0')) + ++context; + s = context; + } + else { + if (!poolAppendChar(&tempPool, *s)) + return XML_FALSE; + s++; + } + } + return XML_TRUE; +} + +static void FASTCALL +normalizePublicId(XML_Char *publicId) +{ + XML_Char *p = publicId; + XML_Char *s; + for (s = publicId; *s; s++) { + switch (*s) { + case 0x20: + case 0xD: + case 0xA: + if (p != publicId && p[-1] != 0x20) + *p++ = 0x20; + break; + default: + *p++ = *s; + } + } + if (p != publicId && p[-1] == 0x20) + --p; + *p = XML_T('\0'); +} + +static DTD * +dtdCreate(const XML_Memory_Handling_Suite *ms) +{ + DTD *p = (DTD *)ms->malloc_fcn(sizeof(DTD)); + if (p == NULL) + return p; + poolInit(&(p->pool), ms); + poolInit(&(p->entityValuePool), ms); + hashTableInit(&(p->generalEntities), ms); + hashTableInit(&(p->elementTypes), ms); + hashTableInit(&(p->attributeIds), ms); + hashTableInit(&(p->prefixes), ms); +#ifdef XML_DTD + p->paramEntityRead = XML_FALSE; + hashTableInit(&(p->paramEntities), ms); +#endif /* XML_DTD */ + p->defaultPrefix.name = NULL; + p->defaultPrefix.binding = NULL; + + p->in_eldecl = XML_FALSE; + p->scaffIndex = NULL; + p->scaffold = NULL; + p->scaffLevel = 0; + p->scaffSize = 0; + p->scaffCount = 0; + p->contentStringLen = 0; + + p->keepProcessing = XML_TRUE; + p->hasParamEntityRefs = XML_FALSE; + p->standalone = XML_FALSE; + return p; +} + +static void +dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms) +{ + HASH_TABLE_ITER iter; + hashTableIterInit(&iter, &(p->elementTypes)); + for (;;) { + ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter); + if (!e) + break; + if (e->allocDefaultAtts != 0) + ms->free_fcn(e->defaultAtts); + } + hashTableClear(&(p->generalEntities)); +#ifdef XML_DTD + p->paramEntityRead = XML_FALSE; + hashTableClear(&(p->paramEntities)); +#endif /* XML_DTD */ + hashTableClear(&(p->elementTypes)); + hashTableClear(&(p->attributeIds)); + hashTableClear(&(p->prefixes)); + poolClear(&(p->pool)); + poolClear(&(p->entityValuePool)); + p->defaultPrefix.name = NULL; + p->defaultPrefix.binding = NULL; + + p->in_eldecl = XML_FALSE; + + ms->free_fcn(p->scaffIndex); + p->scaffIndex = NULL; + ms->free_fcn(p->scaffold); + p->scaffold = NULL; + + p->scaffLevel = 0; + p->scaffSize = 0; + p->scaffCount = 0; + p->contentStringLen = 0; + + p->keepProcessing = XML_TRUE; + p->hasParamEntityRefs = XML_FALSE; + p->standalone = XML_FALSE; +} + +static void +dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms) +{ + HASH_TABLE_ITER iter; + hashTableIterInit(&iter, &(p->elementTypes)); + for (;;) { + ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter); + if (!e) + break; + if (e->allocDefaultAtts != 0) + ms->free_fcn(e->defaultAtts); + } + hashTableDestroy(&(p->generalEntities)); +#ifdef XML_DTD + hashTableDestroy(&(p->paramEntities)); +#endif /* XML_DTD */ + hashTableDestroy(&(p->elementTypes)); + hashTableDestroy(&(p->attributeIds)); + hashTableDestroy(&(p->prefixes)); + poolDestroy(&(p->pool)); + poolDestroy(&(p->entityValuePool)); + if (isDocEntity) { + ms->free_fcn(p->scaffIndex); + ms->free_fcn(p->scaffold); + } + ms->free_fcn(p); +} + +/* Do a deep copy of the DTD. Return 0 for out of memory, non-zero otherwise. + The new DTD has already been initialized. +*/ +static int +dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms) +{ + HASH_TABLE_ITER iter; + + /* Copy the prefix table. */ + + hashTableIterInit(&iter, &(oldDtd->prefixes)); + for (;;) { + const XML_Char *name; + const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter); + if (!oldP) + break; + name = poolCopyString(&(newDtd->pool), oldP->name); + if (!name) + return 0; + if (!lookup(oldParser, &(newDtd->prefixes), name, sizeof(PREFIX))) + return 0; + } + + hashTableIterInit(&iter, &(oldDtd->attributeIds)); + + /* Copy the attribute id table. */ + + for (;;) { + ATTRIBUTE_ID *newA; + const XML_Char *name; + const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter); + + if (!oldA) + break; + /* Remember to allocate the scratch byte before the name. */ + if (!poolAppendChar(&(newDtd->pool), XML_T('\0'))) + return 0; + name = poolCopyString(&(newDtd->pool), oldA->name); + if (!name) + return 0; + ++name; + newA = (ATTRIBUTE_ID *)lookup(oldParser, &(newDtd->attributeIds), name, + sizeof(ATTRIBUTE_ID)); + if (!newA) + return 0; + newA->maybeTokenized = oldA->maybeTokenized; + if (oldA->prefix) { + newA->xmlns = oldA->xmlns; + if (oldA->prefix == &oldDtd->defaultPrefix) + newA->prefix = &newDtd->defaultPrefix; + else + newA->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes), + oldA->prefix->name, 0); + } + } + + /* Copy the element type table. */ + + hashTableIterInit(&iter, &(oldDtd->elementTypes)); + + for (;;) { + int i; + ELEMENT_TYPE *newE; + const XML_Char *name; + const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter); + if (!oldE) + break; + name = poolCopyString(&(newDtd->pool), oldE->name); + if (!name) + return 0; + newE = (ELEMENT_TYPE *)lookup(oldParser, &(newDtd->elementTypes), name, + sizeof(ELEMENT_TYPE)); + if (!newE) + return 0; + if (oldE->nDefaultAtts) { + newE->defaultAtts = (DEFAULT_ATTRIBUTE *) + ms->malloc_fcn(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE)); + if (!newE->defaultAtts) { + ms->free_fcn(newE); + return 0; + } + } + if (oldE->idAtt) + newE->idAtt = (ATTRIBUTE_ID *) + lookup(oldParser, &(newDtd->attributeIds), oldE->idAtt->name, 0); + newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts; + if (oldE->prefix) + newE->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes), + oldE->prefix->name, 0); + for (i = 0; i < newE->nDefaultAtts; i++) { + newE->defaultAtts[i].id = (ATTRIBUTE_ID *) + lookup(oldParser, &(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0); + newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata; + if (oldE->defaultAtts[i].value) { + newE->defaultAtts[i].value + = poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value); + if (!newE->defaultAtts[i].value) + return 0; + } + else + newE->defaultAtts[i].value = NULL; + } + } + + /* Copy the entity tables. */ + if (!copyEntityTable(oldParser, + &(newDtd->generalEntities), + &(newDtd->pool), + &(oldDtd->generalEntities))) + return 0; + +#ifdef XML_DTD + if (!copyEntityTable(oldParser, + &(newDtd->paramEntities), + &(newDtd->pool), + &(oldDtd->paramEntities))) + return 0; + newDtd->paramEntityRead = oldDtd->paramEntityRead; +#endif /* XML_DTD */ + + newDtd->keepProcessing = oldDtd->keepProcessing; + newDtd->hasParamEntityRefs = oldDtd->hasParamEntityRefs; + newDtd->standalone = oldDtd->standalone; + + /* Don't want deep copying for scaffolding */ + newDtd->in_eldecl = oldDtd->in_eldecl; + newDtd->scaffold = oldDtd->scaffold; + newDtd->contentStringLen = oldDtd->contentStringLen; + newDtd->scaffSize = oldDtd->scaffSize; + newDtd->scaffLevel = oldDtd->scaffLevel; + newDtd->scaffIndex = oldDtd->scaffIndex; + + return 1; +} /* End dtdCopy */ + +static int +copyEntityTable(XML_Parser oldParser, + HASH_TABLE *newTable, + STRING_POOL *newPool, + const HASH_TABLE *oldTable) +{ + HASH_TABLE_ITER iter; + const XML_Char *cachedOldBase = NULL; + const XML_Char *cachedNewBase = NULL; + + hashTableIterInit(&iter, oldTable); + + for (;;) { + ENTITY *newE; + const XML_Char *name; + const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter); + if (!oldE) + break; + name = poolCopyString(newPool, oldE->name); + if (!name) + return 0; + newE = (ENTITY *)lookup(oldParser, newTable, name, sizeof(ENTITY)); + if (!newE) + return 0; + if (oldE->systemId) { + const XML_Char *tem = poolCopyString(newPool, oldE->systemId); + if (!tem) + return 0; + newE->systemId = tem; + if (oldE->base) { + if (oldE->base == cachedOldBase) + newE->base = cachedNewBase; + else { + cachedOldBase = oldE->base; + tem = poolCopyString(newPool, cachedOldBase); + if (!tem) + return 0; + cachedNewBase = newE->base = tem; + } + } + if (oldE->publicId) { + tem = poolCopyString(newPool, oldE->publicId); + if (!tem) + return 0; + newE->publicId = tem; + } + } + else { + const XML_Char *tem = poolCopyStringN(newPool, oldE->textPtr, + oldE->textLen); + if (!tem) + return 0; + newE->textPtr = tem; + newE->textLen = oldE->textLen; + } + if (oldE->notation) { + const XML_Char *tem = poolCopyString(newPool, oldE->notation); + if (!tem) + return 0; + newE->notation = tem; + } + newE->is_param = oldE->is_param; + newE->is_internal = oldE->is_internal; + } + return 1; +} + +#define INIT_POWER 6 + +static XML_Bool FASTCALL +keyeq(KEY s1, KEY s2) +{ + for (; *s1 == *s2; s1++, s2++) + if (*s1 == 0) + return XML_TRUE; + return XML_FALSE; +} + +static unsigned long FASTCALL +hash(XML_Parser parser, KEY s) +{ + unsigned long h = hash_secret_salt; + while (*s) + h = CHAR_HASH(h, *s++); + return h; +} + +static NAMED * +lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize) +{ + size_t i; + if (table->size == 0) { + size_t tsize; + if (!createSize) + return NULL; + table->power = INIT_POWER; + /* table->size is a power of 2 */ + table->size = (size_t)1 << INIT_POWER; + tsize = table->size * sizeof(NAMED *); + table->v = (NAMED **)table->mem->malloc_fcn(tsize); + if (!table->v) { + table->size = 0; + return NULL; + } + memset(table->v, 0, tsize); + i = hash(parser, name) & ((unsigned long)table->size - 1); + } + else { + unsigned long h = hash(parser, name); + unsigned long mask = (unsigned long)table->size - 1; + unsigned char step = 0; + i = h & mask; + while (table->v[i]) { + if (keyeq(name, table->v[i]->name)) + return table->v[i]; + if (!step) + step = PROBE_STEP(h, mask, table->power); + i < step ? (i += table->size - step) : (i -= step); + } + if (!createSize) + return NULL; + + /* check for overflow (table is half full) */ + if (table->used >> (table->power - 1)) { + unsigned char newPower = table->power + 1; + size_t newSize = (size_t)1 << newPower; + unsigned long newMask = (unsigned long)newSize - 1; + size_t tsize = newSize * sizeof(NAMED *); + NAMED **newV = (NAMED **)table->mem->malloc_fcn(tsize); + if (!newV) + return NULL; + memset(newV, 0, tsize); + for (i = 0; i < table->size; i++) + if (table->v[i]) { + unsigned long newHash = hash(parser, table->v[i]->name); + size_t j = newHash & newMask; + step = 0; + while (newV[j]) { + if (!step) + step = PROBE_STEP(newHash, newMask, newPower); + j < step ? (j += newSize - step) : (j -= step); + } + newV[j] = table->v[i]; + } + table->mem->free_fcn(table->v); + table->v = newV; + table->power = newPower; + table->size = newSize; + i = h & newMask; + step = 0; + while (table->v[i]) { + if (!step) + step = PROBE_STEP(h, newMask, newPower); + i < step ? (i += newSize - step) : (i -= step); + } + } + } + table->v[i] = (NAMED *)table->mem->malloc_fcn(createSize); + if (!table->v[i]) + return NULL; + memset(table->v[i], 0, createSize); + table->v[i]->name = name; + (table->used)++; + return table->v[i]; +} + +static void FASTCALL +hashTableClear(HASH_TABLE *table) +{ + size_t i; + for (i = 0; i < table->size; i++) { + table->mem->free_fcn(table->v[i]); + table->v[i] = NULL; + } + table->used = 0; +} + +static void FASTCALL +hashTableDestroy(HASH_TABLE *table) +{ + size_t i; + for (i = 0; i < table->size; i++) + table->mem->free_fcn(table->v[i]); + table->mem->free_fcn(table->v); +} + +static void FASTCALL +hashTableInit(HASH_TABLE *p, const XML_Memory_Handling_Suite *ms) +{ + p->power = 0; + p->size = 0; + p->used = 0; + p->v = NULL; + p->mem = ms; +} + +static void FASTCALL +hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table) +{ + iter->p = table->v; + iter->end = iter->p + table->size; +} + +static NAMED * FASTCALL +hashTableIterNext(HASH_TABLE_ITER *iter) +{ + while (iter->p != iter->end) { + NAMED *tem = *(iter->p)++; + if (tem) + return tem; + } + return NULL; +} + +static void FASTCALL +poolInit(STRING_POOL *pool, const XML_Memory_Handling_Suite *ms) +{ + pool->blocks = NULL; + pool->freeBlocks = NULL; + pool->start = NULL; + pool->ptr = NULL; + pool->end = NULL; + pool->mem = ms; +} + +static void FASTCALL +poolClear(STRING_POOL *pool) +{ + if (!pool->freeBlocks) + pool->freeBlocks = pool->blocks; + else { + BLOCK *p = pool->blocks; + while (p) { + BLOCK *tem = p->next; + p->next = pool->freeBlocks; + pool->freeBlocks = p; + p = tem; + } + } + pool->blocks = NULL; + pool->start = NULL; + pool->ptr = NULL; + pool->end = NULL; +} + +static void FASTCALL +poolDestroy(STRING_POOL *pool) +{ + BLOCK *p = pool->blocks; + while (p) { + BLOCK *tem = p->next; + pool->mem->free_fcn(p); + p = tem; + } + p = pool->freeBlocks; + while (p) { + BLOCK *tem = p->next; + pool->mem->free_fcn(p); + p = tem; + } +} + +static XML_Char * +poolAppend(STRING_POOL *pool, const ENCODING *enc, + const char *ptr, const char *end) +{ + if (!pool->ptr && !poolGrow(pool)) + return NULL; + for (;;) { + XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end); + if (ptr == end) + break; + if (!poolGrow(pool)) + return NULL; + } + return pool->start; +} + +static const XML_Char * FASTCALL +poolCopyString(STRING_POOL *pool, const XML_Char *s) +{ + do { + if (!poolAppendChar(pool, *s)) + return NULL; + } while (*s++); + s = pool->start; + poolFinish(pool); + return s; +} + +static const XML_Char * +poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n) +{ + if (!pool->ptr && !poolGrow(pool)) + return NULL; + for (; n > 0; --n, s++) { + if (!poolAppendChar(pool, *s)) + return NULL; + } + s = pool->start; + poolFinish(pool); + return s; +} + +static const XML_Char * FASTCALL +poolAppendString(STRING_POOL *pool, const XML_Char *s) +{ + while (*s) { + if (!poolAppendChar(pool, *s)) + return NULL; + s++; + } + return pool->start; +} + +static XML_Char * +poolStoreString(STRING_POOL *pool, const ENCODING *enc, + const char *ptr, const char *end) +{ + if (!poolAppend(pool, enc, ptr, end)) + return NULL; + if (pool->ptr == pool->end && !poolGrow(pool)) + return NULL; + *(pool->ptr)++ = 0; + return pool->start; +} + +static XML_Bool FASTCALL +poolGrow(STRING_POOL *pool) +{ + if (pool->freeBlocks) { + if (pool->start == 0) { + pool->blocks = pool->freeBlocks; + pool->freeBlocks = pool->freeBlocks->next; + pool->blocks->next = NULL; + pool->start = pool->blocks->s; + pool->end = pool->start + pool->blocks->size; + pool->ptr = pool->start; + return XML_TRUE; + } + if (pool->end - pool->start < pool->freeBlocks->size) { + BLOCK *tem = pool->freeBlocks->next; + pool->freeBlocks->next = pool->blocks; + pool->blocks = pool->freeBlocks; + pool->freeBlocks = tem; + memcpy(pool->blocks->s, pool->start, + (pool->end - pool->start) * sizeof(XML_Char)); + pool->ptr = pool->blocks->s + (pool->ptr - pool->start); + pool->start = pool->blocks->s; + pool->end = pool->start + pool->blocks->size; + return XML_TRUE; + } + } + if (pool->blocks && pool->start == pool->blocks->s) { + int blockSize = (int)(pool->end - pool->start)*2; + BLOCK *temp = (BLOCK *) + pool->mem->realloc_fcn(pool->blocks, + (offsetof(BLOCK, s) + + blockSize * sizeof(XML_Char))); + if (temp == NULL) + return XML_FALSE; + pool->blocks = temp; + pool->blocks->size = blockSize; + pool->ptr = pool->blocks->s + (pool->ptr - pool->start); + pool->start = pool->blocks->s; + pool->end = pool->start + blockSize; + } + else { + BLOCK *tem; + int blockSize = (int)(pool->end - pool->start); + if (blockSize < INIT_BLOCK_SIZE) + blockSize = INIT_BLOCK_SIZE; + else + blockSize *= 2; + tem = (BLOCK *)pool->mem->malloc_fcn(offsetof(BLOCK, s) + + blockSize * sizeof(XML_Char)); + if (!tem) + return XML_FALSE; + tem->size = blockSize; + tem->next = pool->blocks; + pool->blocks = tem; + if (pool->ptr != pool->start) + memcpy(tem->s, pool->start, + (pool->ptr - pool->start) * sizeof(XML_Char)); + pool->ptr = tem->s + (pool->ptr - pool->start); + pool->start = tem->s; + pool->end = tem->s + blockSize; + } + return XML_TRUE; +} + +static int FASTCALL +nextScaffoldPart(XML_Parser parser) +{ + DTD * const dtd = _dtd; /* save one level of indirection */ + CONTENT_SCAFFOLD * me; + int next; + + if (!dtd->scaffIndex) { + dtd->scaffIndex = (int *)MALLOC(groupSize * sizeof(int)); + if (!dtd->scaffIndex) + return -1; + dtd->scaffIndex[0] = 0; + } + + if (dtd->scaffCount >= dtd->scaffSize) { + CONTENT_SCAFFOLD *temp; + if (dtd->scaffold) { + temp = (CONTENT_SCAFFOLD *) + REALLOC(dtd->scaffold, dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD)); + if (temp == NULL) + return -1; + dtd->scaffSize *= 2; + } + else { + temp = (CONTENT_SCAFFOLD *)MALLOC(INIT_SCAFFOLD_ELEMENTS + * sizeof(CONTENT_SCAFFOLD)); + if (temp == NULL) + return -1; + dtd->scaffSize = INIT_SCAFFOLD_ELEMENTS; + } + dtd->scaffold = temp; + } + next = dtd->scaffCount++; + me = &dtd->scaffold[next]; + if (dtd->scaffLevel) { + CONTENT_SCAFFOLD *parent = &dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel-1]]; + if (parent->lastchild) { + dtd->scaffold[parent->lastchild].nextsib = next; + } + if (!parent->childcnt) + parent->firstchild = next; + parent->lastchild = next; + parent->childcnt++; + } + me->firstchild = me->lastchild = me->childcnt = me->nextsib = 0; + return next; +} + +static void +build_node(XML_Parser parser, + int src_node, + XML_Content *dest, + XML_Content **contpos, + XML_Char **strpos) +{ + DTD * const dtd = _dtd; /* save one level of indirection */ + dest->type = dtd->scaffold[src_node].type; + dest->quant = dtd->scaffold[src_node].quant; + if (dest->type == XML_CTYPE_NAME) { + const XML_Char *src; + dest->name = *strpos; + src = dtd->scaffold[src_node].name; + for (;;) { + *(*strpos)++ = *src; + if (!*src) + break; + src++; + } + dest->numchildren = 0; + dest->children = NULL; + } + else { + unsigned int i; + int cn; + dest->numchildren = dtd->scaffold[src_node].childcnt; + dest->children = *contpos; + *contpos += dest->numchildren; + for (i = 0, cn = dtd->scaffold[src_node].firstchild; + i < dest->numchildren; + i++, cn = dtd->scaffold[cn].nextsib) { + build_node(parser, cn, &(dest->children[i]), contpos, strpos); + } + dest->name = NULL; + } +} + +static XML_Content * +build_model (XML_Parser parser) +{ + DTD * const dtd = _dtd; /* save one level of indirection */ + XML_Content *ret; + XML_Content *cpos; + XML_Char * str; + int allocsize = (dtd->scaffCount * sizeof(XML_Content) + + (dtd->contentStringLen * sizeof(XML_Char))); + + ret = (XML_Content *)MALLOC(allocsize); + if (!ret) + return NULL; + + str = (XML_Char *) (&ret[dtd->scaffCount]); + cpos = &ret[1]; + + build_node(parser, 0, ret, &cpos, &str); + return ret; +} + +static ELEMENT_TYPE * +getElementType(XML_Parser parser, + const ENCODING *enc, + const char *ptr, + const char *end) +{ + DTD * const dtd = _dtd; /* save one level of indirection */ + const XML_Char *name = poolStoreString(&dtd->pool, enc, ptr, end); + ELEMENT_TYPE *ret; + + if (!name) + return NULL; + ret = (ELEMENT_TYPE *) lookup(parser, &dtd->elementTypes, name, sizeof(ELEMENT_TYPE)); + if (!ret) + return NULL; + if (ret->name != name) + poolDiscard(&dtd->pool); + else { + poolFinish(&dtd->pool); + if (!setElementTypePrefix(parser, ret)) + return NULL; + } + return ret; +} diff --git a/third_party/freetype-android/BUILD.gn b/third_party/freetype-android/BUILD.gn index 67f6fe8da78e9..e8b3aa80957ac 100644 --- a/third_party/freetype-android/BUILD.gn +++ b/third_party/freetype-android/BUILD.gn @@ -5,7 +5,10 @@ assert(is_android, "This library is only used on Android") config("freetype_config") { - include_dirs = [ "src/include" ] + include_dirs = [ + "include", + "src/include", + ] } source_set("freetype") { @@ -14,12 +17,12 @@ source_set("freetype") { # same order as in Android.mk to ease maintenance. "src/src/base/ftbbox.c", "src/src/base/ftbitmap.c", + "src/src/base/ftfntfmt.c", "src/src/base/ftfstype.c", "src/src/base/ftglyph.c", "src/src/base/ftlcdfil.c", "src/src/base/ftstroke.c", "src/src/base/fttype1.c", - "src/src/base/ftxf86.c", "src/src/base/ftbase.c", "src/src/base/ftsystem.c", "src/src/base/ftinit.c", @@ -39,6 +42,9 @@ source_set("freetype") { defines = [ "FT2_BUILD_LIBRARY", "DARWIN_NO_CARBON", + # Long directory name to avoid accidentally using wrong headers. + "FT_CONFIG_MODULES_H=", + "FT_CONFIG_OPTIONS_H=", ] public_configs = [ ":freetype_config" ] diff --git a/third_party/freetype-android/OWNERS b/third_party/freetype-android/OWNERS new file mode 100644 index 0000000000000..a5ce419f262ff --- /dev/null +++ b/third_party/freetype-android/OWNERS @@ -0,0 +1,3 @@ +wangxianzhu@chromium.org +michaelbai@chromium.org +bungeman@chromium.org diff --git a/third_party/freetype-android/README.chromium b/third_party/freetype-android/README.chromium index 45032d2778b06..72d405af41c69 100644 --- a/third_party/freetype-android/README.chromium +++ b/third_party/freetype-android/README.chromium @@ -1,18 +1,26 @@ -Name: Freetype -URL: https://android.googlesource.com/platform/external/freetype/ -Version: 9c745321260bb728ab1cd1c8fd5f075854b2ad49 +Name: FreeType +URL: http://www.freetype.org/ +Version: VER-2-6 +Revision: e186230678ee8e4ea4ac4797ece8125761e3225a License: Custom license "inspired by the BSD, Artistic, and IJG (Independent JPEG Group) licenses" -License File: src/NOTICE +License File: src/docs/FTL.TXT Security Critical: yes License Android Compatible: yes Description: -This package was copied from Android source tree and just used for Android. -For other platforms, the freetype is normally found outside the Chromium tree; -e.g. on Mac it's in /usr/include +This package tracks upstream FreeType, but the build files and configuration +are based on the Android source tree. This package is only used for Android. +For other platforms the system FreeType library is used. How to update: -1. Follow the directions in src/README.chromium to update the source. -2. Update freetype.gyp and BUILD.gn to reflect any changes in src/Android.mk. -3. Commit build changes while rolling Chromium DEPS to new commit. +1. Find the desired commit in + https://chromium.googlesource.com/chromium/src/third_party/freetype2/ . + If such a commit does not yet exist, branch from the appropriate point with + a branch name like "chromium/android/VER-X-X-X-updates" depending on the + FreeType tag being branched and commit changes there. +2. Update freetype.gyp and BUILD.gn to reflect any changes. These should be kept + in sync with the Android.mk for FreeType in Android as possible. +3. Update this file. +4. Commit build changes while rolling Chromium's freetype-android DEPS to the + new commit. diff --git a/third_party/freetype-android/freetype.gyp b/third_party/freetype-android/freetype.gyp new file mode 100644 index 0000000000000..169f132f1fa66 --- /dev/null +++ b/third_party/freetype-android/freetype.gyp @@ -0,0 +1,67 @@ +# Copyright (c) 2011 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'variables': { + 'ft2_dir': 'src', + }, + 'conditions': [ + [ 'OS == "android"', { + 'targets': [ + { + 'target_name': 'ft2', + 'type': 'static_library', + 'toolsets': ['target'], + 'sources': [ + # The following files are not sorted alphabetically, but in the + # same order as in Android.mk to ease maintenance. + '<(ft2_dir)/src/base/ftbbox.c', + '<(ft2_dir)/src/base/ftbitmap.c', + '<(ft2_dir)/src/base/ftfntfmt.c', + '<(ft2_dir)/src/base/ftfstype.c', + '<(ft2_dir)/src/base/ftglyph.c', + '<(ft2_dir)/src/base/ftlcdfil.c', + '<(ft2_dir)/src/base/ftstroke.c', + '<(ft2_dir)/src/base/fttype1.c', + '<(ft2_dir)/src/base/ftbase.c', + '<(ft2_dir)/src/base/ftsystem.c', + '<(ft2_dir)/src/base/ftinit.c', + '<(ft2_dir)/src/base/ftgasp.c', + '<(ft2_dir)/src/base/ftmm.c', + '<(ft2_dir)/src/gzip/ftgzip.c', + '<(ft2_dir)/src/raster/raster.c', + '<(ft2_dir)/src/sfnt/sfnt.c', + '<(ft2_dir)/src/smooth/smooth.c', + '<(ft2_dir)/src/autofit/autofit.c', + '<(ft2_dir)/src/truetype/truetype.c', + '<(ft2_dir)/src/cff/cff.c', + '<(ft2_dir)/src/psnames/psnames.c', + '<(ft2_dir)/src/pshinter/pshinter.c', + ], + 'dependencies': [ + '../libpng/libpng.gyp:libpng', + '../zlib/zlib.gyp:zlib', + ], + 'include_dirs': [ + 'include', + '<(ft2_dir)/include', + ], + 'defines': [ + 'FT2_BUILD_LIBRARY', + 'DARWIN_NO_CARBON', + # Long directory name to avoid accidentally using wrong headers. + 'FT_CONFIG_MODULES_H=', + 'FT_CONFIG_OPTIONS_H=', + ], + 'direct_dependent_settings': { + 'include_dirs': [ + 'include', + '<(ft2_dir)/include', + ], + }, + }, + ], + }], + ], +} diff --git a/third_party/freetype-android/include/freetype-android-config/ftmodule.h b/third_party/freetype-android/include/freetype-android-config/ftmodule.h new file mode 100644 index 0000000000000..8ec70b80825c6 --- /dev/null +++ b/third_party/freetype-android/include/freetype-android-config/ftmodule.h @@ -0,0 +1,38 @@ +/***************************************************************************/ +/* */ +/* ftmodule.h */ +/* */ +/* User-selectable module macros. */ +/* */ +/* Copyright 1996-2015 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + +FT_USE_MODULE( FT_Module_Class, autofit_module_class ) +FT_USE_MODULE( FT_Driver_ClassRec, tt_driver_class ) +FT_USE_MODULE( FT_Driver_ClassRec, cff_driver_class ) +FT_USE_MODULE( FT_Module_Class, psnames_module_class ) +FT_USE_MODULE( FT_Module_Class, pshinter_module_class ) +FT_USE_MODULE( FT_Renderer_Class, ft_raster1_renderer_class ) +FT_USE_MODULE( FT_Module_Class, sfnt_module_class ) +FT_USE_MODULE( FT_Renderer_Class, ft_smooth_renderer_class ) +FT_USE_MODULE( FT_Renderer_Class, ft_smooth_lcd_renderer_class ) +FT_USE_MODULE( FT_Renderer_Class, ft_smooth_lcdv_renderer_class ) + +/* +FT_USE_MODULE( FT_Driver_ClassRec, t1_driver_class ) +FT_USE_MODULE( FT_Driver_ClassRec, t1cid_driver_class ) +FT_USE_MODULE( FT_Driver_ClassRec, pfr_driver_class ) +FT_USE_MODULE( FT_Driver_ClassRec, t42_driver_class ) +FT_USE_MODULE( FT_Driver_ClassRec, winfnt_driver_class ) +FT_USE_MODULE( FT_Driver_ClassRec, pcf_driver_class ) +FT_USE_MODULE( FT_Driver_ClassRec, bdf_driver_class ) +FT_USE_MODULE( FT_Module_Class, psaux_module_class ) +*/ diff --git a/third_party/freetype-android/include/freetype-android-config/ftoption.h b/third_party/freetype-android/include/freetype-android-config/ftoption.h new file mode 100644 index 0000000000000..24991961cc250 --- /dev/null +++ b/third_party/freetype-android/include/freetype-android-config/ftoption.h @@ -0,0 +1,886 @@ +/***************************************************************************/ +/* */ +/* ftoption.h */ +/* */ +/* User-selectable configuration macros (specification only). */ +/* */ +/* Copyright 1996-2015 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTOPTION_H__ +#define __FTOPTION_H__ + + +#include + + +FT_BEGIN_HEADER + + /*************************************************************************/ + /* */ + /* USER-SELECTABLE CONFIGURATION MACROS */ + /* */ + /* This file contains the default configuration macro definitions for */ + /* a standard build of the FreeType library. There are three ways to */ + /* use this file to build project-specific versions of the library: */ + /* */ + /* - You can modify this file by hand, but this is not recommended in */ + /* cases where you would like to build several versions of the */ + /* library from a single source directory. */ + /* */ + /* - You can put a copy of this file in your build directory, more */ + /* precisely in `$BUILD/config/ftoption.h', where `$BUILD' is the */ + /* name of a directory that is included _before_ the FreeType include */ + /* path during compilation. */ + /* */ + /* The default FreeType Makefiles and Jamfiles use the build */ + /* directory `builds/' by default, but you can easily change */ + /* that for your own projects. */ + /* */ + /* - Copy the file to `$BUILD/ft2build.h' and modify it */ + /* slightly to pre-define the macro FT_CONFIG_OPTIONS_H used to */ + /* locate this file during the build. For example, */ + /* */ + /* #define FT_CONFIG_OPTIONS_H */ + /* #include */ + /* */ + /* will use `$BUILD/myftoptions.h' instead of this file for macro */ + /* definitions. */ + /* */ + /* Note also that you can similarly pre-define the macro */ + /* FT_CONFIG_MODULES_H used to locate the file listing of the modules */ + /* that are statically linked to the library at compile time. By */ + /* default, this file is . */ + /* */ + /* We highly recommend using the third method whenever possible. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** G E N E R A L F R E E T Y P E 2 C O N F I G U R A T I O N ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* Uncomment the line below if you want to activate sub-pixel rendering */ + /* (a.k.a. LCD rendering, or ClearType) in this build of the library. */ + /* */ + /* Note that this feature is covered by several Microsoft patents */ + /* and should not be activated in any default build of the library. */ + /* */ + /* This macro has no impact on the FreeType API, only on its */ + /* _implementation_. For example, using FT_RENDER_MODE_LCD when calling */ + /* FT_Render_Glyph still generates a bitmap that is 3 times wider than */ + /* the original size in case this macro isn't defined; however, each */ + /* triplet of subpixels has R=G=B. */ + /* */ + /* This is done to allow FreeType clients to run unmodified, forcing */ + /* them to display normal gray-level anti-aliased glyphs. */ + /* */ +/* #define FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ + + + /*************************************************************************/ + /* */ + /* Many compilers provide a non-ANSI 64-bit data type that can be used */ + /* by FreeType to speed up some computations. However, this will create */ + /* some problems when compiling the library in strict ANSI mode. */ + /* */ + /* For this reason, the use of 64-bit integers is normally disabled when */ + /* the __STDC__ macro is defined. You can however disable this by */ + /* defining the macro FT_CONFIG_OPTION_FORCE_INT64 here. */ + /* */ + /* For most compilers, this will only create compilation warnings when */ + /* building the library. */ + /* */ + /* ObNote: The compiler-specific 64-bit integers are detected in the */ + /* file `ftconfig.h' either statically or through the */ + /* `configure' script on supported platforms. */ + /* */ +#undef FT_CONFIG_OPTION_FORCE_INT64 + + + /*************************************************************************/ + /* */ + /* If this macro is defined, do not try to use an assembler version of */ + /* performance-critical functions (e.g. FT_MulFix). You should only do */ + /* that to verify that the assembler function works properly, or to */ + /* execute benchmark tests of the various implementations. */ +/* #define FT_CONFIG_OPTION_NO_ASSEMBLER */ + + + /*************************************************************************/ + /* */ + /* If this macro is defined, try to use an inlined assembler version of */ + /* the `FT_MulFix' function, which is a `hotspot' when loading and */ + /* hinting glyphs, and which should be executed as fast as possible. */ + /* */ + /* Note that if your compiler or CPU is not supported, this will default */ + /* to the standard and portable implementation found in `ftcalc.c'. */ + /* */ +#define FT_CONFIG_OPTION_INLINE_MULFIX + + + /*************************************************************************/ + /* */ + /* LZW-compressed file support. */ + /* */ + /* FreeType now handles font files that have been compressed with the */ + /* `compress' program. This is mostly used to parse many of the PCF */ + /* files that come with various X11 distributions. The implementation */ + /* uses NetBSD's `zopen' to partially uncompress the file on the fly */ + /* (see src/lzw/ftgzip.c). */ + /* */ + /* Define this macro if you want to enable this `feature'. */ + /* */ +#define FT_CONFIG_OPTION_USE_LZW + + + /*************************************************************************/ + /* */ + /* Gzip-compressed file support. */ + /* */ + /* FreeType now handles font files that have been compressed with the */ + /* `gzip' program. This is mostly used to parse many of the PCF files */ + /* that come with XFree86. The implementation uses `zlib' to */ + /* partially uncompress the file on the fly (see src/gzip/ftgzip.c). */ + /* */ + /* Define this macro if you want to enable this `feature'. See also */ + /* the macro FT_CONFIG_OPTION_SYSTEM_ZLIB below. */ + /* */ +#define FT_CONFIG_OPTION_USE_ZLIB + + + /*************************************************************************/ + /* */ + /* ZLib library selection */ + /* */ + /* This macro is only used when FT_CONFIG_OPTION_USE_ZLIB is defined. */ + /* It allows FreeType's `ftgzip' component to link to the system's */ + /* installation of the ZLib library. This is useful on systems like */ + /* Unix or VMS where it generally is already available. */ + /* */ + /* If you let it undefined, the component will use its own copy */ + /* of the zlib sources instead. These have been modified to be */ + /* included directly within the component and *not* export external */ + /* function names. This allows you to link any program with FreeType */ + /* _and_ ZLib without linking conflicts. */ + /* */ + /* Do not #undef this macro here since the build system might define */ + /* it for certain configurations only. */ + /* */ +/* #define FT_CONFIG_OPTION_SYSTEM_ZLIB */ + + + /*************************************************************************/ + /* */ + /* Bzip2-compressed file support. */ + /* */ + /* FreeType now handles font files that have been compressed with the */ + /* `bzip2' program. This is mostly used to parse many of the PCF */ + /* files that come with XFree86. The implementation uses `libbz2' to */ + /* partially uncompress the file on the fly (see src/bzip2/ftbzip2.c). */ + /* Contrary to gzip, bzip2 currently is not included and need to use */ + /* the system available bzip2 implementation. */ + /* */ + /* Define this macro if you want to enable this `feature'. */ + /* */ +/* #define FT_CONFIG_OPTION_USE_BZIP2 */ + + + /*************************************************************************/ + /* */ + /* Define to disable the use of file stream functions and types, FILE, */ + /* fopen() etc. Enables the use of smaller system libraries on embedded */ + /* systems that have multiple system libraries, some with or without */ + /* file stream support, in the cases where file stream support is not */ + /* necessary such as memory loading of font files. */ + /* */ +/* #define FT_CONFIG_OPTION_DISABLE_STREAM_SUPPORT */ + + + /*************************************************************************/ + /* */ + /* PNG bitmap support. */ + /* */ + /* FreeType now handles loading color bitmap glyphs in the PNG format. */ + /* This requires help from the external libpng library. Uncompressed */ + /* color bitmaps do not need any external libraries and will be */ + /* supported regardless of this configuration. */ + /* */ + /* Define this macro if you want to enable this `feature'. */ + /* */ +#define FT_CONFIG_OPTION_USE_PNG + + + /*************************************************************************/ + /* */ + /* HarfBuzz support. */ + /* */ + /* FreeType uses the HarfBuzz library to improve auto-hinting of */ + /* OpenType fonts. If available, many glyphs not directly addressable */ + /* by a font's character map will be hinted also. */ + /* */ + /* Define this macro if you want to enable this `feature'. */ + /* */ +/* #define FT_CONFIG_OPTION_USE_HARFBUZZ */ + + + /*************************************************************************/ + /* */ + /* DLL export compilation */ + /* */ + /* When compiling FreeType as a DLL, some systems/compilers need a */ + /* special keyword in front OR after the return type of function */ + /* declarations. */ + /* */ + /* Two macros are used within the FreeType source code to define */ + /* exported library functions: FT_EXPORT and FT_EXPORT_DEF. */ + /* */ + /* FT_EXPORT( return_type ) */ + /* */ + /* is used in a function declaration, as in */ + /* */ + /* FT_EXPORT( FT_Error ) */ + /* FT_Init_FreeType( FT_Library* alibrary ); */ + /* */ + /* */ + /* FT_EXPORT_DEF( return_type ) */ + /* */ + /* is used in a function definition, as in */ + /* */ + /* FT_EXPORT_DEF( FT_Error ) */ + /* FT_Init_FreeType( FT_Library* alibrary ) */ + /* { */ + /* ... some code ... */ + /* return FT_Err_Ok; */ + /* } */ + /* */ + /* You can provide your own implementation of FT_EXPORT and */ + /* FT_EXPORT_DEF here if you want. If you leave them undefined, they */ + /* will be later automatically defined as `extern return_type' to */ + /* allow normal compilation. */ + /* */ + /* Do not #undef these macros here since the build system might define */ + /* them for certain configurations only. */ + /* */ +/* #define FT_EXPORT(x) extern x */ +/* #define FT_EXPORT_DEF(x) x */ + + + /*************************************************************************/ + /* */ + /* Glyph Postscript Names handling */ + /* */ + /* By default, FreeType 2 is compiled with the `psnames' module. This */ + /* module is in charge of converting a glyph name string into a */ + /* Unicode value, or return a Macintosh standard glyph name for the */ + /* use with the TrueType `post' table. */ + /* */ + /* Undefine this macro if you do not want `psnames' compiled in your */ + /* build of FreeType. This has the following effects: */ + /* */ + /* - The TrueType driver will provide its own set of glyph names, */ + /* if you build it to support postscript names in the TrueType */ + /* `post' table. */ + /* */ + /* - The Type 1 driver will not be able to synthesize a Unicode */ + /* charmap out of the glyphs found in the fonts. */ + /* */ + /* You would normally undefine this configuration macro when building */ + /* a version of FreeType that doesn't contain a Type 1 or CFF driver. */ + /* */ +#define FT_CONFIG_OPTION_POSTSCRIPT_NAMES + + + /*************************************************************************/ + /* */ + /* Postscript Names to Unicode Values support */ + /* */ + /* By default, FreeType 2 is built with the `PSNames' module compiled */ + /* in. Among other things, the module is used to convert a glyph name */ + /* into a Unicode value. This is especially useful in order to */ + /* synthesize on the fly a Unicode charmap from the CFF/Type 1 driver */ + /* through a big table named the `Adobe Glyph List' (AGL). */ + /* */ + /* Undefine this macro if you do not want the Adobe Glyph List */ + /* compiled in your `PSNames' module. The Type 1 driver will not be */ + /* able to synthesize a Unicode charmap out of the glyphs found in the */ + /* fonts. */ + /* */ +#define FT_CONFIG_OPTION_ADOBE_GLYPH_LIST + + + /*************************************************************************/ + /* */ + /* Support for Mac fonts */ + /* */ + /* Define this macro if you want support for outline fonts in Mac */ + /* format (mac dfont, mac resource, macbinary containing a mac */ + /* resource) on non-Mac platforms. */ + /* */ + /* Note that the `FOND' resource isn't checked. */ + /* */ +#define FT_CONFIG_OPTION_MAC_FONTS + + + /*************************************************************************/ + /* */ + /* Guessing methods to access embedded resource forks */ + /* */ + /* Enable extra Mac fonts support on non-Mac platforms (e.g. */ + /* GNU/Linux). */ + /* */ + /* Resource forks which include fonts data are stored sometimes in */ + /* locations which users or developers don't expected. In some cases, */ + /* resource forks start with some offset from the head of a file. In */ + /* other cases, the actual resource fork is stored in file different */ + /* from what the user specifies. If this option is activated, */ + /* FreeType tries to guess whether such offsets or different file */ + /* names must be used. */ + /* */ + /* Note that normal, direct access of resource forks is controlled via */ + /* the FT_CONFIG_OPTION_MAC_FONTS option. */ + /* */ +#ifdef FT_CONFIG_OPTION_MAC_FONTS +#define FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK +#endif + + + /*************************************************************************/ + /* */ + /* Allow the use of FT_Incremental_Interface to load typefaces that */ + /* contain no glyph data, but supply it via a callback function. */ + /* This is required by clients supporting document formats which */ + /* supply font data incrementally as the document is parsed, such */ + /* as the Ghostscript interpreter for the PostScript language. */ + /* */ +/* #define FT_CONFIG_OPTION_INCREMENTAL */ + + + /*************************************************************************/ + /* */ + /* The size in bytes of the render pool used by the scan-line converter */ + /* to do all of its work. */ + /* */ +#define FT_RENDER_POOL_SIZE 16384L + + + /*************************************************************************/ + /* */ + /* FT_MAX_MODULES */ + /* */ + /* The maximum number of modules that can be registered in a single */ + /* FreeType library object. 32 is the default. */ + /* */ +#define FT_MAX_MODULES 32 + + + /*************************************************************************/ + /* */ + /* Debug level */ + /* */ + /* FreeType can be compiled in debug or trace mode. In debug mode, */ + /* errors are reported through the `ftdebug' component. In trace */ + /* mode, additional messages are sent to the standard output during */ + /* execution. */ + /* */ + /* Define FT_DEBUG_LEVEL_ERROR to build the library in debug mode. */ + /* Define FT_DEBUG_LEVEL_TRACE to build it in trace mode. */ + /* */ + /* Don't define any of these macros to compile in `release' mode! */ + /* */ + /* Do not #undef these macros here since the build system might define */ + /* them for certain configurations only. */ + /* */ +/* #define FT_DEBUG_LEVEL_ERROR */ +/* #define FT_DEBUG_LEVEL_TRACE */ + + + /*************************************************************************/ + /* */ + /* Autofitter debugging */ + /* */ + /* If FT_DEBUG_AUTOFIT is defined, FreeType provides some means to */ + /* control the autofitter behaviour for debugging purposes with global */ + /* boolean variables (consequently, you should *never* enable this */ + /* while compiling in `release' mode): */ + /* */ + /* _af_debug_disable_horz_hints */ + /* _af_debug_disable_vert_hints */ + /* _af_debug_disable_blue_hints */ + /* */ + /* Additionally, the following functions provide dumps of various */ + /* internal autofit structures to stdout (using `printf'): */ + /* */ + /* af_glyph_hints_dump_points */ + /* af_glyph_hints_dump_segments */ + /* af_glyph_hints_dump_edges */ + /* af_glyph_hints_get_num_segments */ + /* af_glyph_hints_get_segment_offset */ + /* */ + /* As an argument, they use another global variable: */ + /* */ + /* _af_debug_hints */ + /* */ + /* Please have a look at the `ftgrid' demo program to see how those */ + /* variables and macros should be used. */ + /* */ + /* Do not #undef these macros here since the build system might define */ + /* them for certain configurations only. */ + /* */ +/* #define FT_DEBUG_AUTOFIT */ + + + /*************************************************************************/ + /* */ + /* Memory Debugging */ + /* */ + /* FreeType now comes with an integrated memory debugger that is */ + /* capable of detecting simple errors like memory leaks or double */ + /* deletes. To compile it within your build of the library, you */ + /* should define FT_DEBUG_MEMORY here. */ + /* */ + /* Note that the memory debugger is only activated at runtime when */ + /* when the _environment_ variable `FT2_DEBUG_MEMORY' is defined also! */ + /* */ + /* Do not #undef this macro here since the build system might define */ + /* it for certain configurations only. */ + /* */ +/* #define FT_DEBUG_MEMORY */ + + + /*************************************************************************/ + /* */ + /* Module errors */ + /* */ + /* If this macro is set (which is _not_ the default), the higher byte */ + /* of an error code gives the module in which the error has occurred, */ + /* while the lower byte is the real error code. */ + /* */ + /* Setting this macro makes sense for debugging purposes only, since */ + /* it would break source compatibility of certain programs that use */ + /* FreeType 2. */ + /* */ + /* More details can be found in the files ftmoderr.h and fterrors.h. */ + /* */ +#undef FT_CONFIG_OPTION_USE_MODULE_ERRORS + + + /*************************************************************************/ + /* */ + /* Position Independent Code */ + /* */ + /* If this macro is set (which is _not_ the default), FreeType2 will */ + /* avoid creating constants that require address fixups. Instead the */ + /* constants will be moved into a struct and additional intialization */ + /* code will be used. */ + /* */ + /* Setting this macro is needed for systems that prohibit address */ + /* fixups, such as BREW. */ + /* */ +/* #define FT_CONFIG_OPTION_PIC */ + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** S F N T D R I V E R C O N F I G U R A T I O N ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* Define TT_CONFIG_OPTION_EMBEDDED_BITMAPS if you want to support */ + /* embedded bitmaps in all formats using the SFNT module (namely */ + /* TrueType & OpenType). */ + /* */ +#define TT_CONFIG_OPTION_EMBEDDED_BITMAPS + + + /*************************************************************************/ + /* */ + /* Define TT_CONFIG_OPTION_POSTSCRIPT_NAMES if you want to be able to */ + /* load and enumerate the glyph Postscript names in a TrueType or */ + /* OpenType file. */ + /* */ + /* Note that when you do not compile the `PSNames' module by undefining */ + /* the above FT_CONFIG_OPTION_POSTSCRIPT_NAMES, the `sfnt' module will */ + /* contain additional code used to read the PS Names table from a font. */ + /* */ + /* (By default, the module uses `PSNames' to extract glyph names.) */ + /* */ +#define TT_CONFIG_OPTION_POSTSCRIPT_NAMES + + + /*************************************************************************/ + /* */ + /* Define TT_CONFIG_OPTION_SFNT_NAMES if your applications need to */ + /* access the internal name table in a SFNT-based format like TrueType */ + /* or OpenType. The name table contains various strings used to */ + /* describe the font, like family name, copyright, version, etc. It */ + /* does not contain any glyph name though. */ + /* */ + /* Accessing SFNT names is done through the functions declared in */ + /* `ftsnames.h'. */ + /* */ +#define TT_CONFIG_OPTION_SFNT_NAMES + + + /*************************************************************************/ + /* */ + /* TrueType CMap support */ + /* */ + /* Here you can fine-tune which TrueType CMap table format shall be */ + /* supported. */ +#define TT_CONFIG_CMAP_FORMAT_0 +#define TT_CONFIG_CMAP_FORMAT_2 +#define TT_CONFIG_CMAP_FORMAT_4 +#define TT_CONFIG_CMAP_FORMAT_6 +#define TT_CONFIG_CMAP_FORMAT_8 +#define TT_CONFIG_CMAP_FORMAT_10 +#define TT_CONFIG_CMAP_FORMAT_12 +#define TT_CONFIG_CMAP_FORMAT_13 +#define TT_CONFIG_CMAP_FORMAT_14 + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** T R U E T Y P E D R I V E R C O N F I G U R A T I O N ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* Define TT_CONFIG_OPTION_BYTECODE_INTERPRETER if you want to compile */ + /* a bytecode interpreter in the TrueType driver. */ + /* */ + /* By undefining this, you will only compile the code necessary to load */ + /* TrueType glyphs without hinting. */ + /* */ + /* Do not #undef this macro here, since the build system might */ + /* define it for certain configurations only. */ + /* */ +#define TT_CONFIG_OPTION_BYTECODE_INTERPRETER + + + /*************************************************************************/ + /* */ + /* Define TT_CONFIG_OPTION_SUBPIXEL_HINTING if you want to compile */ + /* EXPERIMENTAL subpixel hinting support into the TrueType driver. This */ + /* replaces the native TrueType hinting mechanism when anything but */ + /* FT_RENDER_MODE_MONO is requested. */ + /* */ + /* Enabling this causes the TrueType driver to ignore instructions under */ + /* certain conditions. This is done in accordance with the guide here, */ + /* with some minor differences: */ + /* */ + /* http://www.microsoft.com/typography/cleartype/truetypecleartype.aspx */ + /* */ + /* By undefining this, you only compile the code necessary to hint */ + /* TrueType glyphs with native TT hinting. */ + /* */ + /* This option requires TT_CONFIG_OPTION_BYTECODE_INTERPRETER to be */ + /* defined. */ + /* */ +/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + + + /*************************************************************************/ + /* */ + /* If you define TT_CONFIG_OPTION_UNPATENTED_HINTING, a special version */ + /* of the TrueType bytecode interpreter is used that doesn't implement */ + /* any of the patented opcodes and algorithms. The patents related to */ + /* TrueType hinting have expired worldwide since May 2010; this option */ + /* is now deprecated. */ + /* */ + /* Note that the TT_CONFIG_OPTION_UNPATENTED_HINTING macro is *ignored* */ + /* if you define TT_CONFIG_OPTION_BYTECODE_INTERPRETER; in other words, */ + /* either define TT_CONFIG_OPTION_BYTECODE_INTERPRETER or */ + /* TT_CONFIG_OPTION_UNPATENTED_HINTING but not both at the same time. */ + /* */ + /* This macro is only useful for a small number of font files (mostly */ + /* for Asian scripts) that require bytecode interpretation to properly */ + /* load glyphs. For all other fonts, this produces unpleasant results, */ + /* thus the unpatented interpreter is never used to load glyphs from */ + /* TrueType fonts unless one of the following two options is used. */ + /* */ + /* - The unpatented interpreter is explicitly activated by the user */ + /* through the FT_PARAM_TAG_UNPATENTED_HINTING parameter tag */ + /* when opening the FT_Face. */ + /* */ + /* - FreeType detects that the FT_Face corresponds to one of the */ + /* `trick' fonts (e.g., `Mingliu') it knows about. The font engine */ + /* contains a hard-coded list of font names and other matching */ + /* parameters (see function `tt_face_init' in file */ + /* `src/truetype/ttobjs.c'). */ + /* */ + /* Here a sample code snippet for using FT_PARAM_TAG_UNPATENTED_HINTING. */ + /* */ + /* { */ + /* FT_Parameter parameter; */ + /* FT_Open_Args open_args; */ + /* */ + /* */ + /* parameter.tag = FT_PARAM_TAG_UNPATENTED_HINTING; */ + /* */ + /* open_args.flags = FT_OPEN_PATHNAME | FT_OPEN_PARAMS; */ + /* open_args.pathname = my_font_pathname; */ + /* open_args.num_params = 1; */ + /* open_args.params = ¶meter; */ + /* */ + /* error = FT_Open_Face( library, &open_args, index, &face ); */ + /* ... */ + /* } */ + /* */ +/* #define TT_CONFIG_OPTION_UNPATENTED_HINTING */ + + + /*************************************************************************/ + /* */ + /* Define TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED to compile the */ + /* TrueType glyph loader to use Apple's definition of how to handle */ + /* component offsets in composite glyphs. */ + /* */ + /* Apple and MS disagree on the default behavior of component offsets */ + /* in composites. Apple says that they should be scaled by the scaling */ + /* factors in the transformation matrix (roughly, it's more complex) */ + /* while MS says they should not. OpenType defines two bits in the */ + /* composite flags array which can be used to disambiguate, but old */ + /* fonts will not have them. */ + /* */ + /* http://www.microsoft.com/typography/otspec/glyf.htm */ + /* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6glyf.html */ + /* */ +#undef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED + + + /*************************************************************************/ + /* */ + /* Define TT_CONFIG_OPTION_GX_VAR_SUPPORT if you want to include */ + /* support for Apple's distortable font technology (fvar, gvar, cvar, */ + /* and avar tables). This has many similarities to Type 1 Multiple */ + /* Masters support. */ + /* */ +#define TT_CONFIG_OPTION_GX_VAR_SUPPORT + + + /*************************************************************************/ + /* */ + /* Define TT_CONFIG_OPTION_BDF if you want to include support for */ + /* an embedded `BDF ' table within SFNT-based bitmap formats. */ + /* */ +#define TT_CONFIG_OPTION_BDF + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** T Y P E 1 D R I V E R C O N F I G U R A T I O N ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* T1_MAX_DICT_DEPTH is the maximum depth of nest dictionaries and */ + /* arrays in the Type 1 stream (see t1load.c). A minimum of 4 is */ + /* required. */ + /* */ +#define T1_MAX_DICT_DEPTH 5 + + + /*************************************************************************/ + /* */ + /* T1_MAX_SUBRS_CALLS details the maximum number of nested sub-routine */ + /* calls during glyph loading. */ + /* */ +#define T1_MAX_SUBRS_CALLS 16 + + + /*************************************************************************/ + /* */ + /* T1_MAX_CHARSTRING_OPERANDS is the charstring stack's capacity. A */ + /* minimum of 16 is required. */ + /* */ + /* The Chinese font MingTiEG-Medium (CNS 11643 character set) needs 256. */ + /* */ +#define T1_MAX_CHARSTRINGS_OPERANDS 256 + + + /*************************************************************************/ + /* */ + /* Define this configuration macro if you want to prevent the */ + /* compilation of `t1afm', which is in charge of reading Type 1 AFM */ + /* files into an existing face. Note that if set, the T1 driver will be */ + /* unable to produce kerning distances. */ + /* */ +#undef T1_CONFIG_OPTION_NO_AFM + + + /*************************************************************************/ + /* */ + /* Define this configuration macro if you want to prevent the */ + /* compilation of the Multiple Masters font support in the Type 1 */ + /* driver. */ + /* */ +#undef T1_CONFIG_OPTION_NO_MM_SUPPORT + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** C F F D R I V E R C O N F I G U R A T I O N ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* Using CFF_CONFIG_OPTION_DARKENING_PARAMETER_{X,Y}{1,2,3,4} it is */ + /* possible to set up the default values of the four control points that */ + /* define the stem darkening behaviour of the (new) CFF engine. For */ + /* more details please read the documentation of the */ + /* `darkening-parameters' property of the cff driver module (file */ + /* `ftcffdrv.h'), which allows the control at run-time. */ + /* */ + /* Do *not* undefine these macros! */ + /* */ +#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1 500 +#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1 400 + +#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2 1000 +#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y2 275 + +#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3 1667 +#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y3 275 + +#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4 2333 +#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4 0 + + + /*************************************************************************/ + /* */ + /* CFF_CONFIG_OPTION_OLD_ENGINE controls whether the pre-Adobe CFF */ + /* engine gets compiled into FreeType. If defined, it is possible to */ + /* switch between the two engines using the `hinting-engine' property of */ + /* the cff driver module. */ + /* */ +/* #define CFF_CONFIG_OPTION_OLD_ENGINE */ + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** A U T O F I T M O D U L E C O N F I G U R A T I O N ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* Compile autofit module with CJK (Chinese, Japanese, Korean) script */ + /* support. */ + /* */ +#define AF_CONFIG_OPTION_CJK + + /*************************************************************************/ + /* */ + /* Compile autofit module with Indic script support. */ + /* */ +#define AF_CONFIG_OPTION_INDIC + + /*************************************************************************/ + /* */ + /* Compile autofit module with warp hinting. The idea of the warping */ + /* code is to slightly scale and shift a glyph within a single dimension */ + /* so that as much of its segments are aligned (more or less) on the */ + /* grid. To find out the optimal scaling and shifting value, various */ + /* parameter combinations are tried and scored. */ + /* */ + /* This experimental option is active only if the rendering mode is */ + /* FT_RENDER_MODE_LIGHT; you can switch warping on and off with the */ + /* `warping' property of the auto-hinter (see file `ftautoh.h' for more */ + /* information; by default it is switched off). */ + /* */ +/*#define AF_CONFIG_OPTION_USE_WARPER*/ + + /* */ + + + /* + * This macro is obsolete. Support has been removed in FreeType + * version 2.5. + */ +/* #define FT_CONFIG_OPTION_OLD_INTERNALS */ + + + /* + * This macro is defined if either unpatented or native TrueType + * hinting is requested by the definitions above. + */ +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER +#define TT_USE_BYTECODE_INTERPRETER +#undef TT_CONFIG_OPTION_UNPATENTED_HINTING +#elif defined TT_CONFIG_OPTION_UNPATENTED_HINTING +#define TT_USE_BYTECODE_INTERPRETER +#endif + + + /* + * Check CFF darkening parameters. The checks are the same as in function + * `cff_property_set' in file `cffdrivr.c'. + */ +#if CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1 < 0 || \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2 < 0 || \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3 < 0 || \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4 < 0 || \ + \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1 < 0 || \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y2 < 0 || \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y3 < 0 || \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4 < 0 || \ + \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1 > \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2 || \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2 > \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3 || \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3 > \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4 || \ + \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1 > 500 || \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y2 > 500 || \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y3 > 500 || \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4 > 500 +#error "Invalid CFF darkening parameters!" +#endif + +FT_END_HEADER + + +#endif /* __FTOPTION_H__ */ + + +/* END */ diff --git a/third_party/harfbuzz-ng/BUILD.gn b/third_party/harfbuzz-ng/BUILD.gn index b370348a9fb2e..6e735ab197fac 100644 --- a/third_party/harfbuzz-ng/BUILD.gn +++ b/third_party/harfbuzz-ng/BUILD.gn @@ -2,7 +2,9 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/chrome_build.gni") import("//build/config/linux/pkg_config.gni") +import("//build/config/ui.gni") # The GYP build supports system harfbuzz for non-official builds when using # pangoft2 1.31.0 or greater (which pulls it in). @@ -15,18 +17,15 @@ import("//build/config/linux/pkg_config.gni") declare_args() { # Since version 1.31.0, pangoft2 which we depend on pulls in harfbuzz # anyways. However, we want to have control of the version of harfbuzz - # we use, so don't use system harfbuzz for official builds, unless we - # are building for chrome os, where we have the system harfbuzz under - # control as well. We also do not want to use the system harfbuzz - # when cross-compiling for ARM. - use_system_harfbuzz = is_linux && (is_chromeos || (!is_official_build && - current_cpu != "arm")) && - exec_script(pkg_config_script, - pkg_config_args + [ - "--atleast-version=1.31.0", - "pangoft2", - ], - "value") + # we use, so don't use system harfbuzz unless we are building for + # chrome os, where we have the system harfbuzz under control. + use_system_harfbuzz = + is_linux && is_chromeos && exec_script(pkg_config_script, + pkg_config_args + [ + "--atleast-version=1.31.0", + "pangoft2", + ], + "value") } if (use_system_harfbuzz) { @@ -70,6 +69,8 @@ if (use_system_harfbuzz) { "src/hb-object-private.hh", "src/hb-open-file-private.hh", "src/hb-open-type-private.hh", + "src/hb-ot-font.cc", + "src/hb-ot-font.h", "src/hb-ot-head-table.hh", "src/hb-ot-hhea-table.hh", "src/hb-ot-hmtx-table.hh", @@ -163,5 +164,35 @@ if (use_system_harfbuzz) { ] defines += [ "HAVE_CORETEXT" ] } + + # When without -fvisibility=hidden for pango to use the harfbuzz + # in the tree, all symbols pango needs must be included, or + # pango uses mixed versions of harfbuzz and leads to crash. + # See crbug.com/462689. + if (is_linux && use_pango && !is_chromeos && !is_official_build && + current_cpu != "arm") { + configs -= [ "//build/config/gcc:symbol_visibility_hidden" ] + configs += [ + "//build/config/linux:freetype2", + "//build/config/linux:glib", + ] + sources += [ + "src/hb-ft.cc", + "src/hb-ft.h", + "src/hb-glib.cc", + "src/hb-glib.h", + ] + } + + # See also chrome/browser/ui/libgtk2ui/BUILD.gn which pulls this. + config("pangoft2_link_hack") { + if (is_linux && use_pango && !is_chromeos && !is_official_build && + current_cpu != "arm" && !is_component_build) { + # These symbols are referenced from libpangoft2, which will be + # dynamically linked later. + ldflags = + [ "-Wl,-uhb_ft_face_create_cached,-uhb_glib_get_unicode_funcs" ] + } + } } } diff --git a/third_party/harfbuzz-ng/harfbuzz.gyp b/third_party/harfbuzz-ng/harfbuzz.gyp index 96e4b7c3e23ab..b2f1d914667cf 100644 --- a/third_party/harfbuzz-ng/harfbuzz.gyp +++ b/third_party/harfbuzz-ng/harfbuzz.gyp @@ -7,35 +7,16 @@ '../../build/win_precompile.gypi', ], 'variables': { - 'variables': { - 'conditions': [ - ['sysroot!=""', { - 'pkg-config': '<(chroot_cmd) ../../build/linux/pkg-config-wrapper "<(sysroot)" "<(target_arch)" "<(system_libdir)"', - }, { - 'pkg-config': 'pkg-config' - }], - ], - }, - - 'pkg-config': '<(pkg-config)', - 'conditions': [ - ['OS=="linux" and (buildtype!="Official" or chromeos==1) and embedded==0', { + ['OS=="linux" and chromeos==1', { # Since version 1.31.0, pangoft2 which we depend on pulls in harfbuzz # anyways. However, we want to have control of the version of harfbuzz - # we use, so don't use system harfbuzz for official builds, unless we - # are building for chrome os, where we have the system harfbuzz under - # control as well. + # we use, so don't use system harfbuzz unless we are building for + # chrome os, where we have the system harfbuzz under control. 'use_system_harfbuzz%': 'len = 0; uint32_t status_and = ~0, status_or = 0; double advances_so_far = 0; + /* For right-to-left runs, CoreText returns the glyphs positioned such that + * any trailing whitespace is to the left of (0,0). Adjust coordinate system + * to fix for that. Test with any RTL string with trailing spaces. + * https://code.google.com/p/chromium/issues/detail?id=476913 + */ + if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction)) + { + advances_so_far -= CTLineGetTrailingWhitespaceWidth (line); + if (HB_DIRECTION_IS_VERTICAL (buffer->props.direction)) + advances_so_far = -advances_so_far; + } const CFRange range_all = CFRangeMake (0, 0); diff --git a/third_party/harfbuzz-ng/src/hb-ot-font.cc b/third_party/harfbuzz-ng/src/hb-ot-font.cc index 2af2f54a75932..0e2304e546cc4 100644 --- a/third_party/harfbuzz-ng/src/hb-ot-font.cc +++ b/third_party/harfbuzz-ng/src/hb-ot-font.cc @@ -219,7 +219,7 @@ hb_ot_get_glyph_v_advance (hb_font_t *font HB_UNUSED, void *user_data HB_UNUSED) { const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; - return font->em_scale_y (-ot_font->v_metrics.get_advance (glyph)); + return font->em_scale_y (-(int) ot_font->v_metrics.get_advance (glyph)); } static hb_bool_t diff --git a/third_party/instrumented_libraries/BUILD.gn b/third_party/instrumented_libraries/BUILD.gn new file mode 100644 index 0000000000000..8d113ef091b42 --- /dev/null +++ b/third_party/instrumented_libraries/BUILD.gn @@ -0,0 +1,67 @@ +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/sanitizers/sanitizers.gni") + +prebuilt_available = + is_msan && (msan_track_origins == 0 || msan_track_origins == 2) + +group("deps") { + if (use_prebuilt_instrumented_libraries) { + assert(prebuilt_available, + "Prebuilt instrumented libraries are only available when " + + "is_msan = true and msan_track_origins = {0, 2}") + deps = [ + ":prebuilt", + ] + } +} + +if (prebuilt_available) { + group("prebuilt") { + visibility = [ ":deps" ] + public_configs = [ ":prebuilt_link_helper" ] + deps = [ + ":extract_prebuilt_instrumented_libraries", + ] + } + + if (is_msan) { + sanitizer_type = "msan" + if (msan_track_origins == 0) { + archive_prefix = "msan-no-origins" + } else if (msan_track_origins == 2) { + archive_prefix = "msan-chained-origins" + } + } + + # TODO(GYP): scripts/download_binaries.py uses GYP_DEFINES to decide whether + # to download the archives extracted here. + # Note: This requires a clobber whenever Ubuntu version changes. + action("extract_prebuilt_instrumented_libraries") { + visibility = [ ":prebuilt" ] + script = "scripts/unpack_binaries.py" + depfile = "$target_out_dir/$archive_prefix.d" + args = [ + archive_prefix, + rebase_path("binaries"), + rebase_path(root_build_dir + "/instrumented_libraries_prebuilt"), + rebase_path(target_out_dir, root_build_dir), + ] + outputs = [ + "$target_out_dir/$archive_prefix.txt", + ] + } + + config("prebuilt_link_helper") { + visibility = [ ":prebuilt" ] + ldflags = [ + # Add a relative RPATH entry to Chromium binaries. This puts instrumented + # DSOs before system-installed versions in library search path. + "-Wl,-R,\$ORIGIN/instrumented_libraries_prebuilt/$sanitizer_type/lib", + "-Wl,-z,origin", + ] + } +} +# TODO(GYP): Support building instrumented libraries from source. diff --git a/third_party/instrumented_libraries/OWNERS b/third_party/instrumented_libraries/OWNERS new file mode 100644 index 0000000000000..4ec7dc6d01252 --- /dev/null +++ b/third_party/instrumented_libraries/OWNERS @@ -0,0 +1 @@ +glider@chromium.org diff --git a/third_party/instrumented_libraries/README.chromium b/third_party/instrumented_libraries/README.chromium new file mode 100644 index 0000000000000..222a25c92975e --- /dev/null +++ b/third_party/instrumented_libraries/README.chromium @@ -0,0 +1,14 @@ +Name: instrumented_libbraries +URL: n/a +Version: 0 +Security Critical: no +License: n/a +License File: NOT_SHIPPED + +Description: +Scripts which can download and build several third party libraries +using different instrumentation tools (AddressSanitizer, etc.). + +Flag "use_instrumented_libraries=1" in GYP_DEFINES enables usage of +instrumented libraries and final binary will use them instead of standard +system shared libraries. diff --git a/third_party/instrumented_libraries/binaries/.gitignore b/third_party/instrumented_libraries/binaries/.gitignore new file mode 100644 index 0000000000000..d177d9a553da4 --- /dev/null +++ b/third_party/instrumented_libraries/binaries/.gitignore @@ -0,0 +1,2 @@ +# Ignore downloaded binaries. +*.tgz diff --git a/third_party/instrumented_libraries/binaries/msan-chained-origins-precise.tgz.sha1 b/third_party/instrumented_libraries/binaries/msan-chained-origins-precise.tgz.sha1 new file mode 100644 index 0000000000000..71e2def7573bd --- /dev/null +++ b/third_party/instrumented_libraries/binaries/msan-chained-origins-precise.tgz.sha1 @@ -0,0 +1 @@ +60669b8a67026d92b365c1a2cab756bfe2fdd90f \ No newline at end of file diff --git a/third_party/instrumented_libraries/binaries/msan-chained-origins-trusty.tgz.sha1 b/third_party/instrumented_libraries/binaries/msan-chained-origins-trusty.tgz.sha1 new file mode 100644 index 0000000000000..193be3422debb --- /dev/null +++ b/third_party/instrumented_libraries/binaries/msan-chained-origins-trusty.tgz.sha1 @@ -0,0 +1 @@ +348b21c99365227beb378e6f068984b0f6ea9f9f \ No newline at end of file diff --git a/third_party/instrumented_libraries/binaries/msan-no-origins-precise.tgz.sha1 b/third_party/instrumented_libraries/binaries/msan-no-origins-precise.tgz.sha1 new file mode 100644 index 0000000000000..9f17c0d63636f --- /dev/null +++ b/third_party/instrumented_libraries/binaries/msan-no-origins-precise.tgz.sha1 @@ -0,0 +1 @@ +2a66a901c3b0acd3e5c5cbf49ddfa442f77bb38e \ No newline at end of file diff --git a/third_party/instrumented_libraries/binaries/msan-no-origins-trusty.tgz.sha1 b/third_party/instrumented_libraries/binaries/msan-no-origins-trusty.tgz.sha1 new file mode 100644 index 0000000000000..bbe6657162857 --- /dev/null +++ b/third_party/instrumented_libraries/binaries/msan-no-origins-trusty.tgz.sha1 @@ -0,0 +1 @@ +098097aa3f25d94b73014c9249a41bfe37f3242b \ No newline at end of file diff --git a/third_party/instrumented_libraries/blacklists/asan/libglib2.0-0.txt b/third_party/instrumented_libraries/blacklists/asan/libglib2.0-0.txt new file mode 100644 index 0000000000000..898956889373f --- /dev/null +++ b/third_party/instrumented_libraries/blacklists/asan/libglib2.0-0.txt @@ -0,0 +1,2 @@ +# http://crbug.com/367509 +fun:g_utf8_to_ucs4_fast diff --git a/third_party/instrumented_libraries/blacklists/msan/libglib2.0-0.txt b/third_party/instrumented_libraries/blacklists/msan/libglib2.0-0.txt new file mode 100644 index 0000000000000..45c66832ee95c --- /dev/null +++ b/third_party/instrumented_libraries/blacklists/msan/libglib2.0-0.txt @@ -0,0 +1,2 @@ +# MSan needs an interceptor for wcsxfrm(). http://crbug.com/423410 +fun:g_utf8_collate_key diff --git a/third_party/instrumented_libraries/blacklists/msan/libx11-6.txt b/third_party/instrumented_libraries/blacklists/msan/libx11-6.txt new file mode 100644 index 0000000000000..a72a39d1a44d9 --- /dev/null +++ b/third_party/instrumented_libraries/blacklists/msan/libx11-6.txt @@ -0,0 +1,2 @@ +# https://bugs.freedesktop.org/show_bug.cgi?id=81236 +fun:XIconifyWindow diff --git a/third_party/instrumented_libraries/instrumented_libraries.gyp b/third_party/instrumented_libraries/instrumented_libraries.gyp new file mode 100644 index 0000000000000..307aed194091c --- /dev/null +++ b/third_party/instrumented_libraries/instrumented_libraries.gyp @@ -0,0 +1,860 @@ +# Copyright 2013 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'variables': { + 'verbose_libraries_build%': 0, + 'instrumented_libraries_jobs%': 1, + 'instrumented_libraries_cc%': 'num = 0; + p->size = 0; diff --git a/third_party/instrumented_libraries/patches/libfontconfig.trusty.diff b/third_party/instrumented_libraries/patches/libfontconfig.trusty.diff new file mode 100644 index 0000000000000..7cfeba5e700f0 --- /dev/null +++ b/third_party/instrumented_libraries/patches/libfontconfig.trusty.diff @@ -0,0 +1,13 @@ +diff -rupN ./src/fcpat.c ../fontconfig-2.11.0-patched/src/fcpat.c +--- ./src/fcpat.c 2013-10-11 07:10:18.000000000 +0400 ++++ ../fontconfig-2.11.0-patched/src/fcpat.c 2014-09-30 22:14:55.818360071 +0400 +@@ -33,6 +33,9 @@ FcPatternCreate (void) + p = (FcPattern *) malloc (sizeof (FcPattern)); + if (!p) + return 0; ++ // Silence Valgrind/MemorySanitizer. There is uninitialized padding at the ++ // end of this structure. When serialized to file, this will cause a report. ++ memset(p, 0, sizeof(*p)); + p->num = 0; + p->size = 0; + p->elts_offset = FcPtrToOffset (p, NULL); diff --git a/third_party/instrumented_libraries/patches/libgtk2.0-0.precise.diff b/third_party/instrumented_libraries/patches/libgtk2.0-0.precise.diff new file mode 100644 index 0000000000000..75f4f64206594 --- /dev/null +++ b/third_party/instrumented_libraries/patches/libgtk2.0-0.precise.diff @@ -0,0 +1,28 @@ +diff -rupN ./gtk/gtkmain.c ../gtk+2.0-2.24.10-patched/gtk/gtkmain.c +--- ./gtk/gtkmain.c 2014-05-29 19:39:07.000000000 +0400 ++++ ../gtk+2.0-2.24.10-patched/gtk/gtkmain.c 2015-02-09 21:52:59.213636172 +0300 +@@ -751,6 +751,10 @@ _overlay_scrollbar_init (void) + GModule *module = NULL; + gpointer symbol = NULL; + ++ /* Chrome doesn't use overlay-scrollbar anyway. By disabling it here, we avoid ++ * having to build it. */ ++ return; ++ + gchar *flag = (gchar*) g_getenv ("LIBOVERLAY_SCROLLBAR"); + + /* check if LIBOVERLAY_SCROLLBAR is set to 0 or an empty value +diff -rupN ./gtk/gtkmenushell.h ../gtk+2.0-2.24.10-patched/gtk/gtkmenushell.h +--- ./gtk/gtkmenushell.h 2011-08-16 06:30:52.000000000 +0400 ++++ ../gtk+2.0-2.24.10-patched/gtk/gtkmenushell.h 2015-02-09 21:49:49.052032041 +0300 +@@ -135,7 +135,9 @@ void _gtk_menu_shell_update_mnemonic + void _gtk_menu_shell_set_keyboard_mode (GtkMenuShell *menu_shell, + gboolean keyboard_mode); + gboolean _gtk_menu_shell_get_keyboard_mode (GtkMenuShell *menu_shell); +- ++// https://bugs.launchpad.net/bugs/945135 ++gboolean ubuntu_gtk_menu_shell_activate_mnemonic (GtkMenuShell *shell, GtkWidget *item); ++gboolean ubuntu_gtk_menu_shell_activate_first (GtkMenuShell *menu_shell, gboolean search_sensitive); + G_END_DECLS + + #endif /* __GTK_MENU_SHELL_H__ */ diff --git a/third_party/instrumented_libraries/patches/libgtk2.0-0.trusty.diff b/third_party/instrumented_libraries/patches/libgtk2.0-0.trusty.diff new file mode 100644 index 0000000000000..2a8295b8b18ab --- /dev/null +++ b/third_party/instrumented_libraries/patches/libgtk2.0-0.trusty.diff @@ -0,0 +1,15 @@ +diff -rupN ./gtk/gtkmenushell.h ../gtk+2.0-2.24.23-patched/gtk/gtkmenushell.h +--- ./gtk/gtkmenushell.h 2014-03-06 08:56:42.000000000 +0400 ++++ ../gtk+2.0-2.24.23-patched/gtk/gtkmenushell.h 2014-09-30 23:37:46.908364552 +0400 +@@ -136,6 +136,11 @@ void _gtk_menu_shell_set_keyboard_mo + gboolean keyboard_mode); + gboolean _gtk_menu_shell_get_keyboard_mode (GtkMenuShell *menu_shell); + ++// https://bugs.launchpad.net/bugs/945135 ++gboolean ubuntu_gtk_menu_shell_activate_mnemonic (GtkMenuShell *shell, ++ GtkWidget *item); ++gboolean ubuntu_gtk_menu_shell_activate_first (GtkMenuShell *menu_shell, ++ gboolean search_sensitive); + G_END_DECLS + + #endif /* __GTK_MENU_SHELL_H__ */ diff --git a/third_party/instrumented_libraries/patches/libpixman-1-0.diff b/third_party/instrumented_libraries/patches/libpixman-1-0.diff new file mode 100644 index 0000000000000..a5599a4a42168 --- /dev/null +++ b/third_party/instrumented_libraries/patches/libpixman-1-0.diff @@ -0,0 +1,23 @@ +--- pixman-0.30.2/configure.ac.orig 2014-08-19 15:53:39.376032738 +0400 ++++ pixman-0.30.2/configure.ac 2014-08-19 15:53:55.264181469 +0400 +@@ -844,12 +844,13 @@ if test x$have_gettimeofday = xyes && te + AC_DEFINE(HAVE_GETTIMEOFDAY, 1, [Whether we have gettimeofday()]) + fi + +-dnl ===================================== +-dnl Check for missing sqrtf() as, e.g., for Solaris 9 +- +-AC_SEARCH_LIBS([sqrtf], [m], [], +- [AC_DEFINE([sqrtf], [sqrt], +- [Define to sqrt if you do not have the `sqrtf' function.])]) ++# Not needed for Clang Linux builds. Fixes http://crbug.com/404526. ++#dnl ===================================== ++#dnl Check for missing sqrtf() as, e.g., for Solaris 9 ++# ++#AC_SEARCH_LIBS([sqrtf], [m], [], ++# [AC_DEFINE([sqrtf], [sqrt], ++# [Define to sqrt if you do not have the `sqrtf' function.])]) + + dnl ===================================== + dnl Thread local storage + diff --git a/third_party/instrumented_libraries/patches/libva1.diff b/third_party/instrumented_libraries/patches/libva1.diff new file mode 100644 index 0000000000000..2e4ca7358eddf --- /dev/null +++ b/third_party/instrumented_libraries/patches/libva1.diff @@ -0,0 +1,22 @@ +diff --git a/va/va.c b/va/va.c +index 6cb17ef..0ba595b 100644 +--- a/va/va.c ++++ b/va/va.c +@@ -515,15 +515,15 @@ VAStatus vaTerminate ( + free(old_ctx->vtable_vpp); + old_ctx->vtable_vpp = NULL; + +- if (VA_STATUS_SUCCESS == vaStatus) +- pDisplayContext->vaDestroy(pDisplayContext); +- + VA_TRACE_LOG(va_TraceTerminate, dpy); + + va_TraceEnd(dpy); + + va_FoolEnd(dpy); + ++ if (VA_STATUS_SUCCESS == vaStatus) ++ pDisplayContext->vaDestroy(pDisplayContext); ++ + return vaStatus; + } diff --git a/third_party/instrumented_libraries/patches/libxcb1.precise.diff b/third_party/instrumented_libraries/patches/libxcb1.precise.diff new file mode 100644 index 0000000000000..aeb486ebf6a99 --- /dev/null +++ b/third_party/instrumented_libraries/patches/libxcb1.precise.diff @@ -0,0 +1,26 @@ +diff -rupN ./src/xcb_conn.c ../libxcb-1.8.1-patched/src/xcb_conn.c +--- ./src/xcb_conn.c 2012-01-11 21:05:41.000000000 +0400 ++++ ../libxcb-1.8.1-patched/src/xcb_conn.c 2014-12-10 23:37:44.432834622 +0300 +@@ -418,10 +418,20 @@ int _xcb_conn_wait(xcb_connection_t *c, + + if(ret) + { ++ /* The code allows two threads to call select()/poll() at the same time. ++ * First thread just wants to read, a second thread wants to write, too. ++ * We have to make sure that we don't steal the reading thread's reply ++ * and let it get stuck in select()/poll(). ++ * So a thread may read if either: ++ * - There is no other thread that wants to read (the above situation ++ * did not occur). ++ * - It is the reading thread (above situation occurred). ++ */ ++ int may_read = c->in.reading == 1 || !count; + #if USE_POLL +- if((fd.revents & POLLIN) == POLLIN) ++ if(may_read && (fd.revents & POLLIN) == POLLIN) + #else +- if(FD_ISSET(c->fd, &rfds)) ++ if(may_read && FD_ISSET(c->fd, &rfds)) + #endif + ret = ret && _xcb_in_read(c); + diff --git a/third_party/instrumented_libraries/patches/nss.diff b/third_party/instrumented_libraries/patches/nss.diff new file mode 100644 index 0000000000000..1275e5afb7977 --- /dev/null +++ b/third_party/instrumented_libraries/patches/nss.diff @@ -0,0 +1,30 @@ +diff -rupN ./nss/lib/freebl/Makefile ../nss-3.17.1-patched/nss/lib/freebl/Makefile +--- ./nss/lib/freebl/Makefile 2014-09-23 23:09:22.000000000 +0400 ++++ ../nss-3.17.1-patched/nss/lib/freebl/Makefile 2014-09-26 20:36:05.639317008 +0400 +@@ -196,18 +196,20 @@ endif # Darwin + + ifeq ($(OS_TARGET),Linux) + ifeq ($(CPU_ARCH),x86_64) +- ASFILES = arcfour-amd64-gas.s mpi_amd64_gas.s ++# Disable inline asm in instrumented builds. ++# ASFILES = arcfour-amd64-gas.s mpi_amd64_gas.s + ASFLAGS += -fPIC -Wa,--noexecstack +- DEFINES += -DNSS_BEVAND_ARCFOUR -DMPI_AMD64 -DMP_ASSEMBLY_MULTIPLY +- DEFINES += -DNSS_USE_COMBA ++# DEFINES += -DNSS_BEVAND_ARCFOUR -DMPI_AMD64 -DMP_ASSEMBLY_MULTIPLY ++# DEFINES += -DNSS_USE_COMBA + DEFINES += -DMP_CHAR_STORE_SLOW -DMP_IS_LITTLE_ENDIAN + # DEFINES += -DMPI_AMD64_ADD + # comment the next four lines to turn off Intel HW acceleration. +- DEFINES += -DUSE_HW_AES -DINTEL_GCM +- ASFILES += intel-aes.s intel-gcm.s ++# DEFINES += -DUSE_HW_AES -DINTEL_GCM ++# ASFILES += intel-aes.s intel-gcm.s ++# This is just intrinsics and should be fine. + EXTRA_SRCS += intel-gcm-wrap.c + INTEL_GCM = 1 +- MPI_SRCS += mpi_amd64.c mp_comba.c ++# MPI_SRCS += mpi_amd64.c mp_comba.c + endif + ifeq ($(CPU_ARCH),x86) + ASFILES = mpi_x86.s diff --git a/third_party/instrumented_libraries/patches/pulseaudio.precise.diff b/third_party/instrumented_libraries/patches/pulseaudio.precise.diff new file mode 100644 index 0000000000000..fc2ca0d297c78 --- /dev/null +++ b/third_party/instrumented_libraries/patches/pulseaudio.precise.diff @@ -0,0 +1,16 @@ +diff -rupN ./src/modules/bluetooth/sbc/sbc_primitives_mmx.h ../pulseaudio-1.1-patched/src/modules/bluetooth/sbc/sbc_primitives_mmx.h +--- ./src/modules/bluetooth/sbc/sbc_primitives_mmx.h 2011-10-20 16:54:16.000000000 +0400 ++++ ../pulseaudio-1.1-patched/src/modules/bluetooth/sbc/sbc_primitives_mmx.h 2014-01-30 16:57:43.113946495 +0400 +@@ -29,8 +29,11 @@ + + #include "sbc_primitives.h" + ++// The inline asm causes errors in clang builds. We don't want inline asm in ++// instrumented builds anyway. + #if defined(__GNUC__) && (defined(__i386__) || defined(__amd64__)) && \ +- !defined(SBC_HIGH_PRECISION) && (SCALE_OUT_BITS == 15) ++ !defined(SBC_HIGH_PRECISION) && (SCALE_OUT_BITS == 15) && \ ++ !defined(__clang__) + + #define SBC_BUILD_WITH_MMX_SUPPORT + diff --git a/third_party/instrumented_libraries/patches/zlib1g.diff b/third_party/instrumented_libraries/patches/zlib1g.diff new file mode 100644 index 0000000000000..18a6a3319b0f4 --- /dev/null +++ b/third_party/instrumented_libraries/patches/zlib1g.diff @@ -0,0 +1,12 @@ +diff -rupN ./configure ../zlib-1.2.3.4.dfsg-patched/configure +--- ./configure 2009-12-24 18:09:43.000000000 +0300 ++++ ../zlib-1.2.3.4.dfsg-patched/configure 2014-06-03 17:53:45.082074669 +0400 +@@ -72,6 +72,8 @@ cflags=${CFLAGS-"-O3"} + # to force the asm version use: CFLAGS="-O3 -DASMV" ./configure + case "$cc" in + *gcc*) gcc=1 ;; ++ # Use the version script for clang builds as well. ++ *clang*) gcc=1 ;; + esac + + if test "$gcc" -eq 1 && ($cc -c $cflags $test.c) 2>/dev/null; then diff --git a/third_party/instrumented_libraries/scripts/build_and_package.sh b/third_party/instrumented_libraries/scripts/build_and_package.sh new file mode 100755 index 0000000000000..0de0c914dfebf --- /dev/null +++ b/third_party/instrumented_libraries/scripts/build_and_package.sh @@ -0,0 +1,87 @@ +#!/bin/bash +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +set -eu + +supported_build_types="msan-no-origins msan-chained-origins" +supported_releases="precise trusty" +ubuntu_release=$(lsb_release -cs) + +function show_help { + echo "Usage: build_and_package.sh " + echo "Supported build types: all ${supported_build_types}" +} + +function build_libraries { + local build_type=$1 + case ${build_type} in + "msan-chained-origins") + local gyp_defines="msan=1 msan_track_origins=2" + ;; + "msan-no-origins") + local gyp_defines="msan=1 msan_track_origins=0" + ;; + *) + show_help + exit 1 + ;; + esac + + local archive_name=${build_type}-${ubuntu_release} + local out_dir=out-${archive_name} + + echo "Building instrumented libraries in ${out_dir}..." + + rm -rf $out_dir + mkdir $out_dir + + GYP_DEFINES="${gyp_defines} \ + use_instrumented_libraries=1 instrumented_libraries_jobs=8" \ + GYP_GENERATOR_FLAGS="output_dir=${out_dir}" \ + gclient runhooks + + ninja -j4 -C ${out_dir}/Release instrumented_libraries + + echo "Creating archive ${archive_name}.tgz..." + + files=$(ls -1 ${out_dir}/Release/instrumented_libraries) + + tar zcf ${archive_name}.tgz -C ${out_dir}/Release/instrumented_libraries \ + --exclude="?san/*.txt" ${files} + + echo To upload, run: + echo upload_to_google_storage.py -b \ + chromium-instrumented-libraries ${archive_name}.tgz + echo You should then commit the resulting .sha1 file. +} + +if ! [[ "${supported_releases}" =~ ${ubuntu_release} ]] +then + echo "Unsupported Ubuntu release: ${ubuntu_release}" + echo "Supported releases: ${supported_releases}" + exit 1 +fi + +if [ -z "${1-}" ] +then + show_help + exit 0 +fi + +if ! [[ "all ${supported_build_types}" =~ $1 ]] +then + show_help + exit 1 +fi +if [ "$1" == "all" ] +then + for build_type in ${supported_build_types} + do + build_libraries ${build_type} + done +else + build_libraries $1 +fi + diff --git a/third_party/instrumented_libraries/scripts/download_binaries.py b/third_party/instrumented_libraries/scripts/download_binaries.py new file mode 100755 index 0000000000000..83ec7b6aa86ab --- /dev/null +++ b/third_party/instrumented_libraries/scripts/download_binaries.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python +# Copyright (c) 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Downloads pre-built sanitizer-instrumented third-party libraries from GCS.""" + +import os +import re +import subprocess +import sys + +def get_ubuntu_release(): + supported_releases = ['precise', 'trusty'] + release = subprocess.check_output(['lsb_release', '-cs']).strip() + if release not in supported_releases: + raise Exception("Supported Ubuntu versions: %s", str(supported_releases)) + return release + + +def get_configuration(gyp_defines): + if re.search(r'\b(msan)=1', gyp_defines): + if 'msan_track_origins=0' in gyp_defines: + return 'msan-no-origins' + if 'msan_track_origins=2' in gyp_defines: + return 'msan-chained-origins' + if 'msan_track_origins=' not in gyp_defines: + # NB: must be the same as the default value in common.gypi + return 'msan-chained-origins' + raise Exception( + "Prebuilt instrumented libraries not available for your configuration.") + + +def get_archive_name(gyp_defines): + return "%s-%s.tgz" % (get_configuration(gyp_defines), get_ubuntu_release()) + + +def main(args): + gyp_defines = os.environ.get('GYP_DEFINES', '') + if not 'use_prebuilt_instrumented_libraries=1' in gyp_defines: + return 0 + + if not sys.platform.startswith('linux'): + raise Exception("'use_prebuilt_instrumented_libraries=1' requires Linux.") + + archive_name = get_archive_name(gyp_defines) + sha1file = '%s.sha1' % archive_name + target_directory = 'src/third_party/instrumented_libraries/binaries/' + + subprocess.check_call([ + 'download_from_google_storage', + '--no_resume', + '--no_auth', + '--bucket', 'chromium-instrumented-libraries', + '-s', sha1file], cwd=target_directory) + + return 0 + + +if __name__ == '__main__': + sys.exit(main(sys.argv[1:])) diff --git a/third_party/instrumented_libraries/scripts/download_build_install.py b/third_party/instrumented_libraries/scripts/download_build_install.py new file mode 100755 index 0000000000000..56c4014914d1c --- /dev/null +++ b/third_party/instrumented_libraries/scripts/download_build_install.py @@ -0,0 +1,436 @@ +#!/usr/bin/python +# Copyright 2013 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Downloads, builds (with instrumentation) and installs shared libraries.""" + +import argparse +import os +import platform +import re +import shlex +import shutil +import subprocess +import sys + +SCRIPT_ABSOLUTE_PATH = os.path.dirname(os.path.abspath(__file__)) + +def unescape_flags(s): + """Un-escapes build flags received from GYP. + + GYP escapes build flags as if they are to be inserted directly into a command + line, wrapping each flag in double quotes. When flags are passed via + CFLAGS/LDFLAGS instead, double quotes must be dropped. + """ + return ' '.join(shlex.split(s)) + + +def real_path(path_relative_to_gyp): + """Returns the absolute path to a file. + + GYP generates paths relative to the location of the .gyp file, which is one + level above the location of this script. This function converts them to + absolute paths. + """ + return os.path.realpath(os.path.join(SCRIPT_ABSOLUTE_PATH, '..', + path_relative_to_gyp)) + + +class InstrumentedPackageBuilder(object): + """Checks out and builds a single instrumented package.""" + def __init__(self, args, clobber): + self._cc = args.cc + self._cxx = args.cxx + self._extra_configure_flags = args.extra_configure_flags + self._jobs = args.jobs + self._libdir = args.libdir + self._package = args.package + self._patch = real_path(args.patch) if args.patch else None + self._pre_build = \ + real_path(args.pre_build) if args.pre_build else None + self._sanitizer = args.sanitizer + self._verbose = args.verbose + self._clobber = clobber + self._working_dir = os.path.join( + real_path(args.intermediate_dir), self._package, '') + + product_dir = real_path(args.product_dir) + self._destdir = os.path.join( + product_dir, 'instrumented_libraries', self._sanitizer) + self._source_archives_dir = os.path.join( + product_dir, 'instrumented_libraries', 'sources', self._package) + + self._cflags = unescape_flags(args.cflags) + if args.sanitizer_blacklist: + blacklist_file = real_path(args.sanitizer_blacklist) + self._cflags += ' -fsanitize-blacklist=%s' % blacklist_file + + self._ldflags = unescape_flags(args.ldflags) + + self.init_build_env() + + # Initialized later. + self._source_dir = None + self._source_archives = None + + def init_build_env(self): + self._build_env = os.environ.copy() + + self._build_env['CC'] = self._cc + self._build_env['CXX'] = self._cxx + + self._build_env['CFLAGS'] = self._cflags + self._build_env['CXXFLAGS'] = self._cflags + self._build_env['LDFLAGS'] = self._ldflags + + if self._sanitizer == 'asan': + # Do not report leaks during the build process. + self._build_env['ASAN_OPTIONS'] = \ + '%s:detect_leaks=0' % self._build_env.get('ASAN_OPTIONS', '') + + # libappindicator1 needs this. + self._build_env['CSC'] = '/usr/bin/mono-csc' + + def shell_call(self, command, env=None, cwd=None): + """Wrapper around subprocess.Popen(). + + Calls command with specific environment and verbosity using + subprocess.Popen(). + """ + child = subprocess.Popen( + command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, + env=env, shell=True, cwd=cwd) + stdout, stderr = child.communicate() + if self._verbose or child.returncode: + print stdout + if child.returncode: + raise Exception('Failed to run: %s' % command) + + def maybe_download_source(self): + """Checks out the source code (if needed). + + Checks out the source code for the package, if required (i.e. unless running + in no-clobber mode). Initializes self._source_dir and self._source_archives. + """ + get_fresh_source = self._clobber or not os.path.exists(self._working_dir) + if get_fresh_source: + self.shell_call('rm -rf %s' % self._working_dir) + os.makedirs(self._working_dir) + self.shell_call('apt-get source %s' % self._package, + cwd=self._working_dir) + + (dirpath, dirnames, filenames) = os.walk(self._working_dir).next() + + if len(dirnames) != 1: + raise Exception( + '`apt-get source %s\' must create exactly one subdirectory.' + % self._package) + self._source_dir = os.path.join(dirpath, dirnames[0], '') + + if len(filenames) == 0: + raise Exception('Can\'t find source archives after `apt-get source %s\'.' + % self._package) + self._source_archives = \ + [os.path.join(dirpath, filename) for filename in filenames] + + return get_fresh_source + + def patch_source(self): + if self._patch: + self.shell_call('patch -p1 -i %s' % self._patch, cwd=self._source_dir) + if self._pre_build: + self.shell_call(self._pre_build, cwd=self._source_dir) + + def copy_source_archives(self): + """Copies the downloaded source archives to the output dir. + + For license compliance purposes, every Chromium build that includes + instrumented libraries must include their full source code. + """ + self.shell_call('rm -rf %s' % self._source_archives_dir) + os.makedirs(self._source_archives_dir) + for filename in self._source_archives: + shutil.copy(filename, self._source_archives_dir) + if self._patch: + shutil.copy(self._patch, self._source_archives_dir) + + def download_build_install(self): + got_fresh_source = self.maybe_download_source() + if got_fresh_source: + self.patch_source() + self.copy_source_archives() + + self.shell_call('mkdir -p %s' % self.dest_libdir()) + + try: + self.build_and_install() + except Exception as exception: + print 'ERROR: Failed to build package %s. Have you run ' \ + 'src/third_party/instrumented_libraries/scripts/' \ + 'install-build-deps.sh?' % \ + self._package + print + raise + + # Touch a text file to indicate package is installed. + stamp_file = os.path.join(self._destdir, '%s.txt' % self._package) + open(stamp_file, 'w').close() + + # Remove downloaded package and generated temporary build files. Failed + # builds intentionally skip this step to help debug build failures. + if self._clobber: + self.shell_call('rm -rf %s' % self._working_dir) + + def fix_rpaths(self, directory): + # TODO(earthdok): reimplement fix_rpaths.sh in Python. + script = real_path('scripts/fix_rpaths.sh') + self.shell_call("%s %s" % (script, directory)) + + def temp_dir(self): + """Returns the directory which will be passed to `make install'.""" + return os.path.join(self._source_dir, 'debian', 'instrumented_build') + + def temp_libdir(self): + """Returns the directory under temp_dir() containing the DSOs.""" + return os.path.join(self.temp_dir(), self._libdir) + + def dest_libdir(self): + """Returns the final location of the DSOs.""" + return os.path.join(self._destdir, self._libdir) + + def cleanup_after_install(self): + """Removes unneeded files in self.temp_libdir().""" + # .la files are not needed, nuke them. + # In case --no-static is not supported, nuke any static libraries we built. + self.shell_call( + 'find %s -name *.la -or -name *.a | xargs rm -f' % self.temp_libdir()) + # .pc files are not needed. + self.shell_call('rm %s/pkgconfig -rf' % self.temp_libdir()) + + def make(self, args, jobs=None, env=None, cwd=None): + """Invokes `make'. + + Invokes `make' with the specified args, using self._build_env and + self._source_dir by default. + """ + if jobs is None: + jobs = self._jobs + if cwd is None: + cwd = self._source_dir + if env is None: + env = self._build_env + cmd = ['make', '-j%s' % jobs] + args + self.shell_call(' '.join(cmd), env=env, cwd=cwd) + + def make_install(self, args, **kwargs): + """Invokes `make install'.""" + self.make(['install'] + args, **kwargs) + + def build_and_install(self): + """Builds and installs the DSOs. + + Builds the package with ./configure + make, installs it to a temporary + location, then moves the relevant files to their permanent location. + """ + configure_cmd = './configure --libdir=/%s/ %s' % ( + self._libdir, self._extra_configure_flags) + self.shell_call(configure_cmd, env=self._build_env, cwd=self._source_dir) + + # Some makefiles use BUILDROOT or INSTALL_ROOT instead of DESTDIR. + args = ['DESTDIR', 'BUILDROOT', 'INSTALL_ROOT'] + make_args = ['%s=%s' % (name, self.temp_dir()) for name in args] + self.make(make_args) + + # Some packages don't support parallel install. Use -j1 always. + self.make_install(make_args, jobs=1) + + self.cleanup_after_install() + + self.fix_rpaths(self.temp_libdir()) + + # Now move the contents of the temporary destdir to their final place. + # We only care for the contents of LIBDIR. + self.shell_call('cp %s/* %s/ -rdf' % (self.temp_libdir(), + self.dest_libdir())) + + +class LibcapBuilder(InstrumentedPackageBuilder): + def build_and_install(self): + # libcap2 doesn't have a configure script + build_args = ['CC', 'CXX', 'CFLAGS', 'CXXFLAGS', 'LDFLAGS'] + make_args = [ + '%s="%s"' % (name, self._build_env[name]) for name in build_args + ] + self.make(make_args) + + install_args = [ + 'DESTDIR=%s' % self.temp_dir(), + 'lib=%s' % self._libdir, + # Skip a step that requires sudo. + 'RAISE_SETFCAP=no' + ] + self.make_install(install_args) + + self.cleanup_after_install() + + self.fix_rpaths(self.temp_libdir()) + + # Now move the contents of the temporary destdir to their final place. + # We only care for the contents of LIBDIR. + self.shell_call('cp %s/* %s/ -rdf' % (self.temp_libdir(), + self.dest_libdir())) + + +class Libpci3Builder(InstrumentedPackageBuilder): + def package_version(self): + """Guesses libpci3 version from source directory name.""" + dir_name = os.path.split(os.path.normpath(self._source_dir))[-1] + match = re.match('pciutils-(\d+\.\d+\.\d+)', dir_name) + if match is None: + raise Exception( + 'Unable to guess libpci3 version from directory name: %s' % dir_name) + return match.group(1) + + def temp_libdir(self): + # DSOs have to be picked up from /lib, since `make install' + # doesn't actualy install them anywhere. + return os.path.join(self._source_dir, 'lib') + + def build_and_install(self): + # pciutils doesn't have a configure script + # This build process follows debian/rules. + self.shell_call('mkdir -p %s-udeb/usr/bin' % self.temp_dir()) + + build_args = ['CC', 'CXX', 'CFLAGS', 'CXXFLAGS', 'LDFLAGS'] + make_args = [ + '%s="%s"' % (name, self._build_env[name]) for name in build_args + ] + make_args += [ + 'LIBDIR=/%s/' % self._libdir, + 'PREFIX=/usr', + 'SBINDIR=/usr/bin', + 'IDSDIR=/usr/share/misc', + 'SHARED=yes', + # pciutils-3.2.1 (Trusty) fails to build due to unresolved libkmod + # symbols. The binary package has no dependencies on libkmod, so it + # looks like it was actually built without libkmod support. + 'LIBKMOD=no', + ] + self.make(make_args) + + # `make install' is not needed. + self.fix_rpaths(self.temp_libdir()) + + # Now install the DSOs to their final place. + self.shell_call( + 'install -m 644 %s/libpci.so* %s' % (self.temp_libdir(), + self.dest_libdir())) + self.shell_call( + 'ln -sf libpci.so.%s %s/libpci.so.3' % (self.package_version(), + self.dest_libdir())) + + +class NSSBuilder(InstrumentedPackageBuilder): + def build_and_install(self): + # NSS uses a build system that's different from configure/make/install. All + # flags must be passed as arguments to make. + make_args = [ + # Do an optimized build. + 'BUILD_OPT=1', + # CFLAGS/CXXFLAGS should not be used, as doing so overrides the flags in + # the makefile completely. The only way to append our flags is to tack + # them onto CC/CXX. + 'CC="%s %s"' % (self._build_env['CC'], self._build_env['CFLAGS']), + 'CXX="%s %s"' % (self._build_env['CXX'], self._build_env['CXXFLAGS']), + # We need to override ZDEFS_FLAG at least to avoid -Wl,-z,defs, which + # is not compatible with sanitizers. We also need some way to pass + # LDFLAGS without overriding the defaults. Conveniently, ZDEF_FLAG is + # always appended to link flags when building NSS on Linux, so we can + # just add our LDFLAGS here. + 'ZDEFS_FLAG="-Wl,-z,nodefs %s"' % self._build_env['LDFLAGS'], + 'NSPR_INCLUDE_DIR=/usr/include/nspr', + 'NSPR_LIB_DIR=%s' % self.dest_libdir(), + 'NSS_ENABLE_ECC=1' + ] + if platform.architecture()[0] == '64bit': + make_args.append('USE_64=1') + + # Make sure we don't override the default flags in the makefile. + for variable in ['CFLAGS', 'CXXFLAGS', 'LDFLAGS']: + del self._build_env[variable] + + # Hardcoded paths. + temp_dir = os.path.join(self._source_dir, 'nss') + temp_libdir = os.path.join(temp_dir, 'lib') + + # Parallel build is not supported. Also, the build happens in + # /nss. + self.make(make_args, jobs=1, cwd=temp_dir) + + self.fix_rpaths(temp_libdir) + + # 'make install' is not supported. Copy the DSOs manually. + for (dirpath, dirnames, filenames) in os.walk(temp_libdir): + for filename in filenames: + if filename.endswith('.so'): + full_path = os.path.join(dirpath, filename) + if self._verbose: + print 'download_build_install.py: installing %s' % full_path + shutil.copy(full_path, self.dest_libdir()) + + +def main(): + parser = argparse.ArgumentParser( + description='Download, build and install an instrumented package.') + + parser.add_argument('-j', '--jobs', type=int, default=1) + parser.add_argument('-p', '--package', required=True) + parser.add_argument( + '-i', '--product-dir', default='.', + help='Relative path to the directory with chrome binaries') + parser.add_argument( + '-m', '--intermediate-dir', default='.', + help='Relative path to the directory for temporary build files') + parser.add_argument('--extra-configure-flags', default='') + parser.add_argument('--cflags', default='') + parser.add_argument('--ldflags', default='') + parser.add_argument('-s', '--sanitizer', required=True, + choices=['asan', 'msan', 'tsan']) + parser.add_argument('-v', '--verbose', action='store_true') + parser.add_argument('--cc') + parser.add_argument('--cxx') + parser.add_argument('--patch', default='') + # This should be a shell script to run before building specific libraries. + # This will be run after applying the patch above. + parser.add_argument('--pre-build', default='') + parser.add_argument('--build-method', default='destdir') + parser.add_argument('--sanitizer-blacklist', default='') + # The LIBDIR argument to configure/make. + parser.add_argument('--libdir', default='lib') + + # Ignore all empty arguments because in several cases gyp passes them to the + # script, but ArgumentParser treats them as positional arguments instead of + # ignoring (and doesn't have such options). + args = parser.parse_args([arg for arg in sys.argv[1:] if len(arg) != 0]) + + # Clobber by default, unless the developer wants to hack on the package's + # source code. + clobber = \ + (os.environ.get('INSTRUMENTED_LIBRARIES_NO_CLOBBER', '') != '1') + + if args.build_method == 'destdir': + builder = InstrumentedPackageBuilder(args, clobber) + elif args.build_method == 'custom_nss': + builder = NSSBuilder(args, clobber) + elif args.build_method == 'custom_libcap': + builder = LibcapBuilder(args, clobber) + elif args.build_method == 'custom_libpci3': + builder = Libpci3Builder(args, clobber) + else: + raise Exception('Unrecognized build method: %s' % args.build_method) + + builder.download_build_install() + +if __name__ == '__main__': + main() diff --git a/third_party/instrumented_libraries/scripts/fix_rpaths.sh b/third_party/instrumented_libraries/scripts/fix_rpaths.sh new file mode 100755 index 0000000000000..578243f430138 --- /dev/null +++ b/third_party/instrumented_libraries/scripts/fix_rpaths.sh @@ -0,0 +1,30 @@ +#!/bin/bash +# Copyright 2013 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Changes all RPATHs in a given directory from XORIGIN to $ORIGIN +# See the comment about XORIGIN in instrumented_libraries.gyp + +# Fixes rpath from XORIGIN to $ORIGIN in a single file $1. +function fix_rpath { + if [ -w "$1" ] + then + # Only attempt to fix RPATH if the entry actually exists. + # FIXME(earthdok): find out why zlib1g on Precise doesn't get RPATH set. + if chrpath -l $1 + then + echo "fix_rpaths.sh: fixing $1" + chrpath -r $(chrpath $1 | cut -d " " -f 2 | sed s/XORIGIN/\$ORIGIN/g \ + | sed s/RPATH=//g) $1 + fi + else + # FIXME(earthdok): libcups2 DSOs are created non-writable, causing this + # script to fail. As a temporary measure, ignore non-writable files. + echo "fix_rpaths.sh: skipping non-writable file $1" + fi +} + +for i in $(find $1 | grep -P "\.so(.\d+)*$"); do + fix_rpath $i +done diff --git a/third_party/instrumented_libraries/scripts/install-build-deps.sh b/third_party/instrumented_libraries/scripts/install-build-deps.sh new file mode 100755 index 0000000000000..7b8c3cbddddf8 --- /dev/null +++ b/third_party/instrumented_libraries/scripts/install-build-deps.sh @@ -0,0 +1,98 @@ +#!/bin/bash -e + +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Script to install build dependencies of packages which we instrument. + +# Enable source repositories in Goobuntu. +if hash goobuntu-config 2> /dev/null +then + sudo goobuntu-config set include_deb_src true +fi + +# TODO(earthdok): find a way to pull the list from the build config. +common_packages="\ +atk1.0 \ +dee \ +freetype \ +libappindicator1 \ +libasound2 \ +libcairo2 \ +libcap2 \ +libcups2 \ +libdbus-1-3 \ +libdbus-glib-1-2 \ +libdbusmenu \ +libdbusmenu-glib4 \ +libexpat1 \ +libffi6 \ +libfontconfig1 \ +libgconf-2-4 \ +libgcrypt11 \ +libgdk-pixbuf2.0-0 \ +libglib2.0-0 \ +libgnome-keyring0 \ +libgpg-error0 \ +libgtk2.0-0 \ +libnspr4 \ +libp11-kit0 \ +libpci3 \ +libpcre3 \ +libpixman-1-0 \ +libpng12-0 \ +libunity9 \ +libx11-6 \ +libxau6 \ +libxcb1 \ +libxcomposite1 \ +libxcursor1 \ +libxdamage1 \ +libxdmcp6 \ +libxext6 \ +libxfixes3 \ +libxi6 \ +libxinerama1 \ +libxrandr2 \ +libxrender1 \ +libxss1 \ +libxtst6 \ +nss \ +pango1.0 \ +pulseaudio \ +udev \ +zlib1g \ +brltty" + +precise_specific_packages="libtasn1-3" +trusty_specific_packages="\ +libtasn1-6 \ +harfbuzz +libsecret" + +ubuntu_release=$(lsb_release -cs) + +if test "$ubuntu_release" = "precise" ; then + packages="$common_packages $precise_specific_packages" +else + packages="$common_packages $trusty_specific_packages" +fi + +# Extra build deps for pulseaudio, which apt-get build-dep may fail to install +# for reasons which are not entirely clear. +sudo apt-get install libltdl3-dev libjson0-dev \ + libsndfile1-dev libspeexdsp-dev libjack0 \ + chrpath -y # Chrpath is required by fix_rpaths.sh. + +sudo apt-get build-dep -y $packages + +if test "$ubuntu_release" = "trusty" ; then + # On Trusty, build deps for some of the instrumented packages above conflict + # with Chromium's build deps. In particular: + # zlib1g and libffi remove gcc-4.8 in favor of gcc-multilib, + # libglib2.0-0 removes libelf in favor of libelfg0. + # We let Chromium's build deps take priority. So, run Chromium's + # install-build-deps.sh to reinstall those that have been removed. + $(dirname ${BASH_SOURCE[0]})/../../../build/install-build-deps.sh --no-prompt +fi diff --git a/third_party/instrumented_libraries/scripts/pre-build/autogen.sh b/third_party/instrumented_libraries/scripts/pre-build/autogen.sh new file mode 100755 index 0000000000000..7b3b39035dc42 --- /dev/null +++ b/third_party/instrumented_libraries/scripts/pre-build/autogen.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Sometimes there isn't a pre-generated configure script, and we must first run +# autogen.sh to generate it. Even if there is one, sometimes we need to +# re-generate it (in particular, the autoconf version on Trusty is newer than +# what is expected by pre-generated configure scripts in some packages). + +# Unfortunately, we can't run autogen.sh unconditionally whenever it's present, +# as that sometimes breaks build. Which is why we have this file. + +# Also, some packages may or may not have an autogen script, depending on +# version. Rather than clutter the GYP file with conditionals, we simply do +# nothing if the file is not present. + +if [ -x ./autogen.sh ] +then + NOCONFIGURE=1 ./autogen.sh +fi diff --git a/third_party/instrumented_libraries/scripts/pre-build/autoreconf.sh b/third_party/instrumented_libraries/scripts/pre-build/autoreconf.sh new file mode 100755 index 0000000000000..138fabec3360b --- /dev/null +++ b/third_party/instrumented_libraries/scripts/pre-build/autoreconf.sh @@ -0,0 +1,6 @@ +#!/bin/bash +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +autoreconf --force diff --git a/third_party/instrumented_libraries/scripts/pre-build/freetype.sh b/third_party/instrumented_libraries/scripts/pre-build/freetype.sh new file mode 100755 index 0000000000000..2a3ac3fca2961 --- /dev/null +++ b/third_party/instrumented_libraries/scripts/pre-build/freetype.sh @@ -0,0 +1,13 @@ +#!/bin/bash +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# This script does some preparations before build of instrumented freetype. + +mkdir temp +mv * temp/ +cd temp +./debian/rules patch +mv freetype-*/* ../ +cd .. diff --git a/third_party/instrumented_libraries/scripts/pre-build/libasound2.sh b/third_party/instrumented_libraries/scripts/pre-build/libasound2.sh new file mode 100755 index 0000000000000..d7c59a4df43f2 --- /dev/null +++ b/third_party/instrumented_libraries/scripts/pre-build/libasound2.sh @@ -0,0 +1,16 @@ +#!/bin/bash +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# This script does some preparations before build of instrumented libasound2. + +# Instructions from the INSTALL file. +libtoolize --force --copy --automake +aclocal +autoheader +autoconf +automake --foreign --copy --add-missing + +# Do not warn about undefined sanitizer symbols in object files. +sed -i "s/\(-Wl,--no-undefined\|-Wl,-z,defs\)//g" ./configure diff --git a/third_party/instrumented_libraries/scripts/pre-build/libgdk-pixbuf2.0-0.sh b/third_party/instrumented_libraries/scripts/pre-build/libgdk-pixbuf2.0-0.sh new file mode 100755 index 0000000000000..254804ab819b9 --- /dev/null +++ b/third_party/instrumented_libraries/scripts/pre-build/libgdk-pixbuf2.0-0.sh @@ -0,0 +1,13 @@ +#!/bin/bash +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# This script does some preparations before build of instrumented libgdk-pixbuf2.0-0. + +# Use the system-installed gdk-pixbuf-query-loaders during building. Normally a +# just-built one is used, however in MSan builds it will crash due to +# uninstrumented dependencies. + +sed -i "s|\$(top_builddir)/gdk-pixbuf/gdk-pixbuf-query-loaders|/usr/bin/gdk-pixbuf-query-loaders|g" gdk-pixbuf/Makefile.am +autoreconf diff --git a/third_party/instrumented_libraries/scripts/pre-build/libgtk2.0-0.sh b/third_party/instrumented_libraries/scripts/pre-build/libgtk2.0-0.sh new file mode 100755 index 0000000000000..adaf38f56ee34 --- /dev/null +++ b/third_party/instrumented_libraries/scripts/pre-build/libgtk2.0-0.sh @@ -0,0 +1,13 @@ +#!/bin/bash +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# This script does some preparations before build of instrumented libgtk2.0-0. + +# Use the system-installed gtk-update-icon-cache during building. Normally a +# just-built one is used, however in MSan builds it will crash due to +# uninstrumented dependencies. + +sed -i "s|./gtk-update-icon-cache|/usr/bin/gtk-update-icon-cache|g" gtk/Makefile.am +autoreconf diff --git a/third_party/instrumented_libraries/scripts/pre-build/libnspr4.sh b/third_party/instrumented_libraries/scripts/pre-build/libnspr4.sh new file mode 100755 index 0000000000000..07b790800c4ca --- /dev/null +++ b/third_party/instrumented_libraries/scripts/pre-build/libnspr4.sh @@ -0,0 +1,17 @@ +#!/bin/bash +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# This script does some preparations before build of instrumented libnspr4. + +if [ -d nspr ] +then + mv nspr/* . +elif [ -d mozilla/nsprpub ] +then + mv mozilla/nsprpub/* . +else + echo "libnspr4.sh: package has unexpected directory structure. Please update this script." + return 1 +fi diff --git a/third_party/instrumented_libraries/scripts/pre-build/libva1.sh b/third_party/instrumented_libraries/scripts/pre-build/libva1.sh new file mode 100755 index 0000000000000..d28002ac5bc3d --- /dev/null +++ b/third_party/instrumented_libraries/scripts/pre-build/libva1.sh @@ -0,0 +1,11 @@ +#!/bin/bash +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# This script does some preparations before build of instrumented libva1. + +# autogen is only required on Precise. +NOCONFIGURE=1 ./autogen.sh + +sed -i "s|-no-undefined -Wl,--no-undefined||g" dummy_drv_video/Makefile.in diff --git a/third_party/instrumented_libraries/scripts/pre-build/pulseaudio.sh b/third_party/instrumented_libraries/scripts/pre-build/pulseaudio.sh new file mode 100755 index 0000000000000..a74f1a7ad87be --- /dev/null +++ b/third_party/instrumented_libraries/scripts/pre-build/pulseaudio.sh @@ -0,0 +1,14 @@ +#!/bin/bash +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# This script does some preparations before build of instrumented pulseaudio. + +automake --add-missing +autoreconf + +# Do not warn about undefined sanitizer symbols in object files. +sed -i "s/\(-Wl,--no-undefined\|-Wl,-z,defs\)//g" ./configure +# The configure script enforces FORTIFY_SOURCE=2, but we can't live with that. +sed -i "s/-D_FORTIFY_SOURCE=2/-U_FORTIFY_SOURCE/g" ./configure diff --git a/third_party/instrumented_libraries/scripts/pre-build/udev.sh b/third_party/instrumented_libraries/scripts/pre-build/udev.sh new file mode 100755 index 0000000000000..921b59068e44a --- /dev/null +++ b/third_party/instrumented_libraries/scripts/pre-build/udev.sh @@ -0,0 +1,15 @@ +#!/bin/bash +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# This script does some preparations before build of instrumented udev. + +# Required on Trusty due to autoconf version mismatch. +autoreconf --force + +# Do not warn about undefined sanitizer symbols in object files. +sed -i "s/\(-Wl,--no-undefined\|-Wl,-z,defs\)//g" ./configure + +# Do not fortify source (doesn't work with MSan). +sed -i "s/-D_FORTIFY_SOURCE=2/-U_FORTIFY_SOURCE/g" ./configure diff --git a/third_party/instrumented_libraries/scripts/unpack_binaries.py b/third_party/instrumented_libraries/scripts/unpack_binaries.py new file mode 100755 index 0000000000000..3e1779069dbe8 --- /dev/null +++ b/third_party/instrumented_libraries/scripts/unpack_binaries.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Unpacks pre-built sanitizer-instrumented third-party libraries.""" + +import os +import subprocess +import shutil +import sys + +import download_binaries + + +def get_archive_name(archive_prefix): + return '%s-%s.tgz' % (archive_prefix, download_binaries.get_ubuntu_release()) + + +def main(archive_prefix, archive_dir, target_dir, stamp_dir=None): + shutil.rmtree(target_dir, ignore_errors=True) + + os.mkdir(target_dir) + subprocess.check_call([ + 'tar', + '-zxf', + os.path.join(archive_dir, get_archive_name(archive_prefix)), + '-C', + target_dir]) + stamp_file = os.path.join(stamp_dir or target_dir, '%s.txt' % archive_prefix) + open(stamp_file, 'w').close() + + if stamp_dir: + with open(os.path.join(stamp_dir, '%s.d' % archive_prefix), 'w') as f: + f.write('%s: %s' % ( + stamp_file, os.path.join(archive_dir, + get_archive_name(archive_prefix)))) + return 0 + + +if __name__ == '__main__': + sys.exit(main(*sys.argv[1:])) diff --git a/third_party/instrumented_libraries/standard_instrumented_package_target.gypi b/third_party/instrumented_libraries/standard_instrumented_package_target.gypi new file mode 100644 index 0000000000000..db715be447fad --- /dev/null +++ b/third_party/instrumented_libraries/standard_instrumented_package_target.gypi @@ -0,0 +1,71 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# This file is meant to be included into a target for instrumented dynamic +# packages and describes standard build action for most of the packages. + +{ + 'target_name': '<(_sanitizer_type)-<(_package_name)', + 'type': 'none', + 'actions': [ + { + 'action_name': '<(_package_name)', + 'inputs': [ + # TODO(earthdok): reintroduce some sort of dependency + # See http://crbug.com/343515 + #'download_build_install.py', + ], + 'outputs': [ + '<(PRODUCT_DIR)/instrumented_libraries/<(_sanitizer_type)/<(_package_name).txt', + ], + 'action': ['scripts/download_build_install.py', + '--build-method=>(_build_method)', + '--cc=<(_cc)', + '--cflags=>(_package_cflags)', + '--cxx=<(_cxx)', + '--extra-configure-flags=>(_extra_configure_flags)', + '--intermediate-dir=<(INTERMEDIATE_DIR)', + '--jobs=>(_jobs)', + '--ldflags=>(_package_ldflags)', + '--libdir=<(_libdir)', + '--package=<(_package_name)', + '--product-dir=<(PRODUCT_DIR)', + '--sanitizer=<(_sanitizer_type)', + ], + 'conditions': [ + ['verbose_libraries_build==1', { + 'action+': [ + '--verbose', + ], + }], + ], + 'target_conditions': [ + ['">(_patch)"!=""', { + 'action+': [ + '--patch=>(_patch)', + ], + 'inputs+': [ + '>(_patch)', + ], + }], + ['">(_pre_build)"!=""', { + 'action+': [ + '--pre-build=>(_pre_build)', + ], + 'inputs+': [ + '>(_pre_build)', + ], + }], + ['">(_<(_sanitizer_type)_blacklist)"!=""', { + 'action+': [ + '--sanitizer-blacklist=>(_<(_sanitizer_type)_blacklist)', + ], + 'inputs+': [ + '>(_<(_sanitizer_type)_blacklist)', + ], + }], + ], + }, + ], +} diff --git a/third_party/jsr-305/BUILD.gn b/third_party/jsr-305/BUILD.gn index 3e24063c2fbc7..fdea260639281 100644 --- a/third_party/jsr-305/BUILD.gn +++ b/third_party/jsr-305/BUILD.gn @@ -1,6 +1,7 @@ import("//build/config/android/rules.gni") -android_library("jsr_305_javalib") { +java_library("jsr_305_javalib") { + supports_android = true java_files = [ "src/ri/src/main/java/javax/annotation/PropertyKey.java", "src/ri/src/main/java/javax/annotation/CheckForSigned.java", diff --git a/third_party/junit/junit.gyp b/third_party/junit/junit.gyp index c797e06a5eb4b..9fa92b82867ce 100644 --- a/third_party/junit/junit.gyp +++ b/third_party/junit/junit.gyp @@ -10,6 +10,7 @@ 'type': 'none', 'variables': { 'jar_path': 'src/lib/hamcrest-core-1.1.jar', + 'enable_errorprone': '0', }, 'includes': [ '../../build/host_prebuilt_jar.gypi', @@ -24,6 +25,7 @@ ], 'variables': { 'src_paths': [ 'src/src/main/java' ], + 'enable_errorprone': '0', }, 'includes': [ '../../build/host_jar.gypi', diff --git a/third_party/libpng/BUILD.gn b/third_party/libpng/BUILD.gn index 787d4fa7d00ec..056d91d61a9f0 100644 --- a/third_party/libpng/BUILD.gn +++ b/third_party/libpng/BUILD.gn @@ -61,6 +61,16 @@ source_set("libpng_sources") { public_deps = [ "//third_party/zlib", ] + + # Must be in a config because of how GN orders flags (otherwise -Wall will + # appear after this, and turn it back on). + config("clang_warnings") { + if (is_clang) { + # Upstream uses self-assignment to avoid warnings. + cflags = [ "-Wno-self-assign" ] + } + } + configs += [ ":clang_warnings" ] } if (is_win) { diff --git a/third_party/libpng/libpng.gyp b/third_party/libpng/libpng.gyp index ac8fdb41c929c..48b3fa409c24e 100644 --- a/third_party/libpng/libpng.gyp +++ b/third_party/libpng/libpng.gyp @@ -9,6 +9,10 @@ 'dependencies': [ '../zlib/zlib.gyp:zlib', ], + 'variables': { + # Upstream uses self-assignment to avoid warnings. + 'clang_warning_flags': [ '-Wno-self-assign' ] + }, 'defines': [ 'CHROME_PNG_WRITE_SUPPORT', 'PNG_USER_CONFIG', @@ -67,7 +71,7 @@ 'defines': [ 'PNG_USE_DLL', ], - }, + }, }], ['OS=="android"', { 'toolsets': ['target', 'host'], diff --git a/third_party/libxml/BUILD.gn b/third_party/libxml/BUILD.gn index 7fb667885377e..1f10dee5889d5 100644 --- a/third_party/libxml/BUILD.gn +++ b/third_party/libxml/BUILD.gn @@ -38,13 +38,15 @@ static_library("libxml") { "src/HTMLtree.c", "src/SAX.c", "src/SAX2.c", - "src/acconfig.h", + "src/buf.c", + "src/buf.h", "src/c14n.c", "src/catalog.c", "src/chvalid.c", "src/debugXML.c", "src/dict.c", "src/elfgcchack.h", + "src/enc.h", "src/encoding.c", "src/entities.c", "src/error.c", @@ -103,8 +105,10 @@ static_library("libxml") { "src/parserInternals.c", "src/pattern.c", "src/relaxng.c", + "src/save.h", "src/schematron.c", "src/threads.c", + "src/timsort.h", "src/tree.c", #"src/trio.c", @@ -132,6 +136,9 @@ static_library("libxml") { "src/xmlwriter.c", "src/xpath.c", "src/xpointer.c", + + #"src/xzlib.c", + "src/xzlib.h", "win32/config.h", "win32/include/libxml/xmlversion.h", ] @@ -149,7 +156,7 @@ static_library("libxml") { if (is_win) { cflags_c = [ "/wd4101" ] # Unreferenced local variable. - } else if (is_mac || is_android) { + } else if (is_mac || is_ios || is_android) { # http://www.xmlsoft.org/threads.html says that this is required when using # libxml from several threads, which can possibly happen in chrome. On # linux, this is picked up by transitivity from pkg-config output from @@ -175,6 +182,19 @@ static_library("libxml") { "-Wno-ignored-attributes", ] } + config("libxml_warnings") { + if (is_clang) { + cflags += [ + # libxml casts from int to long to void*. + "-Wno-int-to-void-pointer-cast", + + # libxml passes a volatile LPCRITICAL_SECTION* to a function expecting + # a void* volatile*. + "-Wno-incompatible-pointer-types", + ] + } + } + configs += [ ":libxml_warnings" ] include_dirs = [ "$os_include" ] } diff --git a/third_party/libxml/README.chromium b/third_party/libxml/README.chromium index 1f3162f446a63..1b611f0e174b0 100644 --- a/third_party/libxml/README.chromium +++ b/third_party/libxml/README.chromium @@ -1,62 +1,52 @@ Name: libxml URL: http://xmlsoft.org -Version: 2.7.7 +Version: 2.9.2 License: MIT License File: src/Copyright Security Critical: yes Description: -The src/ directory contains a partial snapshot of the libxml library -with the patches in the patches/ directories applied. -See the files in that directory for discussion of their effects. -Current version: 2.7.7. +libxml2 from libxml.org. Modifications: -- Converted to utf-8 with: vim +"argdo write ++enc=utf-8" *.c -- Import XPath fix http://git.gnome.org/browse/libxml2/commit/?id=91d19754d46acd4a639a8b9e31f50f31c78f8c9c -- Import follow-on for above commit: http://git.gnome.org/browse/libxml2/commit/?id=ea90b894146030c214a7df6d8375310174f134b9 -- Import additional XPath fix http://git.gnome.org/browse/libxml2/commit/?id=df83c17e5a2646bd923f75e5e507bc80d73c9722 -- Import follow-on fix for above commit: http://git.gnome.org/browse/libxml2/commit/?id=fec31bcd452e77c10579467ca87a785b41115de6 -- And a follow-on fix to the previous two fixes, committed upstream: http://git.gnome.org/browse/libxml2/commit/?id=f5048b3e71fc30ad096970b8df6e7af073bae4cb (slightly differently, but we can drop our local fix on the next roll). -- Add a fix for handling of unknown namespaces, commit upstream is pending. -- Add fixes for ending the parse properly if a SAX callback calls xmlStopParser(), commit upstream is pending. -- Add fix for entities, commit upstream is http://git.gnome.org/browse/libxml2/commit/?id=5bd3c061823a8499b27422aee04ea20aae24f03e -- Import UTF-8 fix from upstream: http://git.gnome.org/browse/libxml2/commit/?id=0795348aeb86648723bc391e4d02e20631c10bca -- Import XPath fix http://git.gnome.org/browse/libxml2/commit/xpath.c?id=2ddecc23862bab1a9a9e51e097aefc92ec305e28 -- Merge clang warning fix http://git.gnome.org/browse/libxml2/commit/?id=aae48e64dfbf2b46b157a4c1857e30645116388f -- Add a fix for proper escaping of xpointer expressions, commit upstream is pending. -- Add helper classes in chromium/libxml_utils.cc and chromium/include/libxml/libxml_utils.h. -- Add a tweak to limit problems caused by excessive strings and buffers. -- Change the xmlNs struct a little bit, so it looks like it has no children - if treated as a generic xmlNode object. -- Fix pretty harmless use-after-free in generate-id function. -- Merge a clang warning fix http://git.gnome.org/browse/libxml2/commit/?id=713434d2309da469d64b35e163ea6556dadccada -- Import attribute normalization fix http://git.gnome.org/browse/libxml2/commit/?id=6a36fbe3b3e001a8a840b5c1fdd81cefc9947f0d -- Merge a redundant comparison fix http://git.gnome.org/browse/libxml2/commit/?id=2af19f985b911b6dc6ada478ba8d201d2ddc9309 -- Merge a redundant comparisons fix https://git.gnome.org/browse/libxml2/commit/?id=eea38159be421dbafbee38f40e239f91734bc713 -- Merge XML_PARSER_EOF checks https://git.gnome.org/browse/libxml2/commit/?id=48b4cdde3483e054af8ea02e0cd7ee467b0e9a50 and https://git.gnome.org/browse/libxml2/commit/?id=e50ba8164eee06461c73cd8abb9b46aa0be81869 -- Prevent snprintf from being defined as _snprintf on VS 2015. -- Make ucrt of Win10 SDK not define POSIX error codes. -- Delete/disable nanoftp and nanohttp. - -To import a new snapshot of libxml: - -- Visit http://xmlsoft.org/downloads.html and download the latest source - distribution. -- Copy the files into this directory, omitting files which have been omitted - here. E.g.: for i in $(find . -type f); do cp ../libxml-newver/$i $i; done - This should clobber all local changes to this directory. -- Apply the patches in patches/ and fix any problems. - UPDATE THOSE PATCHES OR EVAN WILL HUNT YOU DOWN. -- On a Linux system, - $ cd linux - $ ../configure --without-iconv --without-ftp --without-http - to generate config.h and include/libxml/xmlversion.h for Linux. -- On a Mac, - $ cd mac - $ ../configure --without-iconv --without-ftp --without-http - to generate config.h and include/libxml/xmlversion.h for Macs. -- On Windows, run build/generate-win32-headers.bat to re-generate config.h and - include/libxml/xmlversion.h for Windows builds. -- Update this README to reflect the new version number. +- Add helper classes in chromium/libxml_utils.cc and + chromium/include/libxml/libxml_utils.h. +- Import https://git.gnome.org/browse/libxml2/commit/?id=7580ce0a7f53891de520fed2c0e360266c286da6 + from upstream. +- Self-assignment removed https://bugzilla.gnome.org/show_bug.cgi?id=751679. + + +To import a new snapshot: + +On Linux, get the latest tar, untar, and replace src/ with libxml2-X.Y.Z/. + +Remove: + src/doc/ + src/example/ + src/os400/ + src/python/ + src/result/ + src/test/ + src/vms/ + src/VxWorks/ + +Generate config.h, include/libxml/xmlversion.h, and xml2-config: + +cd linux +../src/configure --without-iconv --with-icu --without-ftp --without-http +cd .. +Patch config.h to not define HAVE_RAND_R since we use this file on Android +and it does not have it. + +On a Mac, do the same in the mac/ subdir for config.h and +include/libxml/xmlversion.h and copy those to the Linux box in mac/ + +On a Windows box: +cd libxml2-2.9.2\win32 +cscript //E:jscript configure.js compiler=msvc iconv=no icu=yes ftp=no http=no +Then copy config.h and include/libxml/xmlversion.h to win32/ on Linux. + + +Update BUILD.gn and libxml.gyp as necessary to add/remove files, etc. + diff --git a/third_party/libxml/build/generate-win32-headers.bat b/third_party/libxml/build/generate-win32-headers.bat deleted file mode 100755 index 1d0f85de7341e..0000000000000 --- a/third_party/libxml/build/generate-win32-headers.bat +++ /dev/null @@ -1,9 +0,0 @@ -REM Generate config.h and xmlversion.h. We put the generated files in -REM win32 so they don't get included on other platforms. - -cd %~dp0\..\win32 -cscript //E:jscript configure.js compiler=msvc iconv=no icu=yes -move ..\config.h . - -md include\libxml -move ..\include\libxml\xmlversion.h include\libxml\ diff --git a/third_party/libxml/libxml.gyp b/third_party/libxml/libxml.gyp index 51e45db462396..584bba8d4a7b2 100644 --- a/third_party/libxml/libxml.gyp +++ b/third_party/libxml/libxml.gyp @@ -68,9 +68,11 @@ ], }, 'link_settings': { - 'libraries': [ - '$(SDKROOT)/usr/lib/libxml2.dylib', - ], + 'xcode_settings': { + 'OTHER_LDFLAGS': [ + '-lxml2', + ], + }, }, }], ], @@ -129,7 +131,8 @@ 'src/include/libxml/xpointer.h', 'src/include/win32config.h', 'src/include/wsockcompat.h', - 'src/acconfig.h', + 'src/buf.c', + 'src/buf.h', 'src/c14n.c', 'src/catalog.c', 'src/chvalid.c', @@ -137,6 +140,7 @@ 'src/dict.c', 'src/DOCBparser.c', 'src/elfgcchack.h', + 'src/enc.h', 'src/encoding.c', 'src/entities.c', 'src/error.c', @@ -151,10 +155,12 @@ 'src/parserInternals.c', 'src/pattern.c', 'src/relaxng.c', + 'src/save.h', 'src/SAX.c', 'src/SAX2.c', 'src/schematron.c', 'src/threads.c', + 'src/timsort.h', 'src/tree.c', #'src/trio.c', #'src/trio.h', @@ -181,6 +187,8 @@ 'src/xmlwriter.c', 'src/xpath.c', 'src/xpointer.c', + #'src/xzlib.c', + 'src/xzlib.h', 'win32/config.h', 'win32/include/libxml/xmlversion.h', ], @@ -204,6 +212,11 @@ '-Wno-tautological-pointer-compare', # See http://crbug.com/138571#c8 '-Wno-ignored-attributes', + # libxml casts from int to long to void*. + '-Wno-int-to-void-pointer-cast', + # libxml passes a volatile LPCRITICAL_SECTION* to a function + # expecting a void* volatile*. + '-Wno-incompatible-pointer-types', ], }, 'include_dirs': [ diff --git a/third_party/libxml/linux/config.h b/third_party/libxml/linux/config.h index ca2f44031e838..393906f9499b4 100644 --- a/third_party/libxml/linux/config.h +++ b/third_party/libxml/linux/config.h @@ -1,21 +1,8 @@ /* config.h. Generated from config.h.in by configure. */ -/* config.h.in. Generated from configure.in by autoheader. */ -#define PACKAGE "libxml2" -#define VERSION "2.7.7" -#define HAVE_LIBZ 1 -/* #undef HAVE_LIBM */ -#define HAVE_ISINF /**/ -#define HAVE_ISNAN /**/ -/* #undef HAVE_LIBHISTORY */ -/* #undef HAVE_LIBREADLINE */ -#define HAVE_LIBPTHREAD /**/ -#define HAVE_PTHREAD_H /**/ +/* config.h.in. Generated from configure.ac by autoheader. */ -/* Define if IPV6 support is there */ -#define SUPPORT_IP6 /**/ - -/* Define if getaddrinfo is there */ -#define HAVE_GETADDRINFO /**/ +/* Type cast for the gethostbyname() argument */ +#define GETHOSTBYNAME_ARG_CAST /**/ /* Define to 1 if you have the header file. */ /* #undef HAVE_ANSIDECL_H */ @@ -86,8 +73,8 @@ /* Define to 1 if you have the header file. */ #define HAVE_INTTYPES_H 1 -/* Define to 1 if you have the header file. */ -/* #undef HAVE_INTTYPES_H_H */ +/* Define to 1 if you have the `isascii' function. */ +#define HAVE_ISASCII 1 /* Define if isinf is there */ #define HAVE_ISINF /**/ @@ -101,6 +88,9 @@ /* Define if history library is there (-lhistory) */ /* #undef HAVE_LIBHISTORY */ +/* Have compression library */ +/* #undef HAVE_LIBLZMA */ + /* Define if pthread library is there (-lpthread) */ #define HAVE_LIBPTHREAD /**/ @@ -116,6 +106,9 @@ /* Define to 1 if you have the `localtime' function. */ #define HAVE_LOCALTIME 1 +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LZMA_H */ + /* Define to 1 if you have the header file. */ #define HAVE_MALLOC_H 1 @@ -125,6 +118,17 @@ /* Define to 1 if you have the header file. */ #define HAVE_MEMORY_H 1 +/* Define to 1 if you have the `mmap' function. */ +#define HAVE_MMAP 1 + +/* Define to 1 if you have the `munmap' function. */ +#define HAVE_MUNMAP 1 + +/* mmap() is no good without munmap() */ +#if defined(HAVE_MMAP) && !defined(HAVE_MUNMAP) +# undef /**/ HAVE_MMAP +#endif + /* Define to 1 if you have the header file. */ /* #undef HAVE_NAN_H */ @@ -146,6 +150,15 @@ /* Define if is there */ #define HAVE_PTHREAD_H /**/ +/* Define to 1 if you have the `putenv' function. */ +#define HAVE_PUTENV 1 + +/* Define to 1 if you have the `rand' function. */ +#define HAVE_RAND 1 + +/* Define to 1 if you have the `rand_r' function. */ +/* #undef HAVE_RAND_R */ + /* Define to 1 if you have the header file. */ #define HAVE_RESOLV_H 1 @@ -164,6 +177,9 @@ /* Define to 1 if you have the `sprintf' function. */ #define HAVE_SPRINTF 1 +/* Define to 1 if you have the `srand' function. */ +#define HAVE_SRAND 1 + /* Define to 1 if you have the `sscanf' function. */ #define HAVE_SSCANF 1 @@ -226,6 +242,9 @@ /* Define to 1 if you have the header file. */ #define HAVE_SYS_TYPES_H 1 +/* Define to 1 if you have the `time' function. */ +#define HAVE_TIME 1 + /* Define to 1 if you have the header file. */ #define HAVE_TIME_H 1 @@ -281,8 +300,8 @@ /* Define to the version of this package. */ #define PACKAGE_VERSION "" -/* Define to 1 if the C compiler supports function prototypes. */ -#define PROTOTYPES 1 +/* Type cast for the send() function 2nd arg */ +#define SEND_ARG2_CAST /**/ /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 @@ -290,23 +309,26 @@ /* Support for IPv6 */ #define SUPPORT_IP6 /**/ +/* Define if va_list is an array type */ +#define VA_LIST_IS_ARRAY 1 + /* Version number of package */ -#define VERSION "2.7.7" +#define VERSION "2.9.2" /* Determine what socket length (socklen_t) data type is */ #define XML_SOCKLEN_T socklen_t +/* Define for Solaris 2.5.1 so the uint32_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +/* #undef _UINT32_T */ + /* Using the Win32 Socket implementation */ /* #undef _WINSOCKAPI_ */ -/* Define like PROTOTYPES; this can be used by system headers. */ -#define __PROTOTYPES 1 - -/* Win32 Std C name mangling work-around */ -/* #undef snprintf */ - /* ss_family is not defined here, use __ss_family instead */ /* #undef ss_family */ -/* Win32 Std C name mangling work-around */ -/* #undef vsnprintf */ +/* Define to the type of an unsigned integer type of width exactly 32 bits if + such a type exists and the standard includes do not define it. */ +/* #undef uint32_t */ diff --git a/third_party/libxml/linux/include/libxml/xmlversion.h b/third_party/libxml/linux/include/libxml/xmlversion.h index 9e849fa3796a5..6fd386de05bb6 100644 --- a/third_party/libxml/linux/include/libxml/xmlversion.h +++ b/third_party/libxml/linux/include/libxml/xmlversion.h @@ -29,21 +29,21 @@ XMLPUBFUN void XMLCALL xmlCheckVersion(int version); * * the version string like "1.2.3" */ -#define LIBXML_DOTTED_VERSION "2.7.7" +#define LIBXML_DOTTED_VERSION "2.9.2" /** * LIBXML_VERSION: * * the version number: 1.2.3 value is 10203 */ -#define LIBXML_VERSION 20707 +#define LIBXML_VERSION 20902 /** * LIBXML_VERSION_STRING: * * the version number string, 1.2.3 value is "10203" */ -#define LIBXML_VERSION_STRING "20707" +#define LIBXML_VERSION_STRING "20902" /** * LIBXML_VERSION_EXTRA: @@ -58,7 +58,7 @@ XMLPUBFUN void XMLCALL xmlCheckVersion(int version); * Macro to check that the libxml version in use is compatible with * the version the software has been compiled against */ -#define LIBXML_TEST_VERSION xmlCheckVersion(20707); +#define LIBXML_TEST_VERSION xmlCheckVersion(20902); #ifndef VMS #if 0 @@ -97,6 +97,15 @@ XMLPUBFUN void XMLCALL xmlCheckVersion(int version); #endif #endif +/** + * LIBXML_THREAD_ALLOC_ENABLED: + * + * Whether the allocation hooks are per-thread + */ +#if 0 +#define LIBXML_THREAD_ALLOC_ENABLED +#endif + /** * LIBXML_TREE_ENABLED: * @@ -391,6 +400,15 @@ XMLPUBFUN void XMLCALL xmlCheckVersion(int version); #define LIBXML_ZLIB_ENABLED #endif +/** + * LIBXML_LZMA_ENABLED: + * + * Whether the Lzma support is compiled in + */ +#if 0 +#define LIBXML_LZMA_ENABLED +#endif + #ifdef __GNUC__ #ifdef HAVE_ANSIDECL_H #include @@ -403,7 +421,11 @@ XMLPUBFUN void XMLCALL xmlCheckVersion(int version); */ #ifndef ATTRIBUTE_UNUSED -#define ATTRIBUTE_UNUSED __attribute__((unused)) +# if ((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 7))) +# define ATTRIBUTE_UNUSED __attribute__((unused)) +# else +# define ATTRIBUTE_UNUSED +# endif #endif /** diff --git a/third_party/libxml/linux/xml2-config b/third_party/libxml/linux/xml2-config index 799fc11f6628b..d874f80de703f 100755 --- a/third_party/libxml/linux/xml2-config +++ b/third_party/libxml/linux/xml2-config @@ -58,7 +58,7 @@ while test $# -gt 0; do ;; --version) - echo 2.7.7 + echo 2.9.2 exit 0 ;; @@ -86,12 +86,12 @@ while test $# -gt 0; do then if [ "-L${libdir}" = "-L/usr/lib" -o "-L${libdir}" = "-L/usr/lib64" ] then - echo -lxml2 -lz -lm + echo -lxml2 -lz -lm -ldl else - echo -L${libdir} -lxml2 -lz -lm + echo -L${libdir} -lxml2 -lz -lm -ldl fi else - echo -L${libdir} -lxml2 -lz -lm + echo -L${libdir} -lxml2 -lz -lm -ldl fi ;; diff --git a/third_party/libxml/mac/config.h b/third_party/libxml/mac/config.h index d647bf0e869d3..36606f05f453e 100644 --- a/third_party/libxml/mac/config.h +++ b/third_party/libxml/mac/config.h @@ -1,21 +1,8 @@ /* config.h. Generated from config.h.in by configure. */ -/* config.h.in. Generated from configure.in by autoheader. */ -#define PACKAGE "libxml2" -#define VERSION "2.7.7" -#define HAVE_LIBZ 1 -/* #undef HAVE_LIBM */ -#define HAVE_ISINF /**/ -#define HAVE_ISNAN /**/ -/* #undef HAVE_LIBHISTORY */ -/* #undef HAVE_LIBREADLINE */ -#define HAVE_LIBPTHREAD /**/ -#define HAVE_PTHREAD_H /**/ +/* config.h.in. Generated from configure.ac by autoheader. */ -/* Define if IPV6 support is there */ -#define SUPPORT_IP6 /**/ - -/* Define if getaddrinfo is there */ -#define HAVE_GETADDRINFO /**/ +/* Type cast for the gethostbyname() argument */ +#define GETHOSTBYNAME_ARG_CAST /**/ /* Define to 1 if you have the header file. */ /* #undef HAVE_ANSIDECL_H */ @@ -86,8 +73,8 @@ /* Define to 1 if you have the header file. */ #define HAVE_INTTYPES_H 1 -/* Define to 1 if you have the header file. */ -/* #undef HAVE_INTTYPES_H_H */ +/* Define to 1 if you have the `isascii' function. */ +#define HAVE_ISASCII 1 /* Define if isinf is there */ #define HAVE_ISINF /**/ @@ -101,6 +88,9 @@ /* Define if history library is there (-lhistory) */ /* #undef HAVE_LIBHISTORY */ +/* Have compression library */ +/* #undef HAVE_LIBLZMA */ + /* Define if pthread library is there (-lpthread) */ #define HAVE_LIBPTHREAD /**/ @@ -116,6 +106,9 @@ /* Define to 1 if you have the `localtime' function. */ #define HAVE_LOCALTIME 1 +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LZMA_H */ + /* Define to 1 if you have the header file. */ /* #undef HAVE_MALLOC_H */ @@ -125,6 +118,17 @@ /* Define to 1 if you have the header file. */ #define HAVE_MEMORY_H 1 +/* Define to 1 if you have the `mmap' function. */ +#define HAVE_MMAP 1 + +/* Define to 1 if you have the `munmap' function. */ +#define HAVE_MUNMAP 1 + +/* mmap() is no good without munmap() */ +#if defined(HAVE_MMAP) && !defined(HAVE_MUNMAP) +# undef /**/ HAVE_MMAP +#endif + /* Define to 1 if you have the header file. */ /* #undef HAVE_NAN_H */ @@ -146,6 +150,15 @@ /* Define if is there */ #define HAVE_PTHREAD_H /**/ +/* Define to 1 if you have the `putenv' function. */ +#define HAVE_PUTENV 1 + +/* Define to 1 if you have the `rand' function. */ +#define HAVE_RAND 1 + +/* Define to 1 if you have the `rand_r' function. */ +#define HAVE_RAND_R 1 + /* Define to 1 if you have the header file. */ #define HAVE_RESOLV_H 1 @@ -164,6 +177,9 @@ /* Define to 1 if you have the `sprintf' function. */ #define HAVE_SPRINTF 1 +/* Define to 1 if you have the `srand' function. */ +#define HAVE_SRAND 1 + /* Define to 1 if you have the `sscanf' function. */ #define HAVE_SSCANF 1 @@ -195,7 +211,7 @@ #define HAVE_STRING_H 1 /* Define to 1 if you have the `strndup' function. */ -/* #undef HAVE_STRNDUP */ +#define HAVE_STRNDUP 1 /* Define to 1 if you have the header file, and it defines `DIR'. */ @@ -226,6 +242,9 @@ /* Define to 1 if you have the header file. */ #define HAVE_SYS_TYPES_H 1 +/* Define to 1 if you have the `time' function. */ +#define HAVE_TIME 1 + /* Define to 1 if you have the header file. */ #define HAVE_TIME_H 1 @@ -281,8 +300,8 @@ /* Define to the version of this package. */ #define PACKAGE_VERSION "" -/* Define to 1 if the C compiler supports function prototypes. */ -#define PROTOTYPES 1 +/* Type cast for the send() function 2nd arg */ +#define SEND_ARG2_CAST /**/ /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 @@ -290,23 +309,26 @@ /* Support for IPv6 */ #define SUPPORT_IP6 /**/ +/* Define if va_list is an array type */ +#define VA_LIST_IS_ARRAY 1 + /* Version number of package */ -#define VERSION "2.7.7" +#define VERSION "2.9.2" /* Determine what socket length (socklen_t) data type is */ #define XML_SOCKLEN_T socklen_t +/* Define for Solaris 2.5.1 so the uint32_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +/* #undef _UINT32_T */ + /* Using the Win32 Socket implementation */ /* #undef _WINSOCKAPI_ */ -/* Define like PROTOTYPES; this can be used by system headers. */ -#define __PROTOTYPES 1 - -/* Win32 Std C name mangling work-around */ -/* #undef snprintf */ - /* ss_family is not defined here, use __ss_family instead */ /* #undef ss_family */ -/* Win32 Std C name mangling work-around */ -/* #undef vsnprintf */ +/* Define to the type of an unsigned integer type of width exactly 32 bits if + such a type exists and the standard includes do not define it. */ +/* #undef uint32_t */ diff --git a/third_party/libxml/mac/include/libxml/xmlversion.h b/third_party/libxml/mac/include/libxml/xmlversion.h index 9e849fa3796a5..6fd386de05bb6 100644 --- a/third_party/libxml/mac/include/libxml/xmlversion.h +++ b/third_party/libxml/mac/include/libxml/xmlversion.h @@ -29,21 +29,21 @@ XMLPUBFUN void XMLCALL xmlCheckVersion(int version); * * the version string like "1.2.3" */ -#define LIBXML_DOTTED_VERSION "2.7.7" +#define LIBXML_DOTTED_VERSION "2.9.2" /** * LIBXML_VERSION: * * the version number: 1.2.3 value is 10203 */ -#define LIBXML_VERSION 20707 +#define LIBXML_VERSION 20902 /** * LIBXML_VERSION_STRING: * * the version number string, 1.2.3 value is "10203" */ -#define LIBXML_VERSION_STRING "20707" +#define LIBXML_VERSION_STRING "20902" /** * LIBXML_VERSION_EXTRA: @@ -58,7 +58,7 @@ XMLPUBFUN void XMLCALL xmlCheckVersion(int version); * Macro to check that the libxml version in use is compatible with * the version the software has been compiled against */ -#define LIBXML_TEST_VERSION xmlCheckVersion(20707); +#define LIBXML_TEST_VERSION xmlCheckVersion(20902); #ifndef VMS #if 0 @@ -97,6 +97,15 @@ XMLPUBFUN void XMLCALL xmlCheckVersion(int version); #endif #endif +/** + * LIBXML_THREAD_ALLOC_ENABLED: + * + * Whether the allocation hooks are per-thread + */ +#if 0 +#define LIBXML_THREAD_ALLOC_ENABLED +#endif + /** * LIBXML_TREE_ENABLED: * @@ -391,6 +400,15 @@ XMLPUBFUN void XMLCALL xmlCheckVersion(int version); #define LIBXML_ZLIB_ENABLED #endif +/** + * LIBXML_LZMA_ENABLED: + * + * Whether the Lzma support is compiled in + */ +#if 0 +#define LIBXML_LZMA_ENABLED +#endif + #ifdef __GNUC__ #ifdef HAVE_ANSIDECL_H #include @@ -403,7 +421,11 @@ XMLPUBFUN void XMLCALL xmlCheckVersion(int version); */ #ifndef ATTRIBUTE_UNUSED -#define ATTRIBUTE_UNUSED __attribute__((unused)) +# if ((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 7))) +# define ATTRIBUTE_UNUSED __attribute__((unused)) +# else +# define ATTRIBUTE_UNUSED +# endif #endif /** diff --git a/third_party/libxml/patches/LoadLibraryA b/third_party/libxml/patches/LoadLibraryA deleted file mode 100644 index 89fff15c86c4c..0000000000000 --- a/third_party/libxml/patches/LoadLibraryA +++ /dev/null @@ -1,16 +0,0 @@ -Change 'LoadLibrary' to 'LoadLibraryA' (used with 'const char*' as an -argument) - -Index: libxml/xmlmodule.c -=================================================================== ---- libxml.orig/xmlmodule.c 2010-07-09 14:17:46.959288280 -0700 -+++ libxml/xmlmodule.c 2010-07-09 14:17:55.419051003 -0700 -@@ -300,7 +300,7 @@ - static void * - xmlModulePlatformOpen(const char *name) - { -- return LoadLibrary(name); -+ return LoadLibraryA(name); - } - - /* diff --git a/third_party/libxml/patches/bug_651202 b/third_party/libxml/patches/bug_651202 deleted file mode 100644 index 5f93fd705ffee..0000000000000 --- a/third_party/libxml/patches/bug_651202 +++ /dev/null @@ -1,13 +0,0 @@ -Fix for https://bugzilla.gnome.org/show_bug.cgi?id=651202 - ---- libxml/xmlschemas.c.orig Thu May 26 20:21:54 2011 -+++ libxml/xmlschemas.c Thu May 26 20:22:02 2011 -@@ -13946,7 +13946,7 @@ - */ - if ((sub->negNsSet != NULL) && - (super->negNsSet != NULL) && -- (sub->negNsSet->value == sub->negNsSet->value)) -+ (sub->negNsSet->value == super->negNsSet->value)) - return (0); - /* - * 3.1 sub must be a set whose members are either namespace names or �absent�. diff --git a/third_party/libxml/patches/icu b/third_party/libxml/patches/icu deleted file mode 100644 index 4503f922fcb32..0000000000000 --- a/third_party/libxml/patches/icu +++ /dev/null @@ -1,453 +0,0 @@ -Add code support for ICU. - -diff --git a/third_party/libxml/encoding.c b/third_party/libxml/encoding.c -index b86a547..0f41df9 100644 ---- a/third_party/libxml/encoding.c -+++ b/third_party/libxml/encoding.c -@@ -58,7 +58,7 @@ static xmlCharEncodingAliasPtr xmlCharEncodingAliases = NULL; - static int xmlCharEncodingAliasesNb = 0; - static int xmlCharEncodingAliasesMax = 0; - --#ifdef LIBXML_ICONV_ENABLED -+#if defined(LIBXML_ICONV_ENABLED) || defined(LIBXML_ICU_ENABLED) - #if 0 - #define DEBUG_ENCODING /* Define this to get encoding traces */ - #endif -@@ -97,6 +97,54 @@ xmlEncodingErr(xmlParserErrors error, const char *msg, const char *val) - NULL, 0, val, NULL, NULL, 0, 0, msg, val); - } - -+#ifdef LIBXML_ICU_ENABLED -+static uconv_t* -+openIcuConverter(const char* name, int toUnicode) -+{ -+ UErrorCode status = U_ZERO_ERROR; -+ uconv_t *conv = (uconv_t *) xmlMalloc(sizeof(uconv_t)); -+ if (conv == NULL) -+ return NULL; -+ -+ conv->uconv = ucnv_open(name, &status); -+ if (U_FAILURE(status)) -+ goto error; -+ -+ status = U_ZERO_ERROR; -+ if (toUnicode) { -+ ucnv_setToUCallBack(conv->uconv, UCNV_TO_U_CALLBACK_STOP, -+ NULL, NULL, NULL, &status); -+ } -+ else { -+ ucnv_setFromUCallBack(conv->uconv, UCNV_FROM_U_CALLBACK_STOP, -+ NULL, NULL, NULL, &status); -+ } -+ if (U_FAILURE(status)) -+ goto error; -+ -+ status = U_ZERO_ERROR; -+ conv->utf8 = ucnv_open("UTF-8", &status); -+ if (U_SUCCESS(status)) -+ return conv; -+ -+error: -+ if (conv->uconv) -+ ucnv_close(conv->uconv); -+ xmlFree(conv); -+ return NULL; -+} -+ -+static void -+closeIcuConverter(uconv_t *conv) -+{ -+ if (conv != NULL) { -+ ucnv_close(conv->uconv); -+ ucnv_close(conv->utf8); -+ xmlFree(conv); -+ } -+} -+#endif /* LIBXML_ICU_ENABLED */ -+ - /************************************************************************ - * * - * Conversions To/From UTF8 encoding * -@@ -1306,7 +1354,11 @@ xmlNewCharEncodingHandler(const char *name, - #ifdef LIBXML_ICONV_ENABLED - handler->iconv_in = NULL; - handler->iconv_out = NULL; --#endif /* LIBXML_ICONV_ENABLED */ -+#endif -+#ifdef LIBXML_ICU_ENABLED -+ handler->uconv_in = NULL; -+ handler->uconv_out = NULL; -+#endif - - /* - * registers and returns the handler. -@@ -1371,7 +1423,7 @@ xmlInitCharEncodingHandlers(void) { - xmlNewCharEncodingHandler("ASCII", asciiToUTF8, NULL); - xmlNewCharEncodingHandler("US-ASCII", asciiToUTF8, NULL); - #endif /* LIBXML_OUTPUT_ENABLED */ --#ifndef LIBXML_ICONV_ENABLED -+#if !defined(LIBXML_ICONV_ENABLED) && !defined(LIBXML_ICU_ENABLED) - #ifdef LIBXML_ISO8859X_ENABLED - xmlRegisterCharEncodingHandlersISO8859x (); - #endif -@@ -1578,6 +1630,10 @@ xmlFindCharEncodingHandler(const char *name) { - xmlCharEncodingHandlerPtr enc; - iconv_t icv_in, icv_out; - #endif /* LIBXML_ICONV_ENABLED */ -+#ifdef LIBXML_ICU_ENABLED -+ xmlCharEncodingHandlerPtr enc; -+ uconv_t *ucv_in, *ucv_out; -+#endif /* LIBXML_ICU_ENABLED */ - char upper[100]; - int i; - -@@ -1647,6 +1703,35 @@ xmlFindCharEncodingHandler(const char *name) { - "iconv : problems with filters for '%s'\n", name); - } - #endif /* LIBXML_ICONV_ENABLED */ -+#ifdef LIBXML_ICU_ENABLED -+ /* check whether icu can handle this */ -+ ucv_in = openIcuConverter(name, 1); -+ ucv_out = openIcuConverter(name, 0); -+ if (ucv_in != NULL && ucv_out != NULL) { -+ enc = (xmlCharEncodingHandlerPtr) -+ xmlMalloc(sizeof(xmlCharEncodingHandler)); -+ if (enc == NULL) { -+ closeIcuConverter(ucv_in); -+ closeIcuConverter(ucv_out); -+ return(NULL); -+ } -+ enc->name = xmlMemStrdup(name); -+ enc->input = NULL; -+ enc->output = NULL; -+ enc->uconv_in = ucv_in; -+ enc->uconv_out = ucv_out; -+#ifdef DEBUG_ENCODING -+ xmlGenericError(xmlGenericErrorContext, -+ "Found ICU converter handler for encoding %s\n", name); -+#endif -+ return enc; -+ } else if (ucv_in != NULL || ucv_out != NULL) { -+ closeIcuConverter(ucv_in); -+ closeIcuConverter(ucv_out); -+ xmlEncodingErr(XML_ERR_INTERNAL_ERROR, -+ "ICU converter : problems with filters for '%s'\n", name); -+ } -+#endif /* LIBXML_ICU_ENABLED */ - - #ifdef DEBUG_ENCODING - xmlGenericError(xmlGenericErrorContext, -@@ -1737,6 +1822,75 @@ xmlIconvWrapper(iconv_t cd, unsigned char *out, int *outlen, - - /************************************************************************ - * * -+ * ICU based generic conversion functions * -+ * * -+ ************************************************************************/ -+ -+#ifdef LIBXML_ICU_ENABLED -+/** -+ * xmlUconvWrapper: -+ * @cd: ICU uconverter data structure -+ * @toUnicode : non-zero if toUnicode. 0 otherwise. -+ * @out: a pointer to an array of bytes to store the result -+ * @outlen: the length of @out -+ * @in: a pointer to an array of ISO Latin 1 chars -+ * @inlen: the length of @in -+ * -+ * Returns 0 if success, or -+ * -1 by lack of space, or -+ * -2 if the transcoding fails (for *in is not valid utf8 string or -+ * the result of transformation can't fit into the encoding we want), or -+ * -3 if there the last byte can't form a single output char. -+ * -+ * The value of @inlen after return is the number of octets consumed -+ * as the return value is positive, else unpredictable. -+ * The value of @outlen after return is the number of ocetes consumed. -+ */ -+static int -+xmlUconvWrapper(uconv_t *cd, int toUnicode, unsigned char *out, int *outlen, -+ const unsigned char *in, int *inlen) { -+ const char *ucv_in = (const char *) in; -+ char *ucv_out = (char *) out; -+ UErrorCode err = U_ZERO_ERROR; -+ -+ if ((out == NULL) || (outlen == NULL) || (inlen == NULL) || (in == NULL)) { -+ if (outlen != NULL) *outlen = 0; -+ return(-1); -+ } -+ -+ /* -+ * TODO(jungshik) -+ * 1. is ucnv_convert(To|From)Algorithmic better? -+ * 2. had we better use an explicit pivot buffer? -+ * 3. error returned comes from 'fromUnicode' only even -+ * when toUnicode is true ! -+ */ -+ if (toUnicode) { -+ /* encoding => UTF-16 => UTF-8 */ -+ ucnv_convertEx(cd->utf8, cd->uconv, &ucv_out, ucv_out + *outlen, -+ &ucv_in, ucv_in + *inlen, NULL, NULL, NULL, NULL, -+ 0, TRUE, &err); -+ } else { -+ /* UTF-8 => UTF-16 => encoding */ -+ ucnv_convertEx(cd->uconv, cd->utf8, &ucv_out, ucv_out + *outlen, -+ &ucv_in, ucv_in + *inlen, NULL, NULL, NULL, NULL, -+ 0, TRUE, &err); -+ } -+ *inlen = ucv_in - (const char*) in; -+ *outlen = ucv_out - (char *) out; -+ if (U_SUCCESS(err)) -+ return 0; -+ if (err == U_BUFFER_OVERFLOW_ERROR) -+ return -1; -+ if (err == U_INVALID_CHAR_FOUND || err == U_ILLEGAL_CHAR_FOUND) -+ return -2; -+ /* if (err == U_TRUNCATED_CHAR_FOUND) */ -+ return -3; -+} -+#endif /* LIBXML_ICU_ENABLED */ -+ -+/************************************************************************ -+ * * - * The real API used by libxml for on-the-fly conversion * - * * - ************************************************************************/ -@@ -1810,6 +1964,16 @@ xmlCharEncFirstLineInt(xmlCharEncodingHandler *handler, xmlBufferPtr out, - if (ret == -1) ret = -3; - } - #endif /* LIBXML_ICONV_ENABLED */ -+#ifdef LIBXML_ICU_ENABLED -+ else if (handler->uconv_in != NULL) { -+ ret = xmlUconvWrapper(handler->uconv_in, 1, &out->content[out->use], -+ &written, in->content, &toconv); -+ xmlBufferShrink(in, toconv); -+ out->use += written; -+ out->content[out->use] = 0; -+ if (ret == -1) ret = -3; -+ } -+#endif /* LIBXML_ICU_ENABLED */ - #ifdef DEBUG_ENCODING - switch (ret) { - case 0: -@@ -1915,6 +2079,17 @@ xmlCharEncInFunc(xmlCharEncodingHandler * handler, xmlBufferPtr out, - ret = -3; - } - #endif /* LIBXML_ICONV_ENABLED */ -+#ifdef LIBXML_ICU_ENABLED -+ else if (handler->uconv_in != NULL) { -+ ret = xmlUconvWrapper(handler->uconv_in, 1, &out->content[out->use], -+ &written, in->content, &toconv); -+ xmlBufferShrink(in, toconv); -+ out->use += written; -+ out->content[out->use] = 0; -+ if (ret == -1) -+ ret = -3; -+ } -+#endif /* LIBXML_ICU_ENABLED */ - switch (ret) { - case 0: - #ifdef DEBUG_ENCODING -@@ -2015,6 +2190,15 @@ retry: - out->content[out->use] = 0; - } - #endif /* LIBXML_ICONV_ENABLED */ -+#ifdef LIBXML_ICU_ENABLED -+ else if (handler->uconv_out != NULL) { -+ ret = xmlUconvWrapper(handler->uconv_out, 0, -+ &out->content[out->use], -+ &written, NULL, &toconv); -+ out->use += written; -+ out->content[out->use] = 0; -+ } -+#endif /* LIBXML_ICU_ENABLED */ - #ifdef DEBUG_ENCODING - xmlGenericError(xmlGenericErrorContext, - "initialized encoder\n"); -@@ -2061,6 +2245,26 @@ retry: - } - } - #endif /* LIBXML_ICONV_ENABLED */ -+#ifdef LIBXML_ICU_ENABLED -+ else if (handler->uconv_out != NULL) { -+ ret = xmlUconvWrapper(handler->uconv_out, 0, -+ &out->content[out->use], -+ &written, in->content, &toconv); -+ xmlBufferShrink(in, toconv); -+ out->use += written; -+ writtentot += written; -+ out->content[out->use] = 0; -+ if (ret == -1) { -+ if (written > 0) { -+ /* -+ * Can be a limitation of iconv -+ */ -+ goto retry; -+ } -+ ret = -3; -+ } -+ } -+#endif /* LIBXML_ICU_ENABLED */ - else { - xmlEncodingErr(XML_I18N_NO_OUTPUT, - "xmlCharEncOutFunc: no output function !\n", NULL); -@@ -2173,6 +2377,22 @@ xmlCharEncCloseFunc(xmlCharEncodingHandler *handler) { - xmlFree(handler); - } - #endif /* LIBXML_ICONV_ENABLED */ -+#ifdef LIBXML_ICU_ENABLED -+ if ((handler->uconv_out != NULL) || (handler->uconv_in != NULL)) { -+ if (handler->name != NULL) -+ xmlFree(handler->name); -+ handler->name = NULL; -+ if (handler->uconv_out != NULL) { -+ closeIcuConverter(handler->uconv_out); -+ handler->uconv_out = NULL; -+ } -+ if (handler->uconv_in != NULL) { -+ closeIcuConverter(handler->uconv_in); -+ handler->uconv_in = NULL; -+ } -+ xmlFree(handler); -+ } -+#endif - #ifdef DEBUG_ENCODING - if (ret) - xmlGenericError(xmlGenericErrorContext, -@@ -2248,6 +2468,22 @@ xmlByteConsumed(xmlParserCtxtPtr ctxt) { - cur += toconv; - } while (ret == -2); - #endif -+#ifdef LIBXML_ICU_ENABLED -+ } else if (handler->uconv_out != NULL) { -+ do { -+ toconv = in->end - cur; -+ written = 32000; -+ ret = xmlUconvWrapper(handler->uconv_out, 0, &convbuf[0], -+ &written, cur, &toconv); -+ if (ret < 0) { -+ if (written > 0) -+ ret = -2; -+ else -+ return(-1); -+ } -+ unused += written; -+ cur += toconv; -+ } while (ret == -2); - } else { - /* could not find a converter */ - return(-1); -@@ -2259,8 +2495,9 @@ xmlByteConsumed(xmlParserCtxtPtr ctxt) { - } - return(in->consumed + (in->cur - in->base)); - } -+#endif - --#ifndef LIBXML_ICONV_ENABLED -+#if !defined(LIBXML_ICONV_ENABLED) && !defined(LIBXML_ICU_ENABLED) - #ifdef LIBXML_ISO8859X_ENABLED - - /** -diff --git a/third_party/libxml/include/libxml/encoding.h b/third_party/libxml/include/libxml/encoding.h -index c74b25f..b5f8b48 100644 ---- a/third_party/libxml/include/libxml/encoding.h -+++ b/third_party/libxml/include/libxml/encoding.h -@@ -26,6 +26,24 @@ - - #ifdef LIBXML_ICONV_ENABLED - #include -+#else -+#ifdef LIBXML_ICU_ENABLED -+#include -+#if 0 -+/* Forward-declare UConverter here rather than pulling in -+ * to prevent unwanted ICU symbols being exposed to users of libxml2. -+ * One particular case is Qt4 conflicting on UChar32. -+ */ -+#include -+struct UConverter; -+typedef struct UConverter UConverter; -+#ifdef _MSC_VER -+typedef wchar_t UChar; -+#else -+typedef uint16_t UChar; -+#endif -+#endif -+#endif - #endif - #ifdef __cplusplus - extern "C" { -@@ -125,6 +143,13 @@ typedef int (* xmlCharEncodingOutputFunc)(unsigned char *out, int *outlen, - * Block defining the handlers for non UTF-8 encodings. - * If iconv is supported, there are two extra fields. - */ -+#ifdef LIBXML_ICU_ENABLED -+struct _uconv_t { -+ UConverter *uconv; /* for conversion between an encoding and UTF-16 */ -+ UConverter *utf8; /* for conversion between UTF-8 and UTF-16 */ -+}; -+typedef struct _uconv_t uconv_t; -+#endif - - typedef struct _xmlCharEncodingHandler xmlCharEncodingHandler; - typedef xmlCharEncodingHandler *xmlCharEncodingHandlerPtr; -@@ -136,6 +161,10 @@ struct _xmlCharEncodingHandler { - iconv_t iconv_in; - iconv_t iconv_out; - #endif /* LIBXML_ICONV_ENABLED */ -+#ifdef LIBXML_ICU_ENABLED -+ uconv_t *uconv_in; -+ uconv_t *uconv_out; -+#endif /* LIBXML_ICU_ENABLED */ - }; - - #ifdef __cplusplus -diff --git a/third_party/libxml/include/libxml/parser.h b/third_party/libxml/include/libxml/parser.h -index dd79c42..3580b63 100644 ---- a/third_party/libxml/include/libxml/parser.h -+++ b/third_party/libxml/include/libxml/parser.h -@@ -1222,6 +1222,7 @@ typedef enum { - XML_WITH_DEBUG_MEM = 29, - XML_WITH_DEBUG_RUN = 30, - XML_WITH_ZLIB = 31, -+ XML_WITH_ICU = 32, - XML_WITH_NONE = 99999 /* just to be sure of allocation size */ - } xmlFeature; - -diff --git a/third_party/libxml/include/libxml/xmlversion.h.in b/third_party/libxml/include/libxml/xmlversion.h.in -index 4739f3a..de310ab 100644 ---- a/third_party/libxml/include/libxml/xmlversion.h.in -+++ b/third_party/libxml/include/libxml/xmlversion.h.in -@@ -269,6 +269,15 @@ XMLPUBFUN void XMLCALL xmlCheckVersion(int version); - #endif - - /** -+ * LIBXML_ICU_ENABLED: -+ * -+ * Whether icu support is available -+ */ -+#if @WITH_ICU@ -+#define LIBXML_ICU_ENABLED -+#endif -+ -+/** - * LIBXML_ISO8859X_ENABLED: - * - * Whether ISO-8859-* support is made available in case iconv is not -diff --git a/third_party/libxml/parser.c b/third_party/libxml/parser.c -index 85e7599..3ba2a06 100644 ---- a/third_party/libxml/parser.c -+++ b/third_party/libxml/parser.c -@@ -954,6 +954,12 @@ xmlHasFeature(xmlFeature feature) - #else - return(0); - #endif -+ case XML_WITH_ICU: -+#ifdef LIBXML_ICU_ENABLED -+ return(1); -+#else -+ return(0); -+#endif - default: - break; - } diff --git a/third_party/libxml/patches/icu-configure b/third_party/libxml/patches/icu-configure deleted file mode 100644 index f7e2395a3a0a2..0000000000000 --- a/third_party/libxml/patches/icu-configure +++ /dev/null @@ -1,28 +0,0 @@ -Modifications to configure.in: -- set the WITH_ICU flag unconditionally -- only output files we use - -Index: libxml/configure.in -=================================================================== ---- libxml.orig/configure.in 2010-07-09 15:00:21.600113911 -0700 -+++ libxml/configure.in 2010-07-09 15:02:50.299108047 -0700 -@@ -1229,6 +1229,9 @@ - fi - AC_SUBST(WITH_OUTPUT) - -+WITH_ICU=1 -+AC_SUBST(WITH_ICU) -+ - WITH_ICONV=0 - if test "$with_iconv" = "no" ; then - echo Disabling ICONV support -@@ -1456,7 +1459,7 @@ - ln -s Copyright COPYING - - # keep on one line for cygwin c.f. #130896 --AC_OUTPUT(libxml2.spec:libxml.spec.in Makefile include/Makefile include/libxml/Makefile doc/Makefile doc/examples/Makefile doc/devhelp/Makefile example/Makefile python/Makefile python/tests/Makefile xstc/Makefile include/libxml/xmlversion.h xml2-config libxml-2.0.pc libxml-2.0-uninstalled.pc python/setup.py) -+AC_OUTPUT(include/libxml/xmlversion.h xml2-config) - --chmod +x xml2-config python/setup.py -+chmod +x xml2-config - echo Done configuring diff --git a/third_party/libxml/patches/icu-win32 b/third_party/libxml/patches/icu-win32 deleted file mode 100644 index 2ea8f2127baff..0000000000000 --- a/third_party/libxml/patches/icu-win32 +++ /dev/null @@ -1,68 +0,0 @@ -diff --git a/third_party/libxml/win32/Makefile.msvc b/third_party/libxml/win32/Makefile.msvc -index 2409905..253c46e 100644 ---- a/third_party/libxml/win32/Makefile.msvc -+++ b/third_party/libxml/win32/Makefile.msvc -@@ -71,6 +71,9 @@ LIBS = $(LIBS) wsock32.lib ws2_32.lib - !if "$(WITH_ICONV)" == "1" - LIBS = $(LIBS) iconv.lib - !endif -+!if "$(WITH_ICU)" == "1" -+LIBS = $(LIBS) icu.lib -+!endif - !if "$(WITH_ZLIB)" == "1" - LIBS = $(LIBS) zdll.lib - !endif -diff --git a/third_party/libxml/win32/configure.js b/third_party/libxml/win32/configure.js -index e71d2af..75def3f 100644 ---- a/third_party/libxml/win32/configure.js -+++ b/third_party/libxml/win32/configure.js -@@ -40,6 +40,7 @@ var withXpath = true; - var withXptr = true; - var withXinclude = true; - var withIconv = true; -+var withIcu = false; - var withIso8859x = false; - var withZlib = false; - var withDebug = true; -@@ -124,6 +125,7 @@ function usage() - txt += " xptr: Enable XPointer support (" + (withXptr? "yes" : "no") + ")\n"; - txt += " xinclude: Enable XInclude support (" + (withXinclude? "yes" : "no") + ")\n"; - txt += " iconv: Enable iconv support (" + (withIconv? "yes" : "no") + ")\n"; -+ txt += " icu: Enable icu support (" + (withIcu? "yes" : "no") + ")\n"; - txt += " iso8859x: Enable ISO8859X support (" + (withIso8859x? "yes" : "no") + ")\n"; - txt += " zlib: Enable zlib support (" + (withZlib? "yes" : "no") + ")\n"; - txt += " xml_debug: Enable XML debbugging module (" + (withDebug? "yes" : "no") + ")\n"; -@@ -233,6 +235,7 @@ function discoverVersion() - vf.WriteLine("WITH_XPTR=" + (withXptr? "1" : "0")); - vf.WriteLine("WITH_XINCLUDE=" + (withXinclude? "1" : "0")); - vf.WriteLine("WITH_ICONV=" + (withIconv? "1" : "0")); -+ vf.WriteLine("WITH_ICU=" + (withIcu? "1" : "0")); - vf.WriteLine("WITH_ISO8859X=" + (withIso8859x? "1" : "0")); - vf.WriteLine("WITH_ZLIB=" + (withZlib? "1" : "0")); - vf.WriteLine("WITH_DEBUG=" + (withDebug? "1" : "0")); -@@ -319,6 +322,8 @@ function configureLibxml() - of.WriteLine(s.replace(/\@WITH_XINCLUDE\@/, withXinclude? "1" : "0")); - } else if (s.search(/\@WITH_ICONV\@/) != -1) { - of.WriteLine(s.replace(/\@WITH_ICONV\@/, withIconv? "1" : "0")); -+ } else if (s.search(/\@WITH_ICU\@/) != -1) { -+ of.WriteLine(s.replace(/\@WITH_ICU\@/, withIcu? "1" : "0")); - } else if (s.search(/\@WITH_ISO8859X\@/) != -1) { - of.WriteLine(s.replace(/\@WITH_ISO8859X\@/, withIso8859x? "1" : "0")); - } else if (s.search(/\@WITH_ZLIB\@/) != -1) { -@@ -462,6 +467,8 @@ for (i = 0; (i < WScript.Arguments.length) && (error == 0); i++) { - withXinclude = strToBool(arg.substring(opt.length + 1, arg.length)); - else if (opt == "iconv") - withIconv = strToBool(arg.substring(opt.length + 1, arg.length)); -+ else if (opt == "icu") -+ withIcu = strToBool(arg.substring(opt.length + 1, arg.length)); - else if (opt == "iso8859x") - withIso8859x = strToBool(arg.substring(opt.length + 1, arg.length)); - else if (opt == "zlib") -@@ -646,6 +653,7 @@ txtOut += " XPath support: " + boolToStr(withXpath) + "\n"; - txtOut += " XPointer support: " + boolToStr(withXptr) + "\n"; - txtOut += " XInclude support: " + boolToStr(withXinclude) + "\n"; - txtOut += " iconv support: " + boolToStr(withIconv) + "\n"; -+txtOut += " icu support: " + boolToStr(withIcu) + "\n"; - txtOut += " iso8859x support: " + boolToStr(withIso8859x) + "\n"; - txtOut += " zlib support: " + boolToStr(withZlib) + "\n"; - txtOut += " Debugging module: " + boolToStr(withDebug) + "\n"; diff --git a/third_party/libxml/patches/snprintf_config b/third_party/libxml/patches/snprintf_config deleted file mode 100644 index 9d1ca628be2a0..0000000000000 --- a/third_party/libxml/patches/snprintf_config +++ /dev/null @@ -1,14 +0,0 @@ -diff --git a/third_party/libxml/win32/config.h b/third_party/libxml/win32/config.h -index 3fc9be5..5112ce6 100644 ---- a/third_party/libxml/win32/config.h -+++ b/third_party/libxml/win32/config.h -@@ -95,7 +95,9 @@ static int isnan (double d) { - - #if defined(_MSC_VER) - #define mkdir(p,m) _mkdir(p) -+#if _MSC_VER < 1900 - #define snprintf _snprintf -+#endif - #if _MSC_VER < 1500 - #define vsnprintf(b,c,f,a) _vsnprintf(b,c,f,a) - #endif diff --git a/third_party/libxml/patches/snprintf_win32config b/third_party/libxml/patches/snprintf_win32config deleted file mode 100644 index 3fec790de461a..0000000000000 --- a/third_party/libxml/patches/snprintf_win32config +++ /dev/null @@ -1,14 +0,0 @@ -diff --git a/third_party/libxml/src/include/win32config.h b/third_party/libxml/src/include/win32config.h -index 3fc9be5..5112ce6 100644 ---- a/third_party/libxml/src/include/win32config.h -+++ b/third_party/libxml/src/include/win32config.h -@@ -95,7 +95,9 @@ static int isnan (double d) { - - #if defined(_MSC_VER) - #define mkdir(p,m) _mkdir(p) -+#if _MSC_VER < 1900 - #define snprintf _snprintf -+#endif - #if _MSC_VER < 1500 - #define vsnprintf(b,c,f,a) _vsnprintf(b,c,f,a) - #endif diff --git a/third_party/libxml/patches/win32-clobber-makefile b/third_party/libxml/patches/win32-clobber-makefile deleted file mode 100644 index 2f7fbb45eb7b9..0000000000000 --- a/third_party/libxml/patches/win32-clobber-makefile +++ /dev/null @@ -1,19 +0,0 @@ -Index: libxml/win32/configure.js -=================================================================== ---- libxml.orig/win32/configure.js 2010-07-09 14:56:07.769093841 -0700 -+++ libxml/win32/configure.js 2010-07-09 15:36:48.590268611 -0700 -@@ -611,7 +611,13 @@ - makefile = ".\\Makefile.mingw"; - else if (compiler == "bcb") - makefile = ".\\Makefile.bcb"; --fso.CopyFile(makefile, ".\\Makefile", true); -+var new_makefile = ".\\Makefile"; -+var f = fso.FileExists(new_makefile); -+if (f) { -+ var t = fso.GetFile(new_makefile); -+ t.Attributes = 0; -+} -+fso.CopyFile(makefile, new_makefile, true); - WScript.Echo("Created Makefile."); - // Create the config.h. - var confighsrc = "..\\include\\win32config.h"; diff --git a/third_party/libxml/patches/win32-no-posix-error-codes b/third_party/libxml/patches/win32-no-posix-error-codes deleted file mode 100644 index 38be7f7c513d2..0000000000000 --- a/third_party/libxml/patches/win32-no-posix-error-codes +++ /dev/null @@ -1,14 +0,0 @@ -diff --git a/third_party/libxml/src/libxml.h b/third_party/libxml/src/libxml.h -index 1656ac2..f8a368c 100644 ---- a/third_party/libxml/src/libxml.h -+++ b/third_party/libxml/src/libxml.h -@@ -17,6 +17,9 @@ - #define _FILE_OFFSET_BITS 64 - #endif - #endif -+#ifndef _CRT_NO_POSIX_ERROR_CODES -+#define _CRT_NO_POSIX_ERROR_CODES -+#endif - - #if defined(macintosh) - #include "config-mac.h" diff --git a/third_party/libxml/patches/xmlregexp-bogus-cast b/third_party/libxml/patches/xmlregexp-bogus-cast deleted file mode 100644 index aaebfaa69e6a5..0000000000000 --- a/third_party/libxml/patches/xmlregexp-bogus-cast +++ /dev/null @@ -1,15 +0,0 @@ -Change bogus '(unsigned long)' cast to '(unsigned short)' - -Index: libxml/xmlregexp.c -=================================================================== ---- libxml.orig/xmlregexp.c 2010-07-09 14:16:36.990430641 -0700 -+++ libxml/xmlregexp.c 2010-07-09 14:16:40.939742007 -0700 -@@ -6470,7 +6470,7 @@ - if (name != NULL) { - value += 30 * (*name); - while ((ch = *name++) != 0) { -- value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch); -+ value = value ^ ((value << 5) + (value >> 3) + (unsigned short)ch); - } - } - return (value); diff --git a/third_party/libxml/src/ChangeLog b/third_party/libxml/src/ChangeLog index 36045e60c858c..08725dd3d2e8b 100644 --- a/third_party/libxml/src/ChangeLog +++ b/third_party/libxml/src/ChangeLog @@ -8139,7 +8139,7 @@ Wed Dec 10 11:16:29 CET 2003 Daniel Veillard Tue Dec 9 23:50:23 CET 2003 Daniel Veillard - * entities.c: fixed an XML entites content serialization + * entities.c: fixed an XML entities content serialization potentially triggered by XInclude, see #126817 Tue Dec 9 16:12:50 CET 2003 Daniel Veillard diff --git a/third_party/libxml/src/Copyright b/third_party/libxml/src/Copyright index 417e95531fd96..d61318502caf9 100644 --- a/third_party/libxml/src/Copyright +++ b/third_party/libxml/src/Copyright @@ -2,7 +2,7 @@ Except where otherwise noted in the source code (e.g. the files hash.c, list.c and the trio files, which are covered by a similar licence but with different Copyright notices) all the files are: - Copyright (C) 1998-2003 Daniel Veillard. All Rights Reserved. + Copyright (C) 1998-2012 Daniel Veillard. All Rights Reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -17,11 +17,7 @@ all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT- NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -DANIEL VEILLARD BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON- -NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of Daniel Veillard shall not -be used in advertising or otherwise to promote the sale, use or other deal- -ings in this Software without prior written authorization from him. - +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/third_party/libxml/src/DOCBparser.c b/third_party/libxml/src/DOCBparser.c index 3573743352c10..f12511b9e8acb 100644 --- a/third_party/libxml/src/DOCBparser.c +++ b/third_party/libxml/src/DOCBparser.c @@ -53,7 +53,7 @@ docbEncodeEntities(unsigned char *out ATTRIBUTE_UNUSED, /** * docbParseDocument: * @ctxt: an SGML parser context - * + * * parse an SGML document (and build a tree if using the standard SAX * interface). * @@ -163,12 +163,12 @@ docbCreatePushParserCtxt(docbSAXHandlerPtr sax ATTRIBUTE_UNUSED, * @cur: a pointer to an array of xmlChar * @encoding: a free form C string describing the SGML document encoding, or NULL * @sax: the SAX handler block - * @userData: if using SAX, this pointer will be provided on callbacks. + * @userData: if using SAX, this pointer will be provided on callbacks. * * parse an SGML in-memory document and build a tree. * It use the given SAX function block to handle the parsing callback. * If sax is NULL, fallback to the default DOM tree building routines. - * + * * Returns the resulting document tree */ @@ -196,7 +196,7 @@ docbSAXParseDoc(xmlChar * cur ATTRIBUTE_UNUSED, * @encoding: a free form C string describing the SGML document encoding, or NULL * * parse an SGML in-memory document and build a tree. - * + * * Returns the resulting document tree */ @@ -221,7 +221,7 @@ docbParseDoc(xmlChar * cur ATTRIBUTE_UNUSED, * @filename: the filename * @encoding: the SGML document encoding, or NULL * - * Create a parser context for a file content. + * Create a parser context for a file content. * Automatic support for ZLIB/Compress compressed document is provided * by default if found at compile-time. * @@ -247,7 +247,7 @@ docbCreateFileParserCtxt(const char *filename ATTRIBUTE_UNUSED, * @filename: the filename * @encoding: a free form C string describing the SGML document encoding, or NULL * @sax: the SAX handler block - * @userData: if using SAX, this pointer will be provided on callbacks. + * @userData: if using SAX, this pointer will be provided on callbacks. * * parse an SGML file and build a tree. Automatic support for ZLIB/Compress * compressed document is provided by default if found at compile-time. diff --git a/third_party/libxml/src/HTMLparser.c b/third_party/libxml/src/HTMLparser.c index 42dc776ae587e..d329d3b540761 100644 --- a/third_party/libxml/src/HTMLparser.c +++ b/third_party/libxml/src/HTMLparser.c @@ -44,6 +44,9 @@ #include #include +#include "buf.h" +#include "enc.h" + #define HTML_MAX_NAMELEN 1000 #define HTML_PARSER_BIG_BUFFER_SIZE 1000 #define HTML_PARSER_BUFFER_SIZE 100 @@ -727,7 +730,7 @@ static const char* const map_contents[] = { BLOCK, "area", NULL } ; static const char* const name_attr[] = { "name", NULL } ; static const char* const action_attr[] = { "action", NULL } ; static const char* const blockli_elt[] = { BLOCK, "li", NULL } ; -static const char* const meta_attrs[] = { I18N, "http-equiv", "name", "scheme", NULL } ; +static const char* const meta_attrs[] = { I18N, "http-equiv", "name", "scheme", "charset", NULL } ; static const char* const content_attr[] = { "content", NULL } ; static const char* const type_attr[] = { "type", NULL } ; static const char* const noframes_content[] = { "body", FLOW MODIFIER, NULL } ; @@ -1080,9 +1083,9 @@ static const char * const htmlStartClose[] = { "menu", "p", "head", "ul", NULL, "p", "p", "head", "h1", "h2", "h3", "h4", "h5", "h6", FONTSTYLE, NULL, "div", "p", "head", NULL, -"noscript", "p", "head", NULL, +"noscript", "p", NULL, "center", "font", "b", "i", "p", "head", NULL, -"a", "a", NULL, +"a", "a", "head", NULL, "caption", "p", NULL, "colgroup", "caption", "colgroup", "col", "p", NULL, "col", "caption", "col", "p", NULL, @@ -1100,6 +1103,43 @@ static const char * const htmlStartClose[] = { "option", "option", NULL, "fieldset", "legend", "p", "head", "h1", "h2", "h3", "h4", "h5", "h6", "pre", "listing", "xmp", "a", NULL, +/* most tags in in FONTSTYLE, PHRASE and SPECIAL should close */ +"tt", "head", NULL, +"i", "head", NULL, +"b", "head", NULL, +"u", "head", NULL, +"s", "head", NULL, +"strike", "head", NULL, +"big", "head", NULL, +"small", "head", NULL, + +"em", "head", NULL, +"strong", "head", NULL, +"dfn", "head", NULL, +"code", "head", NULL, +"samp", "head", NULL, +"kbd", "head", NULL, +"var", "head", NULL, +"cite", "head", NULL, +"abbr", "head", NULL, +"acronym", "head", NULL, + +/* "a" */ +"img", "head", NULL, +/* "applet" */ +/* "embed" */ +/* "object" */ +"font", "head", NULL, +/* "basefont" */ +"br", "head", NULL, +/* "script" */ +"map", "head", NULL, +"q", "head", NULL, +"sub", "head", NULL, +"sup", "head", NULL, +"span", "head", NULL, +"bdo", "head", NULL, +"iframe", "head", NULL, NULL }; @@ -1137,7 +1177,7 @@ static const char *const htmlScriptAttributes[] = { "onfocus", "onblur", "onsubmit", - "onrest", + "onreset", "onchange", "onselect" }; @@ -2887,9 +2927,11 @@ htmlParseScript(htmlParserCtxtPtr ctxt) { } if ((!(IS_CHAR_CH(cur))) && (!((cur == 0) && (ctxt->progressive)))) { - htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR, - "Invalid char in CDATA 0x%X\n", cur); - NEXT; + htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR, + "Invalid char in CDATA 0x%X\n", cur); + if (ctxt->input->cur < ctxt->input->end) { + NEXT; + } } if ((nbchar != 0) && (ctxt->sax != NULL) && (!ctxt->disableSAX)) { @@ -2939,9 +2981,14 @@ htmlParseCharData(htmlParserCtxtPtr ctxt) { */ if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) { if (areBlanks(ctxt, buf, nbchar)) { - if (ctxt->sax->ignorableWhitespace != NULL) - ctxt->sax->ignorableWhitespace(ctxt->userData, - buf, nbchar); + if (ctxt->keepBlanks) { + if (ctxt->sax->characters != NULL) + ctxt->sax->characters(ctxt->userData, buf, nbchar); + } else { + if (ctxt->sax->ignorableWhitespace != NULL) + ctxt->sax->ignorableWhitespace(ctxt->userData, + buf, nbchar); + } } else { htmlCheckParagraph(ctxt); if (ctxt->sax->characters != NULL) @@ -2972,8 +3019,14 @@ htmlParseCharData(htmlParserCtxtPtr ctxt) { */ if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) { if (areBlanks(ctxt, buf, nbchar)) { - if (ctxt->sax->ignorableWhitespace != NULL) - ctxt->sax->ignorableWhitespace(ctxt->userData, buf, nbchar); + if (ctxt->keepBlanks) { + if (ctxt->sax->characters != NULL) + ctxt->sax->characters(ctxt->userData, buf, nbchar); + } else { + if (ctxt->sax->ignorableWhitespace != NULL) + ctxt->sax->ignorableWhitespace(ctxt->userData, + buf, nbchar); + } } else { htmlCheckParagraph(ctxt); if (ctxt->sax->characters != NULL) @@ -3275,7 +3328,7 @@ htmlParseCharRef(htmlParserCtxtPtr ctxt) { val = val * 16 + (CUR - 'A') + 10; else { htmlParseErr(ctxt, XML_ERR_INVALID_HEX_CHARREF, - "htmlParseCharRef: missing semicolumn\n", + "htmlParseCharRef: missing semicolon\n", NULL, NULL); break; } @@ -3290,7 +3343,7 @@ htmlParseCharRef(htmlParserCtxtPtr ctxt) { val = val * 10 + (CUR - '0'); else { htmlParseErr(ctxt, XML_ERR_INVALID_DEC_CHARREF, - "htmlParseCharRef: missing semicolumn\n", + "htmlParseCharRef: missing semicolon\n", NULL, NULL); break; } @@ -3433,34 +3486,26 @@ htmlParseAttribute(htmlParserCtxtPtr ctxt, xmlChar **value) { } /** - * htmlCheckEncoding: + * htmlCheckEncodingDirect: * @ctxt: an HTML parser context * @attvalue: the attribute value * - * Checks an http-equiv attribute from a Meta tag to detect + * Checks an attribute value to detect * the encoding * If a new encoding is detected the parser is switched to decode * it and pass UTF8 */ static void -htmlCheckEncoding(htmlParserCtxtPtr ctxt, const xmlChar *attvalue) { - const xmlChar *encoding; +htmlCheckEncodingDirect(htmlParserCtxtPtr ctxt, const xmlChar *encoding) { - if ((ctxt == NULL) || (attvalue == NULL)) + if ((ctxt == NULL) || (encoding == NULL) || + (ctxt->options & HTML_PARSE_IGNORE_ENC)) return; /* do not change encoding */ if (ctxt->input->encoding != NULL) return; - encoding = xmlStrcasestr(attvalue, BAD_CAST"charset="); - if (encoding != NULL) { - encoding += 8; - } else { - encoding = xmlStrcasestr(attvalue, BAD_CAST"charset ="); - if (encoding != NULL) - encoding += 9; - } if (encoding != NULL) { xmlCharEncoding enc; xmlCharEncodingHandlerPtr handler; @@ -3498,7 +3543,9 @@ htmlCheckEncoding(htmlParserCtxtPtr ctxt, const xmlChar *attvalue) { xmlSwitchToEncoding(ctxt, handler); ctxt->charset = XML_CHAR_ENCODING_UTF8; } else { - ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING; + htmlParseErr(ctxt, XML_ERR_UNSUPPORTED_ENCODING, + "htmlCheckEncoding: unknown encoding %s\n", + encoding, NULL); } } @@ -3513,23 +3560,50 @@ htmlCheckEncoding(htmlParserCtxtPtr ctxt, const xmlChar *attvalue) { * convert as much as possible to the parser reading buffer. */ processed = ctxt->input->cur - ctxt->input->base; - xmlBufferShrink(ctxt->input->buf->buffer, processed); - nbchars = xmlCharEncInFunc(ctxt->input->buf->encoder, - ctxt->input->buf->buffer, - ctxt->input->buf->raw); + xmlBufShrink(ctxt->input->buf->buffer, processed); + nbchars = xmlCharEncInput(ctxt->input->buf, 1); if (nbchars < 0) { htmlParseErr(ctxt, XML_ERR_INVALID_ENCODING, "htmlCheckEncoding: encoder error\n", NULL, NULL); } - ctxt->input->base = - ctxt->input->cur = ctxt->input->buf->buffer->content; - ctxt->input->end = - &ctxt->input->base[ctxt->input->buf->buffer->use]; + xmlBufResetInput(ctxt->input->buf->buffer, ctxt->input); } } } +/** + * htmlCheckEncoding: + * @ctxt: an HTML parser context + * @attvalue: the attribute value + * + * Checks an http-equiv attribute from a Meta tag to detect + * the encoding + * If a new encoding is detected the parser is switched to decode + * it and pass UTF8 + */ +static void +htmlCheckEncoding(htmlParserCtxtPtr ctxt, const xmlChar *attvalue) { + const xmlChar *encoding; + + if (!attvalue) + return; + + encoding = xmlStrcasestr(attvalue, BAD_CAST"charset"); + if (encoding != NULL) { + encoding += 7; + } + /* + * skip blank + */ + if (encoding && IS_BLANK_CH(*encoding)) + encoding = xmlStrcasestr(attvalue, BAD_CAST"="); + if (encoding && *encoding == '=') { + encoding ++; + htmlCheckEncodingDirect(ctxt, encoding); + } +} + /** * htmlCheckMeta: * @ctxt: an HTML parser context @@ -3554,6 +3628,8 @@ htmlCheckMeta(htmlParserCtxtPtr ctxt, const xmlChar **atts) { if ((value != NULL) && (!xmlStrcasecmp(att, BAD_CAST"http-equiv")) && (!xmlStrcasecmp(value, BAD_CAST"Content-Type"))) http = 1; + else if ((value != NULL) && (!xmlStrcasecmp(att, BAD_CAST"charset"))) + htmlCheckEncodingDirect(ctxt, value); else if ((value != NULL) && (!xmlStrcasecmp(att, BAD_CAST"content"))) content = value; att = atts[i++]; @@ -3595,13 +3671,13 @@ htmlParseStartTag(htmlParserCtxtPtr ctxt) { int i; int discardtag = 0; - if (ctxt->instate == XML_PARSER_EOF) - return(-1); if ((ctxt == NULL) || (ctxt->input == NULL)) { htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR, "htmlParseStartTag: context error\n", NULL, NULL); return -1; } + if (ctxt->instate == XML_PARSER_EOF) + return(-1); if (CUR != '<') return -1; NEXT; @@ -3883,6 +3959,7 @@ htmlParseEndTag(htmlParserCtxtPtr ctxt) if ((oldname != NULL) && (xmlStrEqual(oldname, name))) { if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL)) ctxt->sax->endElement(ctxt->userData, name); + htmlNodeInfoPop(ctxt); htmlnamePop(ctxt); ret = 1; } else { @@ -4289,7 +4366,7 @@ static void htmlParseElementInternal(htmlParserCtxtPtr ctxt) { const xmlChar *name; const htmlElemDesc * info; - htmlParserNodeInfo node_info; + htmlParserNodeInfo node_info = { 0, }; int failed; if ((ctxt == NULL) || (ctxt->input == NULL)) { @@ -4670,7 +4747,7 @@ htmlParseDocument(htmlParserCtxtPtr ctxt) { if ((ctxt->sax) && (ctxt->sax->endDocument != NULL)) ctxt->sax->endDocument(ctxt->userData); - if (ctxt->myDoc != NULL) { + if ((!(ctxt->options & HTML_PARSE_NODEFDTD)) && (ctxt->myDoc != NULL)) { dtd = xmlGetIntSubset(ctxt->myDoc); if (dtd == NULL) ctxt->myDoc->intSubset = @@ -4875,9 +4952,7 @@ htmlCreateMemoryParserCtxt(const char *buffer, int size) { input->filename = NULL; input->buf = buf; - input->base = input->buf->buffer->content; - input->cur = input->buf->buffer->content; - input->end = &input->buf->buffer->content[input->buf->buffer->use]; + xmlBufResetInput(buf->buffer, input); inputPush(ctxt, input); return(ctxt); @@ -4994,8 +5069,8 @@ htmlParseLookupSequence(htmlParserCtxtPtr ctxt, xmlChar first, buf = in->base; len = in->length; } else { - buf = in->buf->buffer->content; - len = in->buf->buffer->use; + buf = xmlBufContent(in->buf->buffer); + len = xmlBufUse(in->buf->buffer); } /* take into account the sequence length */ @@ -5087,13 +5162,13 @@ htmlParseLookupSequence(htmlParserCtxtPtr ctxt, xmlChar first, * @stop: Array of chars, which stop the lookup. * @stopLen: Length of stop-Array * - * Try to find if any char of the stop-Array is available in the input + * Try to find if any char of the stop-Array is available in the input * stream. * This function has a side effect of (possibly) incrementing ctxt->checkIndex * to avoid rescanning sequences of bytes, it DOES change the state of the * parser, do not use liberally. * - * Returns the index to the current parsing point if a stopChar + * Returns the index to the current parsing point if a stopChar * is available, -1 otherwise. */ static int @@ -5121,8 +5196,8 @@ htmlParseLookupChars(htmlParserCtxtPtr ctxt, const xmlChar * stop, buf = in->base; len = in->length; } else { - buf = in->buf->buffer->content; - len = in->buf->buffer->use; + buf = xmlBufContent(in->buf->buffer); + len = xmlBufUse(in->buf->buffer); } for (; base < len; base++) { @@ -5171,6 +5246,8 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { int avail = 0; xmlChar cur, next; + htmlParserNodeInfo node_info; + #ifdef DEBUG_PUSH switch (ctxt->instate) { case XML_PARSER_EOF: @@ -5231,7 +5308,7 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { if (in->buf == NULL) avail = in->length - (in->cur - in->base); else - avail = in->buf->buffer->use - (in->cur - in->base); + avail = xmlBufUse(in->buf->buffer) - (in->cur - in->base); if ((avail == 0) && (terminate)) { htmlAutoCloseOnEnd(ctxt); if ((ctxt->nameNr == 0) && (ctxt->instate != XML_PARSER_EOF)) { @@ -5267,7 +5344,7 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { if (in->buf == NULL) avail = in->length - (in->cur - in->base); else - avail = in->buf->buffer->use - (in->cur - in->base); + avail = xmlBufUse(in->buf->buffer) - (in->cur - in->base); } if ((ctxt->sax) && (ctxt->sax->setDocumentLocator)) ctxt->sax->setDocumentLocator(ctxt->userData, @@ -5309,11 +5386,24 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { if (in->buf == NULL) avail = in->length - (in->cur - in->base); else - avail = in->buf->buffer->use - (in->cur - in->base); - if (avail < 2) + avail = xmlBufUse(in->buf->buffer) - (in->cur - in->base); + /* + * no chars in buffer + */ + if (avail < 1) goto done; + /* + * not enouth chars in buffer + */ + if (avail < 2) { + if (!terminate) + goto done; + else + next = ' '; + } else { + next = in->cur[1]; + } cur = in->cur[0]; - next = in->cur[1]; if ((cur == '<') && (next == '!') && (in->cur[2] == '-') && (in->cur[3] == '-')) { if ((!terminate) && @@ -5369,7 +5459,7 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { if (in->buf == NULL) avail = in->length - (in->cur - in->base); else - avail = in->buf->buffer->use - (in->cur - in->base); + avail = xmlBufUse(in->buf->buffer) - (in->cur - in->base); if (avail < 2) goto done; cur = in->cur[0]; @@ -5410,7 +5500,7 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { if (in->buf == NULL) avail = in->length - (in->cur - in->base); else - avail = in->buf->buffer->use - (in->cur - in->base); + avail = xmlBufUse(in->buf->buffer) - (in->cur - in->base); if (avail < 1) goto done; cur = in->cur[0]; @@ -5463,8 +5553,22 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { int failed; const htmlElemDesc * info; - if (avail < 2) + /* + * no chars in buffer + */ + if (avail < 1) goto done; + /* + * not enouth chars in buffer + */ + if (avail < 2) { + if (!terminate) + goto done; + else + next = ' '; + } else { + next = in->cur[1]; + } cur = in->cur[0]; if (cur != '<') { ctxt->instate = XML_PARSER_CONTENT; @@ -5474,7 +5578,7 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { #endif break; } - if (in->cur[1] == '/') { + if (next == '/') { ctxt->instate = XML_PARSER_END_TAG; ctxt->checkIndex = 0; #ifdef DEBUG_PUSH @@ -5487,6 +5591,14 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { (htmlParseLookupSequence(ctxt, '>', 0, 0, 0, 1) < 0)) goto done; + /* Capture start position */ + if (ctxt->record_info) { + node_info.begin_pos = ctxt->input->consumed + + (CUR_PTR - ctxt->input->base); + node_info.begin_line = ctxt->input->line; + } + + failed = htmlParseStartTag(ctxt); name = ctxt->name; if ((failed == -1) || @@ -5536,6 +5648,9 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { htmlnamePop(ctxt); } + if (ctxt->record_info) + htmlNodeInfoPush(ctxt, &node_info); + ctxt->instate = XML_PARSER_CONTENT; #ifdef DEBUG_PUSH xmlGenericError(xmlGenericErrorContext, @@ -5552,6 +5667,10 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { ctxt->sax->endElement(ctxt->userData, name); htmlnamePop(ctxt); } + + if (ctxt->record_info) + htmlNodeInfoPush(ctxt, &node_info); + ctxt->instate = XML_PARSER_CONTENT; #ifdef DEBUG_PUSH xmlGenericError(xmlGenericErrorContext, @@ -5579,9 +5698,15 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { if ((cur != '<') && (cur != '&')) { if (ctxt->sax != NULL) { if (IS_BLANK_CH(cur)) { - if (ctxt->sax->ignorableWhitespace != NULL) - ctxt->sax->ignorableWhitespace( - ctxt->userData, &cur, 1); + if (ctxt->keepBlanks) { + if (ctxt->sax->characters != NULL) + ctxt->sax->characters( + ctxt->userData, &cur, 1); + } else { + if (ctxt->sax->ignorableWhitespace != NULL) + ctxt->sax->ignorableWhitespace( + ctxt->userData, &cur, 1); + } } else { htmlCheckParagraph(ctxt); if (ctxt->sax->characters != NULL) @@ -5609,7 +5734,7 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { int idx; xmlChar val; - idx = htmlParseLookupSequence(ctxt, '<', '/', 0, 0, 1); + idx = htmlParseLookupSequence(ctxt, '<', '/', 0, 0, 0); if (idx < 0) goto done; val = in->cur[idx + 2]; @@ -5866,7 +5991,7 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { ctxt->sax->endDocument(ctxt->userData); } } - if ((ctxt->myDoc != NULL) && + if ((!(ctxt->options & HTML_PARSE_NODEFDTD)) && (ctxt->myDoc != NULL) && ((terminate) || (ctxt->instate == XML_PARSER_EOF) || (ctxt->instate == XML_PARSER_EPILOG))) { xmlDtdPtr dtd; @@ -5904,8 +6029,8 @@ htmlParseChunk(htmlParserCtxtPtr ctxt, const char *chunk, int size, } if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) && (ctxt->input->buf != NULL) && (ctxt->instate != XML_PARSER_EOF)) { - int base = ctxt->input->base - ctxt->input->buf->buffer->content; - int cur = ctxt->input->cur - ctxt->input->base; + size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer, ctxt->input); + size_t cur = ctxt->input->cur - ctxt->input->base; int res; res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk); @@ -5914,10 +6039,7 @@ htmlParseChunk(htmlParserCtxtPtr ctxt, const char *chunk, int size, ctxt->disableSAX = 1; return (XML_PARSER_EOF); } - ctxt->input->base = ctxt->input->buf->buffer->content + base; - ctxt->input->cur = ctxt->input->base + cur; - ctxt->input->end = - &ctxt->input->buf->buffer->content[ctxt->input->buf->buffer->use]; + xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur); #ifdef DEBUG_PUSH xmlGenericError(xmlGenericErrorContext, "HPP: pushed %d\n", size); #endif @@ -5932,13 +6054,16 @@ htmlParseChunk(htmlParserCtxtPtr ctxt, const char *chunk, int size, if ((in->encoder != NULL) && (in->buffer != NULL) && (in->raw != NULL)) { int nbchars; + size_t base = xmlBufGetInputBase(in->buffer, ctxt->input); + size_t current = ctxt->input->cur - ctxt->input->base; - nbchars = xmlCharEncInFunc(in->encoder, in->buffer, in->raw); + nbchars = xmlCharEncInput(in, terminate); if (nbchars < 0) { htmlParseErr(ctxt, XML_ERR_INVALID_ENCODING, "encoder error\n", NULL, NULL); return(XML_ERR_INVALID_ENCODING); } + xmlBufSetInputBaseCur(in->buffer, ctxt->input, base, current); } } } @@ -6032,24 +6157,18 @@ htmlCreatePushParserCtxt(htmlSAXHandlerPtr sax, void *user_data, inputStream->filename = (char *) xmlCanonicPath((const xmlChar *) filename); inputStream->buf = buf; - inputStream->base = inputStream->buf->buffer->content; - inputStream->cur = inputStream->buf->buffer->content; - inputStream->end = - &inputStream->buf->buffer->content[inputStream->buf->buffer->use]; + xmlBufResetInput(buf->buffer, inputStream); inputPush(ctxt, inputStream); if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) && (ctxt->input->buf != NULL)) { - int base = ctxt->input->base - ctxt->input->buf->buffer->content; - int cur = ctxt->input->cur - ctxt->input->base; + size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer, ctxt->input); + size_t cur = ctxt->input->cur - ctxt->input->base; xmlParserInputBufferPush(ctxt->input->buf, size, chunk); - ctxt->input->base = ctxt->input->buf->buffer->content + base; - ctxt->input->cur = ctxt->input->base + cur; - ctxt->input->end = - &ctxt->input->buf->buffer->content[ctxt->input->buf->buffer->use]; + xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur); #ifdef DEBUG_PUSH xmlGenericError(xmlGenericErrorContext, "HPP: pushed %d\n", size); #endif @@ -6169,12 +6288,16 @@ htmlCreateFileParserCtxt(const char *filename, const char *encoding) /* set encoding */ if (encoding) { - content = xmlMallocAtomic (xmlStrlen(content_line) + strlen(encoding) + 1); - if (content) { - strcpy ((char *)content, (char *)content_line); - strcat ((char *)content, (char *)encoding); - htmlCheckEncoding (ctxt, content); - xmlFree (content); + size_t l = strlen(encoding); + + if (l < 1000) { + content = xmlMallocAtomic (xmlStrlen(content_line) + l + 1); + if (content) { + strcpy ((char *)content, (char *)content_line); + strcat ((char *)content, (char *)encoding); + htmlCheckEncoding (ctxt, content); + xmlFree (content); + } } } @@ -6451,6 +6574,7 @@ htmlCtxtReset(htmlParserCtxtPtr ctxt) ctxt->wellFormed = 1; ctxt->nsWellFormed = 1; + ctxt->disableSAX = 0; ctxt->valid = 1; ctxt->vctxt.userData = ctxt; ctxt->vctxt.error = xmlParserValidityError; @@ -6530,6 +6654,18 @@ htmlCtxtUseOptions(htmlParserCtxtPtr ctxt, int options) ctxt->options |= XML_PARSE_HUGE; options -= XML_PARSE_HUGE; } + if (options & HTML_PARSE_NODEFDTD) { + ctxt->options |= HTML_PARSE_NODEFDTD; + options -= HTML_PARSE_NODEFDTD; + } + if (options & HTML_PARSE_IGNORE_ENC) { + ctxt->options |= HTML_PARSE_IGNORE_ENC; + options -= HTML_PARSE_IGNORE_ENC; + } + if (options & HTML_PARSE_NOIMPLIED) { + ctxt->options |= HTML_PARSE_NOIMPLIED; + options -= HTML_PARSE_NOIMPLIED; + } ctxt->dictNames = 0; return (options); } @@ -6676,6 +6812,7 @@ htmlReadFd(int fd, const char *URL, const char *encoding, int options) if (fd < 0) return (NULL); + xmlInitParser(); xmlInitParser(); input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE); @@ -6723,8 +6860,11 @@ htmlReadIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose, input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, XML_CHAR_ENCODING_NONE); - if (input == NULL) + if (input == NULL) { + if (ioclose != NULL) + ioclose(ioctx); return (NULL); + } ctxt = htmlNewParserCtxt(); if (ctxt == NULL) { xmlFreeParserInputBuffer(input); @@ -6763,6 +6903,7 @@ htmlCtxtReadDoc(htmlParserCtxtPtr ctxt, const xmlChar * cur, return (NULL); if (ctxt == NULL) return (NULL); + xmlInitParser(); htmlCtxtReset(ctxt); @@ -6796,6 +6937,7 @@ htmlCtxtReadFile(htmlParserCtxtPtr ctxt, const char *filename, return (NULL); if (ctxt == NULL) return (NULL); + xmlInitParser(); htmlCtxtReset(ctxt); @@ -6832,6 +6974,7 @@ htmlCtxtReadMemory(htmlParserCtxtPtr ctxt, const char *buffer, int size, return (NULL); if (buffer == NULL) return (NULL); + xmlInitParser(); htmlCtxtReset(ctxt); @@ -6874,6 +7017,7 @@ htmlCtxtReadFd(htmlParserCtxtPtr ctxt, int fd, return (NULL); if (ctxt == NULL) return (NULL); + xmlInitParser(); htmlCtxtReset(ctxt); @@ -6918,13 +7062,17 @@ htmlCtxtReadIO(htmlParserCtxtPtr ctxt, xmlInputReadCallback ioread, return (NULL); if (ctxt == NULL) return (NULL); + xmlInitParser(); htmlCtxtReset(ctxt); input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, XML_CHAR_ENCODING_NONE); - if (input == NULL) + if (input == NULL) { + if (ioclose != NULL) + ioclose(ioctx); return (NULL); + } stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE); if (stream == NULL) { xmlFreeParserInputBuffer(input); diff --git a/third_party/libxml/src/HTMLtree.c b/third_party/libxml/src/HTMLtree.c index b5085836b900a..5c57fc572bc32 100644 --- a/third_party/libxml/src/HTMLtree.c +++ b/third_party/libxml/src/HTMLtree.c @@ -30,16 +30,18 @@ #include #include +#include "buf.h" + /************************************************************************ * * - * Getting/Setting encoding meta tags * + * Getting/Setting encoding meta tags * * * ************************************************************************/ /** * htmlGetMetaEncoding: * @doc: the document - * + * * Encoding definition lookup in the Meta tags * * Returns the current encoding as flagged in the HTML source @@ -126,17 +128,17 @@ htmlGetMetaEncoding(htmlDocPtr doc) { found_content: encoding = xmlStrstr(content, BAD_CAST"charset="); - if (encoding == NULL) + if (encoding == NULL) encoding = xmlStrstr(content, BAD_CAST"Charset="); - if (encoding == NULL) + if (encoding == NULL) encoding = xmlStrstr(content, BAD_CAST"CHARSET="); if (encoding != NULL) { encoding += 8; } else { encoding = xmlStrstr(content, BAD_CAST"charset ="); - if (encoding == NULL) + if (encoding == NULL) encoding = xmlStrstr(content, BAD_CAST"Charset ="); - if (encoding == NULL) + if (encoding == NULL) encoding = xmlStrstr(content, BAD_CAST"CHARSET ="); if (encoding != NULL) encoding += 9; @@ -151,7 +153,7 @@ htmlGetMetaEncoding(htmlDocPtr doc) { * htmlSetMetaEncoding: * @doc: the document * @encoding: the encoding string - * + * * Sets the current encoding in the Meta tags * NOTE: this will not change the document content encoding, just * the META flag associated. @@ -164,6 +166,7 @@ htmlSetMetaEncoding(htmlDocPtr doc, const xmlChar *encoding) { const xmlChar *content = NULL; char newcontent[100]; + newcontent[0] = 0; if (doc == NULL) return(-1); @@ -244,7 +247,7 @@ htmlSetMetaEncoding(htmlDocPtr doc, const xmlChar *encoding) { http = 1; else { - if ((value != NULL) && + if ((value != NULL) && (!xmlStrcasecmp(attr->name, BAD_CAST"content"))) content = value; } @@ -278,8 +281,13 @@ htmlSetMetaEncoding(htmlDocPtr doc, const xmlChar *encoding) { xmlNewProp(meta, BAD_CAST"content", BAD_CAST newcontent); } } else { + /* remove the meta tag if NULL is passed */ + if (encoding == NULL) { + xmlUnlinkNode(meta); + xmlFreeNode(meta); + } /* change the document only if there is a real encoding change */ - if (xmlStrcasestr(content, encoding) == NULL) { + else if (xmlStrcasestr(content, encoding) == NULL) { xmlSetProp(meta, BAD_CAST"content", BAD_CAST newcontent); } } @@ -308,7 +316,7 @@ static const char* htmlBooleanAttrs[] = { * @name: the name of the attribute to check * * Determine if a given attribute is a boolean attribute. - * + * * returns: false if the attribute is not boolean, true otherwise. */ int @@ -332,7 +340,7 @@ xmlOutputBufferPtr xmlAllocOutputBufferInternal(xmlCharEncodingHandlerPtr encoder); /************************************************************************ * * - * Output error handlers * + * Output error handlers * * * ************************************************************************/ /** @@ -381,17 +389,13 @@ htmlSaveErr(int code, xmlNodePtr node, const char *extra) /************************************************************************ * * - * Dumping HTML tree content to a simple buffer * + * Dumping HTML tree content to a simple buffer * * * ************************************************************************/ -static int -htmlNodeDumpFormat(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, - int format); - /** - * htmlNodeDumpFormat: - * @buf: the HTML buffer output + * htmlBufNodeDumpFormat: + * @buf: the xmlBufPtr output * @doc: the document * @cur: the current node * @format: should formatting spaces been added @@ -400,10 +404,10 @@ htmlNodeDumpFormat(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, * * Returns the number of byte written or -1 in case of error */ -static int -htmlNodeDumpFormat(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, +static size_t +htmlBufNodeDumpFormat(xmlBufPtr buf, xmlDocPtr doc, xmlNodePtr cur, int format) { - unsigned int use; + size_t use; int ret; xmlOutputBufferPtr outbuf; @@ -426,10 +430,10 @@ htmlNodeDumpFormat(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, outbuf->context = NULL; outbuf->written = 0; - use = buf->use; + use = xmlBufUse(buf); htmlNodeDumpFormatOutput(outbuf, doc, cur, NULL, format); xmlFree(outbuf); - ret = buf->use - use; + ret = xmlBufUse(buf) - use; return (ret); } @@ -446,9 +450,24 @@ htmlNodeDumpFormat(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, */ int htmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur) { + xmlBufPtr buffer; + size_t ret; + + if ((buf == NULL) || (cur == NULL)) + return(-1); + xmlInitParser(); + buffer = xmlBufFromBuffer(buf); + if (buffer == NULL) + return(-1); + + ret = htmlBufNodeDumpFormat(buffer, doc, cur, 1); - return(htmlNodeDumpFormat(buf, doc, cur, 1)); + xmlBufBackToBuffer(buffer); + + if (ret > INT_MAX) + return(-1); + return((int) ret); } /** @@ -481,7 +500,7 @@ htmlNodeDumpFileFormat(FILE *out, xmlDocPtr doc, if (enc != XML_CHAR_ENCODING_UTF8) { handler = xmlFindCharEncodingHandler(encoding); if (handler == NULL) - return(-1); + htmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, encoding); } } @@ -493,7 +512,7 @@ htmlNodeDumpFileFormat(FILE *out, xmlDocPtr doc, if (handler == NULL) handler = xmlFindCharEncodingHandler("ascii"); - /* + /* * save the content to a temp buffer. */ buf = xmlOutputBufferCreateFile(out, handler); @@ -562,11 +581,9 @@ htmlDocDumpMemoryFormat(xmlDocPtr cur, xmlChar**mem, int *size, int format) { } handler = xmlFindCharEncodingHandler(encoding); - if (handler == NULL) { - *mem = NULL; - *size = 0; - return; - } + if (handler == NULL) + htmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, encoding); + } else { handler = xmlFindCharEncodingHandler(encoding); } @@ -587,15 +604,15 @@ htmlDocDumpMemoryFormat(xmlDocPtr cur, xmlChar**mem, int *size, int format) { return; } - htmlDocContentDumpFormatOutput(buf, cur, NULL, format); + htmlDocContentDumpFormatOutput(buf, cur, NULL, format); xmlOutputBufferFlush(buf); if (buf->conv != NULL) { - *size = buf->conv->use; - *mem = xmlStrndup(buf->conv->content, *size); + *size = xmlBufUse(buf->conv); + *mem = xmlStrndup(xmlBufContent(buf->conv), *size); } else { - *size = buf->buffer->use; - *mem = xmlStrndup(buf->buffer->content, *size); + *size = xmlBufUse(buf->buffer); + *mem = xmlStrndup(xmlBufContent(buf->buffer), *size); } (void)xmlOutputBufferClose(buf); } @@ -617,7 +634,7 @@ htmlDocDumpMemory(xmlDocPtr cur, xmlChar**mem, int *size) { /************************************************************************ * * - * Dumping HTML tree content to an I/O output buffer * + * Dumping HTML tree content to an I/O output buffer * * * ************************************************************************/ @@ -628,7 +645,7 @@ void xmlNsListDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur); * @buf: the HTML buffer output * @doc: the document * @encoding: the encoding string - * + * * TODO: check whether encoding is needed * * Dump the HTML document DTD, if any. @@ -646,14 +663,14 @@ htmlDtdDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlOutputBufferWriteString(buf, (const char *)cur->name); if (cur->ExternalID != NULL) { xmlOutputBufferWriteString(buf, " PUBLIC "); - xmlBufferWriteQuotedString(buf->buffer, cur->ExternalID); + xmlBufWriteQuotedString(buf->buffer, cur->ExternalID); if (cur->SystemID != NULL) { xmlOutputBufferWriteString(buf, " "); - xmlBufferWriteQuotedString(buf->buffer, cur->SystemID); - } + xmlBufWriteQuotedString(buf->buffer, cur->SystemID); + } } else if (cur->SystemID != NULL) { xmlOutputBufferWriteString(buf, " SYSTEM "); - xmlBufferWriteQuotedString(buf->buffer, cur->SystemID); + xmlBufWriteQuotedString(buf->buffer, cur->SystemID); } xmlOutputBufferWriteString(buf, ">\n"); } @@ -673,9 +690,10 @@ htmlAttrDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur, xmlChar *value; /* - * TODO: The html output method should not escape a & character - * occurring in an attribute value immediately followed by - * a { character (see Section B.7.1 of the HTML 4.0 Recommendation). + * The html output method should not escape a & character + * occurring in an attribute value immediately followed by + * a { character (see Section B.7.1 of the HTML 4.0 Recommendation). + * This is implemented in xmlEncodeEntitiesReentrant */ if (cur == NULL) { @@ -698,20 +716,51 @@ htmlAttrDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur, (!xmlStrcasecmp(cur->name, BAD_CAST "src")) || ((!xmlStrcasecmp(cur->name, BAD_CAST "name")) && (!xmlStrcasecmp(cur->parent->name, BAD_CAST "a"))))) { - xmlChar *escaped; xmlChar *tmp = value; + /* xmlURIEscapeStr() escapes '"' so it can be safely used. */ + xmlBufCCat(buf->buffer, "\""); while (IS_BLANK_CH(*tmp)) tmp++; - escaped = xmlURIEscapeStr(tmp, BAD_CAST"@/:=?;#%&,+"); - if (escaped != NULL) { - xmlBufferWriteQuotedString(buf->buffer, escaped); - xmlFree(escaped); - } else { - xmlBufferWriteQuotedString(buf->buffer, value); + /* URI Escape everything, except server side includes. */ + for ( ; ; ) { + xmlChar *escaped; + xmlChar endChar; + xmlChar *end = NULL; + xmlChar *start = (xmlChar *)xmlStrstr(tmp, BAD_CAST ""); + if (end != NULL) { + *start = '\0'; + } + } + + /* Escape the whole string, or until start (set to '\0'). */ + escaped = xmlURIEscapeStr(tmp, BAD_CAST"@/:=?;#%&,+"); + if (escaped != NULL) { + xmlBufCat(buf->buffer, escaped); + xmlFree(escaped); + } else { + xmlBufCat(buf->buffer, tmp); + } + + if (end == NULL) { /* Everything has been written. */ + break; + } + + /* Do not escape anything within server side includes. */ + *start = '<'; /* Restore the first character of "") */ + endChar = *end; + *end = '\0'; + xmlBufCat(buf->buffer, start); + *end = endChar; + tmp = end; } + + xmlBufCCat(buf->buffer, "\""); } else { - xmlBufferWriteQuotedString(buf->buffer, value); + xmlBufWriteQuotedString(buf->buffer, value); } xmlFree(value); } else { @@ -1061,7 +1110,7 @@ htmlDocDump(FILE *f, xmlDocPtr cur) { handler = xmlFindCharEncodingHandler(encoding); if (handler == NULL) - return(-1); + htmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, encoding); } else { handler = xmlFindCharEncodingHandler(encoding); } @@ -1101,7 +1150,7 @@ htmlSaveFile(const char *filename, xmlDocPtr cur) { if ((cur == NULL) || (filename == NULL)) return(-1); - + xmlInitParser(); encoding = (const char *) htmlGetMetaEncoding(cur); @@ -1120,7 +1169,7 @@ htmlSaveFile(const char *filename, xmlDocPtr cur) { handler = xmlFindCharEncodingHandler(encoding); if (handler == NULL) - return(-1); + htmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, encoding); } } @@ -1132,7 +1181,7 @@ htmlSaveFile(const char *filename, xmlDocPtr cur) { if (handler == NULL) handler = xmlFindCharEncodingHandler("ascii"); - /* + /* * save the content to a temp buffer. */ buf = xmlOutputBufferCreateFilename(filename, handler, cur->compression); @@ -1152,7 +1201,7 @@ htmlSaveFile(const char *filename, xmlDocPtr cur) { * @encoding: the document encoding * * Dump an HTML document to a file using a given encoding. - * + * * returns: the number of byte written or -1 in case of failure. */ int @@ -1181,7 +1230,7 @@ htmlSaveFileFormat(const char *filename, xmlDocPtr cur, handler = xmlFindCharEncodingHandler(encoding); if (handler == NULL) - return(-1); + htmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, encoding); } htmlSetMetaEncoding(cur, (const xmlChar *) encoding); } else { @@ -1196,7 +1245,7 @@ htmlSaveFileFormat(const char *filename, xmlDocPtr cur, if (handler == NULL) handler = xmlFindCharEncodingHandler("ascii"); - /* + /* * save the content to a temp buffer. */ buf = xmlOutputBufferCreateFilename(filename, handler, 0); @@ -1216,7 +1265,7 @@ htmlSaveFileFormat(const char *filename, xmlDocPtr cur, * * Dump an HTML document to a file using a given encoding * and formatting returns/spaces are added. - * + * * returns: the number of byte written or -1 in case of failure. */ int diff --git a/third_party/libxml/src/INSTALL b/third_party/libxml/src/INSTALL deleted file mode 100644 index 7d1c323beae76..0000000000000 --- a/third_party/libxml/src/INSTALL +++ /dev/null @@ -1,365 +0,0 @@ -Installation Instructions -************************* - -Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, -2006, 2007, 2008, 2009 Free Software Foundation, Inc. - - Copying and distribution of this file, with or without modification, -are permitted in any medium without royalty provided the copyright -notice and this notice are preserved. This file is offered as-is, -without warranty of any kind. - -Basic Installation -================== - - Briefly, the shell commands `./configure; make; make install' should -configure, build, and install this package. The following -more-detailed instructions are generic; see the `README' file for -instructions specific to this package. Some packages provide this -`INSTALL' file but do not implement all of the features documented -below. The lack of an optional feature in a given package is not -necessarily a bug. More recommendations for GNU packages can be found -in *note Makefile Conventions: (standards)Makefile Conventions. - - The `configure' shell script attempts to guess correct values for -various system-dependent variables used during compilation. It uses -those values to create a `Makefile' in each directory of the package. -It may also create one or more `.h' files containing system-dependent -definitions. Finally, it creates a shell script `config.status' that -you can run in the future to recreate the current configuration, and a -file `config.log' containing compiler output (useful mainly for -debugging `configure'). - - It can also use an optional file (typically called `config.cache' -and enabled with `--cache-file=config.cache' or simply `-C') that saves -the results of its tests to speed up reconfiguring. Caching is -disabled by default to prevent problems with accidental use of stale -cache files. - - If you need to do unusual things to compile the package, please try -to figure out how `configure' could check whether to do them, and mail -diffs or instructions to the address given in the `README' so they can -be considered for the next release. If you are using the cache, and at -some point `config.cache' contains results you don't want to keep, you -may remove or edit it. - - The file `configure.ac' (or `configure.in') is used to create -`configure' by a program called `autoconf'. You need `configure.ac' if -you want to change it or regenerate `configure' using a newer version -of `autoconf'. - - The simplest way to compile this package is: - - 1. `cd' to the directory containing the package's source code and type - `./configure' to configure the package for your system. - - Running `configure' might take a while. While running, it prints - some messages telling which features it is checking for. - - 2. Type `make' to compile the package. - - 3. Optionally, type `make check' to run any self-tests that come with - the package, generally using the just-built uninstalled binaries. - - 4. Type `make install' to install the programs and any data files and - documentation. When installing into a prefix owned by root, it is - recommended that the package be configured and built as a regular - user, and only the `make install' phase executed with root - privileges. - - 5. Optionally, type `make installcheck' to repeat any self-tests, but - this time using the binaries in their final installed location. - This target does not install anything. Running this target as a - regular user, particularly if the prior `make install' required - root privileges, verifies that the installation completed - correctly. - - 6. You can remove the program binaries and object files from the - source code directory by typing `make clean'. To also remove the - files that `configure' created (so you can compile the package for - a different kind of computer), type `make distclean'. There is - also a `make maintainer-clean' target, but that is intended mainly - for the package's developers. If you use it, you may have to get - all sorts of other programs in order to regenerate files that came - with the distribution. - - 7. Often, you can also type `make uninstall' to remove the installed - files again. In practice, not all packages have tested that - uninstallation works correctly, even though it is required by the - GNU Coding Standards. - - 8. Some packages, particularly those that use Automake, provide `make - distcheck', which can by used by developers to test that all other - targets like `make install' and `make uninstall' work correctly. - This target is generally not run by end users. - -Compilers and Options -===================== - - Some systems require unusual options for compilation or linking that -the `configure' script does not know about. Run `./configure --help' -for details on some of the pertinent environment variables. - - You can give `configure' initial values for configuration parameters -by setting variables in the command line or in the environment. Here -is an example: - - ./configure CC=c99 CFLAGS=-g LIBS=-lposix - - *Note Defining Variables::, for more details. - -Compiling For Multiple Architectures -==================================== - - You can compile the package for more than one kind of computer at the -same time, by placing the object files for each architecture in their -own directory. To do this, you can use GNU `make'. `cd' to the -directory where you want the object files and executables to go and run -the `configure' script. `configure' automatically checks for the -source code in the directory that `configure' is in and in `..'. This -is known as a "VPATH" build. - - With a non-GNU `make', it is safer to compile the package for one -architecture at a time in the source code directory. After you have -installed the package for one architecture, use `make distclean' before -reconfiguring for another architecture. - - On MacOS X 10.5 and later systems, you can create libraries and -executables that work on multiple system types--known as "fat" or -"universal" binaries--by specifying multiple `-arch' options to the -compiler but only a single `-arch' option to the preprocessor. Like -this: - - ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ - CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ - CPP="gcc -E" CXXCPP="g++ -E" - - This is not guaranteed to produce working output in all cases, you -may have to build one architecture at a time and combine the results -using the `lipo' tool if you have problems. - -Installation Names -================== - - By default, `make install' installs the package's commands under -`/usr/local/bin', include files under `/usr/local/include', etc. You -can specify an installation prefix other than `/usr/local' by giving -`configure' the option `--prefix=PREFIX', where PREFIX must be an -absolute file name. - - You can specify separate installation prefixes for -architecture-specific files and architecture-independent files. If you -pass the option `--exec-prefix=PREFIX' to `configure', the package uses -PREFIX as the prefix for installing programs and libraries. -Documentation and other data files still use the regular prefix. - - In addition, if you use an unusual directory layout you can give -options like `--bindir=DIR' to specify different values for particular -kinds of files. Run `configure --help' for a list of the directories -you can set and what kinds of files go in them. In general, the -default for these options is expressed in terms of `${prefix}', so that -specifying just `--prefix' will affect all of the other directory -specifications that were not explicitly provided. - - The most portable way to affect installation locations is to pass the -correct locations to `configure'; however, many packages provide one or -both of the following shortcuts of passing variable assignments to the -`make install' command line to change installation locations without -having to reconfigure or recompile. - - The first method involves providing an override variable for each -affected directory. For example, `make install -prefix=/alternate/directory' will choose an alternate location for all -directory configuration variables that were expressed in terms of -`${prefix}'. Any directories that were specified during `configure', -but not in terms of `${prefix}', must each be overridden at install -time for the entire installation to be relocated. The approach of -makefile variable overrides for each directory variable is required by -the GNU Coding Standards, and ideally causes no recompilation. -However, some platforms have known limitations with the semantics of -shared libraries that end up requiring recompilation when using this -method, particularly noticeable in packages that use GNU Libtool. - - The second method involves providing the `DESTDIR' variable. For -example, `make install DESTDIR=/alternate/directory' will prepend -`/alternate/directory' before all installation names. The approach of -`DESTDIR' overrides is not required by the GNU Coding Standards, and -does not work on platforms that have drive letters. On the other hand, -it does better at avoiding recompilation issues, and works well even -when some directory options were not specified in terms of `${prefix}' -at `configure' time. - -Optional Features -================= - - If the package supports it, you can cause programs to be installed -with an extra prefix or suffix on their names by giving `configure' the -option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. - - Some packages pay attention to `--enable-FEATURE' options to -`configure', where FEATURE indicates an optional part of the package. -They may also pay attention to `--with-PACKAGE' options, where PACKAGE -is something like `gnu-as' or `x' (for the X Window System). The -`README' should mention any `--enable-' and `--with-' options that the -package recognizes. - - For packages that use the X Window System, `configure' can usually -find the X include and library files automatically, but if it doesn't, -you can use the `configure' options `--x-includes=DIR' and -`--x-libraries=DIR' to specify their locations. - - Some packages offer the ability to configure how verbose the -execution of `make' will be. For these packages, running `./configure ---enable-silent-rules' sets the default to minimal output, which can be -overridden with `make V=1'; while running `./configure ---disable-silent-rules' sets the default to verbose, which can be -overridden with `make V=0'. - -Particular systems -================== - - On HP-UX, the default C compiler is not ANSI C compatible. If GNU -CC is not installed, it is recommended to use the following options in -order to use an ANSI C compiler: - - ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" - -and if that doesn't work, install pre-built binaries of GCC for HP-UX. - - On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot -parse its `' header file. The option `-nodtk' can be used as -a workaround. If GNU CC is not installed, it is therefore recommended -to try - - ./configure CC="cc" - -and if that doesn't work, try - - ./configure CC="cc -nodtk" - - On Solaris, don't put `/usr/ucb' early in your `PATH'. This -directory contains several dysfunctional programs; working variants of -these programs are available in `/usr/bin'. So, if you need `/usr/ucb' -in your `PATH', put it _after_ `/usr/bin'. - - On Haiku, software installed for all users goes in `/boot/common', -not `/usr/local'. It is recommended to use the following options: - - ./configure --prefix=/boot/common - -Specifying the System Type -========================== - - There may be some features `configure' cannot figure out -automatically, but needs to determine by the type of machine the package -will run on. Usually, assuming the package is built to be run on the -_same_ architectures, `configure' can figure that out, but if it prints -a message saying it cannot guess the machine type, give it the -`--build=TYPE' option. TYPE can either be a short name for the system -type, such as `sun4', or a canonical name which has the form: - - CPU-COMPANY-SYSTEM - -where SYSTEM can have one of these forms: - - OS - KERNEL-OS - - See the file `config.sub' for the possible values of each field. If -`config.sub' isn't included in this package, then this package doesn't -need to know the machine type. - - If you are _building_ compiler tools for cross-compiling, you should -use the option `--target=TYPE' to select the type of system they will -produce code for. - - If you want to _use_ a cross compiler, that generates code for a -platform different from the build platform, you should specify the -"host" platform (i.e., that on which the generated programs will -eventually be run) with `--host=TYPE'. - -Sharing Defaults -================ - - If you want to set default values for `configure' scripts to share, -you can create a site shell script called `config.site' that gives -default values for variables like `CC', `cache_file', and `prefix'. -`configure' looks for `PREFIX/share/config.site' if it exists, then -`PREFIX/etc/config.site' if it exists. Or, you can set the -`CONFIG_SITE' environment variable to the location of the site script. -A warning: not all `configure' scripts look for a site script. - -Defining Variables -================== - - Variables not defined in a site shell script can be set in the -environment passed to `configure'. However, some packages may run -configure again during the build, and the customized values of these -variables may be lost. In order to avoid this problem, you should set -them in the `configure' command line, using `VAR=value'. For example: - - ./configure CC=/usr/local2/bin/gcc - -causes the specified `gcc' to be used as the C compiler (unless it is -overridden in the site shell script). - -Unfortunately, this technique does not work for `CONFIG_SHELL' due to -an Autoconf bug. Until the bug is fixed you can use this workaround: - - CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash - -`configure' Invocation -====================== - - `configure' recognizes the following options to control how it -operates. - -`--help' -`-h' - Print a summary of all of the options to `configure', and exit. - -`--help=short' -`--help=recursive' - Print a summary of the options unique to this package's - `configure', and exit. The `short' variant lists options used - only in the top level, while the `recursive' variant lists options - also present in any nested packages. - -`--version' -`-V' - Print the version of Autoconf used to generate the `configure' - script, and exit. - -`--cache-file=FILE' - Enable the cache: use and save the results of the tests in FILE, - traditionally `config.cache'. FILE defaults to `/dev/null' to - disable caching. - -`--config-cache' -`-C' - Alias for `--cache-file=config.cache'. - -`--quiet' -`--silent' -`-q' - Do not print messages saying which checks are being made. To - suppress all normal output, redirect it to `/dev/null' (any error - messages will still be shown). - -`--srcdir=DIR' - Look for the package's source code in directory DIR. Usually - `configure' can determine that directory automatically. - -`--prefix=DIR' - Use DIR as the installation prefix. *note Installation Names:: - for more details, including other options available for fine-tuning - the installation locations. - -`--no-create' -`-n' - Run the configure checks, but stop before creating any output - files. - -`configure' also accepts some other, not widely useful, options. Run -`configure --help' for more details. - diff --git a/third_party/libxml/src/Makefile.am b/third_party/libxml/src/Makefile.am new file mode 100644 index 0000000000000..70720f3db3d6f --- /dev/null +++ b/third_party/libxml/src/Makefile.am @@ -0,0 +1,1279 @@ +## Process this file with automake to produce Makefile.in + +ACLOCAL_AMFLAGS = -I m4 + +SUBDIRS = include . doc example xstc $(PYTHON_SUBDIR) + +DIST_SUBDIRS = include . doc example python xstc + +AM_CPPFLAGS = -I$(top_builddir)/include -I$(srcdir)/include + +AM_CFLAGS = $(THREAD_CFLAGS) $(Z_CFLAGS) $(LZMA_CFLAGS) + +noinst_PROGRAMS=testSchemas testRelax testSAX testHTML testXPath testURI \ + testThreads testC14N testAutomata testRegexp \ + testReader testapi testModule runtest runsuite testchar \ + testdict runxmlconf testrecurse testlimits + +bin_PROGRAMS = xmllint xmlcatalog + +bin_SCRIPTS=xml2-config + +lib_LTLIBRARIES = libxml2.la +libxml2_la_LIBADD = $(ICU_LIBS) $(THREAD_LIBS) $(Z_LIBS) $(LZMA_LIBS) $(ICONV_LIBS) $(M_LIBS) $(WIN32_EXTRA_LIBADD) + +if USE_VERSION_SCRIPT +LIBXML2_VERSION_SCRIPT = $(VERSION_SCRIPT_FLAGS)$(srcdir)/libxml2.syms +else +LIBXML2_VERSION_SCRIPT = +endif + +libxml2_la_LDFLAGS = $(CYGWIN_EXTRA_LDFLAGS) $(WIN32_EXTRA_LDFLAGS) \ + $(LIBXML2_VERSION_SCRIPT) \ + -version-info $(LIBXML_VERSION_INFO) \ + $(MODULE_PLATFORM_LIBS) + +if WITH_SAX1_SOURCES +docb_sources = DOCBparser.c +else +docb_sources = +endif + +if WITH_TRIO_SOURCES +trio_sources = triostr.c trio.c +else +trio_sources = +endif + +libxml2_la_SOURCES = SAX.c entities.c encoding.c error.c parserInternals.c \ + parser.c tree.c hash.c list.c xmlIO.c xmlmemory.c uri.c \ + valid.c xlink.c HTMLparser.c HTMLtree.c debugXML.c xpath.c \ + xpointer.c xinclude.c nanohttp.c nanoftp.c \ + $(docb_sources) \ + catalog.c globals.c threads.c c14n.c xmlstring.c buf.c \ + xmlregexp.c xmlschemas.c xmlschemastypes.c xmlunicode.c \ + $(trio_sources) \ + xmlreader.c relaxng.c dict.c SAX2.c \ + xmlwriter.c legacy.c chvalid.c pattern.c xmlsave.c \ + xmlmodule.c schematron.c xzlib.c + +DEPS = $(top_builddir)/libxml2.la +LDADDS = $(STATIC_BINARIES) $(top_builddir)/libxml2.la $(THREAD_LIBS) $(Z_LIBS) $(LZMA_LIBS) $(ICONV_LIBS) $(M_LIBS) $(WIN32_EXTRA_LIBADD) + + +man_MANS = xml2-config.1 libxml.3 + +m4datadir = $(datadir)/aclocal +m4data_DATA = libxml.m4 + +runtest_SOURCES=runtest.c +runtest_LDFLAGS = +runtest_DEPENDENCIES = $(DEPS) +runtest_LDADD= $(BASE_THREAD_LIBS) $(RDL_LIBS) $(LDADDS) + +testrecurse_SOURCES=testrecurse.c +testrecurse_LDFLAGS = +testrecurse_DEPENDENCIES = $(DEPS) +testrecurse_LDADD= $(BASE_THREAD_LIBS) $(RDL_LIBS) $(LDADDS) + +testlimits_SOURCES=testlimits.c +testlimits_LDFLAGS = +testlimits_DEPENDENCIES = $(DEPS) +testlimits_LDADD= $(BASE_THREAD_LIBS) $(RDL_LIBS) $(LDADDS) + +testchar_SOURCES=testchar.c +testchar_LDFLAGS = +testchar_DEPENDENCIES = $(DEPS) +testchar_LDADD= $(RDL_LIBS) $(LDADDS) + +testdict_SOURCES=testdict.c +testdict_LDFLAGS = +testdict_DEPENDENCIES = $(DEPS) +testdict_LDADD= $(RDL_LIBS) $(LDADDS) + +runsuite_SOURCES=runsuite.c +runsuite_LDFLAGS = +runsuite_DEPENDENCIES = $(DEPS) +runsuite_LDADD= $(RDL_LIBS) $(LDADDS) + +xmllint_SOURCES=xmllint.c +xmllint_LDFLAGS = +xmllint_DEPENDENCIES = $(DEPS) +xmllint_LDADD= $(RDL_LIBS) $(LDADDS) + +testSAX_SOURCES=testSAX.c +testSAX_LDFLAGS = +testSAX_DEPENDENCIES = $(DEPS) +testSAX_LDADD= $(LDADDS) + +testHTML_SOURCES=testHTML.c +testHTML_LDFLAGS = +testHTML_DEPENDENCIES = $(DEPS) +testHTML_LDADD= $(LDADDS) + +xmlcatalog_SOURCES=xmlcatalog.c +xmlcatalog_LDFLAGS = +xmlcatalog_DEPENDENCIES = $(DEPS) +xmlcatalog_LDADD = $(RDL_LIBS) $(LDADDS) + +testXPath_SOURCES=testXPath.c +testXPath_LDFLAGS = +testXPath_DEPENDENCIES = $(DEPS) +testXPath_LDADD= $(LDADDS) + +testC14N_SOURCES=testC14N.c +testC14N_LDFLAGS = +testC14N_DEPENDENCIES = $(DEPS) +testC14N_LDADD= $(LDADDS) + +if THREADS_W32 +testThreads_SOURCES = testThreadsWin32.c +else +testThreads_SOURCES = testThreads.c +endif +testThreads_LDFLAGS = +testThreads_DEPENDENCIES = $(DEPS) +testThreads_LDADD= $(BASE_THREAD_LIBS) $(LDADDS) + +testURI_SOURCES=testURI.c +testURI_LDFLAGS = +testURI_DEPENDENCIES = $(DEPS) +testURI_LDADD= $(LDADDS) + +testRegexp_SOURCES=testRegexp.c +testRegexp_LDFLAGS = +testRegexp_DEPENDENCIES = $(DEPS) +testRegexp_LDADD= $(LDADDS) + +testAutomata_SOURCES=testAutomata.c +testAutomata_LDFLAGS = +testAutomata_DEPENDENCIES = $(DEPS) +testAutomata_LDADD= $(LDADDS) + +testSchemas_SOURCES=testSchemas.c +testSchemas_LDFLAGS = +testSchemas_DEPENDENCIES = $(DEPS) +testSchemas_LDADD= $(LDADDS) + +testRelax_SOURCES=testRelax.c +testRelax_LDFLAGS = +testRelax_DEPENDENCIES = $(DEPS) +testRelax_LDADD= $(LDADDS) + +testReader_SOURCES=testReader.c +testReader_LDFLAGS = +testReader_DEPENDENCIES = $(DEPS) +testReader_LDADD= $(LDADDS) + +testModule_SOURCES=testModule.c +testModule_LDFLAGS = +testModule_DEPENDENCIES = $(DEPS) +testModule_LDADD= $(LDADDS) + +noinst_LTLIBRARIES = testdso.la +testdso_la_SOURCES = testdso.c +testdso_la_LDFLAGS = -module -no-undefined -avoid-version -rpath $(libdir) + +# that one forces the rebuild when "make rebuild" is run on doc/ +rebuild_testapi: + -@(if [ "$(PYTHON)" != "" ] ; then \ + $(PYTHON) $(srcdir)/gentest.py $(srcdir) ; fi ) + +# that one is just to make sure it is rebuilt if missing +# but adding the dependances generate mess +testapi.c: $(srcdir)/gentest.py + -@(if [ "$(PYTHON)" != "" ] ; then \ + $(PYTHON) $(srcdir)/gentest.py $(srcdir) ; fi ) + +BUILT_SOURCES = testapi.c + +testapi_SOURCES=testapi.c +testapi_LDFLAGS = +testapi_DEPENDENCIES = $(DEPS) +testapi_LDADD= $(LDADDS) + +runxmlconf_SOURCES=runxmlconf.c +runxmlconf_LDFLAGS = +runxmlconf_DEPENDENCIES = $(DEPS) +runxmlconf_LDADD= $(LDADDS) + +#testOOM_SOURCES=testOOM.c testOOMlib.h testOOMlib.c +#testOOM_LDFLAGS = +#testOOM_DEPENDENCIES = $(DEPS) +#testOOM_LDADD= $(LDADDS) + +runtests: + [ -d test ] || $(LN_S) $(srcdir)/test . + [ -d result ] || $(LN_S) $(srcdir)/result . + $(CHECKER) ./runtest$(EXEEXT) && $(CHECKER) ./testrecurse$(EXEEXT) &&$(CHECKER) ./testapi$(EXEEXT) && $(CHECKER) ./testchar$(EXEEXT)&& $(CHECKER) ./testdict$(EXEEXT) && $(CHECKER) ./runxmlconf$(EXEEXT) + @(if [ "$(PYTHON_SUBDIR)" != "" ] ; then cd python ; \ + $(MAKE) tests ; fi) + +check: all runtests + +check-valgrind valgrind: all + @echo '## Running the regression tests under Valgrind' + @echo '## Go get a cup of coffee it is gonna take a while ...' + $(MAKE) CHECKER='valgrind -q' runtests + +testall : tests SVGtests SAXtests + +tests: XMLtests XMLenttests NStests IDtests Errtests APItests $(READER_TEST) $(TEST_SAX) $(TEST_PUSH) $(TEST_HTML) $(TEST_PHTML) $(TEST_VALID) URItests $(TEST_PATTERN) $(TEST_XPATH) $(TEST_XPTR) $(TEST_XINCLUDE) $(TEST_C14N) $(TEST_DEBUG) $(TEST_CATALOG) $(TEST_REGEXPS) $(TEST_SCHEMAS) $(TEST_SCHEMATRON) $(TEST_THREADS) Timingtests $(TEST_VTIME) $(PYTHON_TESTS) $(TEST_MODULES) + @(if [ "$(PYTHON_SUBDIR)" != "" ] ; then cd python ; \ + $(MAKE) tests ; fi) + @(cd doc/examples ; $(MAKE) tests) + +APItests: testapi$(EXEEXT) + @echo "## Running the API regression tests this may take a little while" + -@($(CHECKER) $(top_builddir)/testapi -q) + +HTMLtests : testHTML$(EXEEXT) + @(echo > .memdump) + @echo "## HTML regression tests" + -@(for i in $(srcdir)/test/HTML/* ; do \ + name=`basename $$i`; \ + if [ ! -d $$i ] ; then \ + if [ ! -f $(srcdir)/result/HTML/$$name ] ; then \ + echo New test file $$name ; \ + $(CHECKER) $(top_builddir)/testHTML $$i > $(srcdir)/result/HTML/$$name 2>$(srcdir)/result/HTML/$$name.err ; \ + else \ + log=`$(CHECKER) $(top_builddir)/testHTML $$i > result.$$name 2> error.$$name ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + diff $(srcdir)/result/HTML/$$name result.$$name ; \ + diff -b $(srcdir)/result/HTML/$$name.err error.$$name ; \ + $(CHECKER) $(top_builddir)/testHTML result.$$name > result2.$$name 2>error.$$name ; \ + diff result.$$name result2.$$name` ; \ + if [ -n "$$log" ] ; then echo $$name result ; echo $$log ; fi ; \ + rm result.$$name result2.$$name error.$$name ; \ + fi ; fi ; done) + +HTMLPushtests : testHTML$(EXEEXT) + @echo "## Push HTML regression tests" + -@(for i in $(srcdir)/test/HTML/* ; do \ + name=`basename $$i`; \ + if [ ! -d $$i ] ; then \ + if [ ! -f $(srcdir)/result/HTML/$$name ] ; then \ + echo New test file $$name ; \ + $(CHECKER) $(top_builddir)/testHTML --push $$i > $(srcdir)/result/HTML/$$name 2>$(srcdir)/result/HTML/$$name.err ; \ + else \ + log=`$(CHECKER) $(top_builddir)/testHTML --push $$i > result.$$name 2> error.$$name ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + diff $(srcdir)/result/HTML/$$name result.$$name ; \ + cut -b 1-15 $(srcdir)/result/HTML/$$name.err > errorcut.$$name; \ + cut -b 1-15 error.$$name > errorcut2.$$name; \ + diff -b errorcut.$$name errorcut2.$$name ; \ + $(CHECKER) $(top_builddir)/testHTML --push result.$$name > result2.$$name 2>error.$$name ; \ + diff result.$$name result2.$$name` ; \ + if [ -n "$$log" ] ; then echo $$name result ; echo $$log ; fi ; \ + rm result.$$name result2.$$name error.$$name errorcut.$$name errorcut2.$$name ; \ + fi ; fi ; done) + @echo "## HTML SAX regression tests" + -@(for i in $(srcdir)/test/HTML/* ; do \ + name=`basename $$i`; \ + if [ ! -d $$i ] ; then \ + if [ ! -f $(srcdir)/result/HTML/$$name.sax ] ; then \ + echo New test file $$name ; \ + $(CHECKER) $(top_builddir)/testHTML --sax $$i > $(srcdir)/result/HTML/$$name.sax ; \ + else \ + log=`$(CHECKER) $(top_builddir)/testHTML --sax $$i > result.$$name.sax ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + diff $(srcdir)/result/HTML/$$name.sax result.$$name.sax` ; \ + if [ -n "$$log" ] ; then echo $$name result ; echo $$log ; fi ; \ + rm result.$$name.sax ; \ + fi ; fi ; done) + @echo "## Push HTML SAX regression tests" + -@(for i in $(srcdir)/test/HTML/* ; do \ + name=`basename $$i`; \ + if [ ! -d $$i ] ; then \ + if [ ! -f $(srcdir)/result/HTML/$$name ] ; then \ + echo New test file $$name ; \ + $(CHECKER) $(top_builddir)/testHTML --push --sax $$i > $(srcdir)/result/HTML/$$name.sax ; \ + else \ + log=`$(CHECKER) $(top_builddir)/testHTML --push --sax $$i 2>&1 > result.$$name.sax ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + diff $(srcdir)/result/HTML/$$name.sax result.$$name.sax` ; \ + if [ -n "$$log" ] ; then echo $$name result ; echo $$log ; fi ; \ + rm result.$$name.sax ; \ + fi ; fi ; done) + +XMLtests : xmllint$(EXEEXT) + @(echo > .memdump) + @echo "## XML regression tests" + -@(for i in $(srcdir)/test/* ; do \ + name=`basename $$i`; \ + if [ ! -d $$i ] ; then \ + if [ ! -f $(srcdir)/result/$$name ] ; then \ + echo New test file $$name ; \ + $(CHECKER) $(top_builddir)/xmllint $$i > $(srcdir)/result/$$name ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0"; \ + else \ + log=`$(CHECKER) $(top_builddir)/xmllint $$i 2>&1 > result.$$name ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0"; \ + diff $(srcdir)/result/$$name result.$$name ; \ + $(CHECKER) $(top_builddir)/xmllint result.$$name 2>&1 > result2.$$name | grep -v 'failed to load external entity' ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0"; \ + diff result.$$name result2.$$name` ;\ + if [ -n "$$log" ] ; then echo $$name result ; echo $$log ; fi ; \ + rm result.$$name result2.$$name ; \ + fi ; fi ; done) + @echo "## XML regression tests on memory" + -@(for i in $(srcdir)/test/* ; do \ + name=`basename $$i`; \ + if [ ! -d $$i ] ; then \ + if [ ! -f $(srcdir)/result/$$name ] ; then \ + echo New test file $$name ; \ + $(CHECKER) $(top_builddir)/xmllint --memory $$i > $(srcdir)/result/$$name ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0"; \ + else \ + log=`$(CHECKER) $(top_builddir)/xmllint --memory $$i 2>&1 > result.$$name ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + diff $(srcdir)/result/$$name result.$$name ; \ + $(CHECKER) $(top_builddir)/xmllint --memory result.$$name 2>&1 > result2.$$name | grep -v 'failed to load external entity' ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0"`; \ + if [ -n "$$log" ] ; then echo $$name result ; echo $$log ; fi ; \ + diff result.$$name result2.$$name ; \ + rm result.$$name result2.$$name ; \ + fi ; fi ; done) + +XMLPushtests: xmllint$(EXEEXT) + @(echo > .memdump) + @echo "## XML push regression tests" + -@(for i in $(srcdir)/test/* ; do \ + name=`basename $$i`; \ + if [ ! -d $$i ] ; then \ + if [ ! -f $(srcdir)/result/$$name ] ; then \ + echo New test file $$name ; \ + $(CHECKER) $(top_builddir)/xmllint --push $$i > $(srcdir)/result/$$name ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0"; \ + else \ + log=`$(CHECKER) $(top_builddir)/xmllint --push $$i 2>&1 > result.$$name ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0"; \ + diff $(srcdir)/result/$$name result.$$name ; \ + $(CHECKER) $(top_builddir)/xmllint --push result.$$name 2>&1 > result2.$$name | grep -v 'failed to load external entity' ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0"; \ + diff result.$$name result2.$$name` ; \ + if [ -n "$$log" ] ; then echo $$name result ; echo $$log ; fi ; \ + rm result.$$name result2.$$name ; \ + fi ; fi ; done) + +NStests : xmllint$(EXEEXT) + @(echo > .memdump) + @echo "## XML Namespaces regression tests" + -@(for i in $(srcdir)/test/namespaces/* ; do \ + name=`basename $$i`; \ + if [ ! -d $$i ] ; then \ + if [ ! -f $(srcdir)/result/namespaces/$$name ] ; then \ + echo New test file $$name ; \ + $(CHECKER) $(top_builddir)/xmllint $$i \ + 2> $(srcdir)/result/namespaces/$$name.err \ + > $(srcdir)/result/namespaces/$$name ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0"; \ + else \ + log=`$(CHECKER) $(top_builddir)/xmllint $$i 2> error.$$name > result.$$name ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0"; \ + diff $(srcdir)/result/namespaces/$$name result.$$name ; \ + diff $(srcdir)/result/namespaces/$$name.err error.$$name`; \ + if [ -n "$$log" ] ; then echo $$name result ; echo $$log ; fi ; \ + rm result.$$name error.$$name ; \ + fi ; fi ; done) + +IDtests : xmllint$(EXEEXT) testXPath$(EXEEXT) + @(echo > .memdump) + @echo "## xml:id regression tests" + -@(for i in $(srcdir)/test/xmlid/id_*.xml ; do \ + name=`basename $$i`; \ + if [ ! -d $$i ] ; then \ + if [ ! -f $(srcdir)/result/xmlid/$$name ] ; then \ + echo New test file $$name ; \ + $(CHECKER) $(top_builddir)/testXPath -i $$i "id('bar')" \ + 2> $(srcdir)/result/xmlid/$$name.err \ + > $(srcdir)/result/xmlid/$$name ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0"; \ + else \ + log=`$(CHECKER) $(top_builddir)/testXPath -i $$i "id('bar')" 2> error.$$name > result.$$name ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0"; \ + diff $(srcdir)/result/xmlid/$$name result.$$name ; \ + diff $(srcdir)/result/xmlid/$$name.err error.$$name` ; \ + if [ -n "$$log" ] ; then echo $$name result ; echo $$log ; fi ; \ + rm result.$$name error.$$name ; \ + fi ; fi ; done) + +Errtests : xmllint$(EXEEXT) + @(echo > .memdump) + @echo "## Error cases regression tests" + -@(for i in $(srcdir)/test/errors/*.xml ; do \ + name=`basename $$i`; \ + if [ ! -d $$i ] ; then \ + if [ ! -f $(srcdir)/result/errors/$$name ] ; then \ + echo New test file $$name ; \ + $(CHECKER) $(top_builddir)/xmllint $$i \ + 2> $(srcdir)/result/errors/$$name.err \ + > $(srcdir)/result/errors/$$name ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0"; \ + else \ + log=`$(CHECKER) $(top_builddir)/xmllint $$i 2> error.$$name > result.$$name ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0"; \ + diff $(srcdir)/result/errors/$$name result.$$name ; \ + diff $(srcdir)/result/errors/$$name.err error.$$name` ; \ + if [ -n "$$log" ] ; then echo $$name result ; echo $$log ; fi ; \ + rm result.$$name error.$$name ; \ + fi ; fi ; done) + @echo "## Error cases stream regression tests" + -@(for i in $(srcdir)/test/errors/*.xml ; do \ + name=`basename $$i`; \ + if [ ! -d $$i ] ; then \ + if [ ! -f $(srcdir)/result/errors/$$name.str ] ; then \ + echo New test file $$name ; \ + $(CHECKER) $(top_builddir)/xmllint --stream $$i \ + 2> $(srcdir)/result/errors/$$name.str \ + > /dev/null ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0"; \ + else \ + log=`$(CHECKER) $(top_builddir)/xmllint --stream $$i 2> error.$$name > /dev/null ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0"; \ + diff $(srcdir)/result/errors/$$name.str error.$$name` ; \ + if [ -n "$$log" ] ; then echo $$name result ; echo $$log ; fi ; \ + rm error.$$name ; \ + fi ; fi ; done) + +Docbtests : xmllint$(EXEEXT) + +XMLenttests : xmllint$(EXEEXT) + @(echo > .memdump) + @echo "## XML entity subst regression tests" + -@(for i in $(srcdir)/test/* ; do \ + name=`basename $$i`; \ + if [ ! -d $$i ] ; then \ + if [ ! -f $(srcdir)/result/noent/$$name ] ; then \ + echo New test file $$name ; \ + $(CHECKER) $(top_builddir)/xmllint --noent $$i > $(srcdir)/result/noent/$$name ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0"; \ + else \ + log=`$(CHECKER) $(top_builddir)/xmllint --noent $$i 2>&1 > result.$$name ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0"; \ + diff $(srcdir)/result/noent/$$name result.$$name ; \ + $(CHECKER) $(top_builddir)/xmllint --noent result.$$name 2>&1 > result2.$$name ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0"; \ + diff result.$$name result2.$$name` ; \ + if [ -n "$$log" ] ; then echo $$name result ; echo $$log ; fi ; \ + rm result.$$name result2.$$name ; \ + fi ; fi ; done) + +URItests : testURI$(EXEEXT) + @(echo > .memdump) + @echo "## URI module regression tests" + -@(for i in $(srcdir)/test/URI/*.data ; do \ + name=`basename $$i`; \ + if [ ! -d $$i ] ; then \ + if [ ! -f $(srcdir)/result/URI/$$name ] ; then \ + echo New test file $$name ; \ + $(CHECKER) $(top_builddir)/testURI -base 'http://foo.com/path/to/index.html?orig#help' < $$i > $(srcdir)/result/URI/$$name ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0"; \ + else \ + log=`$(CHECKER) $(top_builddir)/testURI -base 'http://foo.com/path/to/index.html?orig#help' < $$i 2>&1 > result.$$name ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + diff $(srcdir)/result/URI/$$name result.$$name` ; \ + if [ -n "$$log" ] ; then echo $$name result ; echo $$log ; fi ; \ + rm result.$$name ; \ + fi ; fi ; done) + -@(for i in $(srcdir)/test/URI/*.uri ; do \ + name=`basename $$i`; \ + if [ ! -d $$i ] ; then \ + if [ ! -f $(srcdir)/result/URI/$$name ] ; then \ + echo New test file $$name ; \ + $(CHECKER) $(top_builddir)/testURI < $$i > $(srcdir)/result/URI/$$name ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0"; \ + else \ + log=`$(CHECKER) $(top_builddir)/testURI < $$i 2>&1 > result.$$name ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + diff $(srcdir)/result/URI/$$name result.$$name` ; \ + if [ -n "$$log" ] ; then echo $$name result ; echo $$log ; fi ; \ + rm result.$$name ; \ + fi ; fi ; done) + +XPathtests : testXPath$(EXEEXT) + @(echo > .memdump) + @echo "## XPath regression tests" + -@(if [ "`$(top_builddir)/testXPath | grep 'support not compiled in'`" != "" ] ; \ + then echo Skipping debug not compiled in ; exit 0 ; fi ; \ + for i in $(srcdir)/test/XPath/expr/* ; do \ + name=`basename $$i`; \ + if [ ! -d $$i ] ; then \ + if [ ! -f $(srcdir)/result/XPath/expr/$$name ] ; then \ + echo New test file $$name ; \ + $(CHECKER) $(top_builddir)/testXPath -f --expr $$i > $(srcdir)/result/XPath/expr/$$name ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + else \ + log=`$(CHECKER) $(top_builddir)/testXPath -f --expr $$i 2>&1 > result.$$name ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + diff $(srcdir)/result/XPath/expr/$$name result.$$name` ; \ + if [ -n "$$log" ] ; then echo $$name result ; echo $$log ; fi ; \ + rm result.$$name ; \ + fi ; fi ; done ; \ + for i in $(srcdir)/test/XPath/docs/* ; do \ + if [ ! -d $$i ] ; then \ + doc=`basename $$i`; \ + for j in $(srcdir)/test/XPath/tests/$$doc* ; do \ + if [ ! -f $$j ] ; then continue ; fi ; \ + name=`basename $$j`; \ + if [ ! -d $$j ] ; then \ + if [ ! -f $(srcdir)/result/XPath/tests/$$name ] ; then \ + echo New test file $$name ; \ + $(CHECKER) $(top_builddir)/testXPath -f -i $$i $$j > $(srcdir)/result/XPath/tests/$$name ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + else \ + log=`$(CHECKER) $(top_builddir)/testXPath -f -i $$i $$j 2>&1 > result.$$name ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + diff $(srcdir)/result/XPath/tests/$$name result.$$name` ; \ + if [ -n "$$log" ] ; then echo $$name result ; echo $$log ; fi ; \ + rm result.$$name ; \ + fi ; fi ; done ; fi ; done) + +XPtrtests : testXPath$(EXEEXT) + @(echo > .memdump) + @echo "## XPointer regression tests" + -@(if [ "`$(top_builddir)/testXPath | grep 'support not compiled in'`" != "" ] ; \ + then echo Skipping debug not compiled in ; exit 0 ; fi ; \ + for i in $(srcdir)/test/XPath/docs/* ; do \ + if [ ! -d $$i ] ; then \ + doc=`basename $$i`; \ + for j in $(srcdir)/test/XPath/xptr/$$doc* ; do \ + if [ ! -f $$j ] ; then continue ; fi ; \ + name=`basename $$j`; \ + if [ ! -d $$j ] ; then \ + if [ ! -f $(srcdir)/result/XPath/xptr/$$name ] ; then \ + echo New test file $$name ; \ + $(CHECKER) $(top_builddir)/testXPath -xptr -f -i $$i $$j > $(srcdir)/result/XPath/xptr/$$name ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0"; \ + else \ + log=`$(CHECKER) $(top_builddir)/testXPath -xptr -f -i $$i $$j 2>&1 > result.$$name ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + diff $(srcdir)/result/XPath/xptr/$$name result.$$name` ; \ + if [ -n "$$log" ] ; then echo $$name result ; echo $$log ; fi ; \ + rm result.$$name ; \ + fi ; fi ; done ; fi ; done) + +XIncludetests : xmllint$(EXEEXT) + @(echo > .memdump) + @echo "## XInclude regression tests" + -@(for i in $(srcdir)/test/XInclude/docs/* ; do \ + name=`basename $$i`; \ + if [ ! -d $$i ] ; then \ + if [ ! -f $(srcdir)/result/XInclude/$$name ] ; then \ + echo New test file $$name ; \ + $(CHECKER) $(top_builddir)/xmllint --nowarning --xinclude $$i > $(srcdir)/result/XInclude/$$name 2> $(srcdir)/result/XInclude/$$name.err ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + else \ + log=`$(CHECKER) $(top_builddir)/xmllint --nowarning --xinclude $$i > result.$$name 2>error.$$name ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + diff $(srcdir)/result/XInclude/$$name result.$$name ; \ + diff $(srcdir)/result/XInclude/$$name.err error.$$name` ; \ + if [ -n "$$log" ] ; then echo $$name result ; echo $$log ; fi ; \ + rm result.$$name error.$$name ; \ + fi ; fi ; done) + -@(for i in $(srcdir)/test/XInclude/docs/* ; do \ + name=`basename $$i`; \ + if [ ! -d $$i ] ; then \ + if [ ! -f $(srcdir)/result/XInclude/$$name ] ; then \ + echo New test file $$name ; \ + $(CHECKER) $(top_builddir)/xmllint --nowarning --noxincludenode $$i > $(srcdir)/result/XInclude/$$name 2> $(srcdir)/result/XInclude/$$name.err ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + else \ + log=`$(CHECKER) $(top_builddir)/xmllint --nowarning --noxincludenode $$i > result.$$name 2>error.$$name ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + diff $(srcdir)/result/XInclude/$$name result.$$name ; \ + diff $(srcdir)/result/XInclude/$$name.err error.$$name` ; \ + if [ -n "$$log" ] ; then echo $$name result ; echo $$log ; fi ; \ + rm result.$$name error.$$name ; \ + fi ; fi ; done) + @(echo > .memdump) + @echo "## XInclude xmlReader regression tests" + -@(for i in $(srcdir)/test/XInclude/docs/* ; do \ + name=`basename $$i`; \ + if [ ! -d $$i ] ; then \ + if [ ! -f $(srcdir)/result/XInclude/$$name.rdr ] ; then \ + echo New test file $$name ; \ + $(CHECKER) $(top_builddir)/xmllint --nowarning --xinclude --stream --debug $$i > $(srcdir)/result/XInclude/$$name.rdr ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + else \ + log=`$(CHECKER) $(top_builddir)/xmllint --nowarning --xinclude --stream --debug $$i > result.$$name 2>error.$$name ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + diff $(srcdir)/result/XInclude/$$name.err error.$$name ; \ + diff $(srcdir)/result/XInclude/$$name.rdr result.$$name` ; \ + if [ -n "$$log" ] ; then echo $$name result ; echo $$log ; fi ; \ + rm result.$$name error.$$name ; \ + fi ; fi ; done) + -@(for i in $(srcdir)/test/XInclude/docs/* ; do \ + name=`basename $$i`; \ + if [ ! -d $$i ] ; then \ + if [ ! -f $(srcdir)/result/XInclude/$$name.rdr ] ; then \ + echo New test file $$name ; \ + $(CHECKER) $(top_builddir)/xmllint --nowarning --noxincludenode --stream --debug $$i > $(srcdir)/result/XInclude/$$name.rdr ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + else \ + log=`$(CHECKER) $(top_builddir)/xmllint --nowarning --xinclude --stream --debug $$i > result.$$name 2>error.$$name ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + diff $(srcdir)/result/XInclude/$$name.err error.$$name ; \ + diff $(srcdir)/result/XInclude/$$name.rdr result.$$name` ; \ + if [ -n "$$log" ] ; then echo $$name result ; echo $$log ; fi ; \ + rm result.$$name error.$$name ; \ + fi ; fi ; done) + +Scripttests : xmllint$(EXEEXT) + @(echo > .memdump) + @echo "## Scripts regression tests" + @echo "## Some of the base computations may be different if srcdir != ." + -@(for i in $(srcdir)/test/scripts/*.script ; do \ + name=`basename $$i .script`; \ + xml=$(srcdir)/test/scripts/`basename $$i .script`.xml; \ + if [ -f $$xml ] ; then \ + if [ ! -f $(srcdir)/result/scripts/$$name ] ; then \ + echo New test file $$name ; \ + $(CHECKER) $(top_builddir)/xmllint --shell $$xml < $$i > $(srcdir)/result/scripts/$$name 2> $(srcdir)/result/scripts/$$name.err ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + else \ + log=`$(CHECKER) $(top_builddir)/xmllint --shell $$xml < $$i > result.$$name 2> result.$$name.err ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + diff $(srcdir)/result/scripts/$$name result.$$name ; \ + diff $(srcdir)/result/scripts/$$name.err result.$$name.err` ; \ + if [ -n "$$log" ] ; then echo $$name result ; echo $$log ; fi ; \ + rm result.$$name result.$$name.err ; \ + fi ; fi ; done) + +Catatests : xmlcatalog$(EXEEXT) + @(echo > .memdump) + @echo "## Catalog regression tests" + -@(for i in $(srcdir)/test/catalogs/*.script ; do \ + name=`basename $$i .script`; \ + xml=$(srcdir)/test/catalogs/`basename $$i .script`.xml; \ + if [ -f $$xml ] ; then \ + if [ ! -f $(srcdir)/result/catalogs/$$name ] ; then \ + echo New test file $$name ; \ + $(CHECKER) $(top_builddir)/xmlcatalog --shell $$xml < $$i 2>&1 > $(srcdir)/result/catalogs/$$name ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + else \ + log=`$(CHECKER) $(top_builddir)/xmlcatalog --shell $$xml < $$i 2>&1 > result.$$name ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + diff $(srcdir)/result/catalogs/$$name result.$$name` ; \ + if [ -n "$$log" ] ; then echo $$name result ; echo $$log ; fi ; \ + rm result.$$name ; \ + fi ; fi ; done) + -@(for i in $(srcdir)/test/catalogs/*.script ; do \ + name=`basename $$i .script`; \ + sgml=$(srcdir)/test/catalogs/`basename $$i .script`.sgml; \ + if [ -f $$sgml ] ; then \ + if [ ! -f $(srcdir)/result/catalogs/$$name ] ; then \ + echo New test file $$name ; \ + $(CHECKER) $(top_builddir)/xmlcatalog --shell $$sgml < $$i > $(srcdir)/result/catalogs/$$name ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + else \ + log=`$(CHECKER) $(top_builddir)/xmlcatalog --shell $$sgml < $$i > result.$$name ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + diff $(srcdir)/result/catalogs/$$name result.$$name` ; \ + if [ -n "$$log" ] ; then echo $$name result ; echo $$log ; fi ; \ + rm result.$$name ; \ + fi ; fi ; done) + @echo "## Add and del operations on XML Catalogs" + -@($(CHECKER) $(top_builddir)/xmlcatalog --create --noout $(srcdir)/result/catalogs/mycatalog; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0"; \ + $(CHECKER) $(top_builddir)/xmlcatalog --noout --add public Pubid sysid $(srcdir)/result/catalogs/mycatalog; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0"; \ + $(CHECKER) $(top_builddir)/xmlcatalog --noout --add public Pubid2 sysid2 $(srcdir)/result/catalogs/mycatalog; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0"; \ + $(CHECKER) $(top_builddir)/xmlcatalog --noout --add public Pubid3 sysid3 $(srcdir)/result/catalogs/mycatalog; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0"; \ + diff result/catalogs/mycatalog.full $(srcdir)/result/catalogs/mycatalog; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0"; \ + $(CHECKER) $(top_builddir)/xmlcatalog --noout --del sysid $(srcdir)/result/catalogs/mycatalog; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0"; \ + $(CHECKER) $(top_builddir)/xmlcatalog --noout --del sysid3 $(srcdir)/result/catalogs/mycatalog; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0"; \ + $(CHECKER) $(top_builddir)/xmlcatalog --noout --del sysid2 $(srcdir)/result/catalogs/mycatalog; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0"; \ + diff result/catalogs/mycatalog.empty $(srcdir)/result/catalogs/mycatalog; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0"; \ + rm -f $(srcdir)/result/catalogs/mycatalog) + +SVGtests : xmllint$(EXEEXT) + @echo "## SVG parsing regression tests" + -@(for i in $(srcdir)/test/SVG/* ; do \ + name=`basename $$i`; \ + if [ ! -d $$i ] ; then \ + if [ ! -f $(srcdir)/result/SVG/$$name ] ; then \ + echo New test file $$name ; \ + $(CHECKER) $(top_builddir)/xmllint $$i > $(srcdir)/result/SVG/$$name ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + else \ + echo Testing $$name ; \ + $(CHECKER) $(top_builddir)/xmllint $$i > result.$$name ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + diff $(srcdir)/result/SVG/$$name result.$$name ; \ + $(CHECKER) $(top_builddir)/xmllint result.$$name > result2.$$name ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + diff result.$$name result2.$$name ; \ + rm result.$$name result2.$$name ; \ + fi ; fi ; done) + +Threadtests : testThreads$(EXEEXT) + @echo "## Threaded regression tests" + -@($(CHECKER) $(top_builddir)/testThreads ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0"; \ + exit 0) + +Readertests : xmllint$(EXEEXT) + @(echo > .memdump) + @echo "## Reader regression tests" + -@(for i in $(srcdir)/test/* ; do \ + name=`basename $$i`; \ + if [ ! -d $$i ] ; then \ + if [ ! -f $(srcdir)/result/$$name.rdr ] ; then \ + echo New test file $$name ; \ + $(CHECKER) $(top_builddir)/xmllint --nonet --debug --stream $$i > $(srcdir)/result/$$name.rdr 2>/dev/null ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + else \ + log=`$(CHECKER) $(top_builddir)/xmllint --nonet --debug --stream $$i > result.$$name 2>/dev/null ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + diff $(srcdir)/result/$$name.rdr result.$$name` ; \ + if [ -n "$$log" ] ; then echo $$name result ; echo $$log ; fi ; \ + rm result.$$name ; \ + fi ; fi ; done) + @echo "## Reader on memory regression tests" + -@(for i in $(srcdir)/test/* ; do \ + name=`basename $$i`; \ + if [ ! -d $$i ] ; then \ + if [ ! -f $(srcdir)/result/$$name.rdr ] ; then \ + echo New test file $$name ; \ + $(CHECKER) $(top_builddir)/xmllint --memory --nonet --debug --stream $$i > $(srcdir)/result/$$name.rdr 2>/dev/null ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + else \ + log=`$(CHECKER) $(top_builddir)/xmllint --memory --nonet --debug --stream $$i > result.$$name 2>/dev/null ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + diff $(srcdir)/result/$$name.rdr result.$$name` ; \ + if [ -n "$$log" ] ; then echo $$name result ; echo $$log ; fi ; \ + rm result.$$name ; \ + fi ; fi ; done) + @(echo > .memdump) + @echo "## Walker regression tests" + -@(for i in $(srcdir)/test/* ; do \ + name=`basename $$i`; \ + if [ ! -d $$i ] ; then \ + if [ ! -f $(srcdir)/result/$$name.rdr ] ; then \ + echo New test file $$name ; \ + $(CHECKER) $(top_builddir)/xmllint --nonet --debug --walker $$i > $(srcdir)/result/$$name.rdr 2>/dev/null ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + else \ + log=`$(CHECKER) $(top_builddir)/xmllint --nonet --debug --walker $$i > result.$$name 2>/dev/null ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + diff $(srcdir)/result/$$name.rdr result.$$name` ; \ + if [ -n "$$log" ] ; then echo $$name result ; echo $$log ; fi ; \ + rm result.$$name ; \ + fi ; fi ; done) + @echo "## Reader entities substitution regression tests" + -@(for i in $(srcdir)/test/* ; do \ + name=`basename $$i`; \ + if [ ! -d $$i ] ; then \ + if [ ! -f $(srcdir)/result/$$name.rde ] ; then \ + echo New test file $$name ; \ + $(CHECKER) $(top_builddir)/xmllint --noent --nonet --debug --stream $$i > $(srcdir)/result/$$name.rde 2>/dev/null ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + else \ + log=`$(CHECKER) $(top_builddir)/xmllint --noent --nonet --debug --stream $$i > result.$$name 2>/dev/null ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + diff $(srcdir)/result/$$name.rde result.$$name` ; \ + if [ -n "$$log" ] ; then echo $$name result ; echo $$log ; fi ; \ + rm result.$$name ; \ + fi ; fi ; done) + +SAXtests : testSAX$(EXEEXT) + @(echo > .memdump) + @echo "## SAX1 callbacks regression tests" + -@(for i in $(srcdir)/test/* ; do \ + name=`basename $$i`; \ + if [ ! -d $$i ] ; then \ + if [ ! -f $(srcdir)/result/$$name.sax ] ; then \ + echo New test file $$name ; \ + $(CHECKER) $(top_builddir)/testSAX $$i > $(srcdir)/result/$$name.sax 2> /dev/null ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + else \ + log=`$(CHECKER) $(top_builddir)/testSAX $$i > result.$$name 2> /dev/null ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + diff $(srcdir)/result/$$name.sax result.$$name` ; \ + if [ -n "$$log" ] ; then echo $$name result ; echo $$log ; fi ; \ + rm result.$$name ; \ + fi ; fi ; done) + @echo "## SAX2 callbacks regression tests" + -@(for i in $(srcdir)/test/* ; do \ + name=`basename $$i`; \ + if [ ! -d $$i ] ; then \ + if [ ! -f $(srcdir)/result/$$name.sax2 ] ; then \ + echo New test file $$name ; \ + $(CHECKER) $(top_builddir)/testSAX --sax2 $$i > $(srcdir)/result/$$name.sax2 2> /dev/null ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + else \ + log=`$(CHECKER) $(top_builddir)/testSAX --sax2 $$i > result.$$name 2> /dev/null ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + diff $(srcdir)/result/$$name.sax2 result.$$name` ; \ + if [ -n "$$log" ] ; then echo $$name result ; echo $$log ; fi ; \ + rm result.$$name ; \ + fi ; fi ; done) + +Validtests : xmllint$(EXEEXT) + @(echo > .memdump) + @echo "## Valid documents regression tests" + -@(for i in $(srcdir)/test/VCM/* ; do \ + name=`basename $$i`; \ + if [ ! -d $$i ] ; then \ + log=`$(CHECKER) $(top_builddir)/xmllint --valid --noout --nowarning $$i ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0"`;\ + if [ -n "$$log" ] ; then echo $$name result ; echo $$log ; fi ; \ + fi ; done ; exit 0) + @echo "## Validity checking regression tests" + -@(for i in $(srcdir)/test/VC/* ; do \ + name=`basename $$i`; \ + if [ ! -d $$i ] ; then \ + if [ ! -f $(srcdir)/result/VC/$$name ] ; then \ + echo New test file $$name ; \ + $(CHECKER) $(top_builddir)/xmllint --noout --valid $$i 2> $(srcdir)/result/VC/$$name ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + else \ + log=`$(CHECKER) $(top_builddir)/xmllint --noout --valid $$i 2> result.$$name ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + diff $(srcdir)/result/VC/$$name result.$$name` ; \ + if [ -n "$$log" ] ; then echo $$name result ; echo $$log ; fi ; \ + rm result.$$name ; \ + fi ; fi ; done) + @echo "## General documents valid regression tests" + -@(for i in $(srcdir)/test/valid/* ; do \ + name=`basename $$i`; \ + if [ ! -d $$i ] ; then \ + if [ ! -f $(srcdir)/result/valid/$$name ] ; then \ + echo New test file $$name ; \ + $(CHECKER) $(top_builddir)/xmllint --valid $$i > $(srcdir)/result/valid/$$name 2>$(srcdir)/result/valid/$$name.err ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + else \ + log=`$(CHECKER) $(top_builddir)/xmllint --valid $$i > result.$$name 2>error.$$name ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + diff $(srcdir)/result/valid/$$name result.$$name ; \ + diff $(srcdir)/result/valid/$$name.err error.$$name` ; \ + if [ -n "$$log" ] ; then echo $$name result ; echo $$log ; fi ; \ + rm result.$$name error.$$name ; \ + fi ; fi ; done) + +Regexptests: testRegexp$(EXEEXT) + @(echo > .memdump) + @echo "## Regexp regression tests" + -@(for i in $(srcdir)/test/regexp/* ; do \ + name=`basename $$i`; \ + if [ ! -d $$i ] ; then \ + if [ ! -f $(srcdir)/result/regexp/$$name ] ; then \ + echo New test file $$name ; \ + $(CHECKER) $(top_builddir)/testRegexp -i $$i > $(srcdir)/result/regexp/$$name; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + else \ + log=`$(CHECKER) $(top_builddir)/testRegexp -i $$i 2>&1 > result.$$name ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + diff $(srcdir)/result/regexp/$$name result.$$name` ; \ + if [ -n "$$log" ] ; then echo $$name result ; echo $$log ; fi ; \ + rm result.$$name ; \ + fi ; fi ; done) + @echo "## Formal expresssions regression tests" + -@(for i in $(srcdir)/test/expr/* ; do \ + name=`basename $$i`; \ + if [ ! -d $$i ] ; then \ + if [ ! -f $(srcdir)/result/expr/$$name ] ; then \ + echo New test file $$name ; \ + $(CHECKER) $(top_builddir)/testRegexp --expr -i $$i > $(srcdir)/result/expr/$$name; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + else \ + log=`$(CHECKER) $(top_builddir)/testRegexp --expr -i $$i 2>&1 > result.$$name ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + diff $(srcdir)/result/expr/$$name result.$$name` ; \ + if [ -n "$$log" ] ; then echo $$name result ; echo $$log ; fi ; \ + rm result.$$name ; \ + fi ; fi ; done) + +Automatatests: testAutomata$(EXEEXT) + @(echo > .memdump) + @echo "## Automata regression tests" + -@(for i in $(srcdir)/test/automata/* ; do \ + name=`basename $$i`; \ + if [ ! -d $$i ] ; then \ + if [ ! -f $(srcdir)/result/automata/$$name ] ; then \ + echo New test file $$name ; \ + $(CHECKER) $(top_builddir)/testAutomata $$i > $(srcdir)/result/automata/$$name; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + else \ + log=`$(CHECKER) $(top_builddir)/testAutomata $$i 2>&1 > result.$$name ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + diff $(srcdir)/result/automata/$$name result.$$name` ; \ + if [ -n "$$log" ] ; then echo $$name result ; echo $$log ; fi ; \ + rm result.$$name ; \ + fi ; fi ; done) + +dba100000.xml: dbgenattr.pl + @echo "## generating dba100000.xml" + @($(PERL) $(top_srcdir)/dbgenattr.pl 100000 > dba100000.xml) + +Timingtests: xmllint$(EXEEXT) dba100000.xml + @echo "## Timing tests to try to detect performance" + @echo "## as well a memory usage breakage when streaming" + @echo "## 1/ using the file interface" + @echo "## 2/ using the memory interface" + @echo "## 3/ repeated DOM parsing" + @echo "## 4/ repeated DOM validation" + -@($(top_builddir)/xmllint --stream --timing dba100000.xml; \ + MEM=`cat .memdump | grep "MEMORY ALLOCATED" | awk '{ print $$7}'`;\ + if [ "$$MEM" != "" ] ; then echo Using $$MEM bytes ; fi ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + exit 0) + -@($(top_builddir)/xmllint --stream --timing --memory dba100000.xml; \ + MEM=`cat .memdump | grep "MEMORY ALLOCATED" | awk '{ print $$7}'`;\ + if [ "$$MEM" != "" ] ; then echo Using $$MEM bytes ; fi ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + exit 0) + -@($(top_builddir)/xmllint --noout --timing --repeat $(srcdir)/test/valid/REC-xml-19980210.xml; \ + MEM=`cat .memdump | grep "MEMORY ALLOCATED" | awk '{ print $$7}'`;\ + if [ "$$MEM" != "" ] ; then echo Using $$MEM bytes ; fi ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + exit 0) + +VTimingtests: xmllint$(EXEEXT) + -@($(top_builddir)/xmllint --noout --timing --valid --repeat $(srcdir)/test/valid/REC-xml-19980210.xml; \ + MEM=`cat .memdump | grep "MEMORY ALLOCATED" | awk '{ print $$7}'`;\ + if [ "$$MEM" != "" ] ; then echo Using $$MEM bytes ; fi ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + exit 0) + +C14Ntests : testC14N$(EXEEXT) + @echo "## C14N and XPath regression tests" + -@(for m in with-comments without-comments 1-1-without-comments exc-without-comments ; do \ + for i in $(srcdir)/test/c14n/$$m/*.xml ; do \ + if [ ! -d $$i ] ; then \ + name=`basename $$i .xml`; \ + cmdline="$(CHECKER) $(top_builddir)/testC14N --$$m $$i"; \ + if [ -f $(srcdir)/test/c14n/$$m/$$name.xpath ] ; then \ + cmdline="$$cmdline $(srcdir)/test/c14n/$$m/$$name.xpath"; \ + if [ -f $(srcdir)/test/c14n/$$m/$$name.ns ] ; then \ + cmdline="$$cmdline '`cat $(srcdir)/test/c14n/$$m/$$name.ns`'"; \ + fi; \ + fi; \ + $$cmdline > $(srcdir)/test/c14n/test.tmp; \ + if [ $$? -eq 0 ]; then \ + diff $(srcdir)/result/c14n/$$m/$$name $(srcdir)/test/c14n/test.tmp; \ + if [ $$? -ne 0 ]; then \ + echo "Test $$m/$$name failed"; \ + cat $(srcdir)/test/c14n/test.tmp; \ + fi; \ + else \ + echo "C14N failed"; \ + fi; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + fi; \ + rm -f $(srcdir)/test/c14n/test.tmp; \ + done; \ + done) + +Schemastests: testSchemas$(EXEEXT) + @(echo > .memdump) + @echo "## Schemas regression tests" + -@(for i in $(srcdir)/test/schemas/*_*.xsd ; do \ + name=`basename $$i | sed 's+_.*++'`; \ + sno=`basename $$i | sed 's+.*_\(.*\).xsd+\1+'`; \ + for j in $(srcdir)/test/schemas/"$$name"_*.xml ; do \ + if [ -f $$j ] ; then \ + xno=`basename $$j | sed 's+.*_\(.*\).xml+\1+'`; \ + if [ ! -f $(srcdir)/result/schemas/"$$name"_"$$sno"_"$$xno" ]; \ + then \ + echo New test file "$$name"_"$$sno"_"$$xno" ; \ + $(CHECKER) $(top_builddir)/testSchemas $$i $$j \ + > $(srcdir)/result/schemas/"$$name"_"$$sno"_"$$xno" \ + 2> $(srcdir)/result/schemas/"$$name"_"$$sno"_"$$xno".err; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + else \ + log=`$(CHECKER) $(top_builddir)/testSchemas $$i $$j \ + > res.$$name 2> err.$$name;\ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + diff $(srcdir)/result/schemas/"$$name"_"$$sno"_"$$xno" \ + res.$$name;\ + diff $(srcdir)/result/schemas/"$$name"_"$$sno"_"$$xno".err \ + err.$$name;\ + grep Unimplemented err.$$name`; \ + if [ -n "$$log" ] ; then echo "$$name"_"$$sno"_"$$xno" result ; echo $$log ; fi ; \ + rm res.$$name err.$$name ; \ + fi ; fi ;\ + done; done) + +Relaxtests: xmllint$(EXEEXT) + @(echo > .memdump) + @echo "## Relax-NG regression tests" + -@(for i in $(srcdir)/test/relaxng/*.rng ; do \ + name=`basename $$i | sed 's+\.rng++'`; \ + if [ ! -f $(srcdir)/result/relaxng/"$$name"_valid ] ; then \ + echo New schemas $$name ; \ + $(CHECKER) $(top_builddir)/xmllint$(EXEEXT) --noout --relaxng $(srcdir)/test/relaxng/tutorA.rng $$i \ + > $(srcdir)/result/relaxng/"$$name"_valid \ + 2> $(srcdir)/result/relaxng/"$$name"_err; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + else \ + log=`$(CHECKER) $(top_builddir)/xmllint$(EXEEXT) --noout --relaxng $(srcdir)/test/relaxng/tutorA.rng $$i \ + > res.$$name 2> err.$$name;\ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + diff $(srcdir)/result/relaxng/"$$name"_valid \ + res.$$name;\ + diff $(srcdir)/result/relaxng/"$$name"_err \ + err.$$name | grep -v "error detected at";\ + grep Unimplemented err.$$name`; \ + if [ -n "$$log" ] ; then echo schemas $$name result ; echo $$log ; fi ; \ + rm res.$$name err.$$name ; \ + fi; \ + for j in $(srcdir)/test/relaxng/"$$name"_*.xml ; do \ + if [ -f $$j ] ; then \ + xno=`basename $$j | sed 's+.*_\(.*\).xml+\1+'`; \ + if [ ! -f $(srcdir)/result/relaxng/"$$name"_"$$xno" ]; \ + then \ + echo New test file "$$name"_"$$xno" ; \ + $(CHECKER) $(top_builddir)/xmllint$(EXEEXT) --noout --relaxng $$i $$j \ + > $(srcdir)/result/relaxng/"$$name"_"$$xno" \ + 2> $(srcdir)/result/relaxng/"$$name"_"$$xno".err; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + else \ + log=`$(CHECKER) $(top_builddir)/xmllint$(EXEEXT) --noout --relaxng $$i $$j \ + > res.$$name 2> err.$$name;\ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + diff $(srcdir)/result/relaxng/"$$name"_"$$xno" \ + res.$$name;\ + diff $(srcdir)/result/relaxng/"$$name"_"$$xno".err \ + err.$$name | grep -v "error detected at";\ + grep Unimplemented err.$$name`; \ + if [ -n "$$log" ] ; then echo "$$name"_"$$xno" result ; echo $$log ; fi ; \ + rm res.$$name err.$$name ; \ + fi ; fi ; \ + done; done) + @echo "## Relax-NG streaming regression tests" + -@(for i in $(srcdir)/test/relaxng/*.rng ; do \ + name=`basename $$i | sed 's+\.rng++'`; \ + for j in $(srcdir)/test/relaxng/"$$name"_*.xml ; do \ + if [ -f $$j ] ; then \ + xno=`basename $$j | sed 's+.*_\(.*\).xml+\1+'`; \ + if [ ! -f $(srcdir)/result/relaxng/"$$name"_"$$xno" ]; \ + then \ + echo New test file "$$name"_"$$xno" ; \ + $(CHECKER) $(top_builddir)/xmllint$(EXEEXT) --noout --relaxng $$i $$j \ + > $(srcdir)/result/relaxng/"$$name"_"$$xno" \ + 2> $(srcdir)/result/relaxng/"$$name"_"$$xno".err; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + else \ + log=`$(CHECKER) $(top_builddir)/xmllint$(EXEEXT) --noout --stream --relaxng $$i $$j \ + > res.$$name 2> err.$$name;\ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + diff $(srcdir)/result/relaxng/"$$name"_"$$xno" res.$$name;\ + if [ "$$name" != "tutor10_1" -a "$$name" != "tutor10_2" -a "$$name" != "tutor3_2" -a "$$name" != "307377" -a "$$name" != "tutor8_2" ] ; then \ + diff $(srcdir)/result/relaxng/"$$name"_"$$xno".err \ + err.$$name | grep -v "error detected at";\ + fi ; grep Unimplemented err.$$name`; \ + if [ -n "$$log" ] ; then echo "$$name"_"$$xno" result ; echo $$log ; fi ; \ + rm res.$$name err.$$name ; \ + fi ; fi ; \ + done; done) + +Schematrontests: xmllint$(EXEEXT) + @(echo > .memdump) + @echo "## Schematron regression tests" + -@(for i in $(srcdir)/test/schematron/*.sct ; do \ + name=`basename $$i | sed 's+\.sct++'`; \ + for j in $(srcdir)/test/schematron/"$$name"_*.xml ; do \ + if [ -f $$j ] ; then \ + xno=`basename $$j | sed 's+.*_\(.*\).xml+\1+'`; \ + if [ ! -f $(srcdir)/result/schematron/"$$name"_"$$xno" ]; \ + then \ + echo New test file "$$name"_"$$xno" ; \ + $(CHECKER) $(top_builddir)/xmllint$(EXEEXT) --schematron $$i $$j \ + > $(srcdir)/result/schematron/"$$name"_"$$xno" \ + 2> $(srcdir)/result/schematron/"$$name"_"$$xno".err; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + else \ + log=`$(CHECKER) $(top_builddir)/xmllint$(EXEEXT) --schematron $$i $$j \ + > res.$$name 2> err.$$name;\ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + diff $(srcdir)/result/schematron/"$$name"_"$$xno" \ + res.$$name;\ + diff $(srcdir)/result/schematron/"$$name"_"$$xno".err \ + err.$$name | grep -v "error detected at";\ + grep Unimplemented err.$$name`; \ + if [ -n "$$log" ] ; then echo "$$name"_"$$xno" result ; echo $$log ; fi ; \ + rm res.$$name err.$$name ; \ + fi ; fi ; \ + done; done) + +RelaxNGPythonTests: + @(if [ -x $(PYTHON) ] ; then \ + PYTHONPATH=$(top_builddir)/python:$(top_builddir)/python/.libs:$$PYTHONPATH ; \ + export PYTHONPATH; \ + LD_LIBRARY_PATH="$(top_builddir)/.libs:$$LD_LIBRARY_PATH" ; \ + export LD_LIBRARY_PATH; \ + echo "## Relax-NG Python based test suite 1" ; \ + $(CHECKER) $(PYTHON) $(srcdir)/check-relaxng-test-suite.py ; \ + echo "## Relax-NG Python based test suite 2" ; \ + $(CHECKER) $(PYTHON) $(srcdir)/check-relaxng-test-suite2.py ; \ + fi) + +SchemasPythonTests: + @(if [ -x $(PYTHON) ] ; then \ + PYTHONPATH=$(top_builddir)/python:$(top_builddir)/python/.libs:$$PYTHONPATH; \ + export PYTHONPATH; \ + LD_LIBRARY_PATH="$(top_builddir)/.libs:$$LD_LIBRARY_PATH" ; \ + export LD_LIBRARY_PATH; \ + echo "## XML Schemas datatypes Python based test suite" ; \ + echo "## It is normal to see 11 errors reported" ; \ + $(CHECKER) $(PYTHON) $(srcdir)/check-xsddata-test-suite.py ; \ + fi) + @(if [ -x $(PYTHON) -a -d xstc ] ; then cd xstc ; $(MAKE) CHECKER="$(CHECKER)" pytests ; fi) + +Patterntests: xmllint$(EXEEXT) + @(echo > .memdump) + @echo "## Pattern regression tests" + -@(for i in $(srcdir)/test/pattern/*.pat ; do \ + name=`basename $$i .pat`; \ + if [ -f $(srcdir)/test/pattern/$$name.xml ] ; then \ + if [ ! -f $(srcdir)/result/pattern/$$name ] ; then \ + rm -f result.$$name ; \ + echo New test file $$name ; \ + for pat in `cat $$i` ; do \ + $(CHECKER) $(top_builddir)/xmllint --walker --pattern $$pat $(srcdir)/test/pattern/$$name.xml >> $(srcdir)/result/pattern/$$name ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + done ;\ + else \ + rm -f result.$$name ; \ + lst=`cat $$i` ; \ + log=`for pat in $$lst ; do $(CHECKER) $(top_builddir)/xmllint --walker --pattern $$pat $(srcdir)/test/pattern/$$name.xml 2>&1 >> result.$$name ; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ + done ;\ + diff $(srcdir)/result/pattern/$$name result.$$name` ; \ + if [ -n "$$log" ] ; then echo $$name result ; echo $$log ; fi ; \ + rm result.$$name ; \ + fi ; fi ; done ;) + +ModuleTests: testModule$(EXEEXT) testdso.la + @echo "## Module tests" + @(./testModule$(EXEEXT)) + +cleanup: + -@(find . -name .\#\* -exec rm {} \;) + -@(find . -name \*.gcda -o -name \*.gcno -exec rm -f {} \;) + -@(find . -name \*.orig -o -name \*.rej -o -name \*.old -exec rm -f {} \;) + +dist-hook: cleanup libxml2.spec + -cp libxml2.spec $(distdir) + (cd $(srcdir) ; tar -cf - --exclude CVS --exclude .svn --exclude .git win32 macos os400 vms VxWorks bakefile test result) | (cd $(distdir); tar xf -) + +dist-source: distdir + $(AMTAR) -chof - --exclude Tests --exclude test --exclude result $(distdir) | GZIP=$(GZIP_ENV) gzip -c >`echo "$(distdir)" | sed "s+libxml2+libxml2-sources+"`.tar.gz + +dist-test: distdir + (mkdir -p $(distdir)) + (cd $(srcdir) ; tar -cf - --exclude CVS --exclude .svn --exclude .git xstc/Tests) | (cd $(distdir); tar xf -) + tar -cf - $(distdir)/test $(distdir)/result $(distdir)/xstc/Tests $(distdir)/Makefile.tests $(distdir)/README $(distdir)/README.tests $(distdir)/AUTHORS $(distdir)/testapi.c $(distdir)/runtest.c $(distdir)/runsuite.c | GZIP=$(GZIP_ENV) gzip -c >`echo "$(distdir)" | sed "s+libxml2+libxml2-tests+"`.tar.gz + @(rm -rf $(distdir)/xstc/Test) + +cleantar: + @(rm -f libxml*.tar.gz COPYING.LIB) + +rpm: cleanup cleantar + @(unset CDPATH ; $(MAKE) dist-source dist && rpmbuild -ta $(distdir).tar.gz) + +## We create xml2Conf.sh here and not from configure because we want +## to get the paths expanded correctly. Macros like srcdir are given +## the value NONE in configure if the user doesn't specify them (this +## is an autoconf feature, not a bug). + +xml2Conf.sh: xml2Conf.sh.in Makefile +## Use sed and then mv to avoid problems if the user interrupts. + sed -e 's?\@XML_LIBDIR\@?$(XML_LIBDIR)?g' \ + -e 's?\@XML_INCLUDEDIR\@?$(XML_INCLUDEDIR)?g' \ + -e 's?\@VERSION\@?$(VERSION)?g' \ + -e 's?\@XML_LIBS\@?$(XML_LIBS)?g' \ + < $(srcdir)/xml2Conf.sh.in > xml2Conf.tmp \ + && mv xml2Conf.tmp xml2Conf.sh + +CLEANFILES = runxmlconf.log test.out xml2Conf.sh *.gcda *.gcno *.res +DISTCLEANFILES = COPYING missing.lst + +confexecdir=$(libdir) +confexec_DATA = xml2Conf.sh +CVS_EXTRA_DIST= +EXTRA_DIST = xml2-config.in xml2Conf.sh.in libxml.spec.in libxml2.spec \ + libxml.m4 Copyright check-xml-test-suite.py gentest.py \ + check-relaxng-test-suite.py check-relaxng-test-suite2.py \ + check-xsddata-test-suite.py check-xinclude-test-suite.py \ + example/Makefile.am example/gjobread.c example/gjobs.xml \ + $(man_MANS) libxml-2.0.pc.in libxml-2.0-uninstalled.pc.in \ + libxml2-config.cmake.in \ + trionan.c trionan.h triostr.c triostr.h trio.c trio.h \ + triop.h triodef.h libxml.h elfgcchack.h xzlib.h buf.h \ + enc.h save.h testThreadsWin32.c genUnicode.py TODO_SCHEMAS \ + dbgen.pl dbgenattr.pl regressions.py regressions.xml \ + README.tests Makefile.tests libxml2.syms timsort.h \ + $(CVS_EXTRA_DIST) + + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = libxml-2.0.pc + +cmakedir = $(libdir)/cmake/libxml2 +cmake_DATA = libxml2-config.cmake + +# +# Install the tests program sources as examples +# +BASE_DIR=$(datadir)/doc +DOC_MODULE=libxml2-$(VERSION) +EXAMPLES_DIR=$(BASE_DIR)/$(DOC_MODULE)/examples + +install-data-local: + $(MKDIR_P) $(DESTDIR)$(BASE_DIR)/$(DOC_MODULE) + -$(INSTALL) -m 0644 $(srcdir)/Copyright $(DESTDIR)$(BASE_DIR)/$(DOC_MODULE) + $(MKDIR_P) $(DESTDIR)$(EXAMPLES_DIR) + -$(INSTALL) -m 0644 $(srcdir)/xmllint.c $(DESTDIR)$(EXAMPLES_DIR) + -$(INSTALL) -m 0644 $(srcdir)/testSAX.c $(DESTDIR)$(EXAMPLES_DIR) + -$(INSTALL) -m 0644 $(srcdir)/testHTML.c $(DESTDIR)$(EXAMPLES_DIR) + -$(INSTALL) -m 0644 $(srcdir)/testXPath.c $(DESTDIR)$(EXAMPLES_DIR) + +uninstall-local: + rm -f $(DESTDIR)$(EXAMPLES_DIR)/testXPath.c + rm -f $(DESTDIR)$(EXAMPLES_DIR)/testHTML.c + rm -f $(DESTDIR)$(EXAMPLES_DIR)/testSAX.c + rm -f $(DESTDIR)$(EXAMPLES_DIR)/xmllint.c + rm -rf $(DESTDIR)$(EXAMPLES_DIR) + rm -f $(DESTDIR)$(BASE_DIR)/$(DOC_MODULE)/Copyright + rm -rf $(DESTDIR)$(BASE_DIR)/$(DOC_MODULE) + +tst: tst.c + $(CC) $(CFLAGS) -Iinclude -o tst tst.c .libs/libxml2.a -lpthread -lm -lz -llzma + +sparse: clean + $(MAKE) CC=cgcc + +# +# Coverage support, largely borrowed from libvirt +# Both binaries comes from the lcov package in Fedora +# +LCOV = /usr/bin/lcov +GENHTML = /usr/bin/genhtml + +cov: clean-cov + if [ "`echo $(LDFLAGS) | grep coverage`" = "" ] ; then \ + echo not configured with coverage; exit 1 ; fi + if [ ! -x $(LCOV) -o ! -x $(GENHTML) ] ; then \ + echo Need $(LCOV) and $(GENHTML) excecutables; exit 1 ; fi + -@($(MAKE) check) + -@(./runsuite$(EXEEXT)) + mkdir $(top_builddir)/coverage + $(LCOV) -c -o $(top_builddir)/coverage/libxml2.info.tmp -d $(top_srcdir) + $(LCOV) -r $(top_builddir)/coverage/libxml2.info.tmp -o $(top_builddir)/coverage/libxml2.info *usr* + rm $(top_builddir)/coverage/libxml2.info.tmp + $(GENHTML) -s -t "libxml2" -o $(top_builddir)/coverage --legend $(top_builddir)/coverage/libxml2.info + echo "Coverage report is in $(top_builddir)/coverage/index.html" + +clean-cov: + rm -rf $(top_builddir)/coverage + diff --git a/third_party/libxml/src/Makefile.tests b/third_party/libxml/src/Makefile.tests new file mode 100644 index 0000000000000..619cbfb85974a --- /dev/null +++ b/third_party/libxml/src/Makefile.tests @@ -0,0 +1,41 @@ +# +# You may have to ajust to call the right compiler, or other oprions +# for compiling and linking +# + +CFLAGS=`xml2-config --cflags` +LIBS=`xml2-config --libs` +THREADLIB= -lpthread +EXEEXT= + +all: runtest$(EXEEXT) runsuite$(EXEEXT) testapi$(EXEEXT) testchar$(EXEEXT) + +clean: + $(RM) runtest$(EXEEXT) runsuite$(EXEEXT) testapi$(EXEEXT) + +check: do_runtest do_testchar do_testapi do_runsuite + +runtest$(EXEEXT): runtest.c + $(CC) -o runtest$(EXEEXT) $(CFLAGS) runtest.c $(LIBS) $(THREADLIB) + +do_runtest: runtest$(EXEEXT) + ./runtest + +runsuite$(EXEEXT): runsuite.c + $(CC) -o runsuite$(EXEEXT) $(CFLAGS) runsuite.c $(LIBS) + +do_runsuite: runsuite$(EXEEXT) + ./runsuite + +testapi$(EXEEXT): testapi.c + $(CC) -o testapi$(EXEEXT) $(CFLAGS) testapi.c $(LIBS) + +do_testapi: testapi$(EXEEXT) + ./testapi + +testchar$(EXEEXT): testchar.c + $(CC) -o testchar$(EXEEXT) $(CFLAGS) testchar.c $(LIBS) + +do_testchar: testchar$(EXEEXT) + ./testchar + diff --git a/third_party/libxml/src/NEWS b/third_party/libxml/src/NEWS index cdfdda6f8d4f3..8027d55c0fd40 100644 --- a/third_party/libxml/src/NEWS +++ b/third_party/libxml/src/NEWS @@ -4,17 +4,647 @@ Note that this is automatically generated from the news webpage at: http://xmlsoft.org/news.html -Items not finished and worked on, get in touch with the list if you want -to help those - More testing on RelaxNG - - Finishing up XML - Schemas - The change log at ChangeLog.html describes the recents commits -to the SVN at -http://svn.gnome.org/viewvc/libxml2/trunk/ +to the GIT at +http://git.gnome.org/browse/libxml2/ code base.Here is the list of public releases: +2.9.2: Oct 16 2014: + - Security: + Fix for CVE-2014-3660 billion laugh variant (Daniel Veillard), + CVE-2014-0191 Do not fetch external parameter entities (Daniel Veillard) + + - Bug Fixes: + fix memory leak xml header encoding field with XML_PARSE_IGNORE_ENC (Bart De Schuymer), + xmlmemory: handle realloc properly (Yegor Yefremov), + Python generator bug raised by the const change (Daniel Veillard), + Windows Critical sections not released correctly (Daniel Veillard), + Parser error on repeated recursive entity expansion containing < (Daniel Veillard), + xpointer : fixing Null Pointers (Gaurav Gupta), + Remove Unnecessary Null check in xpointer.c (Gaurav Gupta), + parser bug on misformed namespace attributes (Dennis Filder), + Pointer dereferenced before null check (Daniel Veillard), + Leak of struct addrinfo in xmlNanoFTPConnect() (Gaurav Gupta), + Possible overflow in HTMLParser.c (Daniel Veillard), + python/tests/sync.py assumes Python dictionaries are ordered (John Beck), + Fix Enum check and missing break (Gaurav Gupta), + xmlIO: Handle error returns from dup() (Philip Withnall), + Fix a problem properly saving URIs (Daniel Veillard), + wrong error column in structured error when parsing attribute values (Juergen Keil), + wrong error column in structured error when skipping whitespace in xml decl (Juergen Keil), + no error column in structured error handler for xml schema validation errors (Juergen Keil), + Couple of Missing Null checks (Gaurav Gupta), + Add couple of missing Null checks (Daniel Veillard), + xmlschemastypes: Fix potential array overflow (Philip Withnall), + runtest: Fix a memory leak on parse failure (Philip Withnall), + xmlIO: Fix an FD leak on gzdopen() failure (Philip Withnall), + xmlcatalog: Fix a memory leak on quit (Philip Withnall), + HTMLparser: Correctly initialise a stack allocated structure (Philip Withnall), + Check for tmon in _xmlSchemaDateAdd() is incorrect (David Kilzer), + Avoid Possible Null Pointer in trio.c (Gaurav Gupta), + Fix processing in SAX2 in case of an allocation failure (Daniel Veillard), + XML Shell command "cd" does not handle "/" at end of path (Daniel Veillard), + Fix various Missing Null checks (Gaurav Gupta), + Fix a potential NULL dereference (Daniel Veillard), + Add a couple of misisng check in xmlRelaxNGCleanupTree (Gaurav Gupta), + Add a missing argument check (Gaurav Gupta), + Adding a check in case of allocation error (Gaurav Gupta), + xmlSaveUri() incorrectly recomposes URIs with rootless paths (Dennis Filder), + Adding some missing NULL checks (Gaurav), + Fixes for xmlInitParserCtxt (Daniel Veillard), + Fix regressions introduced by CVE-2014-0191 patch (Daniel Veillard), + erroneously ignores a validation error if no error callback set (Daniel Veillard), + xmllint was not parsing the --c14n11 flag (Sérgio Batista), + Avoid Possible null pointer dereference in memory debug mode (Gaurav), + Avoid Double Null Check (Gaurav), + Restore context size and position after XPATH_OP_ARG (Nick Wellnhofer), + Fix xmlParseInNodeContext() if node is not element (Daniel Veillard), + Avoid a possible NULL pointer dereference (Gaurav), + Fix xmlTextWriterWriteElement when a null content is given (Daniel Veillard), + Fix an typo 'onrest' in htmlScriptAttributes (Daniel Veillard), + fixing a ptotential uninitialized access (Daniel Veillard), + Fix an fd leak in an error case (Daniel Veillard), + Missing initialization for the catalog module (Daniel Veillard), + Handling of XPath function arguments in error case (Nick Wellnhofer), + Fix a couple of missing NULL checks (Gaurav), + Avoid a possibility of dangling encoding handler (Gaurav), + Fix HTML push parser to accept HTML_PARSE_NODEFDTD (Arnold Hendriks), + Fix a bug loading some compressed files (Mike Alexander), + Fix XPath node comparison bug (Gaurav), + Type mismatch in xmlschemas.c (Gaurav), + Type mismatch in xmlschemastypes.c (Gaurav), + Avoid a deadcode in catalog.c (Daniel Veillard), + run close socket on Solaris, same as we do on other platforms (Denis Pauk), + Fix pointer dereferenced before null check (Gaurav), + Fix a potential NULL dereference in tree code (Daniel Veillard), + Fix potential NULL pointer dereferences in regexp code (Gaurav), + xmllint --pretty crashed without following numeric argument (Tim Galeckas), + Fix XPath expressions of the form '@ns:*' (Nick Wellnhofer), + Fix XPath '//' optimization with predicates (Nick Wellnhofer), + Clear up a potential NULL dereference (Daniel Veillard), + Fix a possible NULL dereference (Gaurav), + Avoid crash if allocation fails (Daniel Veillard), + Remove occasional leading space in XPath number formatting (Daniel Veillard), + Fix handling of mmap errors (Daniel Veillard), + Catch malloc error and exit accordingly (Daniel Veillard), + missing else in xlink.c (Ami Fischman), + Fix a parsing bug on non-ascii element and CR/LF usage (Daniel Veillard), + Fix a regression in xmlGetDocCompressMode() (Daniel Veillard), + properly quote the namespace uris written out during c14n (Aleksey Sanin), + Remove premature XInclude check on URI being relative (Alexey Neyman), + Fix missing break on last() function for attributes (dcb), + Do not URI escape in server side includes (Romain Bondue), + Fix an error in xmlCleanupParser (Alexander Pastukhov) + + - Documentation: + typo in error messages "colon are forbidden from..." (Daniel Veillard), + Fix a link to James SAX documentation old page (Daniel Veillard), + Fix typos in relaxng.c (Jan Pokorný), + Fix a doc typo (Daniel Veillard), + Fix typos in {tree,xpath}.c (errror) (Jan Pokorný), + Add limitations about encoding conversion (Daniel Veillard), + Fix typos in xmlschemas{,types}.c (Jan Pokorný), + Fix incorrect spelling entites->entities (Jan Pokorný), + Forgot to document 2.9.1 release, regenerate docs (Daniel Veillard) + + - Portability: + AC_CONFIG_FILES and executable bit (Roumen Petrov), + remove HAVE_CONFIG_H dependency in testlimits.c (Roumen Petrov), + fix some tabs mixing incompatible with python3 (Roumen Petrov), + Visual Studio 14 CTP defines snprintf() (Francis Dupont), + OS400: do not try to copy unexisting doc files (Patrick Monnerat), + OS400: use either configure.ac or configure.in. (Patrick Monnerat), + os400: make-src.sh: create physical file with target CCSID (Patrick Monnerat), + OS400: Add some more C macros equivalent procedures. (Patrick Monnerat), + OS400: use C macros to implement equivalent RPG support procedures. (Patrick Monnerat), + OS400: implement XPath macros as procedures for ILE/RPG support. (Patrick Monnerat), + OS400: include in distribution tarball. (Patrick Monnerat), + OS400: Add README: compilation directives and OS/400 specific stuff. (Patrick Monnerat), + OS400: Add compilation scripts. (Patrick Monnerat), + OS400: ILE RPG language header files. (Patrick Monnerat), + OS400: implement some macros as functions for ILE/RPG language support (that as no macros). (Patrick Monnerat), + OS400: UTF8<-->EBCDIC wrappers for system and external library calls (Patrick Monnerat), + OS400: Easy character transcoding support (Patrick Monnerat), + OS400: iconv functions compatibility wrappers and table builder. (Patrick Monnerat), + OS400: create architecture directory. Implement dlfcn emulation. (Patrick Monnerat), + Fix building when configuring without xpath and xptr (Daniel Veillard), + configure: Add --with-python-install-dir (Jonas Eriksson), + Fix compilation with minimum and xinclude. (Nicolas Le Cam), + Compile out use of xmlValidateNCName() when not available. (Nicolas Le Cam), + Fix compilation with minimum and schematron. (Nicolas Le Cam), + Legacy needs xmlSAX2StartElement() and xmlSAX2EndElement(). (Nicolas Le Cam), + Don't use xmlValidateName() when not available. (Nicolas Le Cam), + Fix a portability issue on Windows (Longstreth Jon), + Various portability patches for OpenVMS (Jacob (Jouk) Jansen), + Use specific macros for portability to OS/400 (Patrick Monnerat), + Add macros needed for OS/400 portability (Patrick Monnerat), + Portability patch for fopen on OS/400 (Patrick Monnerat), + Portability fixes for OS/400 (Patrick Monnerat), + Improve va_list portability (Patrick Monnerat), + Portability fix (Patrick Monnerat), + Portability fix (Patrick Monnerat), + Generic portability fix (Patrick Monnerat), + Shortening lines in headers (Patrick Monnerat), + build: Use pkg-config to find liblzma in preference to AC_CHECK_LIB (Philip Withnall), + build: Add @LZMA_LIBS@ to libxml’s pkg-config files (Philip Withnall), + fix some tabs mixing incompatible with python3 (Daniel Veillard), + add additional defines checks for support "./configure --with-minimum" (Denis Pauk), + Another round of fixes for older versions of Python (Arfrever Frehtes Taifersar Arahesis), + python: fix drv_libxml2.py for python3 compatibility (Alexandre Rostovtsev), + python: Fix compiler warnings when building python3 bindings (Armin K), + Fix for compilation with python 2.6.8 (Petr Sumbera) + + - Improvements: + win32/libxml2.def.src after rebuild in doc (Roumen Petrov), + elfgcchack.h: more legacy needs xmlSAX2StartElement() and xmlSAX2EndElement() (Roumen Petrov), + elfgcchack.h: add xmlXPathNodeEval and xmlXPathSetContextNode (Roumen Petrov), + Provide cmake module (Samuel Martin), + Fix a couple of issues raised by make dist (Daniel Veillard), + Fix and add const qualifiers (Kurt Roeckx), + Preparing for upcoming release of 2.9.2 (Daniel Veillard), + Fix zlib and lzma libraries check via command line (Dmitriy), + wrong error column in structured error when parsing end tag (Juergen Keil), + doc/news.html: small update to avoid line join while generating NEWS. (Patrick Monnerat), + Add methods for python3 iterator (Ron Angeles), + Support element node traversal in document fragments. (Kyle VanderBeek), + xmlNodeSetName: Allow setting the name to a substring of the currently set name (Tristan Van Berkom), + Added macros for argument casts (Eric Zurcher), + adding init calls to xml and html Read parsing entry points (Daniel Veillard), + Get rid of 'REPLACEMENT CHARACTER' Unicode chars in xmlschemas.c (Jan Pokorný), + Implement choice for name classes on attributes (Shaun McCance), + Two small namespace tweaks (Daniel Veillard), + xmllint --memory should fail on empty files (Daniel Veillard), + Cast encoding name to char pointer to match arg type (Nikolay Sivov) + + - Cleanups: + Removal of old configure.in (Daniel Veillard), + Unreachable code in tree.c (Gaurav Gupta), + Remove a couple of dead conditions (Gaurav Gupta), + Avoid some dead code and cleanup in relaxng.c (Gaurav), + Drop not needed checks (Denis Pauk), + Fix a wrong test (Daniel Veillard) + + + +2.9.1: Apr 19 2013: + - Features: + Support for Python3 (Daniel Veillard), + Add xmlXPathSetContextNode and xmlXPathNodeEval (Alex Bligh) + + - Documentation: + Add documentation for xmllint --xpath (Daniel Veillard), + Fix the URL of the SAX documentation from James (Daniel Veillard), + Fix spelling of "length". (Michael Wood) + + - Portability: + Fix python bindings with versions older than 2.7 (Daniel Veillard), + rebuild docs:Makefile.am (Roumen Petrov), + elfgcchack.h after rebuild in doc (Roumen Petrov), + elfgcchack for buf module (Roumen Petrov), + Fix a uneeded and wrong extra link parameter (Daniel Veillard), + Few cleanup patches for Windows (Denis Pauk), + Fix rpmbuild --nocheck (Mark Salter), + Fix for win32/configure.js and WITH_THREAD_ALLOC (Daniel Richard), + Fix Broken multi-arch support in xml2-config (Daniel Veillard), + Fix a portability issue for GCC < 3.4.0 (Daniel Veillard), + Windows build fixes (Daniel Richard), + Fix a thread portability problem (Friedrich Haubensak), + Downgrade autoconf requirement to 2.63 (Daniel Veillard) + + - Bug Fixes: + Fix a linking error for python bindings (Daniel Veillard), + Fix a couple of return without value (Jüri Aedla), + Improve the hashing functions (Daniel Franke), + Improve handling of xmlStopParser() (Daniel Veillard), + Remove risk of lockup in dictionary initialization (Daniel Veillard), + Activate detection of encoding in external subset (Daniel Veillard), + Fix an output buffer flushing conversion bug (Mikhail Titov), + Fix an old bug in xmlSchemaValidateOneElement (Csaba László), + Fix configure cannot remove messages (Gilles Espinasse), + fix schema validation in combination with xsi:nil (Daniel Veillard), + xmlCtxtReadFile doesn't work with literal IPv6 URLs (Steve Wolf), + Fix a few problems with setEntityLoader (Alexey Neyman), + Detect excessive entities expansion upon replacement (Daniel Veillard), + Fix the flushing out of raw buffers on encoding conversions (Daniel, +Veillard), + Fix some buffer conversion issues (Daniel Veillard), + When calling xmlNodeDump make sure we grow the buffer quickly (Daniel, +Veillard), + Fix an error in the progressive DTD parsing code (Dan Winship), + xmllint should not load DTD by default when using the reader (Daniel, +Veillard), + Try IBM-037 when looking for EBCDIC handlers (Petr Sumbera), + Fix potential out of bound access (Daniel Veillard), + Fix large parse of file from memory (Daniel Veillard), + Fix a bug in the nsclean option of the parser (Daniel Veillard), + Fix a regression in 2.9.0 breaking validation while streaming (Daniel, +Veillard), + Remove potential calls to exit() (Daniel Veillard) + + - Improvements: + Regenerated API, and testapi, rebuild documentation (Daniel Veillard), + Fix tree iterators broken by 2to3 script (Daniel Veillard), + update all tests for Python3 and Python2 (Daniel Veillard), + A few more fixes for python 3 affecting libxml2.py (Daniel Veillard), + Fix compilation on Python3 (Daniel Veillard), + Converting apibuild.py to python3 (Daniel Veillard), + First pass at starting porting to python3 (Daniel Veillard), + updated configure.in for python3 (Daniel Veillard), + Add support for xpathRegisterVariable in Python (Shaun McCance), + Added a regression tests from bug 694228 data (Daniel Veillard), + Cache presence of '<' in entities content (Daniel Veillard), + Avoid extra processing on entities (Daniel Veillard), + Python binding for xmlRegisterInputCallback (Alexey Neyman), + Python bindings: DOM casts everything to xmlNode (Alexey Neyman), + Define LIBXML_THREAD_ALLOC_ENABLED via xmlversion.h (Tim Starling), + Adding streaming validation to runtest checks (Daniel Veillard), + Add a --pushsmall option to xmllint (Daniel Veillard) + + - Cleanups: + Switched comment in file to UTF-8 encoding (Daniel Veillard), + Extend gitignore (Daniel Veillard), + Silent the new python test on input (Alexey Neyman), + Cleanup of a duplicate test (Daniel Veillard), + Cleanup on duplicate test expressions (Daniel Veillard), + Fix compiler warning after 153cf15905cf4ec080612ada6703757d10caba1e (Patrick, +Gansterer), + Spec cleanups and a fix for multiarch support (Daniel Veillard), + Silence a clang warning (Daniel Veillard), + Cleanup the Copyright to be pure MIT Licence wording (Daniel Veillard), + rand_seed should be static in dict.c (Wouter Van Rooy), + Fix typos in parser comments (Jan Pokorný) + + + +2.9.0: Sep 11 2012: + - Features: + A few new API entry points, + More resilient push parser mode, + A lot of portability improvement, + Faster XPath evaluation + + - Documentation: + xml2-config.1 markup error (Christian Weisgerber), + libxml(3) manpage typo fix (John Bradshaw), + More cleanups to the documentation part of libxml2 (Daniel Richard G) + + - Portability: + Bug 676544 - fails to build with --without-sax1 (Akira TAGOH), + fix builds not having stdint.h (Rob Richards), + GetProcAddressA is available only on WinCE (Daniel Veillard), + More updates and cleanups on autotools and Makefiles (Daniel Richard G), + More changes for Win32 compilation (Eric Zurcher), + Basic changes for Win32 builds of release 2.9.0: compile buf.c (Eric Zurcher), + Bundles all generated files for python into the distribution (Daniel Richard G), + Fix compiler warnings of wincecompat.c (Patrick Gansterer), + Fix non __GNUC__ build (Patrick Gansterer), + Fix windows unicode build (Patrick Gansterer), + clean redefinition of {v}snprintf in C-source (Roumen Petrov), + use xmlBuf... if DEBUG_INPUT is defined (Roumen Petrov), + fix runtests to use pthreads support for various Unix platforms (Daniel Richard G), + Various "make distcheck" and portability fixups 2nd part (Daniel Richard G), + Various "make distcheck" and portability fixups (Daniel Richard G), + Fix compilation on older Visual Studio (Daniel Veillard) + + - Bug Fixes: + Change the XPath code to percolate allocation errors (Daniel Veillard), + Fix reuse of xmlInitParser (Daniel Veillard), + Fix potential crash on entities errors (Daniel Veillard), + initialize var (Rob Richards), + Fix the XPath arity check to also check the XPath stack limits (Daniel Veillard), + Fix problem with specific and generic error handlers (Pietro Cerutti), + Avoid a potential infinite recursion (Daniel Veillard), + Fix an XSD error when generating internal automata (Daniel Veillard), + Patch for xinclude of text using multibyte characters (Vitaly Ostanin), + Fix a segfault on XSD validation on pattern error (Daniel Veillard), + Fix missing xmlsave.h module which was ignored in recent builds (Daniel Veillard), + Add a missing element check (Daniel Veillard), + Adding various checks on node type though the API (Daniel Veillard), + Namespace nodes can't be unlinked with xmlUnlinkNode (Daniel Veillard), + Fix make dist to include new private header files (Daniel Veillard), + More fixups on the push parser behaviour (Daniel Veillard), + Strengthen behaviour of the push parser in problematic situations (Daniel Veillard), + Enforce XML_PARSER_EOF state handling through the parser (Daniel Veillard), + Fixup limits parser (Daniel Veillard), + Do not fetch external parsed entities (Daniel Veillard), + Fix an error in previous commit (Aron Xu), + Fix entities local buffers size problems (Daniel Veillard), + Fix parser local buffers size problems (Daniel Veillard), + Fix a failure to report xmlreader parsing failures (Daniel Veillard) + + - Improvements: + Keep libxml2.syms when running "make distclean" (Daniel Veillard), + Allow to set the quoting character of an xmlWriter (Csaba Raduly), + Keep non-significant blanks node in HTML parser (Daniel Veillard), + Add a forbidden variable error number and message to XPath (Daniel Veillard), + Support long path names on WNT (Michael Stahl), + Improve HTML escaping of attribute on output (Daniel Veillard), + Handle ICU_LIBS as LIBADD, not LDFLAGS to prevent linking errors (Arfrever Frehtes Taifersar Arahesis), + Switching XPath node sorting to Timsort (Vojtech Fried), + Optimizing '//' in XPath expressions (Nick Wellnhofer), + Expose xmlBufShrink in the public tree API (Daniel Veillard), + Visible HTML elements close the head tag (Conrad Irwin), + Fix file and line report for XSD SAX and reader streaming validation (Daniel Veillard), + Fix const qualifyer to definition of xmlBufferDetach (Daniel Veillard), + minimize use of HAVE_CONFIG_H (Roumen Petrov), + fixup regression in Various "make distcheck" and portability fixups (Roumen Petrov), + Add support for big line numbers in error reporting (Daniel Veillard), + Avoid using xmlBuffer for serialization (Daniel Veillard), + Improve compatibility between xmlBuf and xmlBuffer (Daniel Veillard), + Provide new accessors for xmlOutputBuffer (Daniel Veillard), + Improvements for old buffer compatibility (Daniel Veillard), + Expand the limit test program (Daniel Veillard), + Improve error reporting on parser errors (Daniel Veillard), + Implement some default limits in the XPath module (Daniel Veillard), + Introduce some default parser limits (Daniel Veillard), + Cleanups and new limit APIs for dictionaries (Daniel Veillard), + Fixup for buf.c (Daniel Veillard), + Cleanup URI module memory allocation code (Daniel Veillard), + Extend testlimits (Daniel Veillard), + More avoid quadratic behaviour (Daniel Veillard), + Impose a reasonable limit on PI size (Daniel Veillard), + first version of testlimits new test (Daniel Veillard), + Avoid quadratic behaviour in some push parsing cases (Daniel Veillard), + Impose a reasonable limit on comment size (Daniel Veillard), + Impose a reasonable limit on attribute size (Daniel Veillard), + Harden the buffer code and make it more compatible (Daniel Veillard), + More cleanups for input/buffers code (Daniel Veillard), + Cleanup function xmlBufResetInput(), to set input from Buffer (Daniel Veillard) + Swicth the test program for characters to new input buffers (Daniel Veillard), + Convert the HTML tree module to the new buffers (Daniel Veillard), + Convert of the HTML parser to new input buffers (Daniel Veillard), + Convert the writer to new output buffer and save APIs (Daniel Veillard), + Convert XMLReader to the new input buffers (Daniel Veillard), + New saving functions using xmlBuf and conversion (Daniel Veillard), + Provide new xmlBuf based saving functions (Daniel Veillard), + Convert XInclude to the new input buffers (Daniel Veillard), + Convert catalog code to the new input buffers (Daniel Veillard), + Convert C14N to the new Input buffer (Daniel Veillard), + Convert xmlIO.c to the new input and output buffers (Daniel Veillard), + Convert XML parser to the new input buffers (Daniel Veillard), + Incompatible change to the Input and Output buffers (Daniel Veillard), + Adding new encoding function to deal with the new structures (Daniel Veillard), + Convert XPath to xmlBuf (Daniel Veillard), + Adding a new buf module for buffers (Daniel Veillard), + Memory error within SAX2 reuse common framework (Daniel Veillard), + Fix xmllint --xpath node initialization (Daniel Veillard) + + - Cleanups: + Various cleanups to avoid compiler warnings (Daniel Veillard), + Big space and tab cleanup (Daniel Veillard), + Followup to LibXML2 docs/examples cleanup patch (Daniel Veillard), + Second round of cleanups for LibXML2 docs/examples (Daniel Richard), + Remove all .cvsignore as they are not used anymore (Daniel Veillard), + Fix a Timsort function helper comment (Daniel Veillard), + Small cleanup for valgrind target (Daniel Veillard), + Patch for portability of latin characters in C files (Daniel Veillard), + Cleanup some of the parser code (Daniel Veillard), + Fix a variable name in comment (Daniel Veillard), + Regenerated testapi.c (Daniel Veillard), + Regenerating docs and API files (Daniel Veillard), + Small cleanup of unused variables in test (Daniel Veillard), + Expand .gitignore with more files (Daniel Veillard) + + + +2.8.0: May 23 2012: + - Features: + add lzma compression support (Anders F Bjorklund) + + - Documentation: + xmlcatalog: Add uri and delegateURI to possible add types in man page. (Ville Skyttä), + Update README.tests (Daniel Veillard), + URI handling code is not OOM resilient (Daniel Veillard), + Fix an error in comment (Daniel Veillard), + Fixed bug #617016 (Daniel Mustieles), + Fixed two typos in the README document (Daniel Neel), + add generated html files (Anders F Bjorklund), + Clarify the need to use xmlFreeNode after xmlUnlinkNode (Daniel Veillard), + Improve documentation a bit (Daniel Veillard), + Updated URL for lxml python bindings (Daniel Veillard) + + - Portability: + Restore code for Windows compilation (Daniel Veillard), + Remove git error message during configure (Christian Dywan), + xmllint: Build fix for endTimer if !defined(HAVE_GETTIMEOFDAY) (Patrick R. Gansterer), + remove a bashism in confgure.in (John Hein), + undef ERROR if already defined (Patrick R. Gansterer), + Fix library problems with mingw-w64 (Michael Cronenworth), + fix windows build. ifdef addition from bug 666491 makes no sense (Rob Richards), + prefer native threads on win32 (Sam Thursfield), + Allow to compile with Visual Studio 2010 (Thomas Lemm), + Fix mingw's snprintf configure check (Andoni Morales), + fixed a 64bit big endian issue (Marcus Meissner), + Fix portability failure if netdb.h lacks NO_ADDRESS (Daniel Veillard), + Fix windows build from lzma addition (Rob Richards), + autogen: Only check for libtoolize (Colin Walters), + Fix the Windows build files (Patrick von Reth), + 634846 Remove a linking option breaking Windows VC10 (Daniel Veillard), + 599241 fix an initialization problem on Win64 (Andrew W. Nosenko), + fix win build (Rob Richards) + + - Bug fixes: + Part for rand_r checking missing (Daniel Veillard), + Cleanup on randomization (Daniel Veillard), + Fix undefined reference in python module (Pacho Ramos), + Fix a race in xmlNewInputStream (Daniel Veillard), + Fix weird streaming RelaxNG errors (Noam), + Fix various bugs in new code raised by the API checking (Daniel Veillard), + Fix various problems with "make dist" (Daniel Veillard), + Fix a memory leak in the xzlib code (Daniel Veillard), + HTML parser error with