Import Cobalt 20.master.0.217501
diff --git a/src/LICENSE b/src/LICENSE index 3d0f7d3..a32e00c 100644 --- a/src/LICENSE +++ b/src/LICENSE
@@ -1,4 +1,4 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Copyright 2015 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
diff --git a/src/cobalt/CHANGELOG.md b/src/cobalt/CHANGELOG.md index 6f368aa..45f312d 100644 --- a/src/cobalt/CHANGELOG.md +++ b/src/cobalt/CHANGELOG.md
@@ -3,11 +3,22 @@ This document records all notable changes made to Cobalt since the last release. ## Version 20 - - **Improvements and Bug Fixes** - - Fix bug where Cobalt would not refresh the layout when the textContent - property of a DOM TextNode is modified. - - **Add support for decoding JPEG images as multi-plane YUV** + - **Support for QUIC and SPDY is now enabled.** + + QUIC and SPDY networking protocol support is added and these are enabled by + default (if the server supports the protocol). This reduces roundtrip + overhead and will improve networking overhead performance, especially on + lower quality connections. + + - **BoringSSL replaces OpenSSL enabling architecture-specific optimizations.** + + The update to BoringSSL brings with it the introduction of assembly-optimized + architecture-specific optimizations that can bring a 5x speed up to + cryptographic functions. This is especially useful when decrypting TLS for + high-bandwidth video. + + - **Added support for decoding JPEG images as multi-plane YUV.** JPEG images are decoded into RGBA in previous versions of Cobalt. The native format of most JPEG images is YV12, which takes only 3/8 of memory compare to @@ -19,6 +30,108 @@ parameter "allow_image_decoding_to_multi_plane" to Cobalt with value "true" or "false". + - **Improved image cache purge strategy.** + + Cobalt's image cache is now more aware of which images are likely to be + reused (e.g. the ones referenced by HTMLImageElements, even if they are not + currently displayed), and will now prioritize purging completely unreferenced + images before weakly referenced images. + + - **Added support for encoded image caching.** + + Cobalt now has support for caching the encoded image data fetched from the + network. This enables Cobalt to keep the cached encoded image data resident + so that when the user resumes, Cobalt does not need to do a network fetch + for images again. The size of this cache can be adjusted via the gyp + option `encoded_image_cache_size_in_bytes`, or the command line switch + `--encoded_image_cache_size_in_bytes`. + + - **Added support for Device Authentication URL signing.** + + Cobalt will now add URL parameters signed with the device's secret key and + certification scope to the initial URL. + + - **Updated Chromium net and base libraries from m25 to m70.** + + Cobalt now has rebased its m25 net and base libraries to Chromium's m70 + version of those libraries, bringing with it more functionality, better + performance, and fewer bugs. + + - **Media Codec Support.** + + Cobalt now supports the AV1 codec, the HEVC (H.265) codec, Dolby Digital + (AC-3) and Dolby Digital Plus (Enhanced AC-3, or EAC-3). + + - **Flexbox support added.** + + Cobalt now supports the Flexible Box Module, enabling web applications to + take advantage of the more expressive layout model. + + - **Support added for Chromium DevTools with V8.** + + Cobalt now supports the Chromium DevTools to help debug web applications. + You can access it on non-gold builds by first starting Cobalt, and then using + a browser to navigate to `http://YOUR_DEVICE_IP:9222`. The Elements, + Sources, Console and Performance panels are supported. + + - **Support added for Intersection Observer Web API.** + + Cobalt now supports the Intersection Observer Web API to enable more + performant checking of whether HTML elements are visible or not. Note that + Cobalt's implementation currently does not support triggering visibility + events that occur during CSS animation/transition playback. + + - **Support for custom interface HTMLVideoElement.setMaxVideoCapabilities()** + + This allows the web application to express a guarantee to the platform's + video player that a video will never exceed a maximum quality in a particular + property. You could use this for example to indicate that a video will never + adapt past a maximum resolution. + + - **Platform Services API added** + + This API enables web applications to communicate directly to + platform-specific services and systems, assuming the platform explicitly + enables the given service. + + - **EGL/GLES-based reference implementation of the Blitter API now available.** + + The Blitter API is now much easier to test locally on desktop computers or + any device that already supports EGL/GLES. The new platform configuration + is named `linux-x64x11-blittergles`. + + - **Add support for AbortController to the Fetch API.** + + The Fetch API is now updated to support the `AbortController` feature. + + - **Support added for HTMLAudioElement HTML tag.** + + This can be used to play audio-only media. + + - **Add support for CSS3 Media Queries “dpi” value.** + + This can be used by the web application to adjust its layout depending + on the physical size of the display device, if known. + + - **Add support for scrollWidth, scrollHeight, scrollLeft, and scrollTop.** + + The web application can now query and set scroll properties of containers. + + - **Initial support for Cobalt Evergreen automatic software updater added.** + + Cobalt is transitioning towards a runtime-linkable environment in order to + support automatic software updates. Changes have been made around the + Starboard interface in anticipation of this. Most notably, the EGL/GLES + interface is no longer assumed to be available but rather Cobalt will now + query the Starboard implementation for a structure of function pointers that + implement the EGL/GLES APIs. + + Part of this process involves moving options that were formerly build-time + options to be instead run-time options. This will primarily be enabled + by the new Starboard extensions framework. An example of an platform + specific option added in this way can be found in + `cobalt/extension/graphis.h`. + - **Cobalt code assumes that no errors are generated for unused parameters** There now exists Cobalt code where input parameters may be unused, and it @@ -45,6 +158,19 @@ that may be copied and queried on any thread to get a coherent view of attributes set by the the web app on the `MediaSession`. + - **Improvements and Bug Fixes** + + - Fix bug where Cobalt would not refresh the layout when the textContent + property of a DOM TextNode is modified. + - Media codecs can now be disabled with the “--disable_media_codecs” command + line option to help with debugging. + - Enable “--proxy” command line flag in gold builds of Cobalt. + - Add `GetMaximumFrameIntervalInMilliseconds()` platform Cobalt configuration + setting (in `cobalt/extension/graphics.h`) to allow a platform to indicate a + minimum framerate causing Cobalt to rerender the display even if nothing has + changed after the specified interval. + + ## Version 19 - **Add support for V8 JavaScript Engine**
diff --git a/src/cobalt/audio/audio_device.cc b/src/cobalt/audio/audio_device.cc index 73f91bc..11ed4d2 100644 --- a/src/cobalt/audio/audio_device.cc +++ b/src/cobalt/audio/audio_device.cc
@@ -30,17 +30,13 @@ namespace { const int kRenderBufferSizeFrames = 1024; +// AudioDevice will keep writing silence frames at the end of playback until the +// buffer is full to ensure the audible frames being played on platforms with +// strict underflow control. A large |kFramesPerChannel| will increase the +// silence between two sounds. So it shouldn't be set to a very large number. const int kFramesPerChannel = kRenderBufferSizeFrames * 8; } // namespace -namespace { -// Write |kTailSizeInFrames| frames of silence at the end of playback to ensure -// the audible frames being played on platforms with strict underflow control. -// Increasing this value will also increase the silence between two sounds. So -// it shouldn't be set to a very too large. -const int kTailSizeInFrames = kRenderBufferSizeFrames * 8; -} // namespace - class AudioDevice::Impl { public: Impl(int number_of_channels, RenderCallback* callback); @@ -162,6 +158,9 @@ bool* is_playing, bool* is_eos_reached) { TRACE_EVENT0("cobalt::audio", "AudioDevice::Impl::UpdateSourceStatus()"); + // AudioDevice may be reused after stopped but before destroyed. Keep writing + // silence before destroyed to let |audio_sink_| keep working without + // underflow. It will cause latency between two sounds. *is_playing = true; *is_eos_reached = false; @@ -182,28 +181,23 @@ render_callback_->FillAudioBus(all_consumed, &input_audio_bus_, &silence); - bool fill_output = true; if (silence) { - fill_output = kTailSizeInFrames > silence_written_; silence_written_ += kRenderBufferSizeFrames; } else { // Reset |silence_written_| if a new sound is played after some silence // frames were injected. silence_written_ = 0; } - if (fill_output) { - FillOutputAudioBus(); - frames_rendered_ += kRenderBufferSizeFrames; - *frames_in_buffer += kRenderBufferSizeFrames; - } + FillOutputAudioBus(); + + frames_rendered_ += kRenderBufferSizeFrames; + *frames_in_buffer += kRenderBufferSizeFrames; was_silence_last_update_ = silence; } *offset_in_frames = frames_consumed_ % kFramesPerChannel; - *is_playing = - !(silence_written_ != 0 && *frames_in_buffer <= silence_written_); } void AudioDevice::Impl::ConsumeFrames(int frames_consumed) {
diff --git a/src/cobalt/browser/browser_module.cc b/src/cobalt/browser/browser_module.cc index fad5331..1708028 100644 --- a/src/cobalt/browser/browser_module.cc +++ b/src/cobalt/browser/browser_module.cc
@@ -465,7 +465,11 @@ #endif } -void BrowserModule::Navigate(const GURL& url) { +void BrowserModule::Navigate(const GURL& url_reference) { + // The argument is sometimes |pending_navigate_url_|, and Navigate can modify + // |pending_navigate_url_|, so we want to keep a copy of the argument to + // preserve its original value. + GURL url = url_reference; DLOG(INFO) << "In BrowserModule::Navigate " << url; TRACE_EVENT1("cobalt::browser", "BrowserModule::Navigate()", "url", url.spec());
diff --git a/src/cobalt/browser/browser_module.h b/src/cobalt/browser/browser_module.h index 74e0fc3..0bc7d1a 100644 --- a/src/cobalt/browser/browser_module.h +++ b/src/cobalt/browser/browser_module.h
@@ -125,7 +125,7 @@ // currently suspended, this defers the navigation and instead sets // |pending_navigate_url_| to the specified url, which will trigger a // navigation when Cobalt resumes. - void Navigate(const GURL& url); + void Navigate(const GURL& url_reference); // Reloads web module. void Reload();
diff --git a/src/cobalt/build/all.gyp b/src/cobalt/build/all.gyp index 8909d7a..a53c52f 100644 --- a/src/cobalt/build/all.gyp +++ b/src/cobalt/build/all.gyp
@@ -86,6 +86,7 @@ '<(DEPTH)/cobalt/websocket/websocket.gyp:*', '<(DEPTH)/cobalt/xhr/xhr.gyp:*', '<(DEPTH)/crypto/crypto.gyp:crypto_unittests', + '<(DEPTH)/third_party/boringssl/boringssl_tool.gyp:*', '<(DEPTH)/net/net.gyp:net_unittests', '<(DEPTH)/sql/sql.gyp:sql_unittests', ],
diff --git a/src/cobalt/build/build.id b/src/cobalt/build/build.id index 04c18cb..80c1e89 100644 --- a/src/cobalt/build/build.id +++ b/src/cobalt/build/build.id
@@ -1 +1 @@ -215766 \ No newline at end of file +217501 \ No newline at end of file
diff --git a/src/cobalt/cssom/cssom.gyp b/src/cobalt/cssom/cssom.gyp index bab7890..3fdf9f1 100644 --- a/src/cobalt/cssom/cssom.gyp +++ b/src/cobalt/cssom/cssom.gyp
@@ -233,7 +233,6 @@ 'unicode_range_value.h', 'universal_selector.cc', 'universal_selector.h', - 'used_style.h', 'user_agent_style_sheet.cc', 'user_agent_style_sheet.h', 'url_src_value.cc',
diff --git a/src/cobalt/cssom/used_style.h b/src/cobalt/cssom/used_style.h deleted file mode 100644 index 7aa05c7..0000000 --- a/src/cobalt/cssom/used_style.h +++ /dev/null
@@ -1,77 +0,0 @@ -// Copyright 2019 The Cobalt Authors. 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. - -#ifndef COBALT_CSSOM_USED_STYLE_H_ -#define COBALT_CSSOM_USED_STYLE_H_ - -#include "base/optional.h" -#include "cobalt/cssom/calc_value.h" -#include "cobalt/cssom/length_value.h" -#include "cobalt/cssom/percentage_value.h" -#include "cobalt/cssom/property_value_visitor.h" -#include "cobalt/layout/layout_unit.h" - -namespace cobalt { -namespace cssom { - -template <typename LengthType> -class UsedLengthValueProvider : public NotReachedPropertyValueVisitor { - public: - explicit UsedLengthValueProvider(LengthType percentage_base, - bool calc_permitted = false) - : percentage_base_(percentage_base), calc_permitted_(calc_permitted) {} - - void VisitLength(LengthValue* length) { - depends_on_containing_block_ = false; - - DCHECK_EQ(kPixelsUnit, length->unit()); - used_length_ = LengthType(length->value()); - } - - void VisitPercentage(PercentageValue* percentage) { - depends_on_containing_block_ = true; - used_length_ = percentage->value() * percentage_base_; - } - - void VisitCalc(CalcValue* calc) { - if (!calc_permitted_) { - NOTREACHED(); - } - depends_on_containing_block_ = true; - used_length_ = LengthType(calc->length_value()->value()) + - calc->percentage_value()->value() * percentage_base_; - } - - bool depends_on_containing_block() const { - return depends_on_containing_block_; - } - - const base::Optional<LengthType>& used_length() const { return used_length_; } - - protected: - bool depends_on_containing_block_; - - private: - const LengthType percentage_base_; - const bool calc_permitted_; - - base::Optional<LengthType> used_length_; - - DISALLOW_COPY_AND_ASSIGN(UsedLengthValueProvider); -}; - -} // namespace cssom -} // namespace cobalt - -#endif // COBALT_CSSOM_USED_STYLE_H_
diff --git a/src/cobalt/demos/content/media-element-demo/multi-video-demo.js b/src/cobalt/demos/content/media-element-demo/multi-video-demo.js index 6df7c71..cab4d58 100644 --- a/src/cobalt/demos/content/media-element-demo/multi-video-demo.js +++ b/src/cobalt/demos/content/media-element-demo/multi-video-demo.js
@@ -37,7 +37,7 @@ } onsourceopen() { - if (this.video_url.base::EndsWith('.mp4')) { + if (this.video_url.endsWith('.mp4')) { this.video_source_buffer = this.mediasource.addSourceBuffer( 'video/mp4; codecs="avc1.640028"'); } else {
diff --git a/src/cobalt/dom/dom.gyp b/src/cobalt/dom/dom.gyp index 7d1278a..f20646d 100644 --- a/src/cobalt/dom/dom.gyp +++ b/src/cobalt/dom/dom.gyp
@@ -99,6 +99,8 @@ 'dom_token_list.h', 'element.cc', 'element.h', + 'element_intersection_observer_module.cc', + 'element_intersection_observer_module.h', 'eme/media_encrypted_event.cc', 'eme/media_encrypted_event.h', 'eme/media_key_message_event.cc', @@ -193,9 +195,6 @@ 'intersection_observer_entry.h', 'intersection_observer_entry_init.h', 'intersection_observer_init.h', - 'intersection_observer_registration.h', - 'intersection_observer_target.h', - 'intersection_observer_target.cc', 'intersection_observer_task_manager.cc', 'intersection_observer_task_manager.h', 'keyboard_event.cc', @@ -264,8 +263,6 @@ 'progress_event.h', 'pseudo_element.cc', 'pseudo_element.h', - 'intersection_observer_registration_list.cc', - 'intersection_observer_registration_list.h', 'registered_observer.h', 'registered_observer_list.cc', 'registered_observer_list.h',
diff --git a/src/cobalt/dom/element.cc b/src/cobalt/dom/element.cc index dd4638f..04aff96 100644 --- a/src/cobalt/dom/element.cc +++ b/src/cobalt/dom/element.cc
@@ -15,7 +15,6 @@ #include "cobalt/dom/element.h" #include <algorithm> -#include <ctime> #include "base/lazy_instance.h" #include "base/strings/string_util.h" @@ -240,7 +239,7 @@ if (document && GetRootNode() == document) { document->OnDOMMutation(); } - OnSetAttribute(name, value); + OnSetAttribute(attr_name, value); } // Algorithm for RemoveAttribute: @@ -302,7 +301,7 @@ if (document && GetRootNode() == document) { document->OnDOMMutation(); } - OnRemoveAttribute(name); + OnRemoveAttribute(attr_name); } // Algorithm for tag_name: @@ -625,37 +624,71 @@ } } -void Element::RegisterIntersectionObserverTarget( - const scoped_refptr<IntersectionObserver>& observer) { - if (!intersection_observer_target_) { - intersection_observer_target_ = std::unique_ptr<IntersectionObserverTarget>( - new IntersectionObserverTarget(this)); +void Element::RegisterIntersectionObserverRoot(IntersectionObserver* observer) { + EnsureIntersectionObserverModuleInitialized(); + element_intersection_observer_module_->RegisterIntersectionObserverForRoot( + observer); +} + +void Element::UnregisterIntersectionObserverRoot( + IntersectionObserver* observer) { + if (element_intersection_observer_module_) { + element_intersection_observer_module_ + ->UnregisterIntersectionObserverForRoot(observer); } - intersection_observer_target_->RegisterIntersectionObserver(observer); +} + +void Element::RegisterIntersectionObserverTarget( + IntersectionObserver* observer) { + EnsureIntersectionObserverModuleInitialized(); + element_intersection_observer_module_->RegisterIntersectionObserverForTarget( + observer); } void Element::UnregisterIntersectionObserverTarget( - const scoped_refptr<IntersectionObserver>& observer) { - intersection_observer_target_->UnregisterIntersectionObserver(observer); + IntersectionObserver* observer) { + element_intersection_observer_module_ + ->UnregisterIntersectionObserverForTarget(observer); } -void Element::UpdateIntersectionObservationsForTarget( - const scoped_refptr<IntersectionObserver>& observer) { - intersection_observer_target_->UpdateIntersectionObservationsForTarget( - observer); +ElementIntersectionObserverModule::LayoutIntersectionObserverRootVector +Element::GetLayoutIntersectionObserverRoots() { + ElementIntersectionObserverModule::LayoutIntersectionObserverRootVector + layout_roots; + if (element_intersection_observer_module_) { + layout_roots = element_intersection_observer_module_ + ->GetLayoutIntersectionObserverRootsForElement(); + } + return layout_roots; +} + +ElementIntersectionObserverModule::LayoutIntersectionObserverTargetVector +Element::GetLayoutIntersectionObserverTargets() { + ElementIntersectionObserverModule::LayoutIntersectionObserverTargetVector + layout_targets; + if (element_intersection_observer_module_) { + layout_targets = element_intersection_observer_module_ + ->GetLayoutIntersectionObserverTargetsForElement(); + } + return layout_targets; } scoped_refptr<HTMLElement> Element::AsHTMLElement() { return NULL; } // Explicitly defined because DOMTokenList is forward declared and held by // scoped_refptr in Element's header. -Element::~Element() {} +Element::~Element() { + // Reset the ElementIntersectionObserverModule so that functions such as + // UnregisterIntersectionRoot/Target will not be called on deleted objects. + element_intersection_observer_module_.reset(); +} void Element::TraceMembers(script::Tracer* tracer) { Node::TraceMembers(tracer); tracer->Trace(named_node_map_); tracer->Trace(class_list_); + tracer->Trace(element_intersection_observer_module_); } bool Element::GetBooleanAttribute(const std::string& name) const { @@ -695,5 +728,13 @@ LOG(WARNING) << "Error when parsing inner HTML or outer HTML: " << error; } +void Element::EnsureIntersectionObserverModuleInitialized() { + if (!element_intersection_observer_module_) { + element_intersection_observer_module_ = + std::unique_ptr<ElementIntersectionObserverModule>( + new ElementIntersectionObserverModule(this)); + } +} + } // namespace dom } // namespace cobalt
diff --git a/src/cobalt/dom/element.h b/src/cobalt/dom/element.h index 22b1bfd..d37f9bc 100644 --- a/src/cobalt/dom/element.h +++ b/src/cobalt/dom/element.h
@@ -25,8 +25,8 @@ #include "cobalt/base/token.h" #include "cobalt/cssom/style_sheet_list.h" #include "cobalt/dom/dom_exception.h" +#include "cobalt/dom/element_intersection_observer_module.h" #include "cobalt/dom/intersection_observer.h" -#include "cobalt/dom/intersection_observer_target.h" #include "cobalt/dom/node.h" #include "cobalt/script/exception_state.h" #include "cobalt/web_animations/animation_set.h" @@ -199,17 +199,14 @@ return animations_; } - void RegisterIntersectionObserverTarget( - const scoped_refptr<IntersectionObserver>& observer); - - void UnregisterIntersectionObserverTarget( - const scoped_refptr<IntersectionObserver>& observer); - - // Queues an IntersectionObserverEntry if the thresholdIndex or isIntersecting - // properties have changed for the IntersectionObserverRegistration record - // corresponding to the given observer and this element (the target). - void UpdateIntersectionObservationsForTarget( - const scoped_refptr<IntersectionObserver>& observer); + void RegisterIntersectionObserverRoot(IntersectionObserver* observer); + void UnregisterIntersectionObserverRoot(IntersectionObserver* observer); + void RegisterIntersectionObserverTarget(IntersectionObserver* observer); + void UnregisterIntersectionObserverTarget(IntersectionObserver* observer); + ElementIntersectionObserverModule::LayoutIntersectionObserverRootVector + GetLayoutIntersectionObserverRoots(); + ElementIntersectionObserverModule::LayoutIntersectionObserverTargetVector + GetLayoutIntersectionObserverTargets(); DEFINE_WRAPPABLE_TYPE(Element); void TraceMembers(script::Tracer* tracer) override; @@ -243,6 +240,8 @@ // Callback for error when parsing inner / outer HTML. void HTMLParseError(const std::string& error); + void EnsureIntersectionObserverModuleInitialized(); + // Local name of the element. base::Token local_name_; // A map that holds the actual element attributes. @@ -261,7 +260,8 @@ // A set of all animations currently applied to this element. scoped_refptr<web_animations::AnimationSet> animations_; - std::unique_ptr<IntersectionObserverTarget> intersection_observer_target_; + std::unique_ptr<ElementIntersectionObserverModule> + element_intersection_observer_module_; }; } // namespace dom
diff --git a/src/cobalt/dom/element_intersection_observer_module.cc b/src/cobalt/dom/element_intersection_observer_module.cc new file mode 100644 index 0000000..01fb8a3 --- /dev/null +++ b/src/cobalt/dom/element_intersection_observer_module.cc
@@ -0,0 +1,183 @@ +// Copyright 2019 The Cobalt Authors. 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 "cobalt/dom/element_intersection_observer_module.h" + +#include "cobalt/dom/document.h" +#include "cobalt/dom/dom_rect_read_only.h" +#include "cobalt/dom/element.h" +#include "cobalt/dom/intersection_observer_entry_init.h" +#include "cobalt/dom/performance.h" + +namespace cobalt { +namespace dom { + +ElementIntersectionObserverModule::ElementIntersectionObserverModule( + Element* element) + : element_(element) {} + +void ElementIntersectionObserverModule::RegisterIntersectionObserverForRoot( + IntersectionObserver* observer) { + for (auto it = root_registered_intersection_observers_.begin(); + it != root_registered_intersection_observers_.end(); ++it) { + if (*it == observer) { + return; + } + } + root_registered_intersection_observers_.push_back( + base::WrapRefCounted(observer)); + + // Also create the observer's layout root at this time. + scoped_refptr<layout::IntersectionObserverRoot> new_root = + new layout::IntersectionObserverRoot( + observer->root_margin_property_value(), + observer->thresholds_vector()); + observer->set_layout_root(new_root); + + InvalidateLayoutBoxesForElement(); +} + +void ElementIntersectionObserverModule::UnregisterIntersectionObserverForRoot( + IntersectionObserver* observer) { + for (auto it = root_registered_intersection_observers_.begin(); + it != root_registered_intersection_observers_.end(); ++it) { + if (*it == observer) { + root_registered_intersection_observers_.erase(it); + InvalidateLayoutBoxesForElement(); + return; + } + } + NOTREACHED() + << "Did not find an intersection observer to unregister for the root."; +} + +void ElementIntersectionObserverModule::RegisterIntersectionObserverForTarget( + IntersectionObserver* observer) { + for (auto it = target_registered_intersection_observers_.begin(); + it != target_registered_intersection_observers_.end(); ++it) { + if (*it == observer) { + return; + } + } + target_registered_intersection_observers_.push_back( + base::WrapRefCounted(observer)); + AddLayoutTargetForObserver(observer); + + InvalidateLayoutBoxesForElement(); +} + +void ElementIntersectionObserverModule::UnregisterIntersectionObserverForTarget( + IntersectionObserver* observer) { + for (auto it = target_registered_intersection_observers_.begin(); + it != target_registered_intersection_observers_.end(); ++it) { + if (*it == observer) { + target_registered_intersection_observers_.erase(it); + RemoveLayoutTargetForObserver(observer); + InvalidateLayoutBoxesForElement(); + return; + } + } + NOTREACHED() + << "Did not find an intersection observer to unregister for the target."; +} + +ElementIntersectionObserverModule::LayoutIntersectionObserverRootVector +ElementIntersectionObserverModule:: + GetLayoutIntersectionObserverRootsForElement() { + ElementIntersectionObserverModule::LayoutIntersectionObserverRootVector + layout_roots; + for (const auto& intersection_observer : + root_registered_intersection_observers_) { + layout_roots.push_back(intersection_observer->layout_root()); + } + return layout_roots; +} + +ElementIntersectionObserverModule::LayoutIntersectionObserverTargetVector +ElementIntersectionObserverModule:: + GetLayoutIntersectionObserverTargetsForElement() { + return layout_targets_; +} + +void ElementIntersectionObserverModule:: + CreateIntersectionObserverEntryForObserver( + const base::WeakPtr<IntersectionObserver>& observer, + math::RectF root_bounds, math::RectF target_rect, + math::RectF intersection_rect, bool is_intersecting, + float intersection_ratio) { + if (!observer) { + return; + } + + IntersectionObserverEntryInit init_dict; + init_dict.set_time(element_->owner_document() + ->window() + ->performance() + ->timing() + ->GetNavigationStartClock() + ->Now() + .InMillisecondsF()); + init_dict.set_root_bounds( + base::WrapRefCounted(new DOMRectReadOnly(root_bounds))); + init_dict.set_bounding_client_rect( + base::WrapRefCounted(new DOMRectReadOnly(target_rect))); + init_dict.set_intersection_rect( + base::WrapRefCounted(new DOMRectReadOnly(intersection_rect))); + init_dict.set_is_intersecting(is_intersecting); + init_dict.set_intersection_ratio(intersection_ratio); + init_dict.set_target(base::WrapRefCounted(element_)); + observer->QueueIntersectionObserverEntry( + base::WrapRefCounted(new IntersectionObserverEntry(init_dict))); +} + +void ElementIntersectionObserverModule::TraceMembers(script::Tracer* tracer) { + tracer->TraceItems(root_registered_intersection_observers_); + tracer->TraceItems(target_registered_intersection_observers_); +} + +void ElementIntersectionObserverModule::AddLayoutTargetForObserver( + IntersectionObserver* observer) { + layout::IntersectionObserverTarget::OnIntersectionCallback + on_intersection_callback = + base::Bind(&ElementIntersectionObserverModule:: + CreateIntersectionObserverEntryForObserver, + base::Unretained(this), base::AsWeakPtr(observer)); + scoped_refptr<layout::IntersectionObserverTarget> layout_target = + new layout::IntersectionObserverTarget(on_intersection_callback, + observer->layout_root()); + layout_targets_.push_back(layout_target); +} + +void ElementIntersectionObserverModule::RemoveLayoutTargetForObserver( + IntersectionObserver* observer) { + for (auto it = layout_targets_.begin(); it != layout_targets_.end(); ++it) { + if ((*it)->intersection_observer_root() == observer->layout_root()) { + layout_targets_.erase(it); + return; + } + } + NOTREACHED() << "Did not find a layout target to remove"; +} + +void ElementIntersectionObserverModule::InvalidateLayoutBoxesForElement() { + HTMLElement* html_element = element_->AsHTMLElement(); + if (!html_element) { + NOTREACHED(); + return; + } + html_element->InvalidateLayoutBoxesOfNodeAndDescendants(); +} + +} // namespace dom +} // namespace cobalt
diff --git a/src/cobalt/dom/element_intersection_observer_module.h b/src/cobalt/dom/element_intersection_observer_module.h new file mode 100644 index 0000000..348dddc --- /dev/null +++ b/src/cobalt/dom/element_intersection_observer_module.h
@@ -0,0 +1,76 @@ +// Copyright 2019 The Cobalt Authors. 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. + +#ifndef COBALT_DOM_ELEMENT_INTERSECTION_OBSERVER_MODULE_H_ +#define COBALT_DOM_ELEMENT_INTERSECTION_OBSERVER_MODULE_H_ + +#include <vector> + +#include "cobalt/dom/intersection_observer.h" +#include "cobalt/math/rect_f.h" +#include "cobalt/script/tracer.h" + +namespace cobalt { +namespace dom { + +class Element; + +// This helper class groups the methods and data related to the root and target +// elements outlined in the intersection observer spec. +// https://www.w3.org/TR/intersection-observer +class ElementIntersectionObserverModule : public script::Traceable { + public: + typedef std::vector<scoped_refptr<IntersectionObserver>> + IntersectionObserverVector; + typedef std::vector<scoped_refptr<layout::IntersectionObserverRoot>> + LayoutIntersectionObserverRootVector; + typedef std::vector<scoped_refptr<layout::IntersectionObserverTarget>> + LayoutIntersectionObserverTargetVector; + + explicit ElementIntersectionObserverModule(Element* element); + ~ElementIntersectionObserverModule() {} + + void RegisterIntersectionObserverForRoot(IntersectionObserver* observer); + void UnregisterIntersectionObserverForRoot(IntersectionObserver* observer); + void RegisterIntersectionObserverForTarget(IntersectionObserver* observer); + void UnregisterIntersectionObserverForTarget(IntersectionObserver* observer); + + LayoutIntersectionObserverRootVector + GetLayoutIntersectionObserverRootsForElement(); + LayoutIntersectionObserverTargetVector + GetLayoutIntersectionObserverTargetsForElement(); + + void CreateIntersectionObserverEntryForObserver( + const base::WeakPtr<IntersectionObserver>& observer, + math::RectF root_bounds, math::RectF target_rect, + math::RectF intersection_rect, bool is_intersecting, + float intersection_ratio); + + void TraceMembers(script::Tracer* tracer) override; + + private: + void InvalidateLayoutBoxesForElement(); + void AddLayoutTargetForObserver(IntersectionObserver* observer); + void RemoveLayoutTargetForObserver(IntersectionObserver* observer); + + Element* element_; + IntersectionObserverVector root_registered_intersection_observers_; + IntersectionObserverVector target_registered_intersection_observers_; + LayoutIntersectionObserverTargetVector layout_targets_; +}; + +} // namespace dom +} // namespace cobalt + +#endif // COBALT_DOM_ELEMENT_INTERSECTION_OBSERVER_MODULE_H_
diff --git a/src/cobalt/dom/html_anchor_element.cc b/src/cobalt/dom/html_anchor_element.cc index 74c96aa..c262595 100644 --- a/src/cobalt/dom/html_anchor_element.cc +++ b/src/cobalt/dom/html_anchor_element.cc
@@ -32,12 +32,16 @@ if (!ResolveAndSetURL(value)) { url_utils_.set_url(GURL(value)); } + } else { + HTMLElement::OnSetAttribute(name, value); } } void HTMLAnchorElement::OnRemoveAttribute(const std::string& name) { if (name == "href") { url_utils_.set_url(GURL()); + } else { + HTMLElement::OnRemoveAttribute(name); } }
diff --git a/src/cobalt/dom/html_element.cc b/src/cobalt/dom/html_element.cc index 4cb3861..636ef72 100644 --- a/src/cobalt/dom/html_element.cc +++ b/src/cobalt/dom/html_element.cc
@@ -1015,7 +1015,7 @@ descendant_computed_styles_valid_ = true; } -void HTMLElement::MarkDisplayNoneOnNodeAndDescendants() { +void HTMLElement::MarkNotDisplayedOnNodeAndDescendants() { // While we do want to clear the animations immediately, we also want to // ensure that they are also reset starting with the next computed style // update. This ensures that for example a transition will not be triggered @@ -1039,7 +1039,7 @@ } } - MarkDisplayNoneOnDescendants(); + MarkNotDisplayedOnDescendants(); } void HTMLElement::PurgeCachedBackgroundImagesOfNodeAndDescendants() { @@ -1727,7 +1727,7 @@ } if (invalidation_flags.mark_descendants_as_display_none) { - MarkDisplayNoneOnDescendants(); + MarkNotDisplayedOnDescendants(); } if (invalidation_flags.invalidate_computed_styles_of_descendants) { InvalidateComputedStylesOfDescendants();
diff --git a/src/cobalt/dom/html_element.h b/src/cobalt/dom/html_element.h index de9d187..abb2f2e 100644 --- a/src/cobalt/dom/html_element.h +++ b/src/cobalt/dom/html_element.h
@@ -278,7 +278,7 @@ const base::TimeDelta& style_change_event_time, AncestorsAreDisplayed ancestor_is_displayed); - void MarkDisplayNoneOnNodeAndDescendants() override; + void MarkNotDisplayedOnNodeAndDescendants() override; void PurgeCachedBackgroundImagesOfNodeAndDescendants() override; void InvalidateComputedStylesOfNodeAndDescendants() override; void InvalidateLayoutBoxesOfNodeAndAncestors() override; @@ -346,6 +346,11 @@ void OnInsertedIntoDocument() override; void OnRemovedFromDocument() override; + // From Element. + void OnSetAttribute(const std::string& name, + const std::string& value) override; + void OnRemoveAttribute(const std::string& name) override; + // HTMLElement keeps a pointer to the dom stat tracker to ensure that it can // make stat updates even after its weak pointer to its document has been // deleted. This is protected because some derived classes need access to it. @@ -355,11 +360,6 @@ // From Node. void OnMutation() override; - // From Element. - void OnSetAttribute(const std::string& name, - const std::string& value) override; - void OnRemoveAttribute(const std::string& name) override; - bool IsFocusable(); bool HasTabindexFocusFlag() const; bool IsBeingRendered();
diff --git a/src/cobalt/dom/html_element_test.cc b/src/cobalt/dom/html_element_test.cc index df6f1be..8fa740f 100644 --- a/src/cobalt/dom/html_element_test.cc +++ b/src/cobalt/dom/html_element_test.cc
@@ -68,6 +68,11 @@ const char kFooBarDeclarationString[] = "foo: bar;"; const char kDisplayInlineDeclarationString[] = "display: inline;"; +const char* kHtmlElementTagNames[] = { + // "audio", "script", and "video" are excluded since they need more setup. + "a", "body", "br", "div", "head", "h1", "html", "img", "link", + "meta", "p", "span", "style", "title" +}; class MockLayoutBoxes : public LayoutBoxes { public: @@ -204,31 +209,48 @@ } TEST_F(HTMLElementTest, Dir) { - scoped_refptr<HTMLElement> html_element = - document_->CreateElement("div")->AsHTMLElement(); - EXPECT_EQ("", html_element->dir()); + for (size_t i = 0; i < arraysize(kHtmlElementTagNames); ++i) { + scoped_refptr<HTMLElement> html_element = + document_->CreateElement(kHtmlElementTagNames[i])->AsHTMLElement(); + EXPECT_EQ("", html_element->dir()); - html_element->set_dir("invalid"); - EXPECT_EQ("", html_element->dir()); + html_element->set_dir("invalid"); + EXPECT_EQ("", html_element->dir()); - html_element->set_dir("ltr"); - EXPECT_EQ("ltr", html_element->dir()); + html_element->set_dir("ltr"); + EXPECT_EQ("ltr", html_element->dir()); - html_element->set_dir("rtl"); - EXPECT_EQ("rtl", html_element->dir()); + html_element->set_dir("rtl"); + EXPECT_EQ("rtl", html_element->dir()); - // Value "auto" is not supported. - html_element->set_dir("auto"); - EXPECT_EQ("", html_element->dir()); + // Value "auto" is not supported. + html_element->set_dir("auto"); + EXPECT_EQ("", html_element->dir()); + + html_element->SetAttribute("Dir", "rtl"); + EXPECT_EQ("rtl", html_element->dir()); + + html_element->RemoveAttribute("diR"); + EXPECT_EQ("", html_element->dir()); + } } TEST_F(HTMLElementTest, TabIndex) { - scoped_refptr<HTMLElement> html_element = - document_->CreateElement("div")->AsHTMLElement(); - EXPECT_EQ(0, html_element->tab_index()); + for (size_t i = 0; i < arraysize(kHtmlElementTagNames); ++i) { + scoped_refptr<HTMLElement> html_element = + document_->CreateElement(kHtmlElementTagNames[i])->AsHTMLElement(); - html_element->set_tab_index(-1); - EXPECT_EQ(-1, html_element->tab_index()); + EXPECT_EQ(0, html_element->tab_index()); + + html_element->set_tab_index(-1); + EXPECT_EQ(-1, html_element->tab_index()); + + html_element->SetAttribute("tabIndex", "-2"); + EXPECT_EQ(-2, html_element->tab_index()); + + html_element->RemoveAttribute("Tabindex"); + EXPECT_EQ(0, html_element->tab_index()); + } } TEST_F(HTMLElementTest, Focus) {
diff --git a/src/cobalt/dom/html_image_element.cc b/src/cobalt/dom/html_image_element.cc index b98a5f9..511d83c 100644 --- a/src/cobalt/dom/html_image_element.cc +++ b/src/cobalt/dom/html_image_element.cc
@@ -51,7 +51,7 @@ } void HTMLImageElement::OnSetAttribute(const std::string& name, - const std::string& /* value */) { + const std::string& value) { // A user agent that obtains images immediately must synchronously update the // image data of an img element whenever that element is created with a src // attribute. A user agent that obtains images immediately must also @@ -59,6 +59,8 @@ // has its src or crossorigin attribute set, changed, or removed. if (name == "src") { UpdateImageData(); + } else { + HTMLElement::OnSetAttribute(name, value); } } @@ -70,6 +72,8 @@ // has its src or crossorigin attribute set, changed, or removed. if (name == "src") { UpdateImageData(); + } else { + HTMLElement::OnRemoveAttribute(name); } }
diff --git a/src/cobalt/dom/intersection_observer.cc b/src/cobalt/dom/intersection_observer.cc index 7af988a..6fce9cd 100644 --- a/src/cobalt/dom/intersection_observer.cc +++ b/src/cobalt/dom/intersection_observer.cc
@@ -81,13 +81,23 @@ } IntersectionObserver::~IntersectionObserver() { - task_manager()->OnIntersectionObserverDestroyed(this); + if (root_) { + root_->UnregisterIntersectionObserverRoot(this); + } + if (intersection_observer_task_manager_) { + intersection_observer_task_manager_->OnIntersectionObserverDestroyed(this); + } } -script::Sequence<double> const IntersectionObserver::thresholds() { +void IntersectionObserver::set_layout_root( + const scoped_refptr<layout::IntersectionObserverRoot>& layout_root) { + layout_root_ = layout_root; +} + +script::Sequence<double> IntersectionObserver::thresholds() const { script::Sequence<double> result; - for (std::vector<double>::iterator it = thresholds_.begin(); + for (std::vector<double>::const_iterator it = thresholds_.begin(); it != thresholds_.end(); ++it) { result.push_back(*it); } @@ -101,7 +111,7 @@ NOTREACHED(); return; } - target->RegisterIntersectionObserverTarget(base::WrapRefCounted(this)); + target->RegisterIntersectionObserverTarget(this); TrackObservationTarget(target); } @@ -112,7 +122,7 @@ NOTREACHED(); return; } - target->UnregisterIntersectionObserverTarget(base::WrapRefCounted(this)); + target->UnregisterIntersectionObserverTarget(this); UntrackObservationTarget(target); } @@ -125,7 +135,7 @@ it != observation_targets_.end(); ++it) { Element* target = it->get(); if (target != NULL) { - target->UnregisterIntersectionObserverTarget(base::WrapRefCounted(this)); + target->UnregisterIntersectionObserverTarget(this); } } observation_targets_.clear(); @@ -146,21 +156,8 @@ TRACE_EVENT0("cobalt::dom", "IntersectionObserver::QueueIntersectionObserverEntry()"); queued_entries_.push_back(entry); - task_manager()->QueueIntersectionObserverTask(); -} - -void IntersectionObserver::UpdateObservationTargets() { - TRACE_EVENT0("cobalt::dom", - "IntersectionObserver::UpdateObservationTargets()"); - // https://www.w3.org/TR/intersection-observer/#notify-intersection-observers-algo - // Step 2 of "run the update intersection observations steps" algorithm: - // 1. Let rootBounds be observer's root intersection rectangle. - // 2. For each target in observer's internal [[ObservationTargets]] slot, - // processed in the same order that observe() was called on each - // target, run a set of subtasks (subtasks are implemented in - // IntersectionObserverRegistration::Update): - for (auto target : observation_targets_) { - target->UpdateIntersectionObservationsForTarget(this); + if (intersection_observer_task_manager_) { + intersection_observer_task_manager_->QueueIntersectionObserverTask(); } } @@ -184,35 +181,18 @@ } void IntersectionObserver::TraceMembers(script::Tracer* tracer) { + tracer->Trace(root_); tracer->TraceItems(observation_targets_); tracer->TraceItems(queued_entries_); } -IntersectionObserverTaskManager* IntersectionObserver::task_manager() { - return root_->owner_document()->intersection_observer_task_manager(); -} - void IntersectionObserver::InitIntersectionObserverInternal( script::EnvironmentSettings* settings, const IntersectionObserverCallbackArg& callback, const IntersectionObserverInit& options, script::ExceptionState* exception_state) { // https://www.w3.org/TR/intersection-observer/#intersection-observer-interface - // 1. Let this be a new IntersectionObserver object - // 2. Set this's internal [[callback]] slot to callback. - callback_.reset(new ScriptCallback(callback, this)); - - // 3. Set this.root to options.root. - if (options.root()) { - root_ = options.root(); - } else { - root_ = base::polymorphic_downcast<dom::DOMSettings*>(settings) - ->window() - ->document() - ->document_element(); - } - - // 4. Attempt to parse a root margin from options.rootMargin. If a list is + // Attempt to parse a root margin from options.rootMargin. If a list is // returned, set this's internal [[rootMargin]] slot to that. Otherwise, throw // a SyntaxError exception. // https://www.w3.org/TR/intersection-observer/#parse-a-root-margin @@ -237,12 +217,9 @@ "Not able to parse IntersectionObserver root margin."); } - // 5. Let thresholds be a list equal to options.threshold. - // 6. If any value in thresholds is less than 0.0 or greater than 1.0, throw a + // Let thresholds be a list equal to options.threshold. + // If any value in thresholds is less than 0.0 or greater than 1.0, throw a // RangeError exception. - // 7. Sort thresholds in ascending order. - // 8. If thresholds is empty, append 0 to thresholds. - // 9. Set this.thresholds to thresholds. ThresholdType threshold = options.threshold(); if (threshold.IsType<double>()) { if (threshold.AsType<double>() < 0 || threshold.AsType<double>() > 1) { @@ -266,13 +243,33 @@ } thresholds_.push_back(*it); } + // Sort thresholds in ascending order. sort(thresholds_.begin(), thresholds_.end()); } + // If thresholds is empty, append 0 to thresholds. + if (thresholds_.empty()) { thresholds_.push_back(0); } - task_manager()->OnIntersectionObserverCreated(this); + // Set this's internal [[callback]] slot to callback. + callback_.reset(new ScriptCallback(callback, this)); + + // Set this.root to options.root. + if (options.root()) { + root_ = base::AsWeakPtr(options.root().get()); + } else { + root_ = + base::AsWeakPtr(base::polymorphic_downcast<dom::DOMSettings*>(settings) + ->window() + ->document() + ->document_element() + .get()); + } + root_->RegisterIntersectionObserverRoot(this); + intersection_observer_task_manager_ = + root_->owner_document()->intersection_observer_task_manager(); + intersection_observer_task_manager_->OnIntersectionObserverCreated(this); } void IntersectionObserver::TrackObservationTarget( @@ -288,7 +285,7 @@ } ++it; } - observation_targets_.push_back(base::WrapRefCounted(target.get())); + observation_targets_.push_back(base::AsWeakPtr(target.get())); } void IntersectionObserver::UntrackObservationTarget(
diff --git a/src/cobalt/dom/intersection_observer.h b/src/cobalt/dom/intersection_observer.h index 10b6bab..c1b6ba6 100644 --- a/src/cobalt/dom/intersection_observer.h +++ b/src/cobalt/dom/intersection_observer.h
@@ -20,8 +20,11 @@ #include "base/callback.h" #include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" #include "cobalt/cssom/property_list_value.h" #include "cobalt/dom/intersection_observer_entry.h" +#include "cobalt/layout/intersection_observer_root.h" +#include "cobalt/layout/intersection_observer_target.h" #include "cobalt/script/callback_function.h" #include "cobalt/script/environment_settings.h" #include "cobalt/script/exception_state.h" @@ -40,7 +43,8 @@ // The IntersectionObserver can be used to observe changes in the intersection // of an intersection root and one or more target Elements. // https://www.w3.org/TR/intersection-observer/#intersection-observer-interfaces -class IntersectionObserver : public script::Wrappable { +class IntersectionObserver : public base::SupportsWeakPtr<IntersectionObserver>, + public script::Wrappable { public: typedef script::Sequence<scoped_refptr<IntersectionObserverEntry>> IntersectionObserverEntrySequence; @@ -64,17 +68,24 @@ script::ExceptionState* exception_state); ~IntersectionObserver(); - const scoped_refptr<Element>& root() { return root_; } + const base::WeakPtr<Element>& root() const { return root_; } + void set_layout_root( + const scoped_refptr<layout::IntersectionObserverRoot>& layout_root); + const scoped_refptr<layout::IntersectionObserverRoot>& layout_root() const { + return layout_root_; + } // Part of the IntersectionObserver interface, but differs from the web spec // in that it returns the exact string passed into |options|, regardless of // whether it is formatted as four space-separated pixels lengths/percentages. std::string root_margin() const { return root_margin_; } // Not part of the IntersectionObserver interface. Returns the root margin // parsed as a PropertyListValue. - const scoped_refptr<cssom::PropertyListValue>& root_margin_property_value() { + const scoped_refptr<cssom::PropertyListValue>& root_margin_property_value() + const { return root_margin_property_value_; } - script::Sequence<double> const thresholds(); + script::Sequence<double> thresholds() const; + std::vector<double> thresholds_vector() const { return thresholds_; } void Observe(const scoped_refptr<Element>& target); void Unobserve(const scoped_refptr<Element>& target); void Disconnect(); @@ -86,11 +97,6 @@ void QueueIntersectionObserverEntry( const scoped_refptr<IntersectionObserverEntry>& entry); - // Not part of the IntersectionObserver interface. Implements step (2) of the - // "run the update intersection observations steps" algorithm. - // https://www.w3.org/TR/intersection-observer/#notify-intersection-observers-algo - void UpdateObservationTargets(); - // Not part of the the IntersectionObserver interface. Implements step (3) of // the "notify intersection observers" algorithm. // https://www.w3.org/TR/intersection-observer/#notify-intersection-observers-algo @@ -115,13 +121,16 @@ void UntrackObservationTarget(const scoped_refptr<Element>& target); std::unique_ptr<CallbackInternal> callback_; - scoped_refptr<Element> root_; + base::WeakPtr<Element> root_; + scoped_refptr<layout::IntersectionObserverRoot> layout_root_; std::string root_margin_; scoped_refptr<cssom::PropertyListValue> root_margin_property_value_; std::vector<double> thresholds_; - typedef std::vector<scoped_refptr<Element>> ElementVector; + typedef std::vector<base::WeakPtr<Element>> ElementVector; ElementVector observation_targets_; IntersectionObserverEntrySequence queued_entries_; + scoped_refptr<IntersectionObserverTaskManager> + intersection_observer_task_manager_; }; } // namespace dom
diff --git a/src/cobalt/dom/intersection_observer_registration.h b/src/cobalt/dom/intersection_observer_registration.h deleted file mode 100644 index 4979227..0000000 --- a/src/cobalt/dom/intersection_observer_registration.h +++ /dev/null
@@ -1,65 +0,0 @@ -// Copyright 2019 The Cobalt Authors. 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. - -#ifndef COBALT_DOM_INTERSECTION_OBSERVER_REGISTRATION_H_ -#define COBALT_DOM_INTERSECTION_OBSERVER_REGISTRATION_H_ - -#include "base/memory/ref_counted.h" -#include "cobalt/dom/intersection_observer.h" -#include "cobalt/script/tracer.h" - -namespace cobalt { -namespace dom { - -class Element; - -// Represents the concept of an "intersection observer registration" as -// described in the Intersection Observer spec. -// https://www.w3.org/TR/intersection-observer/#intersectionobserverregistration -// This class is expected to be used internally in the Element class as a part -// of intersection reporting. -class IntersectionObserverRegistration : public script::Traceable { - public: - // An IntersectionObserverRegistration must not outlive the |target| element - // that is being observed. - IntersectionObserverRegistration( - const scoped_refptr<IntersectionObserver>& observer) - : observer_(observer), - previous_threshold_index_(-1), - previous_is_intersecting_(false) {} - - const IntersectionObserver* observer() const { return observer_; } - int32 previous_threshold_index() const { return previous_threshold_index_; } - void set_previous_threshold_index(int32 previous_threshold_index) { - previous_threshold_index_ = previous_threshold_index; - } - bool previous_is_intersecting() const { return previous_is_intersecting_; } - void set_previous_is_intersecting(bool previous_is_intersecting) { - previous_is_intersecting_ = previous_is_intersecting; - } - - void TraceMembers(script::Tracer* tracer) override { - tracer->Trace(observer_); - } - - private: - IntersectionObserver* observer_; - int32 previous_threshold_index_; - bool previous_is_intersecting_; -}; - -} // namespace dom -} // namespace cobalt - -#endif // COBALT_DOM_INTERSECTION_OBSERVER_REGISTRATION_H_
diff --git a/src/cobalt/dom/intersection_observer_registration_list.cc b/src/cobalt/dom/intersection_observer_registration_list.cc deleted file mode 100644 index 14b0541..0000000 --- a/src/cobalt/dom/intersection_observer_registration_list.cc +++ /dev/null
@@ -1,71 +0,0 @@ -// Copyright 2019 The Cobalt Authors. 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 "cobalt/dom/intersection_observer_registration_list.h" - -namespace cobalt { -namespace dom { - -void IntersectionObserverRegistrationList::AddIntersectionObserver( - const scoped_refptr<IntersectionObserver>& observer) { - // https://www.w3.org/TR/intersection-observer/#ref-for-dom-intersectionobserver-observe - // 1. If target is in this's internal [[ObservationTargets]] slot, return. - for (auto it = registered_intersection_observers_.begin(); - it != registered_intersection_observers_.end(); ++it) { - if (it->observer() == observer) { - registered_intersection_observers_.erase(it); - return; - } - } - // 2. Let intersectionObserverRegistration be an - // IntersectionObserverRegistration record with an observer property set to - // this, a previousThresholdIndex property set to -1, and a - // previousIsIntersecting property set to false. - // 3. Append intersectionObserverRegistration to target's internal - // [[RegisteredIntersectionObservers]] slot. - registered_intersection_observers_.push_back( - IntersectionObserverRegistration(observer)); - return; -} - -void IntersectionObserverRegistrationList::RemoveIntersectionObserver( - const scoped_refptr<IntersectionObserver>& observer) { - for (auto it = registered_intersection_observers_.begin(); - it != registered_intersection_observers_.end(); ++it) { - if (it->observer() == observer) { - registered_intersection_observers_.erase(it); - return; - } - } - NOTREACHED() << "Did not find an intersection observer to unregister."; -} - -IntersectionObserverRegistration* -IntersectionObserverRegistrationList::FindRegistrationForObserver( - const scoped_refptr<IntersectionObserver>& observer) { - for (auto& record : registered_intersection_observers_) { - if (record.observer() == observer) { - return &record; - } - } - return NULL; -} - -void IntersectionObserverRegistrationList::TraceMembers( - script::Tracer* tracer) { - tracer->TraceItems(registered_intersection_observers_); -} - -} // namespace dom -} // namespace cobalt
diff --git a/src/cobalt/dom/intersection_observer_registration_list.h b/src/cobalt/dom/intersection_observer_registration_list.h deleted file mode 100644 index c3f5b07..0000000 --- a/src/cobalt/dom/intersection_observer_registration_list.h +++ /dev/null
@@ -1,67 +0,0 @@ -// Copyright 2019 The Cobalt Authors. 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. - -#ifndef COBALT_DOM_INTERSECTION_OBSERVER_REGISTRATION_LIST_H_ -#define COBALT_DOM_INTERSECTION_OBSERVER_REGISTRATION_LIST_H_ - -#include <vector> - -#include "base/memory/ref_counted.h" -#include "cobalt/dom/intersection_observer.h" -#include "cobalt/dom/intersection_observer_registration.h" - -namespace cobalt { -namespace dom { - -// A list of "intersection observer registrations" as described in the -// Intersection Observer spec. -// https://www.w3.org/TR/intersection-observer/#intersectionobserverregistration -// -// Implements the functionality described in the IntersectionObserver.observe -// method: -// https://www.w3.org/TR/intersection-observer/#ref-for-dom-intersectionobserver-observe -class IntersectionObserverRegistrationList : public script::Traceable { - public: - typedef std::vector<IntersectionObserverRegistration> - IntersectionObserverRegistrationVector; - - IntersectionObserverRegistrationList() {} - - // Implement the IntersectionObserver.observe method - // https://www.w3.org/TR/intersection-observer/#ref-for-dom-intersectionobserver-observe - void AddIntersectionObserver( - const scoped_refptr<IntersectionObserver>& observer); - // Implement the IntersectionObserver.unobserve method - // https://www.w3.org/TR/intersection-observer/#dom-intersectionobserver-unobserve - void RemoveIntersectionObserver( - const scoped_refptr<IntersectionObserver>& observer); - - IntersectionObserverRegistration* FindRegistrationForObserver( - const scoped_refptr<IntersectionObserver>& observer); - - const IntersectionObserverRegistrationVector& - registered_intersection_observers() { - return registered_intersection_observers_; - } - - void TraceMembers(script::Tracer* tracer) override; - - private: - IntersectionObserverRegistrationVector registered_intersection_observers_; -}; - -} // namespace dom -} // namespace cobalt - -#endif // COBALT_DOM_INTERSECTION_OBSERVER_REGISTRATION_LIST_H_
diff --git a/src/cobalt/dom/intersection_observer_target.cc b/src/cobalt/dom/intersection_observer_target.cc deleted file mode 100644 index 36c944c..0000000 --- a/src/cobalt/dom/intersection_observer_target.cc +++ /dev/null
@@ -1,440 +0,0 @@ -// Copyright 2019 The Cobalt Authors. 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 "cobalt/dom/intersection_observer_target.h" - -#include <algorithm> - -#include "cobalt/cssom/computed_style_utils.h" -#include "cobalt/cssom/css_computed_style_data.h" -#include "cobalt/cssom/used_style.h" -#include "cobalt/dom/document.h" -#include "cobalt/dom/element.h" -#include "cobalt/dom/html_element.h" -#include "cobalt/dom/intersection_observer_entry_init.h" -#include "cobalt/dom/performance.h" -#include "cobalt/script/sequence.h" - -namespace cobalt { -namespace dom { - -namespace { - -HTMLElement* GetContainingBlockOfHTMLElement(HTMLElement* html_element) { - // Establish the containing block, as described in - // http://www.w3.org/TR/CSS2/visudet.html#containing-block-details - DCHECK(html_element->node_document()); - html_element->node_document()->DoSynchronousLayout(); - - scoped_refptr<cssom::PropertyValue> position = - html_element->computed_style()->position(); - - // The containing block in which the root element lives is a rectangle called - // the initial containing block. For continuous media, it has the dimensions - // of the viewport and is anchored at the canvas origin; it is the page area - // for paged media. - if (html_element->IsRootElement()) { - return html_element->owner_document()->document_element()->AsHTMLElement(); - } - - for (Node* ancestor_node = html_element->parent_node(); ancestor_node; - ancestor_node = ancestor_node->parent_node()) { - Element* ancestor_element = ancestor_node->AsElement(); - if (!ancestor_element) { - continue; - } - HTMLElement* ancestor_html_element = ancestor_element->AsHTMLElement(); - if (!ancestor_html_element) { - continue; - } - - // If the element has 'position: absolute', the containing block is - // established by the nearest ancestor with a 'position' of 'absolute', - // 'relative' or 'fixed'. - // Transformed elements also act as a containing block for all descendants. - // https://www.w3.org/TR/css-transforms-1/#transform-rendering. - if (position == cssom::KeywordValue::GetAbsolute() && - ancestor_html_element->computed_style()->position() == - cssom::KeywordValue::GetStatic() && - ancestor_html_element->computed_style()->transform() == - cssom::KeywordValue::GetNone()) { - continue; - } - - // If the element has 'position: fixed', the containing block is established - // by the viewport in the case of continuous media or the page area in the - // case of paged media. - // Transformed elements also act as a containing block for all descendants. - // https://www.w3.org/TR/css-transforms-1/#transform-rendering. - if (position == cssom::KeywordValue::GetFixed() && - ancestor_html_element->computed_style()->transform() == - cssom::KeywordValue::GetNone()) { - continue; - } - - // For other elements, if the element's position is 'relative' or 'static', - // the containing block is formed by the content edge of the nearest block - // container ancestor box. - return ancestor_html_element; - } - - // If there is no such ancestor, the containing block is the initial - // containing block. - return html_element->owner_document()->document_element()->AsHTMLElement(); -} - -bool IsInContainingBlockChain(const HTMLElement* potential_containing_block, - HTMLElement* html_element) { - // Walk up the containing block chain, as described in - // http://www.w3.org/TR/CSS2/visudet.html#containing-block-details - HTMLElement* containing_block_element = - GetContainingBlockOfHTMLElement(html_element); - while (containing_block_element != potential_containing_block) { - if (!containing_block_element->parent_element()) { - return false; - } - containing_block_element = - GetContainingBlockOfHTMLElement(containing_block_element); - } - return true; -} - -} // namespace - -IntersectionObserverTarget::IntersectionObserverTarget(Element* target_element) - : target_element_(target_element) {} - -void IntersectionObserverTarget::RegisterIntersectionObserver( - const scoped_refptr<IntersectionObserver>& observer) { - intersection_observer_registration_list_.AddIntersectionObserver(observer); -} - -void IntersectionObserverTarget::UnregisterIntersectionObserver( - const scoped_refptr<IntersectionObserver>& observer) { - intersection_observer_registration_list_.RemoveIntersectionObserver(observer); -} - -void IntersectionObserverTarget::UpdateIntersectionObservationsForTarget( - const scoped_refptr<IntersectionObserver>& observer) { - // https://www.w3.org/TR/intersection-observer/#update-intersection-observations-algo - // Subtasks for step 2 of the "run the update intersection observations steps" - // algorithm: - // 1. If the intersection root is not the implicit root and target is - // not a descendant of the intersection root in the containing block - // chain, skip further processing for target. - HTMLElement* html_target = target_element_->AsHTMLElement(); - HTMLElement* html_intersection_root = observer->root()->AsHTMLElement(); - if (!html_target || !html_intersection_root) { - NOTREACHED(); - return; - } - - if (html_intersection_root != - target_element_->owner_document()->document_element() && - !IsInContainingBlockChain(html_intersection_root, html_target)) { - return; - } - - // 2. If the intersection root is not the implicit root, and target is - // not in the same Document as the intersection root, skip further - // processing for target. - if (html_intersection_root != - target_element_->owner_document()->document_element() && - html_intersection_root->owner_document() != - target_element_->owner_document()) { - return; - } - - // 3. Let targetRect be a DOMRectReadOnly obtained by running the - // getBoundingClientRect() algorithm on target. - scoped_refptr<DOMRectReadOnly> target_rect = - target_element_->GetBoundingClientRect(); - - // 4. Let intersectionRect be the result of running the compute the - // intersection algorithm on target. - scoped_refptr<DOMRectReadOnly> root_bounds = GetRootBounds( - html_intersection_root, observer->root_margin_property_value()); - scoped_refptr<DOMRectReadOnly> intersection_rect = - ComputeIntersectionBetweenTargetAndRoot( - html_intersection_root, root_bounds, target_rect, - base::WrapRefCounted(html_target)); - - // 5. Let targetArea be targetRect's area. - float target_area = target_rect->rect().size().GetArea(); - - // 6. Let intersectionArea be intersectionRect's area. - float intersection_area = intersection_rect->rect().size().GetArea(); - - // 7. Let isIntersecting be true if targetRect and rootBounds intersect or - // are edge-adjacent, even if the intersection has zero area (because - // rootBounds or targetRect have zero area); otherwise, let - // isIntersecting be false. - bool is_intersecting = - intersection_rect->width() != 0 || intersection_rect->height() != 0; - - // 8. If targetArea is non-zero, let intersectionRatio be intersectionArea - // divided by targetArea. Otherwise, let intersectionRatio be 1 if - // isIntersecting is true, or 0 if isIntersecting is false. - float intersection_ratio = is_intersecting ? 1.0f : 0.0f; - if (target_area != 0) { - intersection_ratio = intersection_area / target_area; - } - - // 9. Let thresholdIndex be the index of the first entry in - // observer.thresholds whose value is greater than intersectionRatio, - // or the length of observer.thresholds if intersectionRatio is greater - // than or equal to the last entry in observer.thresholds. - const script::Sequence<double>& thresholds = observer->thresholds(); - size_t threshold_index; - for (threshold_index = 0; threshold_index < thresholds.size(); - ++threshold_index) { - if (thresholds.at(threshold_index) > intersection_ratio) { - break; - } - } - - // 10. Let intersectionObserverRegistration be the - // IntersectionObserverRegistration record in target's internal - // [[RegisteredIntersectionObservers]] slot whose observer property is - // equal to observer. - IntersectionObserverRegistration* intersection_observer_registration = - intersection_observer_registration_list_.FindRegistrationForObserver( - observer); - - if (!intersection_observer_registration) { - NOTREACHED(); - return; - } - - // 11. Let previousThresholdIndex be the - // intersectionObserverRegistration's previousThresholdIndex property. - int32 previous_threshold_index = - intersection_observer_registration->previous_threshold_index(); - - // 12. Let previousIsIntersecting be the - // intersectionObserverRegistration's previousIsIntersecting property. - bool previous_is_intersecting = - intersection_observer_registration->previous_is_intersecting(); - - // 13. If thresholdIndex does not equal previousThresholdIndex or if - // isIntersecting does not equal previousIsIntersecting, queue an - // IntersectionObserverEntry, passing in observer, time, rootBounds, - // boundingClientRect, intersectionRect, isIntersecting, and target. - if (static_cast<int32>(threshold_index) != previous_threshold_index || - is_intersecting != previous_is_intersecting) { - IntersectionObserverEntryInit init_dict; - init_dict.set_time(target_element_->owner_document() - ->window() - ->performance() - ->timing() - ->GetNavigationStartClock() - ->Now() - .InMillisecondsF()); - init_dict.set_root_bounds(root_bounds); - init_dict.set_bounding_client_rect(target_rect); - init_dict.set_intersection_rect(intersection_rect); - init_dict.set_is_intersecting(is_intersecting); - init_dict.set_intersection_ratio(intersection_ratio); - init_dict.set_target(base::WrapRefCounted(target_element_)); - observer->QueueIntersectionObserverEntry( - base::WrapRefCounted(new IntersectionObserverEntry(init_dict))); - } - - // 14. Assign threshold to intersectionObserverRegistration's - // previousThresholdIndex property. - intersection_observer_registration->set_previous_threshold_index( - static_cast<int32>(threshold_index)); - - // 15. Assign isIntersecting to intersectionObserverRegistration's - // previousIsIntersecting property. - intersection_observer_registration->set_previous_is_intersecting( - is_intersecting); -} - -scoped_refptr<DOMRectReadOnly> IntersectionObserverTarget::GetRootBounds( - const scoped_refptr<HTMLElement>& html_intersection_root, - scoped_refptr<cssom::PropertyListValue> root_margin_property_value) { - // https://www.w3.org/TR/intersection-observer/#intersectionobserver-root-intersection-rectangle - // Rules for determining the root intersection rectangle bounds. - LayoutBoxes* intersection_root_layout_boxes = - html_intersection_root->layout_boxes(); - DCHECK(intersection_root_layout_boxes); - - math::RectF root_bounds_without_margins; - // If the intersection root is the implicit root, it's the viewport's size. - if (html_intersection_root == - html_intersection_root->owner_document()->document_element()) { - root_bounds_without_margins = math::RectF( - 0.0, 0.0, - html_intersection_root->owner_document()->viewport_size().width(), - html_intersection_root->owner_document()->viewport_size().height()); - } else if (IsOverflowCropped(html_intersection_root->computed_style())) { - // If the intersection root has an overflow clip, it's the element's content - // area. - math::Vector2dF content_edge_offset = - intersection_root_layout_boxes->GetContentEdgeOffset(); - root_bounds_without_margins = - math::RectF(content_edge_offset.x(), content_edge_offset.y(), - intersection_root_layout_boxes->GetContentEdgeWidth(), - intersection_root_layout_boxes->GetContentEdgeHeight()); - } else { - // Otherwise, it's the result of running the getBoundingClientRect() - // algorithm on the intersection root. - root_bounds_without_margins = - math::RectF(html_intersection_root->GetBoundingClientRect()->rect()); - } - int32 top_margin = GetUsedLengthOfRootMarginPropertyValue( - root_margin_property_value->value()[0], - root_bounds_without_margins.height()); - int32 right_margin = GetUsedLengthOfRootMarginPropertyValue( - root_margin_property_value->value()[1], - root_bounds_without_margins.width()); - int32 bottom_margin = GetUsedLengthOfRootMarginPropertyValue( - root_margin_property_value->value()[2], - root_bounds_without_margins.height()); - int32 left_margin = GetUsedLengthOfRootMarginPropertyValue( - root_margin_property_value->value()[3], - root_bounds_without_margins.width()); - - // Remember to grow or shrink the root intersection rectangle bounds based - // on the root margin property. - scoped_refptr<DOMRectReadOnly> root_bounds = new DOMRectReadOnly( - root_bounds_without_margins.x() - left_margin, - root_bounds_without_margins.y() - top_margin, - root_bounds_without_margins.width() + left_margin + right_margin, - root_bounds_without_margins.height() + top_margin + bottom_margin); - return root_bounds; -} - -int32 IntersectionObserverTarget::GetUsedLengthOfRootMarginPropertyValue( - const scoped_refptr<cssom::PropertyValue>& length_property_value, - float percentage_base) { - cssom::UsedLengthValueProvider<float> used_length_provider(percentage_base); - length_property_value->Accept(&used_length_provider); - // Not explicitly stated in web spec, but has been observed that Chrome - // truncates root margin decimal values - return static_cast<int32>(used_length_provider.used_length().value_or(0.0f)); -} - -scoped_refptr<DOMRectReadOnly> -IntersectionObserverTarget::ComputeIntersectionBetweenTargetAndRoot( - const scoped_refptr<HTMLElement>& html_intersection_root, - const scoped_refptr<DOMRectReadOnly>& root_bounds, - const scoped_refptr<DOMRectReadOnly>& target_rect, - const scoped_refptr<HTMLElement>& html_target) { - // https://www.w3.org/TR/intersection-observer/#calculate-intersection-rect-algo - // To compute the intersection between a target and the observer's - // intersection root, run these steps: - // 1. Let intersectionRect be the result of running the - // getBoundingClientRect() algorithm on the target. - math::RectF intersection_rect = target_rect->rect(); - - // 2. Let container be the containing block of the target. - LayoutBoxes* target_layout_boxes = html_target->layout_boxes(); - DCHECK(target_layout_boxes); - math::Vector2dF total_offset_from_containing_block = - target_layout_boxes->GetBorderEdgeOffsetFromContainingBlock(); - - HTMLElement* prev_container = html_target; - HTMLElement* container = GetContainingBlockOfHTMLElement(prev_container); - - // 3. While container is not the intersection root: - while (container != html_intersection_root) { - // 1. Map intersectionRect to the coordinate space of container. - intersection_rect.set_x(total_offset_from_containing_block.x()); - intersection_rect.set_y(total_offset_from_containing_block.y()); - - // 2. If container has overflow clipping or a css clip-path property, - // update intersectionRect by applying container's clip. - // (Note: The containing block of an element with 'position: absolute' - // is formed by the padding edge of the ancestor. - // https://www.w3.org/TR/CSS2/visudet.html) - LayoutBoxes* container_layout_boxes = container->layout_boxes(); - DCHECK(container_layout_boxes); - if (IsOverflowCropped(container->computed_style())) { - math::Vector2dF container_clip_dimensions = - prev_container->computed_style()->position() == - cssom::KeywordValue::GetAbsolute() - ? math::Vector2dF(container_layout_boxes->GetPaddingEdgeWidth(), - container_layout_boxes->GetPaddingEdgeHeight()) - : math::Vector2dF(container_layout_boxes->GetContentEdgeWidth(), - container_layout_boxes->GetContentEdgeHeight()); - math::RectF container_clip(0, 0, container_clip_dimensions.x(), - container_clip_dimensions.y()); - intersection_rect = - IntersectIntersectionObserverRects(intersection_rect, container_clip); - } - - // 3. If container is the root element of a nested browsing context, - // update container to be the browsing context container of container, - // and update intersectionRect by clipping to the viewport of the nested - // browsing context. Otherwise, update container to be the containing - // block of container. - // (Note: The containing block of an element with 'position: absolute' - // is formed by the padding edge of the ancestor. - // https://www.w3.org/TR/CSS2/visudet.html) - math::Vector2dF next_offset_from_containing_block = - prev_container->computed_style()->position() == - cssom::KeywordValue::GetAbsolute() - ? container_layout_boxes->GetPaddingEdgeOffsetFromContainingBlock() - : container_layout_boxes->GetContentEdgeOffsetFromContainingBlock(); - total_offset_from_containing_block += next_offset_from_containing_block; - - prev_container = container; - container = GetContainingBlockOfHTMLElement(prev_container); - } - - // Modification of steps 4-6: - // Map intersectionRect to the coordinate space of the viewport of the - // Document containing the target. - // (Note: The containing block of an element with 'position: absolute' - // is formed by the padding edge of the ancestor. - // https://www.w3.org/TR/CSS2/visudet.html) - LayoutBoxes* container_layout_boxes = container->layout_boxes(); - DCHECK(container_layout_boxes); - math::Vector2dF containing_block_offset_from_origin = - prev_container->computed_style()->position() == - cssom::KeywordValue::GetAbsolute() - ? container_layout_boxes->GetPaddingEdgeOffset() - : container_layout_boxes->GetContentEdgeOffset(); - - intersection_rect.set_x(total_offset_from_containing_block.x() + - containing_block_offset_from_origin.x()); - intersection_rect.set_y(total_offset_from_containing_block.y() + - containing_block_offset_from_origin.y()); - - // Update intersectionRect by intersecting it with the root intersection - // rectangle, which is already in this coordinate space. - intersection_rect = IntersectIntersectionObserverRects(intersection_rect, - root_bounds->rect()); - - return base::WrapRefCounted(new DOMRectReadOnly(intersection_rect)); -} - -math::RectF IntersectionObserverTarget::IntersectIntersectionObserverRects( - const math::RectF& a, const math::RectF& b) { - float rx = std::max(a.x(), b.x()); - float ry = std::max(a.y(), b.y()); - float rr = std::min(a.right(), b.right()); - float rb = std::min(a.bottom(), b.bottom()); - - if (rx > rr || ry > rb) { - return math::RectF(0.0f, 0.0f, 0.0f, 0.0f); - } - - return math::RectF(rx, ry, rr - rx, rb - ry); -} - -} // namespace dom -} // namespace cobalt
diff --git a/src/cobalt/dom/intersection_observer_target.h b/src/cobalt/dom/intersection_observer_target.h deleted file mode 100644 index 9ac0b4e..0000000 --- a/src/cobalt/dom/intersection_observer_target.h +++ /dev/null
@@ -1,74 +0,0 @@ -// Copyright 2019 The Cobalt Authors. 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. - -#ifndef COBALT_DOM_INTERSECTION_OBSERVER_TARGET_H_ -#define COBALT_DOM_INTERSECTION_OBSERVER_TARGET_H_ - -#include "cobalt/dom/intersection_observer_registration_list.h" -#include "cobalt/math/rect_f.h" - -namespace cobalt { -namespace dom { - -class Element; -class HTMLElement; - -// The Intersection Observer spec describes a sequence of steps to update the -// the target elements of an observer in step 2.2 of the "Run the Update -// Intersection Observations Steps" algorithm. This helper class represents -// one of those target elements. -// https://www.w3.org/TR/intersection-observer/#update-intersection-observations-algo -class IntersectionObserverTarget { - public: - explicit IntersectionObserverTarget(Element* target_element); - - void RegisterIntersectionObserver( - const scoped_refptr<IntersectionObserver>& observer); - - void UnregisterIntersectionObserver( - const scoped_refptr<IntersectionObserver>& observer); - - void UpdateIntersectionObservationsForTarget( - const scoped_refptr<IntersectionObserver>& observer); - - private: - scoped_refptr<DOMRectReadOnly> GetRootBounds( - const scoped_refptr<HTMLElement>& html_intersection_root, - scoped_refptr<cssom::PropertyListValue> root_margin_property_value); - - int32 GetUsedLengthOfRootMarginPropertyValue( - const scoped_refptr<cssom::PropertyValue>& length_property_value, - float percentage_base); - - scoped_refptr<DOMRectReadOnly> ComputeIntersectionBetweenTargetAndRoot( - const scoped_refptr<HTMLElement>& intersection_root, - const scoped_refptr<DOMRectReadOnly>& root_bounds, - const scoped_refptr<DOMRectReadOnly>& target_rect, - const scoped_refptr<HTMLElement>& html_target); - - // Similar to the IntersectRects function in math::RectF, but handles edge - // adjacent intersections as valid intersections (instead of returning a - // rectangle with zero dimensions) - math::RectF IntersectIntersectionObserverRects(const math::RectF& a, - const math::RectF& b); - - Element* target_element_; - - IntersectionObserverRegistrationList intersection_observer_registration_list_; -}; - -} // namespace dom -} // namespace cobalt - -#endif // COBALT_DOM_INTERSECTION_OBSERVER_TARGET_H_
diff --git a/src/cobalt/dom/intersection_observer_task_manager.cc b/src/cobalt/dom/intersection_observer_task_manager.cc index 4ce591b..c46c09d 100644 --- a/src/cobalt/dom/intersection_observer_task_manager.cc +++ b/src/cobalt/dom/intersection_observer_task_manager.cc
@@ -71,23 +71,6 @@ base::Unretained(this))); } -void IntersectionObserverTaskManager::UpdateIntersectionObservations() { - TRACE_EVENT0( - "cobalt::dom", - "IntersectionObserverTaskManager::UpdateIntersectionObservations()"); - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - - // https://www.w3.org/TR/intersection-observer/#update-intersection-observations-algo - // To run the update intersection observations steps for a Document document - // given a timestamp time, run these steps: 1. Let observer list be a list of - // all IntersectionObservers whose root is in the DOM tree of document. - // 2. For each observer in observer list, run a set of subtasks (subtasks are - // implemented in IntersectionObserver::UpdateObservationTargets): - for (auto observer : observer_list_) { - observer->UpdateObservationTargets(); - } -} - void IntersectionObserverTaskManager::TraceMembers(script::Tracer* tracer) { tracer->TraceItems(observer_list_); }
diff --git a/src/cobalt/dom/intersection_observer_task_manager.h b/src/cobalt/dom/intersection_observer_task_manager.h index 21b960f..5d78e9b 100644 --- a/src/cobalt/dom/intersection_observer_task_manager.h +++ b/src/cobalt/dom/intersection_observer_task_manager.h
@@ -48,10 +48,6 @@ // posted. void QueueIntersectionObserverTask(); - // Update intersection observer registrations for intersection observers whose - // root is in the DOM tree of document - void UpdateIntersectionObservations(); - void TraceMembers(script::Tracer* tracer) override; private:
diff --git a/src/cobalt/dom/layout_boxes.h b/src/cobalt/dom/layout_boxes.h index 79fc8c3..69c160e 100644 --- a/src/cobalt/dom/layout_boxes.h +++ b/src/cobalt/dom/layout_boxes.h
@@ -59,7 +59,6 @@ virtual float GetBorderEdgeTop() const = 0; virtual float GetBorderEdgeWidth() const = 0; virtual float GetBorderEdgeHeight() const = 0; - virtual math::Vector2dF GetBorderEdgeOffsetFromContainingBlock() const = 0; // Returns the border width (thickness) values. virtual float GetBorderLeftWidth() const = 0; @@ -75,14 +74,6 @@ virtual math::Vector2dF GetPaddingEdgeOffset() const = 0; virtual float GetPaddingEdgeWidth() const = 0; virtual float GetPaddingEdgeHeight() const = 0; - virtual math::Vector2dF GetPaddingEdgeOffsetFromContainingBlock() const = 0; - - // Returns content edge values. - // See https://www.w3.org/TR/CSS21/box.html#box-dimensions - virtual math::Vector2dF GetContentEdgeOffset() const = 0; - virtual float GetContentEdgeWidth() const = 0; - virtual float GetContentEdgeHeight() const = 0; - virtual math::Vector2dF GetContentEdgeOffsetFromContainingBlock() const = 0; // Return scrolling area. // See https://www.w3.org/TR/cssom-view-1/#scrolling-area
diff --git a/src/cobalt/dom/node.cc b/src/cobalt/dom/node.cc index 8e6ed9d..c7f01b7 100644 --- a/src/cobalt/dom/node.cc +++ b/src/cobalt/dom/node.cc
@@ -497,8 +497,8 @@ } } -void Node::MarkDisplayNoneOnNodeAndDescendants() { - MarkDisplayNoneOnDescendants(); +void Node::MarkNotDisplayedOnNodeAndDescendants() { + MarkNotDisplayedOnDescendants(); } void Node::PurgeCachedBackgroundImagesOfNodeAndDescendants() { @@ -517,10 +517,10 @@ InvalidateLayoutBoxesOfDescendants(); } -void Node::MarkDisplayNoneOnDescendants() { +void Node::MarkNotDisplayedOnDescendants() { Node* child = first_child_.get(); while (child) { - child->MarkDisplayNoneOnNodeAndDescendants(); + child->MarkNotDisplayedOnNodeAndDescendants(); child = child->next_sibling_.get(); } } @@ -772,6 +772,7 @@ bool was_inserted_to_document = node->inserted_into_document_; if (was_inserted_to_document) { node->OnRemovedFromDocument(); + node->MarkNotDisplayedOnNodeAndDescendants(); } // 1. 5. Not needed by Cobalt.
diff --git a/src/cobalt/dom/node.h b/src/cobalt/dom/node.h index 3653d7c..3f6cd23 100644 --- a/src/cobalt/dom/node.h +++ b/src/cobalt/dom/node.h
@@ -250,7 +250,7 @@ virtual bool IsInDocument() const { return inserted_into_document_; } - virtual void MarkDisplayNoneOnNodeAndDescendants(); + virtual void MarkNotDisplayedOnNodeAndDescendants(); virtual void PurgeCachedBackgroundImagesOfNodeAndDescendants(); virtual void InvalidateComputedStylesOfNodeAndDescendants(); virtual void InvalidateLayoutBoxesOfNodeAndAncestors(); @@ -260,7 +260,7 @@ virtual void InvalidateLayoutBoxCrossReferences() {} virtual void InvalidateLayoutBoxRenderTreeNodes() {} - void MarkDisplayNoneOnDescendants(); + void MarkNotDisplayedOnDescendants(); void PurgeCachedBackgroundImagesOfDescendants(); void InvalidateComputedStylesOfDescendants(); void InvalidateLayoutBoxesOfAncestors();
diff --git a/src/cobalt/layout/box.cc b/src/cobalt/layout/box.cc index 521051f..403fc1a 100644 --- a/src/cobalt/layout/box.cc +++ b/src/cobalt/layout/box.cc
@@ -706,6 +706,11 @@ UpdateUiNavigationItem(); } + // Update intersection observers for any targets represented by this box. + if (box_intersection_observer_module_) { + box_intersection_observer_module_->UpdateIntersectionObservations(); + } + // The painting order is: // - background color. // - background image. @@ -2102,5 +2107,30 @@ return true; } +void Box::AddIntersectionObserverRootsAndTargets( + BoxIntersectionObserverModule::IntersectionObserverRootVector&& roots, + BoxIntersectionObserverModule::IntersectionObserverTargetVector&& targets) { + if (!box_intersection_observer_module_) { + box_intersection_observer_module_ = + std::unique_ptr<BoxIntersectionObserverModule>( + new BoxIntersectionObserverModule(this)); + } + + box_intersection_observer_module_->AddIntersectionObserverRoots( + std::move(roots)); + box_intersection_observer_module_->AddIntersectionObserverTargets( + std::move(targets)); +} + +bool Box::ContainsIntersectionObserverRoot( + const scoped_refptr<IntersectionObserverRoot>& intersection_observer_root) + const { + if (box_intersection_observer_module_) { + return box_intersection_observer_module_ + ->BoxContainsIntersectionObserverRoot(intersection_observer_root); + } + return false; +} + } // namespace layout } // namespace cobalt
diff --git a/src/cobalt/layout/box.h b/src/cobalt/layout/box.h index 2368108..596b2b4 100644 --- a/src/cobalt/layout/box.h +++ b/src/cobalt/layout/box.h
@@ -26,6 +26,7 @@ #include "cobalt/cssom/css_style_declaration.h" #include "cobalt/dom/node.h" #include "cobalt/layout/base_direction.h" +#include "cobalt/layout/box_intersection_observer_module.h" #include "cobalt/layout/insets_layout_unit.h" #include "cobalt/layout/layout_stat_tracker.h" #include "cobalt/layout/layout_unit.h" @@ -643,6 +644,14 @@ ui_nav_item_ = item; } + void AddIntersectionObserverRootsAndTargets( + BoxIntersectionObserverModule::IntersectionObserverRootVector&& roots, + BoxIntersectionObserverModule::IntersectionObserverTargetVector&& + targets); + bool ContainsIntersectionObserverRoot( + const scoped_refptr<IntersectionObserverRoot>& intersection_observer_root) + const; + protected: UsedStyleProvider* used_style_provider() const { return used_style_provider_; @@ -927,6 +936,9 @@ // UI navigation items are used to help animate certain elements. scoped_refptr<ui_navigation::NavItem> ui_nav_item_; + std::unique_ptr<BoxIntersectionObserverModule> + box_intersection_observer_module_; + // For write access to parent/containing_block members. friend class ContainerBox; friend class LayoutBoxes;
diff --git a/src/cobalt/layout/box_generator.cc b/src/cobalt/layout/box_generator.cc index 2b85645..b9fe273 100644 --- a/src/cobalt/layout/box_generator.cc +++ b/src/cobalt/layout/box_generator.cc
@@ -990,6 +990,13 @@ container_box_before_split->SetUiNavItem(html_element->GetUiNavItem()); boxes_.push_back(container_box_before_split); + BoxIntersectionObserverModule::IntersectionObserverRootVector roots = + html_element->GetLayoutIntersectionObserverRoots(); + BoxIntersectionObserverModule::IntersectionObserverTargetVector targets = + html_element->GetLayoutIntersectionObserverTargets(); + container_box_before_split->AddIntersectionObserverRootsAndTargets( + std::move(roots), std::move(targets)); + AppendPseudoElementToLine(html_element, dom::kBeforePseudoElementType); // Generate child boxes.
diff --git a/src/cobalt/layout/box_intersection_observer_module.cc b/src/cobalt/layout/box_intersection_observer_module.cc new file mode 100644 index 0000000..d09d3b6 --- /dev/null +++ b/src/cobalt/layout/box_intersection_observer_module.cc
@@ -0,0 +1,58 @@ +// Copyright 2019 The Cobalt Authors. 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 "cobalt/layout/box_intersection_observer_module.h" + +#include "cobalt/layout/box.h" + +namespace cobalt { +namespace layout { + +BoxIntersectionObserverModule::BoxIntersectionObserverModule(Box* box) + : box_(box) {} + +void BoxIntersectionObserverModule::AddIntersectionObserverRoots( + IntersectionObserverRootVector&& roots) { + intersection_observer_roots_ = std::move(roots); +} + +void BoxIntersectionObserverModule::AddIntersectionObserverTargets( + IntersectionObserverTargetVector&& targets) { + intersection_observer_targets_ = std::move(targets); +} + +bool BoxIntersectionObserverModule::BoxContainsIntersectionObserverRoot( + const scoped_refptr<IntersectionObserverRoot>& intersection_observer_root) + const { + for (auto it = intersection_observer_roots_.begin(); + it != intersection_observer_roots_.end(); ++it) { + if (*it == intersection_observer_root) { + return true; + } + } + return false; +} + +void BoxIntersectionObserverModule::UpdateIntersectionObservations() { + ContainerBox* container_box = box_->AsContainerBox(); + if (!container_box) { + return; + } + for (const auto& target : intersection_observer_targets_) { + target->UpdateIntersectionObservationsForTarget(container_box); + } +} + +} // namespace layout +} // namespace cobalt
diff --git a/src/cobalt/layout/box_intersection_observer_module.h b/src/cobalt/layout/box_intersection_observer_module.h new file mode 100644 index 0000000..f8668fa --- /dev/null +++ b/src/cobalt/layout/box_intersection_observer_module.h
@@ -0,0 +1,58 @@ +// Copyright 2019 The Cobalt Authors. 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. + +#ifndef COBALT_LAYOUT_BOX_INTERSECTION_OBSERVER_MODULE_H_ +#define COBALT_LAYOUT_BOX_INTERSECTION_OBSERVER_MODULE_H_ + +#include <vector> + +#include "cobalt/layout/intersection_observer_root.h" +#include "cobalt/layout/intersection_observer_target.h" + +namespace cobalt { +namespace layout { + +class Box; + +// This helper class groups the methods and data related to the intersection +// root and target elements produced by a particular box. +class BoxIntersectionObserverModule { + public: + typedef std::vector<scoped_refptr<IntersectionObserverRoot>> + IntersectionObserverRootVector; + typedef std::vector<scoped_refptr<IntersectionObserverTarget>> + IntersectionObserverTargetVector; + + explicit BoxIntersectionObserverModule(Box* box); + ~BoxIntersectionObserverModule() {} + + void AddIntersectionObserverRoots(IntersectionObserverRootVector&& roots); + void AddIntersectionObserverTargets( + IntersectionObserverTargetVector&& targets); + bool BoxContainsIntersectionObserverRoot( + const scoped_refptr<IntersectionObserverRoot>& intersection_observer_root) + const; + void UpdateIntersectionObservations(); + + private: + Box* box_; + + IntersectionObserverRootVector intersection_observer_roots_; + IntersectionObserverTargetVector intersection_observer_targets_; +}; + +} // namespace layout +} // namespace cobalt + +#endif // COBALT_LAYOUT_BOX_INTERSECTION_OBSERVER_MODULE_H_
diff --git a/src/cobalt/layout/intersection_observer_root.h b/src/cobalt/layout/intersection_observer_root.h new file mode 100644 index 0000000..b7b6447 --- /dev/null +++ b/src/cobalt/layout/intersection_observer_root.h
@@ -0,0 +1,59 @@ +// Copyright 2019 The Cobalt Authors. 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. + +#ifndef COBALT_LAYOUT_INTERSECTION_OBSERVER_ROOT_H_ +#define COBALT_LAYOUT_INTERSECTION_OBSERVER_ROOT_H_ + +#include <vector> + +#include "base/memory/ref_counted.h" +#include "cobalt/cssom/property_list_value.h" + +namespace cobalt { +namespace layout { + +class Box; + +// An IntersectionObserverRoot holds information associated with the W3 +// IntersectionObserver object, such as rootMargin and thresholds. +// IntersectionObserverTarget objects reference these objects, instead of the +// other way around. +class IntersectionObserverRoot + : public base::RefCountedThreadSafe<IntersectionObserverRoot> { + public: + IntersectionObserverRoot( + const scoped_refptr<cssom::PropertyListValue>& root_margin_property_value, + std::vector<double> thresholds_vector) + : root_margin_property_value_(root_margin_property_value), + thresholds_vector_(thresholds_vector) {} + + ~IntersectionObserverRoot() {} + + const scoped_refptr<cssom::PropertyListValue>& root_margin_property_value() + const { + return root_margin_property_value_; + } + + std::vector<double> thresholds_vector() const { return thresholds_vector_; } + + private: + // Properties associated with the IntersectionObserver object. + scoped_refptr<cssom::PropertyListValue> root_margin_property_value_; + std::vector<double> thresholds_vector_; +}; + +} // namespace layout +} // namespace cobalt + +#endif // COBALT_LAYOUT_INTERSECTION_OBSERVER_ROOT_H_
diff --git a/src/cobalt/layout/intersection_observer_target.cc b/src/cobalt/layout/intersection_observer_target.cc new file mode 100644 index 0000000..19fd041 --- /dev/null +++ b/src/cobalt/layout/intersection_observer_target.cc
@@ -0,0 +1,276 @@ +// Copyright 2019 The Cobalt Authors. 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 "cobalt/layout/intersection_observer_target.h" + +#include <algorithm> +#include <vector> + +#include "cobalt/cssom/computed_style_utils.h" +#include "cobalt/cssom/keyword_value.h" +#include "cobalt/layout/box.h" +#include "cobalt/layout/container_box.h" +#include "cobalt/layout/intersection_observer_root.h" +#include "cobalt/layout/used_style.h" + +namespace cobalt { +namespace layout { + +void IntersectionObserverTarget::UpdateIntersectionObservationsForTarget( + ContainerBox* target_box) { + // Walk up the containing block chain looking for the box referencing the + // IntersectionObserverRoot corresponding to this IntersectionObserverTarget. + // Skip further processing for the target if it is not a descendant of the + // root in the containing block chain. + const ContainerBox* root_box = target_box->GetContainingBlock(); + while (!root_box->ContainsIntersectionObserverRoot( + intersection_observer_root_)) { + if (!root_box->parent()) { + return; + } + root_box = root_box->GetContainingBlock(); + } + + // Let targetRect be target's bounding border box. + RectLayoutUnit target_transformed_border_box( + target_box->GetTransformedBorderBoxFromRoot()); + math::RectF target_rect = + math::RectF(target_transformed_border_box.x().toFloat(), + target_transformed_border_box.y().toFloat(), + target_transformed_border_box.width().toFloat(), + target_transformed_border_box.height().toFloat()); + + // Let intersectionRect be the result of running the compute the intersection + // algorithm on target. + math::RectF root_bounds = GetRootBounds( + root_box, intersection_observer_root_->root_margin_property_value()); + math::RectF intersection_rect = ComputeIntersectionBetweenTargetAndRoot( + root_box, root_bounds, target_rect, target_box); + + // Let targetArea be targetRect's area. + float target_area = target_rect.size().GetArea(); + + // Let intersectionArea be intersectionRect's area. + float intersection_area = intersection_rect.size().GetArea(); + + // Let isIntersecting be true if targetRect and rootBounds intersect or are + // edge-adjacent, even if the intersection has zero area (because rootBounds + // or targetRect have zero area); otherwise, let isIntersecting be false. + bool is_intersecting = + intersection_rect.width() != 0 || intersection_rect.height() != 0; + + // If targetArea is non-zero, let intersectionRatio be intersectionArea + // divided by targetArea. Otherwise, let intersectionRatio be 1 if + // isIntersecting is true, or 0 if isIntersecting is false. + float intersection_ratio = is_intersecting ? 1.0f : 0.0f; + if (target_area != 0) { + intersection_ratio = intersection_area / target_area; + } + + // Let thresholdIndex be the index of the first entry in observer.thresholds + // whose value is greater than intersectionRatio, or the length of + // observer.thresholds if intersectionRatio is greater than or equal to the + // last entry in observer.thresholds. + const std::vector<double>& thresholds = + intersection_observer_root_->thresholds_vector(); + size_t threshold_index; + for (threshold_index = 0; threshold_index < thresholds.size(); + ++threshold_index) { + if (thresholds.at(threshold_index) > intersection_ratio) { + break; + } + } + + // If thresholdIndex does not equal previousThresholdIndex or if + // isIntersecting does not equal previousIsIntersecting, queue an + // IntersectionObserverEntry, passing in observer, time, rootBounds, + // boundingClientRect, intersectionRect, isIntersecting, and target. + if (static_cast<int32>(threshold_index) != previous_threshold_index_ || + is_intersecting != previous_is_intersecting_) { + on_intersection_callback_.Run(root_bounds, target_rect, intersection_rect, + is_intersecting, intersection_ratio); + } + + // Update the previousThresholdIndex and previousIsIntersecting properties. + previous_threshold_index_ = static_cast<int32>(threshold_index); + previous_is_intersecting_ = is_intersecting; +} + +bool IntersectionObserverTarget::IsInContainingBlockChain( + const ContainerBox* potential_containing_block, + const ContainerBox* target_box) { + const ContainerBox* containing_block = target_box->GetContainingBlock(); + while (containing_block != potential_containing_block) { + if (!containing_block->parent()) { + return false; + } + containing_block = containing_block->GetContainingBlock(); + } + return true; +} + +math::RectF IntersectionObserverTarget::GetRootBounds( + const ContainerBox* root_box, + scoped_refptr<cssom::PropertyListValue> root_margin_property_value) { + math::RectF root_bounds_without_margins; + if (IsOverflowCropped(root_box->computed_style())) { + // If the intersection root has an overflow clip, it's the element's content + // area. + Vector2dLayoutUnit content_edge_offset = + root_box->GetContentBoxOffsetFromRoot(false /*transform_forms_root*/); + root_bounds_without_margins = math::RectF( + content_edge_offset.x().toFloat(), content_edge_offset.y().toFloat(), + root_box->width().toFloat(), root_box->height().toFloat()); + } else { + // Otherwise, it's the result of running the getBoundingClientRect() + // algorithm on the intersection root. + RectLayoutUnit root_transformed_border_box( + root_box->GetTransformedBorderBoxFromRoot()); + root_bounds_without_margins = + math::RectF(root_transformed_border_box.x().toFloat(), + root_transformed_border_box.y().toFloat(), + root_transformed_border_box.width().toFloat(), + root_transformed_border_box.height().toFloat()); + } + int32 top_margin = GetUsedLengthOfRootMarginPropertyValue( + root_margin_property_value->value()[0], + LayoutUnit(root_bounds_without_margins.height())); + int32 right_margin = GetUsedLengthOfRootMarginPropertyValue( + root_margin_property_value->value()[1], + LayoutUnit(root_bounds_without_margins.width())); + int32 bottom_margin = GetUsedLengthOfRootMarginPropertyValue( + root_margin_property_value->value()[2], + LayoutUnit(root_bounds_without_margins.height())); + int32 left_margin = GetUsedLengthOfRootMarginPropertyValue( + root_margin_property_value->value()[3], + LayoutUnit(root_bounds_without_margins.width())); + + // Remember to grow or shrink the root intersection rectangle bounds based + // on the root margin property. + math::RectF root_bounds = math::RectF( + root_bounds_without_margins.x() - left_margin, + root_bounds_without_margins.y() - top_margin, + root_bounds_without_margins.width() + left_margin + right_margin, + root_bounds_without_margins.height() + top_margin + bottom_margin); + return root_bounds; +} + +int32 IntersectionObserverTarget::GetUsedLengthOfRootMarginPropertyValue( + const scoped_refptr<cssom::PropertyValue>& length_property_value, + LayoutUnit percentage_base) { + UsedLengthValueProvider used_length_provider(percentage_base); + length_property_value->Accept(&used_length_provider); + // Not explicitly stated in web spec, but has been observed that Chrome + // truncates root margin decimal values. + return static_cast<int32>( + used_length_provider.used_length().value_or(LayoutUnit(0.0f)).toFloat()); +} + +math::RectF IntersectionObserverTarget::ComputeIntersectionBetweenTargetAndRoot( + const ContainerBox* root_box, const math::RectF& root_bounds, + const math::RectF& target_rect, const ContainerBox* target_box) { + // Let intersectionRect be target's bounding border box. + math::RectF intersection_rect = target_rect; + + // Let container be the containing block of the target. + math::Vector2dF total_offset_from_containing_block = + target_box->GetBorderBoxOffsetFromContainingBlock(); + const ContainerBox* prev_container = target_box; + const ContainerBox* container = prev_container->GetContainingBlock(); + + // While container is not the intersection root: + while (container != root_box) { + // Map intersectionRect to the coordinate space of container. + intersection_rect.set_x(total_offset_from_containing_block.x()); + intersection_rect.set_y(total_offset_from_containing_block.y()); + + // If container has overflow clipping or a css clip-path property, update + // intersectionRect by applying container's clip. (Note: The containing + // block of an element with 'position: absolute' is formed by the padding + // edge of the ancestor. https://www.w3.org/TR/CSS2/visudet.html) + if (IsOverflowCropped(container->computed_style())) { + Vector2dLayoutUnit container_clip_dimensions = + prev_container->computed_style()->position() == + cssom::KeywordValue::GetAbsolute() + ? Vector2dLayoutUnit(container->GetPaddingBoxWidth(), + container->GetPaddingBoxHeight()) + : Vector2dLayoutUnit(container->width(), container->height()); + math::RectF container_clip(0.0f, 0.0f, + container_clip_dimensions.x().toFloat(), + container_clip_dimensions.y().toFloat()); + intersection_rect = + IntersectIntersectionObserverRects(intersection_rect, container_clip); + } + + // If container is the root element of a nested browsing context, update + // container to be the browsing context container of container, and update + // intersectionRect by clipping to the viewport of the nested browsing + // context. Otherwise, update container to be the containing block of + // container. (Note: The containing block of an element with 'position: + // absolute' is formed by the padding edge of the ancestor. + // https://www.w3.org/TR/CSS2/visudet.html) + math::Vector2dF next_offset_from_containing_block = + prev_container->computed_style()->position() == + cssom::KeywordValue::GetAbsolute() + ? container->GetPaddingBoxOffsetFromContainingBlock() + : container->GetContentBoxOffsetFromContainingBlockContentBox( + container->GetContainingBlock()); + total_offset_from_containing_block += next_offset_from_containing_block; + + prev_container = container; + container = prev_container->GetContainingBlock(); + } + + // Map intersectionRect to the coordinate space of the viewport of the + // Document containing the target. + // (Note: The containing block of an element with 'position: absolute' + // is formed by the padding edge of the ancestor. + // https://www.w3.org/TR/CSS2/visudet.html) + math::Vector2dF containing_block_offset_from_origin = + prev_container->computed_style()->position() == + cssom::KeywordValue::GetAbsolute() && + !IsOverflowCropped(container->computed_style()) + ? container->GetPaddingBoxOffsetFromRoot( + false /*transform_forms_root*/) + : container->GetContentBoxOffsetFromRoot( + false /*transform_forms_root*/); + + intersection_rect.set_x(total_offset_from_containing_block.x() + + containing_block_offset_from_origin.x()); + intersection_rect.set_y(total_offset_from_containing_block.y() + + containing_block_offset_from_origin.y()); + + // Update intersectionRect by intersecting it with the root intersection + // rectangle, which is already in this coordinate space. + intersection_rect = + IntersectIntersectionObserverRects(intersection_rect, root_bounds); + return intersection_rect; +} + +math::RectF IntersectionObserverTarget::IntersectIntersectionObserverRects( + const math::RectF& a, const math::RectF& b) { + float rx = std::max(a.x(), b.x()); + float ry = std::max(a.y(), b.y()); + float rr = std::min(a.right(), b.right()); + float rb = std::min(a.bottom(), b.bottom()); + + if (rx > rr || ry > rb) { + return math::RectF(0.0f, 0.0f, 0.0f, 0.0f); + } + + return math::RectF(rx, ry, rr - rx, rb - ry); +} + +} // namespace layout +} // namespace cobalt
diff --git a/src/cobalt/layout/intersection_observer_target.h b/src/cobalt/layout/intersection_observer_target.h new file mode 100644 index 0000000..a40d41d --- /dev/null +++ b/src/cobalt/layout/intersection_observer_target.h
@@ -0,0 +1,118 @@ +// Copyright 2019 The Cobalt Authors. 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. + +#ifndef COBALT_LAYOUT_INTERSECTION_OBSERVER_TARGET_H_ +#define COBALT_LAYOUT_INTERSECTION_OBSERVER_TARGET_H_ + +#include "base/basictypes.h" +#include "base/callback.h" +#include "base/memory/ref_counted.h" +#include "cobalt/cssom/property_list_value.h" +#include "cobalt/layout/layout_unit.h" +#include "cobalt/math/rect_f.h" + +namespace cobalt { +namespace layout { + +class Box; +class ContainerBox; +class IntersectionObserverRoot; + +// A IntersectionObserverTarget roughly maps to |target| in a call to observe() +// (https://www.w3.org/TR/intersection-observer/#dom-intersectionobserver-observe). +// In lieu of having IntersectionObserverRegistration records, these objects can +// keep track of the |previousThresholdIndex| and |previousIsIntersecting| +// properties that determine whether IntersectionObserver objects need to be +// notified of changes +// (https://www.w3.org/TR/intersection-observer/#intersectionobserverregistration). +// An IntersectionObserverTarget references the IntersectionObserverRoot that it +// it associated with, not the other way around. +class IntersectionObserverTarget + : public base::RefCountedThreadSafe<IntersectionObserverTarget> { + public: + // Callback that runs when an intersection change is observed, that goes back + // into DOM logic to notify the intersection observers. + typedef base::Callback<void(math::RectF root_bounds, math::RectF target_rect, + math::RectF intersection_rect, + bool is_intersecting, float intersection_ratio)> + OnIntersectionCallback; + + IntersectionObserverTarget( + const OnIntersectionCallback& on_intersection_callback, + scoped_refptr<IntersectionObserverRoot> intersection_observer_root) + : on_intersection_callback_(on_intersection_callback), + intersection_observer_root_(intersection_observer_root), + previous_threshold_index_(-1), + previous_is_intersecting_(false) {} + + ~IntersectionObserverTarget() {} + + // The Intersection Observer spec describes a sequence of steps to update the + // target element of an observer in step 2.2 of the "Run the Update + // Intersection Observation Steps" algorithm. + // This function follows the algorithm in the web spec, with a few notable + // modifications: (1) All computations occur with respect to objects in the + // box tree, not the dom tree. (2) This class already keeps track of the + // previousThresholdIndex and previousIsIntersecting fields, so no + // intersection observer registration objects are used to determine whether + // IntersectionObserver objects need to be notified of a change. + // https://www.w3.org/TR/intersection-observer/#update-intersection-observations-algo + void UpdateIntersectionObservationsForTarget(ContainerBox* target_box); + + scoped_refptr<IntersectionObserverRoot> intersection_observer_root() { + return intersection_observer_root_; + } + + private: + // Walk up the containing block chain, as described in + // http://www.w3.org/TR/CSS2/visudet.html#containing-block-details + bool IsInContainingBlockChain(const ContainerBox* potential_containing_block, + const ContainerBox* target_box); + + int32 GetUsedLengthOfRootMarginPropertyValue( + const scoped_refptr<cssom::PropertyValue>& length_property_value, + LayoutUnit percentage_base); + + // Rules for determining the root intersection rectangle bounds. + // https://www.w3.org/TR/intersection-observer/#intersectionobserver-root-intersection-rectangle + math::RectF GetRootBounds( + const ContainerBox* root_box, + scoped_refptr<cssom::PropertyListValue> root_margin_property_value); + + // Compute the intersection between a target and the observer's intersection + // root. + // https://www.w3.org/TR/intersection-observer/#calculate-intersection-rect-algo + math::RectF ComputeIntersectionBetweenTargetAndRoot( + const ContainerBox* root_box, const math::RectF& root_bounds, + const math::RectF& target_rect, const ContainerBox* target_box); + + // Similar to the IntersectRects function in math::RectF, but handles edge + // adjacent intersections as valid intersections (instead of returning a + // rectangle with zero dimensions) + math::RectF IntersectIntersectionObserverRects(const math::RectF& a, + const math::RectF& b); + + OnIntersectionCallback on_intersection_callback_; + + scoped_refptr<IntersectionObserverRoot> intersection_observer_root_; + + int32 previous_threshold_index_; + + bool previous_is_intersecting_; +}; + +} // namespace layout +} // namespace cobalt + +#endif // COBALT_LAYOUT_INTERSECTION_OBSERVER_TARGET_H_
diff --git a/src/cobalt/layout/layout.cc b/src/cobalt/layout/layout.cc index bcaaebf..b298940 100644 --- a/src/cobalt/layout/layout.cc +++ b/src/cobalt/layout/layout.cc
@@ -93,6 +93,18 @@ LayoutStatTracker::kStopWatchTypeBoxGeneration, base::StopWatch::kAutoStartOn, layout_stat_tracker); + // If the implicit root is a root for any observers, the initial containing + // block should reference the corresponding IntersectionObserverRoots. + dom::HTMLElement* html_element = + document->document_element()->AsHTMLElement(); + BoxIntersectionObserverModule::IntersectionObserverRootVector roots = + html_element->GetLayoutIntersectionObserverRoots(); + BoxIntersectionObserverModule::IntersectionObserverTargetVector targets = + html_element->GetLayoutIntersectionObserverTargets(); + (*initial_containing_block) + ->AddIntersectionObserverRootsAndTargets(std::move(roots), + std::move(targets)); + ScopedParagraph scoped_paragraph( new Paragraph(locale, (*initial_containing_block)->base_direction(), Paragraph::DirectionalEmbeddingStack(),
diff --git a/src/cobalt/layout/layout.gyp b/src/cobalt/layout/layout.gyp index 30b1717..884553b 100644 --- a/src/cobalt/layout/layout.gyp +++ b/src/cobalt/layout/layout.gyp
@@ -38,6 +38,8 @@ 'box.h', 'box_generator.cc', 'box_generator.h', + 'box_intersection_observer_module.cc', + 'box_intersection_observer_module.h', 'container_box.cc', 'container_box.h', 'flex_container_box.cc', @@ -61,6 +63,9 @@ 'inline_level_replaced_box.h', 'insets_layout_unit.cc', 'insets_layout_unit.h', + 'intersection_observer_root.h', + 'intersection_observer_target.cc', + 'intersection_observer_target.h', 'layout.cc', 'layout.h', 'layout_unit.h',
diff --git a/src/cobalt/layout/layout_boxes.cc b/src/cobalt/layout/layout_boxes.cc index b459474..da333da 100644 --- a/src/cobalt/layout/layout_boxes.cc +++ b/src/cobalt/layout/layout_boxes.cc
@@ -89,11 +89,6 @@ return GetBoundingBorderRectangle().height(); } -math::Vector2dF LayoutBoxes::GetBorderEdgeOffsetFromContainingBlock() const { - DCHECK(!boxes_.empty()); - return boxes_.front()->GetBorderBoxOffsetFromContainingBlock(); -} - float LayoutBoxes::GetBorderLeftWidth() const { DCHECK(!boxes_.empty()); return boxes_.front()->border_left_width().toFloat(); @@ -130,33 +125,6 @@ return boxes_.front()->GetPaddingBoxHeight().toFloat(); } -math::Vector2dF LayoutBoxes::GetPaddingEdgeOffsetFromContainingBlock() const { - DCHECK(!boxes_.empty()); - return boxes_.front()->GetPaddingBoxOffsetFromContainingBlock(); -} - -math::Vector2dF LayoutBoxes::GetContentEdgeOffset() const { - DCHECK(!boxes_.empty()); - return boxes_.front()->GetContentBoxOffsetFromRoot( - false /*transform_forms_root*/); -} - -float LayoutBoxes::GetContentEdgeWidth() const { - DCHECK(!boxes_.empty()); - return boxes_.front()->width().toFloat(); -} - -float LayoutBoxes::GetContentEdgeHeight() const { - DCHECK(!boxes_.empty()); - return boxes_.front()->height().toFloat(); -} - -math::Vector2dF LayoutBoxes::GetContentEdgeOffsetFromContainingBlock() const { - DCHECK(!boxes_.empty()); - return boxes_.front()->GetContentBoxOffsetFromContainingBlockContentBox( - boxes_.front()->GetContainingBlock()); -} - math::RectF LayoutBoxes::GetScrollArea(dom::Directionality dir) const { // https://www.w3.org/TR/cssom-view-1/#scrolling-area // For rightward and downward:
diff --git a/src/cobalt/layout/layout_boxes.h b/src/cobalt/layout/layout_boxes.h index 81114a1..0e838c0 100644 --- a/src/cobalt/layout/layout_boxes.h +++ b/src/cobalt/layout/layout_boxes.h
@@ -45,7 +45,6 @@ float GetBorderEdgeTop() const override; float GetBorderEdgeWidth() const override; float GetBorderEdgeHeight() const override; - math::Vector2dF GetBorderEdgeOffsetFromContainingBlock() const override; float GetBorderLeftWidth() const override; float GetBorderTopWidth() const override; @@ -56,12 +55,6 @@ math::Vector2dF GetPaddingEdgeOffset() const override; float GetPaddingEdgeWidth() const override; float GetPaddingEdgeHeight() const override; - math::Vector2dF GetPaddingEdgeOffsetFromContainingBlock() const override; - - math::Vector2dF GetContentEdgeOffset() const override; - float GetContentEdgeWidth() const override; - float GetContentEdgeHeight() const override; - math::Vector2dF GetContentEdgeOffsetFromContainingBlock() const override; math::RectF GetScrollArea(dom::Directionality dir) const override;
diff --git a/src/cobalt/layout/layout_manager.cc b/src/cobalt/layout/layout_manager.cc index c571f16..a913178 100644 --- a/src/cobalt/layout/layout_manager.cc +++ b/src/cobalt/layout/layout_manager.cc
@@ -428,11 +428,6 @@ is_render_tree_pending_ = false; } - // Run the Update Intersection Observation Steps - // https://www.w3.org/TR/intersection-observer/#update-intersection-observations-algo - document->intersection_observer_task_manager() - ->UpdateIntersectionObservations(); - TRACE_EVENT_END0("cobalt::layout", kBenchmarkStatLayout); }
diff --git a/src/cobalt/layout/used_style.cc b/src/cobalt/layout/used_style.cc index a38110e..7a811f7 100644 --- a/src/cobalt/layout/used_style.cc +++ b/src/cobalt/layout/used_style.cc
@@ -23,7 +23,6 @@ #include "cobalt/base/polymorphic_downcast.h" #include "cobalt/cssom/absolute_url_value.h" -#include "cobalt/cssom/calc_value.h" #include "cobalt/cssom/font_style_value.h" #include "cobalt/cssom/font_weight_value.h" #include "cobalt/cssom/keyword_value.h" @@ -38,7 +37,6 @@ #include "cobalt/cssom/string_value.h" #include "cobalt/cssom/transform_function_visitor.h" #include "cobalt/cssom/translate_function.h" -#include "cobalt/cssom/used_style.h" #include "cobalt/loader/mesh/mesh_cache.h" #include "cobalt/math/transform_2d.h" #include "cobalt/render_tree/animations/animate_node.h" @@ -53,8 +51,6 @@ namespace { -typedef cssom::UsedLengthValueProvider<LayoutUnit> UsedLengthValueProvider; - struct BackgroundImageTransformData { BackgroundImageTransformData( const math::SizeF& image_node_size,
diff --git a/src/cobalt/layout/used_style.h b/src/cobalt/layout/used_style.h index 07c543e..6aede9f 100644 --- a/src/cobalt/layout/used_style.h +++ b/src/cobalt/layout/used_style.h
@@ -15,6 +15,7 @@ #ifndef COBALT_LAYOUT_USED_STYLE_H_ #define COBALT_LAYOUT_USED_STYLE_H_ +#include "cobalt/cssom/calc_value.h" #include "cobalt/cssom/css_computed_style_data.h" #include "cobalt/cssom/keyword_value.h" #include "cobalt/cssom/linear_gradient_value.h" @@ -282,6 +283,50 @@ DISALLOW_COPY_AND_ASSIGN(UsedBorderRadiusProvider); }; +class UsedLengthValueProvider : public cssom::NotReachedPropertyValueVisitor { + public: + explicit UsedLengthValueProvider(LayoutUnit percentage_base, + bool calc_permitted = false) + : percentage_base_(percentage_base), calc_permitted_(calc_permitted) {} + + void VisitLength(cssom::LengthValue* length) override { + depends_on_containing_block_ = false; + + DCHECK_EQ(cssom::kPixelsUnit, length->unit()); + used_length_ = LayoutUnit(length->value()); + } + + void VisitPercentage(cssom::PercentageValue* percentage) override { + depends_on_containing_block_ = true; + used_length_ = percentage->value() * percentage_base_; + } + + void VisitCalc(cssom::CalcValue* calc) override { + if (!calc_permitted_) { + NOTREACHED(); + } + depends_on_containing_block_ = true; + used_length_ = LayoutUnit(calc->length_value()->value()) + + calc->percentage_value()->value() * percentage_base_; + } + + bool depends_on_containing_block() const { + return depends_on_containing_block_; + } + const base::Optional<LayoutUnit>& used_length() const { return used_length_; } + + protected: + bool depends_on_containing_block_; + + private: + const LayoutUnit percentage_base_; + const bool calc_permitted_; + + base::Optional<LayoutUnit> used_length_; + + DISALLOW_COPY_AND_ASSIGN(UsedLengthValueProvider); +}; + class UsedLineHeightProvider : public cssom::NotReachedPropertyValueVisitor { public: explicit UsedLineHeightProvider(
diff --git a/src/cobalt/layout_tests/testdata/css3-transitions/3-transition-not-started-on-reattach-expected.png b/src/cobalt/layout_tests/testdata/css3-transitions/3-transition-not-started-on-reattach-expected.png new file mode 100644 index 0000000..e7821e6 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css3-transitions/3-transition-not-started-on-reattach-expected.png Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css3-transitions/3-transition-not-started-on-reattach.html b/src/cobalt/layout_tests/testdata/css3-transitions/3-transition-not-started-on-reattach.html new file mode 100644 index 0000000..df8f7c0 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css3-transitions/3-transition-not-started-on-reattach.html
@@ -0,0 +1,75 @@ +<!DOCTYPE html> +<html> +<!-- + | Verify that the transition is not started when an element is removed then + | reattached to the DOM. + --> +<head> + <style> + body { + background-color: #000000; + } + + div { + width: 100px; + height: 100px; + background-color: #FF0000; + transition: background-color 5s; + } + </style> + <script> + if (window.testRunner) { + window.testRunner.waitUntilDone(); + } + + window.onload = function() { + var frame = 0; + var e = document.getElementById("animated"); + + function requestAnimationFrame(callback) { + window.requestAnimationFrame(callback); + if (window.testRunner) { + window.testRunner.DoNonMeasuredLayout(); + } + } + + function frameCallback() { + switch(++frame) { + case 1: + case 2: + requestAnimationFrame(frameCallback); + break; + case 3: + document.body.removeChild(e); + requestAnimationFrame(frameCallback); + break; + case 4: + requestAnimationFrame(frameCallback); + break; + case 5: + // Should not trigger a transition; color should change immediately. + e.style.backgroundColor = "#0000FF"; + document.body.appendChild(e); + requestAnimationFrame(frameCallback); + break; + case 6: + requestAnimationFrame(frameCallback); + break; + case 7: + if (window.testRunner) { + window.testRunner.notifyDone(); + } + break; + } + } + + // Trigger initial transition. + e.style.backgroundColor = "#00FF00"; + frameCallback(); + } + </script> +</head> +<body> + <div id="animated"></div> +</body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/css3-transitions/layout_tests.txt b/src/cobalt/layout_tests/testdata/css3-transitions/layout_tests.txt index 3aa4d83..9313518 100644 --- a/src/cobalt/layout_tests/testdata/css3-transitions/layout_tests.txt +++ b/src/cobalt/layout_tests/testdata/css3-transitions/layout_tests.txt
@@ -6,6 +6,7 @@ 2-transition-start-during-display-none-does-not-transition 2-transition-start-during-display-none-does-not-transition-from-ancestor 2-transition-started-on-display-none-pseudoelement-does-not-dcheck +3-transition-not-started-on-reattach 5-multiple-transitions-should-fire-in-correct-order 5-simple-transition 5-simple-transition-for-pseudoelement
diff --git a/src/cobalt/layout_tests/testdata/intersection-observer/layout_tests.txt b/src/cobalt/layout_tests/testdata/intersection-observer/layout_tests.txt index 1c4329b..8962d98 100644 --- a/src/cobalt/layout_tests/testdata/intersection-observer/layout_tests.txt +++ b/src/cobalt/layout_tests/testdata/intersection-observer/layout_tests.txt
@@ -2,6 +2,7 @@ element-in-containing-block-chain-has-overflow-clip-without-padding-or-border multiple-observers-with-different-roots-and-targets no-intersection-when-root-is-not-in-containing-block-chain-of-target +observers-should-update-when-elements-move previous-threshold-index-and-is-intersecting-fields-should-be-updated root-has-nonzero-padding-and-border root-has-nonzero-padding-and-border-and-overflow-clip @@ -11,3 +12,4 @@ target-has-nonzero-padding-and-border target-with-nonzero-area-is-edge-adjacent-to-root target-with-zero-area-is-edge-adjacent-to-root +unobserved-targets-do-not-get-included-in-next-update
diff --git a/src/cobalt/layout_tests/testdata/intersection-observer/observers-should-update-when-elements-move-expected.png b/src/cobalt/layout_tests/testdata/intersection-observer/observers-should-update-when-elements-move-expected.png new file mode 100644 index 0000000..7b242a2 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/intersection-observer/observers-should-update-when-elements-move-expected.png Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/intersection-observer/observers-should-update-when-elements-move.html b/src/cobalt/layout_tests/testdata/intersection-observer/observers-should-update-when-elements-move.html new file mode 100644 index 0000000..eb74022 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/intersection-observer/observers-should-update-when-elements-move.html
@@ -0,0 +1,81 @@ +<!DOCTYPE html> +<!-- + | This test checks that the observer objects get updated when the elements + | themselves move around. + | The color of the target element is blue if the intersection ratio is above + | the threshold, and green if it is below. In this test, the intersection ratio + | crosses the threshold when the target element moves; the target element + | should initially be blue but end up green. + | https://www.w3.org/TR/intersection-observer/ + --> +<html> +<head> + <style> + div { + position: absolute; + } + #root { + margin: 100px; + background-color: red; + width: 250px; + height: 150px; + } + #target { + width: 150px; + height: 50px; + top: 50px; + left: 50px; + } + </style> +</head> +<body> + <div id="root"> + <div id="target"></div> + </div> + + <script> + if (window.testRunner) { + window.testRunner.waitUntilDone(); + } + + window.addEventListener("load", function() { + var rootElement = document.querySelector('#root'); + var targetElement = document.querySelector('#target'); + + function handleIntersect(entries, observer) { + entries.forEach(function(entry) { + if (entry.intersectionRatio > 0.5) { + entry.target.style.backgroundColor = "blue"; + } else { + entry.target.style.backgroundColor = "green"; + } + }); + } + + var options = { + root: rootElement, + rootMargin: "0px", + threshold: 0.5 + }; + + var observer = new IntersectionObserver(handleIntersect, options); + observer.observe(targetElement); + + if (window.testRunner) { + window.testRunner.DoNonMeasuredLayout(); + } + + // Move the target element so that the intersection ratio now crosses + // the threshold value. An intersection observer update should be + // triggered and the callback should run. + targetElement.style.top = "-30px"; + + if (window.testRunner) { + window.testRunner.DoNonMeasuredLayout(); + window.setTimeout(function() { window.testRunner.notifyDone(); }, 0); + } + }); + </script> + +</body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/intersection-observer/root-has-nonzero-padding-and-border-and-overflow-clip.html b/src/cobalt/layout_tests/testdata/intersection-observer/root-has-nonzero-padding-and-border-and-overflow-clip.html index d3362a4..2966803 100644 --- a/src/cobalt/layout_tests/testdata/intersection-observer/root-has-nonzero-padding-and-border-and-overflow-clip.html +++ b/src/cobalt/layout_tests/testdata/intersection-observer/root-has-nonzero-padding-and-border-and-overflow-clip.html
@@ -28,7 +28,7 @@ position: absolute; } #target { - background-color: rgba(0, 128, 0, 255); + background-color: rgba(0, 128, 0, 0); width: 200px; height: 200px; }
diff --git a/src/cobalt/layout_tests/testdata/intersection-observer/root-has-nonzero-root-margin.html b/src/cobalt/layout_tests/testdata/intersection-observer/root-has-nonzero-root-margin.html index 1617161..12cd034 100644 --- a/src/cobalt/layout_tests/testdata/intersection-observer/root-has-nonzero-root-margin.html +++ b/src/cobalt/layout_tests/testdata/intersection-observer/root-has-nonzero-root-margin.html
@@ -18,7 +18,7 @@ height: 150px; } #target { - background-color: rgba(0, 128, 0, 255); + background-color: rgba(0, 128, 0, 0); width: 150px; height: 250px; margin: 50px 150px;
diff --git a/src/cobalt/layout_tests/testdata/intersection-observer/unobserved-targets-do-not-get-included-in-next-update-expected.png b/src/cobalt/layout_tests/testdata/intersection-observer/unobserved-targets-do-not-get-included-in-next-update-expected.png new file mode 100644 index 0000000..1015b8b --- /dev/null +++ b/src/cobalt/layout_tests/testdata/intersection-observer/unobserved-targets-do-not-get-included-in-next-update-expected.png Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/intersection-observer/unobserved-targets-do-not-get-included-in-next-update.html b/src/cobalt/layout_tests/testdata/intersection-observer/unobserved-targets-do-not-get-included-in-next-update.html new file mode 100644 index 0000000..e23d332 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/intersection-observer/unobserved-targets-do-not-get-included-in-next-update.html
@@ -0,0 +1,81 @@ +<!DOCTYPE html> +<!-- + | This test checks that the observers no longer check the intersections + | for targets that have been unobserved. + | Observed targets become green if they intersect with the root (i.e. are + | visible on the screen). Unobserved targets do not change color. + | https://www.w3.org/TR/intersection-observer/ + --> +<html> +<head> + <style> + div { + background-color: yellow; + width: 50px; + height: 100px; + margin: 25px; + display: inline-block; + } + </style> +</head> +<body> + <div id="firsttarget"></div> + <div id="secondtarget"></div> + <div id="thirdtarget"></div> + <div id="fourthtarget"></div> + <div id="fifthtarget"></div> + + <script> + if (window.testRunner) { + window.testRunner.waitUntilDone(); + } + + window.addEventListener("load", function() { + + function handleIntersect(entries, observer) { + entries.forEach(function(entry) { + if (entry.isIntersecting) { + entry.target.style.backgroundColor = "green"; + } + }); + } + + function createObserverAndUnobserveTargets() { + var firstTargetElement = document.querySelector('#firsttarget'); + var secondTargetElement = document.querySelector('#secondtarget'); + var thirdTargetElement = document.querySelector('#thirdtarget'); + var fourthTargetElement = document.querySelector('#fourthtarget'); + var fifthTargetElement = document.querySelector('#fifthtarget'); + + var options = { + root: null, + rootMargin: "0px", + threshold: 0.0 + }; + + // Create observer and observe elements. + var observer = new IntersectionObserver(handleIntersect, options); + observer.observe(firstTargetElement); + observer.observe(secondTargetElement); + observer.observe(thirdTargetElement); + observer.observe(fourthTargetElement); + observer.observe(fifthTargetElement); + + // Unobserve some of these targets. When the observer checks for + // intersections, these elements should not be included. + observer.unobserve(secondTargetElement); + observer.unobserve(fourthTargetElement); + observer.unobserve(fifthTargetElement); + } + + createObserverAndUnobserveTargets(); + + if (window.testRunner) { + window.testRunner.DoNonMeasuredLayout(); + window.setTimeout(function() { window.testRunner.notifyDone(); }, 0); + } + }); + </script> + +</body> +</html>
diff --git a/src/cobalt/network/url_request_context.cc b/src/cobalt/network/url_request_context.cc index 5c20925..850eade 100644 --- a/src/cobalt/network/url_request_context.cc +++ b/src/cobalt/network/url_request_context.cc
@@ -153,9 +153,6 @@ storage_.set_job_factory( std::unique_ptr<net::URLRequestJobFactory>(job_factory)); - if (!net::GetGlobalCertNetFetcher()) { - net::SetGlobalCertNetFetcher(net::CreateCertNetFetcher(this)); - } } URLRequestContext::~URLRequestContext() {}
diff --git a/src/cobalt/site/docs/development/setup-raspi.md b/src/cobalt/site/docs/development/setup-raspi.md index da7cc94..50faeb9 100644 --- a/src/cobalt/site/docs/development/setup-raspi.md +++ b/src/cobalt/site/docs/development/setup-raspi.md
@@ -23,6 +23,18 @@ Raspbian. </aside> +Cobalt assumes the Raspberry Pi is configured to use non-default thread +schedulers and priorities. Ensure that **/etc/security/limits.conf** sets +**rtprio** and **nice** limits for the user. For example, if the user is **pi**, +then limits.conf should have the following lines: + +``` +@pi hard rtprio 99 +@pi soft rtprio 99 +@pi hard nice -20 +@pi soft nice -20 +``` + The following commands update the package configuration on your Raspberry Pi so that Cobalt can run properly: @@ -63,7 +75,7 @@ 1. Run `mkdir -p $RASPI_HOME/sysroot` 1. Run: - ``` + ``` rsync -avzh --safe-links \ --delete-after pi@$RASPI_ADDR:/{opt,lib,usr} \ --exclude="lib/firmware" --exclude="lib/modules" \
diff --git a/src/cobalt/speech/google_speech_service.cc b/src/cobalt/speech/google_speech_service.cc index f3dec39..550b541 100644 --- a/src/cobalt/speech/google_speech_service.cc +++ b/src/cobalt/speech/google_speech_service.cc
@@ -35,7 +35,6 @@ #include "cobalt/base/language.h" #include "cobalt/loader/fetcher_factory.h" #include "cobalt/network/network_module.h" -#include "cobalt/speech/google_streaming_api.pb.h" #include "cobalt/speech/microphone.h" #include "cobalt/speech/speech_configuration.h" #include "cobalt/speech/speech_recognition_error.h" @@ -85,7 +84,9 @@ } SpeechRecognitionResultList::SpeechRecognitionResults -ProcessProtoSuccessResults(const proto::SpeechRecognitionEvent& event) { +ProcessProtoSuccessResults(proto::SpeechRecognitionEvent event) { + // This method handles wrappables and should run on the MainWebModule thread. + DCHECK_EQ(event.status(), proto::SpeechRecognitionEvent::STATUS_SUCCESS); SpeechRecognitionResultList::SpeechRecognitionResults results; @@ -117,8 +118,9 @@ // TODO: Feed error messages when creating SpeechRecognitionError. void ProcessAndFireErrorEvent( - const proto::SpeechRecognitionEvent& event, - const GoogleSpeechService::EventCallback& event_callback) { + proto::SpeechRecognitionEvent event, + GoogleSpeechService::EventCallback event_callback) { + // This method handles wrappables and should run on the MainWebModule thread. scoped_refptr<dom::Event> error_event; switch (event.status()) { case proto::SpeechRecognitionEvent::STATUS_SUCCESS: @@ -162,6 +164,12 @@ event_callback.Run(error_event); } +void HandleNetworkResponseFailure( + const GoogleSpeechService::EventCallback& event_callback) { + event_callback.Run(new SpeechRecognitionError( + kSpeechRecognitionErrorCodeNetwork, "Network response failure.")); +} + bool IsResponseCodeSuccess(int response_code) { // NetFetcher only considers success to be if the network request // was successful *and* we get a 2xx response back. @@ -181,7 +189,11 @@ started_(false), event_callback_(event_callback), fetcher_creator_(fetcher_creator), - thread_("speech_recognizer") { + thread_("speech_recognizer"), + ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)), + ALLOW_THIS_IN_INITIALIZER_LIST( + weak_this_(weak_ptr_factory_.GetWeakPtr())), + wrappables_task_runner_(base::MessageLoop::current()->task_runner()) { thread_.StartWithOptions( base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); } @@ -240,14 +252,20 @@ } if (event.status() == proto::SpeechRecognitionEvent::STATUS_SUCCESS) { - ProcessAndFireSuccessEvent(ProcessProtoSuccessResults(event)); + wrappables_task_runner_->PostTask( + FROM_HERE, + base::Bind(&GoogleSpeechService::ProcessAndFireSuccessEvent, + weak_this_, event)); } else { - ProcessAndFireErrorEvent(event, event_callback_); + wrappables_task_runner_->PostTask( + FROM_HERE, + base::Bind(&ProcessAndFireErrorEvent, event, event_callback_)); } } } else { - event_callback_.Run(new SpeechRecognitionError( - kSpeechRecognitionErrorCodeNetwork, "Network response failure.")); + wrappables_task_runner_->PostTask( + FROM_HERE, + base::Bind(&HandleNetworkResponseFailure, event_callback_)); } } } @@ -358,12 +376,19 @@ downstream_fetcher_.reset(); encoder_.reset(); - // Clear the final results. - final_results_.clear(); + wrappables_task_runner_->PostTask( + FROM_HERE, + base::Bind(&GoogleSpeechService::ClearFinalResults, weak_this_)); // Clear any remaining audio data. chunked_byte_buffer_.Clear(); } +void GoogleSpeechService::ClearFinalResults() { + // This method handles wrappables and should run on the MainWebModule thread. + DCHECK(wrappables_task_runner_->BelongsToCurrentThread()); + final_results_.clear(); +} + void GoogleSpeechService::UploadAudioDataInternal( std::unique_ptr<ShellAudioBus> audio_bus, bool is_last_chunk) { DCHECK_EQ(thread_.message_loop(), base::MessageLoop::current()); @@ -384,8 +409,11 @@ } void GoogleSpeechService::ProcessAndFireSuccessEvent( - const SpeechRecognitionResults& new_results) { - DCHECK_EQ(thread_.message_loop(), base::MessageLoop::current()); + proto::SpeechRecognitionEvent event) { + // This method handles wrappables and should run on the MainWebModule thread. + DCHECK(wrappables_task_runner_->BelongsToCurrentThread()); + + SpeechRecognitionResults new_results = ProcessProtoSuccessResults(event); SpeechRecognitionResults success_results; size_t total_size = final_results_.size() + new_results.size();
diff --git a/src/cobalt/speech/google_speech_service.h b/src/cobalt/speech/google_speech_service.h index b6779cb..20179c6 100644 --- a/src/cobalt/speech/google_speech_service.h +++ b/src/cobalt/speech/google_speech_service.h
@@ -24,6 +24,7 @@ #include "cobalt/media/base/shell_audio_bus.h" #include "cobalt/network/network_module.h" #include "cobalt/speech/audio_encoder_flac.h" +#include "cobalt/speech/google_streaming_api.pb.h" #include "cobalt/speech/speech_recognition_config.h" #include "cobalt/speech/speech_recognition_event.h" #include "content/browser/speech/chunked_byte_buffer.h" @@ -78,9 +79,12 @@ private: void StartInternal(const SpeechRecognitionConfig& config, int sample_rate); void StopInternal(); + // This method handles wrappables and should run on the MainWebModule thread. + void ClearFinalResults(); void UploadAudioDataInternal(std::unique_ptr<ShellAudioBus> audio_bus, bool is_last_chunk); - void ProcessAndFireSuccessEvent(const SpeechRecognitionResults& new_results); + // This method handles wrappables, and so it must run on the MainWebModule. + void ProcessAndFireSuccessEvent(proto::SpeechRecognitionEvent event); // This is used for creating fetchers. network::NetworkModule* network_module_; @@ -105,6 +109,11 @@ base::Thread thread_; // Stores fetched response. CobaltURLFetcherStringWriter* download_data_writer_ = nullptr; + + // Use a task runner to deal with all wrappables. + base::WeakPtrFactory<GoogleSpeechService> weak_ptr_factory_; + base::WeakPtr<GoogleSpeechService> weak_this_; + scoped_refptr<base::SingleThreadTaskRunner> const wrappables_task_runner_; }; } // namespace speech
diff --git a/src/net/cert/cert_verify_proc.cc b/src/net/cert/cert_verify_proc.cc index 7f30d04..5b23772 100644 --- a/src/net/cert/cert_verify_proc.cc +++ b/src/net/cert/cert_verify_proc.cc
@@ -48,10 +48,8 @@ #elif defined(OS_WIN) #include "base/win/windows_version.h" #include "net/cert/cert_verify_proc_win.h" -#elif defined(OS_FUCHSIA) +#elif defined(OS_FUCHSIA) || defined(STARBOARD) #include "net/cert/cert_verify_proc_builtin.h" -#elif defined(STARBOARD) -#include "net/cert/cert_verify_proc_openssl.h" #else #error Implement certificate verification. #endif @@ -480,10 +478,8 @@ return new CertVerifyProcMac(); #elif defined(OS_WIN) return new CertVerifyProcWin(); -#elif defined(OS_FUCHSIA) +#elif defined(OS_FUCHSIA) || defined(STARBOARD) return CreateCertVerifyProcBuiltin(); -#elif defined(STARBOARD) - return new CertVerifyProcOpenSSL(); #else #error Unsupported platform #endif
diff --git a/src/net/cert/cert_verify_proc_builtin.cc b/src/net/cert/cert_verify_proc_builtin.cc index 9345b47..5129c90 100644 --- a/src/net/cert/cert_verify_proc_builtin.cc +++ b/src/net/cert/cert_verify_proc_builtin.cc
@@ -454,6 +454,8 @@ // |input_cert|. path_builder.AddCertIssuerSource(intermediates); +// Cobalt does not need AIA fetching. +#if !defined(STARBOARD) // Allow the path builder to discover intermediates through AIA fetching. std::unique_ptr<CertIssuerSourceAia> aia_cert_issuer_source; if (net_fetcher) { @@ -462,6 +464,7 @@ } else { LOG(ERROR) << "No net_fetcher for performing AIA chasing."; } +#endif path_builder.Run(); } @@ -481,6 +484,13 @@ // builder should always return some partial path (even if just containing // the target), then there is a CertErrors to test. verify_result->cert_status |= CERT_STATUS_AUTHORITY_INVALID; +#if defined(STARBOARD) + // Cobalt only trusts root certificates that come with the binary, + // If the code reaches this point, it usually means the root certificate + // of the chain is not found in the content directory of trusted + // certificates. + DLOG(ERROR) << "Certificate Authority invalid!"; +#endif return ERR_CERT_AUTHORITY_INVALID; } @@ -597,7 +607,13 @@ } // Get the global dependencies. +#if defined(STARBOARD) + // cert net fetcher is used for fetching AIA certs which Cobalt should not + // need. + CertNetFetcher* net_fetcher = nullptr; +#else CertNetFetcher* net_fetcher = GetGlobalCertNetFetcher(); +#endif const EVRootCAMetadata* ev_metadata = EVRootCAMetadata::GetInstance(); // This boolean tracks whether online revocation checking was performed for
diff --git a/src/net/cert/cert_verify_proc_openssl.cc b/src/net/cert/cert_verify_proc_openssl.cc index a2520e7..e69de29 100644 --- a/src/net/cert/cert_verify_proc_openssl.cc +++ b/src/net/cert/cert_verify_proc_openssl.cc
@@ -1,378 +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 "net/cert/cert_verify_proc_openssl.h" - -#include "third_party/boringssl/src/include/openssl/mem.h" -#include "third_party/boringssl/src/include/openssl/ssl.h" -#include "third_party/boringssl/src/include/openssl/x509_vfy.h" -#include "third_party/boringssl/src/include/openssl/x509v3.h" - -#include <string> -#include <vector> - -#include "base/base_paths.h" -#include "base/logging.h" -#include "base/memory/singleton.h" -#include "base/path_service.h" -#include "base/sha1.h" -#include "crypto/openssl_util.h" -#include "crypto/sha2.h" -#include "net/base/net_errors.h" -#include "net/cert/asn1_util.h" -#include "net/cert/cert_status_flags.h" -#include "net/cert/cert_verifier.h" -#include "net/cert/cert_verify_result.h" -#include "net/cert/x509_certificate.h" -#include "net/cert/x509_util.h" - -namespace net { - -namespace { - -// Maps X509_STORE_CTX_get_error() return values to our cert status flags. -CertStatus MapCertErrorToCertStatus(int err) { - switch (err) { - case X509_V_ERR_SUBJECT_ISSUER_MISMATCH: - return CERT_STATUS_COMMON_NAME_INVALID; - case X509_V_ERR_CERT_NOT_YET_VALID: - case X509_V_ERR_CERT_HAS_EXPIRED: - case X509_V_ERR_CRL_NOT_YET_VALID: - case X509_V_ERR_CRL_HAS_EXPIRED: - case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: - case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: - case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: - case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: - return CERT_STATUS_DATE_INVALID; - case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: - case X509_V_ERR_UNABLE_TO_GET_CRL: - case X509_V_ERR_INVALID_CA: - case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER: - case X509_V_ERR_INVALID_NON_CA: - case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: - case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: - case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: - return CERT_STATUS_AUTHORITY_INVALID; -#if 0 -// TODO(bulach): what should we map to these status? - return CERT_STATUS_NO_REVOCATION_MECHANISM; - return CERT_STATUS_UNABLE_TO_CHECK_REVOCATION; -#endif - case X509_V_ERR_CERT_REVOKED: - return CERT_STATUS_REVOKED; - // All these status are mapped to CERT_STATUS_INVALID. - case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: - case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: - case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: - case X509_V_ERR_CERT_SIGNATURE_FAILURE: - case X509_V_ERR_CRL_SIGNATURE_FAILURE: - case X509_V_ERR_OUT_OF_MEM: - case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: - case X509_V_ERR_CERT_CHAIN_TOO_LONG: - case X509_V_ERR_PATH_LENGTH_EXCEEDED: - case X509_V_ERR_INVALID_PURPOSE: - case X509_V_ERR_CERT_UNTRUSTED: - case X509_V_ERR_CERT_REJECTED: - case X509_V_ERR_AKID_SKID_MISMATCH: - case X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH: - case X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION: - case X509_V_ERR_KEYUSAGE_NO_CERTSIGN: - case X509_V_ERR_KEYUSAGE_NO_CRL_SIGN: - case X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION: - case X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED: - case X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE: - case X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED: - case X509_V_ERR_INVALID_EXTENSION: - case X509_V_ERR_INVALID_POLICY_EXTENSION: - case X509_V_ERR_NO_EXPLICIT_POLICY: - case X509_V_ERR_UNNESTED_RESOURCE: - case X509_V_ERR_APPLICATION_VERIFICATION: - return CERT_STATUS_INVALID; - default: - NOTREACHED() << "Invalid X509 err " << err; - return CERT_STATUS_INVALID; - } -} - -template <typename T, void (*destructor)(T*)> -class ScopedOpenSSL { - public: - ScopedOpenSSL() : ptr_(NULL) {} - explicit ScopedOpenSSL(T* ptr) : ptr_(ptr) {} - ~ScopedOpenSSL() { reset(NULL); } - - T* get() const { return ptr_; } - void reset(T* ptr) { - if (ptr != ptr_) { - if (ptr_) - (*destructor)(ptr_); - ptr_ = ptr; - } - } - - private: - T* ptr_; - - DISALLOW_COPY_AND_ASSIGN(ScopedOpenSSL); -}; - -// x509_to_buffer returns a |CRYPTO_BUFFER| that contains the serialised -// contents of |x509|. -static bssl::UniquePtr<CRYPTO_BUFFER> x509_to_buffer(X509* x509) { - uint8_t* buf = NULL; - int cert_len = i2d_X509(x509, &buf); - if (cert_len <= 0) { - return 0; - } - - bssl::UniquePtr<CRYPTO_BUFFER> buffer(CRYPTO_BUFFER_new(buf, cert_len, NULL)); - OPENSSL_free(buf); - - return buffer; -} - -struct DERCache { - unsigned char* data; - int data_length; -}; - -void DERCache_free(void* parent, - void* ptr, - CRYPTO_EX_DATA* ad, - int idx, - long argl, - void* argp) { - DERCache* der_cache = static_cast<DERCache*>(ptr); - if (!der_cache) - return; - if (der_cache->data) - OPENSSL_free(der_cache->data); - OPENSSL_free(der_cache); -} - -class X509InitSingleton { - public: - static X509InitSingleton* GetInstance() { - // We allow the X509 store to leak, because it is used from a non-joinable - // worker that is not stopped on shutdown, hence may still be using - // OpenSSL library after the AtExit runner has completed. - return base::Singleton<X509InitSingleton, base::LeakySingletonTraits< - X509InitSingleton>>::get(); - } - int der_cache_ex_index() const { return der_cache_ex_index_; } - X509_STORE* store() const { return store_.get(); } - - X509InitSingleton() { - crypto::EnsureOpenSSLInit(); - der_cache_ex_index_ = X509_get_ex_new_index(0, 0, 0, 0, DERCache_free); - DCHECK_NE(der_cache_ex_index_, -1); - ResetCertStore(); - } - - void ResetCertStore() { - store_.reset(X509_STORE_new()); - DCHECK(store_.get()); - // Configure the SSL certs dir. We don't implement getenv() or hardcode - // the SSL_CERTS_DIR, which are the default methods OpenSSL uses to find - // the certs path. - base::FilePath cert_path; - base::PathService::Get(base::DIR_EXE, &cert_path); - cert_path = cert_path.Append("ssl").Append("certs"); - X509_STORE_load_locations(store_.get(), NULL, cert_path.value().c_str()); - } - - private: - int der_cache_ex_index_; - ScopedOpenSSL<X509_STORE, X509_STORE_free> store_; - - DISALLOW_COPY_AND_ASSIGN(X509InitSingleton); -}; - -// Takes ownership of |data| (which must have been allocated by OpenSSL). -DERCache* SetDERCache(X509* cert, - int x509_der_cache_index, - unsigned char* data, - int data_length) { - DERCache* internal_cache = - static_cast<DERCache*>(OPENSSL_malloc(sizeof(*internal_cache))); - if (!internal_cache) { - // We took ownership of |data|, so we must free if we can't add it to - // |cert|. - OPENSSL_free(data); - return NULL; - } - internal_cache->data = data; - internal_cache->data_length = data_length; - X509_set_ex_data(cert, x509_der_cache_index, internal_cache); - return internal_cache; -} - -// Returns true if |der_cache| points to valid data, false otherwise. -// (note: the DER-encoded data in |der_cache| is owned by |cert|, callers should -// not free it). -bool GetDERAndCacheIfNeeded(X509* cert, DERCache* der_cache) { - int x509_der_cache_index = - X509InitSingleton::GetInstance()->der_cache_ex_index(); - - // Re-encoding the DER data via i2d_X509 is an expensive operation, but it's - // necessary for comparing two certificates. We re-encode at most once per - // certificate and cache the data within the X509 cert using X509_set_ex_data. - DERCache* internal_cache = - static_cast<DERCache*>(X509_get_ex_data(cert, x509_der_cache_index)); - if (!internal_cache) { - unsigned char* data = NULL; - int data_length = i2d_X509(cert, &data); - if (data_length <= 0 || !data) - return false; - internal_cache = SetDERCache(cert, x509_der_cache_index, data, data_length); - if (!internal_cache) - return false; - } - *der_cache = *internal_cache; - return true; -} - -// sk_X509_free is a function-style macro, so can't be used as a template -// param directly. -void sk_X509_free_fn(STACK_OF(X509) * st) { - sk_X509_pop_free(st, X509_free); -} - -void GetCertChainInfo(X509_STORE_CTX* store_ctx, - CertVerifyResult* verify_result) { - STACK_OF(X509)* chain = X509_STORE_CTX_get_chain(store_ctx); - bssl::UniquePtr<CRYPTO_BUFFER> verified_cert = NULL; - std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> verified_chain; - for (int i = 0; i < sk_X509_num(chain); ++i) { - X509* cert = sk_X509_value(chain, i); - auto DER_buffer = x509_to_buffer(cert); - auto x509_cert = - x509_util::CreateCryptoBuffer(CRYPTO_BUFFER_data(DER_buffer.get()), - CRYPTO_BUFFER_len(DER_buffer.get())); - if (i == 0) { - verified_cert = std::move(x509_cert); - } else { - verified_chain.push_back(std::move(x509_cert)); - } - - // Only check the algorithm status for certificates that are not in the - // trust store. - if (i < store_ctx->last_untrusted) { - int sig_alg = OBJ_obj2nid(cert->sig_alg->algorithm); - if (sig_alg == NID_md2WithRSAEncryption) { - verify_result->has_md2 = true; - } else if (sig_alg == NID_md4WithRSAEncryption) { - verify_result->has_md4 = true; - } else if (sig_alg == NID_md5WithRSAEncryption) { - verify_result->has_md5 = true; - } else if (sig_alg == NID_sha1WithRSAEncryption) { - verify_result->has_sha1 = true; - } - } - } - - if (verified_cert) { - verify_result->verified_cert = X509Certificate::CreateFromBuffer( - std::move(verified_cert), std::move(verified_chain)); - } -} - -void AppendPublicKeyHashes(X509_STORE_CTX* store_ctx, HashValueVector* hashes) { - STACK_OF(X509)* chain = X509_STORE_CTX_get_chain(store_ctx); - for (int i = 0; i < sk_X509_num(chain); ++i) { - X509* cert = sk_X509_value(chain, i); - - DERCache der_cache; - if (!GetDERAndCacheIfNeeded(cert, &der_cache)) - continue; - std::string der_data; - der_data.assign(reinterpret_cast<const char*>(der_cache.data), - der_cache.data_length); - - base::StringPiece der_bytes(der_data); - base::StringPiece spki_bytes; - if (!asn1::ExtractSPKIFromDERCert(der_bytes, &spki_bytes)) - continue; - - HashValue sha256(HASH_VALUE_SHA256); - crypto::SHA256HashString(spki_bytes, sha256.data(), crypto::kSHA256Length); - hashes->push_back(sha256); - } -} - -} // namespace - -CertVerifyProcOpenSSL::CertVerifyProcOpenSSL() {} - -CertVerifyProcOpenSSL::~CertVerifyProcOpenSSL() {} - -int CertVerifyProcOpenSSL::VerifyInternal( - X509Certificate* cert, - const std::string& hostname, - const std::string& /*ocsp_response*/, - int flags, - CRLSet* crl_set, - const CertificateList& /*additional_trust_anchors*/, - CertVerifyResult* verify_result) { - crypto::EnsureOpenSSLInit(); - - if (!cert->VerifyNameMatch(hostname)) - verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID; - - ScopedOpenSSL<X509_STORE_CTX, X509_STORE_CTX_free> ctx(X509_STORE_CTX_new()); - - ScopedOpenSSL<STACK_OF(X509), sk_X509_free_fn> intermediates( - sk_X509_new_null()); - if (!intermediates.get()) { - return ERR_OUT_OF_MEMORY; - } - - const auto& cert_current_intermediates = cert->intermediate_buffers(); - for (auto it = cert_current_intermediates.begin(); - it != cert_current_intermediates.end(); ++it) { - X509* x509_intermediate = X509_parse_from_buffer(it->get()); - if (!sk_X509_push(intermediates.get(), x509_intermediate)) { - return ERR_OUT_OF_MEMORY; - } - } - - ScopedOpenSSL<X509, X509_free> cert_in_x509; - cert_in_x509.reset(X509_parse_from_buffer(cert->cert_buffer())); - if (X509_STORE_CTX_init(ctx.get(), X509InitSingleton::GetInstance()->store(), - cert_in_x509.get(), intermediates.get()) != 1) { - NOTREACHED(); - return ERR_FAILED; - } - - if (X509_verify_cert(ctx.get()) != 1) { - int x509_error = X509_STORE_CTX_get_error(ctx.get()); - // TODO[johnx]: replace this with net's map function. - CertStatus cert_status = MapCertErrorToCertStatus(x509_error); - LOG(ERROR) << "X509 Verification error " - << X509_verify_cert_error_string(x509_error) << " : " - << x509_error << " : " - << X509_STORE_CTX_get_error_depth(ctx.get()) << " : " - << cert_status; - verify_result->cert_status |= cert_status; - } - - GetCertChainInfo(ctx.get(), verify_result); - AppendPublicKeyHashes(ctx.get(), &verify_result->public_key_hashes); - - if (IsCertStatusError(verify_result->cert_status)) { - return MapCertStatusToNetError(verify_result->cert_status); - } - - // Currently we only ues OpenSSL's default root CA paths, so treat all - // correctly verified certs as being from a known root. - // TODO(joth): if the motivations described in - // http://src.chromium.org/viewvc/chrome?view=rev&revision=80778 become an - // issue on OpenSSL builds, we will need to embed a hardcoded list of well - // known root CAs, as per the _mac and _win versions. - verify_result->is_issued_by_known_root = true; - - return OK; -} - -} // namespace net
diff --git a/src/net/cert/cert_verify_proc_openssl.h b/src/net/cert/cert_verify_proc_openssl.h deleted file mode 100644 index 0524db1..0000000 --- a/src/net/cert/cert_verify_proc_openssl.h +++ /dev/null
@@ -1,39 +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 NET_BASE_CERT_VERIFY_PROC_OPENSSL_H_ -#define NET_BASE_CERT_VERIFY_PROC_OPENSSL_H_ - -#include "net/cert/cert_verify_proc.h" - -// Note: CertVerifyProcOpenSSL was copied from the old Chromium(m27) to support -// verifying certs with openSSL which has been used by Cobalt since day 1. -// This Method has somehow been deprecated by new Chromium(m70). -// TODO[johnx]: Switch to Chromium's new CertVerifyProcBuiltin soon after the -// rebase. - -namespace net { - -// Performs certificate path construction and validation using OpenSSL. -class CertVerifyProcOpenSSL : public CertVerifyProc { - public: - CertVerifyProcOpenSSL(); - - protected: - virtual ~CertVerifyProcOpenSSL(); - - private: - virtual int VerifyInternal(X509Certificate* cert, - const std::string& hostname, - const std::string& ocsp_response, - int flags, - CRLSet* crl_set, - const CertificateList& additional_trust_anchors, - CertVerifyResult* verify_result) override; - virtual bool SupportsAdditionalTrustAnchors() const override { return false; } -}; - -} // namespace net - -#endif // NET_BASE_CERT_VERIFY_PROC_OPENSSL_H_
diff --git a/src/net/cert/internal/system_trust_store.cc b/src/net/cert/internal/system_trust_store.cc index c5bb003..d0dbf8a 100644 --- a/src/net/cert/internal/system_trust_store.cc +++ b/src/net/cert/internal/system_trust_store.cc
@@ -36,6 +36,8 @@ #include "net/cert/x509_util_mac.h" #elif defined(OS_FUCHSIA) #include "third_party/boringssl/src/include/openssl/pool.h" +#elif defined(STARBOARD) +#include "net/cert/internal/trust_store_in_memory_starboard.h" #endif namespace net { @@ -218,21 +220,43 @@ #elif defined(STARBOARD) -// Starboard does not currently provide support for system trust store access, -// so we indicate that it should not be used. +namespace { + +class StarboardSystemCerts { + public: + StarboardSystemCerts() {} + + TrustStoreInMemoryStarboard* system_trust_store() { + return &system_trust_store_; + } + + private: + TrustStoreInMemoryStarboard system_trust_store_; +}; + +base::LazyInstance<StarboardSystemCerts>::Leaky g_root_certs_starboard = + LAZY_INSTANCE_INITIALIZER; + +} // namespace + +// Starboard does not use system certificate stores but Cobalt ships with a +// set of trusted CA certificates that can be used for validations. class SystemTrustStoreStarboard : public BaseSystemTrustStore { public: SystemTrustStoreStarboard() { + trust_store_.AddTrustStore( + g_root_certs_starboard.Get().system_trust_store()); if (TestRootCerts::HasInstance()) { trust_store_.AddTrustStore( TestRootCerts::GetInstance()->test_trust_store()); } } - bool UsesSystemTrustStore() const override { return false; } + bool UsesSystemTrustStore() const override { return true; } bool IsKnownRoot(const ParsedCertificate* trust_anchor) const override { - return false; + return g_root_certs_starboard.Get().system_trust_store()->Contains( + trust_anchor); } };
diff --git a/src/net/cert/internal/trust_store_in_memory_starboard.cc b/src/net/cert/internal/trust_store_in_memory_starboard.cc new file mode 100644 index 0000000..3d53b20 --- /dev/null +++ b/src/net/cert/internal/trust_store_in_memory_starboard.cc
@@ -0,0 +1,178 @@ +// Copyright 2019 The Cobalt Authors. 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 "net/cert/internal/trust_store_in_memory_starboard.h" + +#include "base/files/file_path.h" +#include "base/path_service.h" +#include "base/time/time.h" +#include "net/cert/internal/cert_errors.h" +#include "net/cert/pem_tokenizer.h" +#include "net/cert/x509_certificate.h" +#include "net/cert/x509_util.h" +#include "starboard/directory.h" +#include "starboard/file.h" +#include "starboard/string.h" +#include "third_party/boringssl/src/include/openssl/digest.h" +#include "third_party/boringssl/src/include/openssl/sha.h" +#include "third_party/boringssl/src/include/openssl/x509.h" + +namespace net { + +namespace { +// PEM encoded DER cert is usually around or less than 2000 bytes long. +const short kCertBufferSize = 8 * 1024; +// Each certificate file name is 8 bit hash + ".0" suffix. +const short kCertFileNameLength = 10; +const char kCertificateHeader[] = "CERTIFICATE"; +const char kSSLDirName[] = "ssl"; +const char kCertsDirName[] = "certs"; + +// Essentially an X509_NAME_hash without using X509_NAME. We did not use the +// boringSSL function directly because net does not store certs with X509 +// struct anymore and converting binary certs to X509_NAME is slightly +// expensive. +unsigned long CertNameHash(const void* data, size_t length) { + unsigned long ret = 0; + unsigned char md[SHA_DIGEST_LENGTH]; + if (!EVP_Digest(data, length, md, NULL, EVP_sha1(), NULL)) + return 0; + + ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) | + ((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L)) & + 0xffffffffL; + return ret; +} + +base::FilePath GetCertificateDirPath() { + base::FilePath cert_path; + base::PathService::Get(base::DIR_EXE, &cert_path); + cert_path = cert_path.Append(kSSLDirName).Append(kCertsDirName); + return std::move(cert_path); +} + +std::unordered_set<std::string> GetCertNamesOnDisk() { + auto sb_certs_directory = + SbDirectoryOpen(GetCertificateDirPath().value().c_str(), nullptr); + if (!SbDirectoryIsValid(sb_certs_directory)) { +// Unit tests, for example, do not use production certificates. +#if defined(STARBOARD_BUILD_TYPE_QA) || defined(STARBOARD_BUILD_TYPE_GOLD) + SB_CHECK(false); +#else + DLOG(WARNING) << "ssl/certs directory is not valid, no root certificates" + " will be loaded"; +#endif + return std::unordered_set<std::string>(); + } + SbDirectoryEntry dir_entry; + std::unordered_set<std::string> trusted_certs_on_disk; + + while (SbDirectoryGetNext(sb_certs_directory, &dir_entry)) { + if (SbStringGetLength(dir_entry.name) != kCertFileNameLength) { + continue; + } + trusted_certs_on_disk.emplace(dir_entry.name); + } + SbDirectoryClose(sb_certs_directory); + return std::move(trusted_certs_on_disk); +} +} // namespace + +scoped_refptr<ParsedCertificate> TrustStoreInMemoryStarboard::TryLoadCert( + const base::StringPiece& cert_name) const { + auto hash = CertNameHash(cert_name.data(), cert_name.length()); + char cert_file_name[256]; + SbStringFormatF(cert_file_name, 256, "%08lx.%d", hash, 0); + + if (trusted_cert_names_on_disk_.find(cert_file_name) == + trusted_cert_names_on_disk_.end()) { + // The requested certificate is not found. + return nullptr; + } + + SbFileError out_error; + char cert_buffer[kCertBufferSize]; + base::FilePath cert_path = GetCertificateDirPath().Append(cert_file_name); + SbFile sb_cert_file = + SbFileOpen(cert_path.value().c_str(), kSbFileOpenOnly | kSbFileRead, + nullptr, &out_error); + // The file was in certs directory when we iterated the directory at startup, + // opening it should not fail. + if (!SbFileIsValid(sb_cert_file)) { + NOTREACHED() << "ssl/certs/" << cert_path << " failed to open."; + return nullptr; + } + int cert_size = SbFileReadAll(sb_cert_file, cert_buffer, kCertBufferSize); + SbFileClose(sb_cert_file); + PEMTokenizer pem_tokenizer(base::StringPiece(cert_buffer, cert_size), + {kCertificateHeader}); + pem_tokenizer.GetNext(); + std::string decoded(pem_tokenizer.data()); + DCHECK(!pem_tokenizer.GetNext()); + bssl::UniquePtr<CRYPTO_BUFFER> crypto_buffer = + X509Certificate::CreateCertBufferFromBytes(decoded.data(), + decoded.length()); + DCHECK(crypto_buffer); + CertErrors errors; + auto parsed = ParsedCertificate::Create( + bssl::UpRef(crypto_buffer.get()), + x509_util::DefaultParseCertificateOptions(), &errors); + CHECK(parsed) << errors.ToDebugString(); + return parsed; +} + +TrustStoreInMemoryStarboard::TrustStoreInMemoryStarboard() + : trusted_cert_names_on_disk_(std::move(GetCertNamesOnDisk())) {} + +TrustStoreInMemoryStarboard::~TrustStoreInMemoryStarboard() = default; + +void TrustStoreInMemoryStarboard::SyncGetIssuersOf( + const ParsedCertificate* cert, + ParsedCertificateList* issuers) { + DCHECK(issuers); + DCHECK(issuers->empty()); + starboard::ScopedLock scoped_lock(load_mutex_); + // Look up the request certificate first in the trust store in memory. + underlying_trust_store_.SyncGetIssuersOf(cert, issuers); + if (issuers->empty()) { + // If the requested certificate is not found, compute certificate hash name + // and see if the certificate is stored on disk. + auto parsed_cert = TryLoadCert(cert->normalized_issuer().AsStringPiece()); + if (parsed_cert.get()) { + issuers->push_back(parsed_cert); + underlying_trust_store_.AddTrustAnchor(parsed_cert); + } + } +} + +void TrustStoreInMemoryStarboard::GetTrust( + const scoped_refptr<ParsedCertificate>& cert, + CertificateTrust* trust) const { + DCHECK(trust); + starboard::ScopedLock scoped_lock(load_mutex_); + // Loop up the request certificate first in the trust store in memory. + underlying_trust_store_.GetTrust(cert, trust); + if (trust->HasUnspecifiedTrust()) { + // If the requested certificate is not found, compute certificate hash name + // and see if the certificate is stored on disk. + auto parsed_cert = TryLoadCert(cert->normalized_subject().AsStringPiece()); + if (parsed_cert.get()) { + *trust = CertificateTrust::ForTrustAnchor(); + const_cast<TrustStoreInMemoryStarboard*>(this) + ->underlying_trust_store_.AddTrustAnchor(parsed_cert); + } + } +} + +} // namespace net
diff --git a/src/net/cert/internal/trust_store_in_memory_starboard.h b/src/net/cert/internal/trust_store_in_memory_starboard.h new file mode 100644 index 0000000..bed671e --- /dev/null +++ b/src/net/cert/internal/trust_store_in_memory_starboard.h
@@ -0,0 +1,68 @@ +// Copyright 2019 The Cobalt Authors. 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. + +#ifndef NET_CERT_INTERNAL_TRUST_STORE_IN_MEMORY_STARBOARD_H_ +#define NET_CERT_INTERNAL_TRUST_STORE_IN_MEMORY_STARBOARD_H_ + +#include <unordered_set> + +#include "base/strings/string_piece.h" +#include "net/cert/internal/trust_store_in_memory.h" +#include "starboard/common/mutex.h" + +namespace net { + +// Wrapper around TrustStoreInMemory to lazily load trusted root certificates. +class NET_EXPORT TrustStoreInMemoryStarboard : public TrustStore { + public: + TrustStoreInMemoryStarboard(); + ~TrustStoreInMemoryStarboard() override; + + // TrustStore implementation: + void SyncGetIssuersOf(const ParsedCertificate* cert, + ParsedCertificateList* issuers) override; + void GetTrust(const scoped_refptr<ParsedCertificate>& cert, + CertificateTrust* trust) const override; + + // Returns true if the trust store contains the given ParsedCertificate + // (matches by DER). + bool Contains(const ParsedCertificate* cert) const { + starboard::ScopedLock scoped_lock(load_mutex_); + return underlying_trust_store_.Contains(cert); + } + + private: + TrustStoreInMemoryStarboard(const TrustStoreInMemoryStarboard&) = delete; + TrustStoreInMemoryStarboard& operator=(const TrustStoreInMemoryStarboard&) = + delete; + + TrustStoreInMemory underlying_trust_store_; + + // Given a certificate's canonical name, try to load this cert from trusted + // certs on disk if it is found. + scoped_refptr<ParsedCertificate> TryLoadCert( + const base::StringPiece& cert_name) const; + + // The memory trust store can be accessed by multiple threads, in Chromium, + // the synchronization issue is solved by initializing trust store at startup + // and passing constant reference to consumers. Cobalt loads certs lazily and + // therefore guards the underlying_trust_store_ with mutex. + starboard::Mutex load_mutex_; + + const std::unordered_set<std::string> trusted_cert_names_on_disk_; +}; + +} // namespace net + +#endif // NET_CERT_INTERNAL_TRUST_STORE_IN_MEMORY_STARBOARD_H_
diff --git a/src/net/dns/host_resolver_impl_unittest.cc b/src/net/dns/host_resolver_impl_unittest.cc index f8afb04..0bdd7b2 100644 --- a/src/net/dns/host_resolver_impl_unittest.cc +++ b/src/net/dns/host_resolver_impl_unittest.cc
@@ -2625,7 +2625,11 @@ // https://crbug.com/115051 is fixed. // Test the retry attempts simulating host resolver proc that takes too long. +#if defined(STARBOARD) +TEST_F(HostResolverImplTest, FLAKY_MultipleAttempts) { +#else TEST_F(HostResolverImplTest, MultipleAttempts) { +#endif // Total number of attempts would be 3 and we want the 3rd attempt to resolve // the host. First and second attempt will be forced to wait until they get // word that a resolution has completed. The 3rd resolution attempt will try @@ -2636,7 +2640,13 @@ // Add a little bit of extra fudge to the delay to allow reasonable // flexibility for time > vs >= etc. We don't need to fail the test if we // retry at t=6001 instead of t=6000. +#if defined(STARBOARD) + // The 1 millisecond delay is not enough on some of Cobalt's Linux platforms + // to ensure all delayed tasks are executed. + base::TimeDelta kSleepFudgeFactor = base::TimeDelta::FromMilliseconds(30); +#else base::TimeDelta kSleepFudgeFactor = base::TimeDelta::FromMilliseconds(1); +#endif scoped_refptr<LookupAttemptHostResolverProc> resolver_proc( new LookupAttemptHostResolverProc(
diff --git a/src/net/net.gyp b/src/net/net.gyp index e87dbc9..f9d74c7 100644 --- a/src/net/net.gyp +++ b/src/net/net.gyp
@@ -183,6 +183,8 @@ 'cert/internal/trust_store_collection.h', 'cert/internal/trust_store_in_memory.cc', 'cert/internal/trust_store_in_memory.h', + 'cert/internal/trust_store_in_memory_starboard.cc', + 'cert/internal/trust_store_in_memory_starboard.h', 'cert/internal/verify_certificate_chain.cc', 'cert/internal/verify_certificate_chain.h', 'cert/internal/verify_name_match.cc', @@ -431,10 +433,8 @@ 'cert/cert_verify_proc.h', # TODO[johnx]: Investigate why net deprecated openssl verifier and # if justified switch back to builtin verifier. - # 'cert/cert_verify_proc_builtin.cc', - # 'cert/cert_verify_proc_builtin.h', - 'cert/cert_verify_proc_openssl.cc', - 'cert/cert_verify_proc_openssl.h', + 'cert/cert_verify_proc_builtin.cc', + 'cert/cert_verify_proc_builtin.h', 'cert/ct_log_response_parser.cc', 'cert/ct_log_response_parser.h', 'cert/ct_log_verifier.cc',
diff --git a/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/AudioTrackBridge.java b/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/AudioTrackBridge.java index 494f57b..733cf2b 100644 --- a/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/AudioTrackBridge.java +++ b/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/AudioTrackBridge.java
@@ -35,6 +35,23 @@ private AudioTimestamp audioTimestamp = new AudioTimestamp(); private long maxFramePositionSoFar = 0; + private int GetFrameSize(int sampleType, int channelCount) { + switch (sampleType) { + case AudioFormat.ENCODING_PCM_16BIT: + { + return 2 * channelCount; + } + case AudioFormat.ENCODING_PCM_FLOAT: + { + return 4 * channelCount; + } + default: + { + throw new RuntimeException("Unsupported sample type: " + sampleType); + } + } + } + public AudioTrackBridge(int sampleType, int sampleRate, int channelCount, int framesPerChannel) { int channelConfig; switch (channelCount) { @@ -63,13 +80,12 @@ .setChannelMask(channelConfig) .build(); - int minBufferSizeBytes = AudioTrack.getMinBufferSize(sampleRate, channelConfig, sampleType); - int audioTrackBufferSize = minBufferSizeBytes; - // Use framesPerChannel to determine the buffer size. To use a large buffer on a small - // framesPerChannel may lead to audio playback not able to start. - while (audioTrackBufferSize < framesPerChannel) { - audioTrackBufferSize *= 2; - } + // Try to create AudioTrack with the same size buffer as in renderer. But AudioTrack would not + // start playing until the buffer is fully filled once. A large buffer may cause + // AudioTrack not able to start. And we now pass no more than 1s of audio data to + // starboard player, limit the buffer size to store at most 0.5s of audio data. + int audioTrackBufferSize = + Math.min(framesPerChannel, sampleRate / 2) * GetFrameSize(sampleType, channelCount); while (audioTrackBufferSize > 0) { try { if (Build.VERSION.SDK_INT >= 26) { @@ -105,7 +121,8 @@ TAG, String.format( "AudioTrack created with buffer size %d. The minimum buffer size is %d.", - audioTrackBufferSize, minBufferSizeBytes)); + audioTrackBufferSize, + AudioTrack.getMinBufferSize(sampleRate, channelConfig, sampleType))); } public Boolean isAudioTrackValid() {
diff --git a/src/starboard/android/apk/build.id b/src/starboard/android/apk/build.id new file mode 100644 index 0000000..80c1e89 --- /dev/null +++ b/src/starboard/android/apk/build.id
@@ -0,0 +1 @@ +217501 \ No newline at end of file
diff --git a/src/starboard/android/shared/audio_track_audio_sink_type.cc b/src/starboard/android/shared/audio_track_audio_sink_type.cc index a6584f2..24f1c5f 100644 --- a/src/starboard/android/shared/audio_track_audio_sink_type.cc +++ b/src/starboard/android/shared/audio_track_audio_sink_type.cc
@@ -36,6 +36,11 @@ const jint kNoOffset = 0; +const size_t kSilenceFramesPerAppend = 1024; +// 6 (max channels) * 4 (max sample size) * kSilenceFramesPerAppend, the number +// is to ensure we always have at least 1024 frames silence to write. +const uint8_t kSilenceBuffer[24 * kSilenceFramesPerAppend] = {0}; + // Helper function to compute the size of the two valid starboard audio sample // types. size_t GetSampleSize(SbMediaAudioSampleType sample_type) { @@ -99,6 +104,8 @@ static void* ThreadEntryPoint(void* context); void AudioThreadFunc(); + int WriteData(JniEnvExt* env, const void* buffer, int size); + Type* type_; int channels_; int sampling_frequency_hz_; @@ -292,48 +299,26 @@ std::min(expected_written_frames, kMaxFramesPerRequest); if (expected_written_frames == 0) { // It is possible that all the frames in buffer are written to the - // soundcard, but those are not being consumed. + // soundcard, but those are not being consumed. If eos is reached, + // write silence to make sure audio track start working and avoid + // underflow. Android audio track would not start working before + // its buffer is fully filled once. + if (is_eos_reached) { + // Currently AudioDevice and AudioRenderer will write tail silence. + // It should be reached only in tests. + WriteData(env, kSilenceBuffer, kSilenceFramesPerAppend); + } SbThreadSleep(10 * kSbTimeMillisecond); continue; } SB_DCHECK(expected_written_frames > 0); - bool written_fully = false; - - if (sample_type_ == kSbMediaAudioSampleTypeFloat32) { - int expected_written_size = expected_written_frames * channels_; - env->SetFloatArrayRegion( - static_cast<jfloatArray>(j_audio_data_), kNoOffset, - expected_written_size, - static_cast<const float*>(IncrementPointerByBytes( - frame_buffer_, - start_position * channels_ * GetSampleSize(sample_type_)))); - int written = - env->CallIntMethodOrAbort(j_audio_track_bridge_, "write", "([FI)I", - j_audio_data_, expected_written_size); - SB_DCHECK(written >= 0); - SB_DCHECK(written % channels_ == 0); - written_frames_ += written / channels_; - written_fully = (written == expected_written_frames); - } else if (sample_type_ == kSbMediaAudioSampleTypeInt16Deprecated) { - int expected_written_size = - expected_written_frames * channels_ * GetSampleSize(sample_type_); - env->SetByteArrayRegion( - static_cast<jbyteArray>(j_audio_data_), kNoOffset, - expected_written_size, - static_cast<const jbyte*>(IncrementPointerByBytes( - frame_buffer_, - start_position * channels_ * GetSampleSize(sample_type_)))); - int written = - env->CallIntMethodOrAbort(j_audio_track_bridge_, "write", "([BI)I", - j_audio_data_, expected_written_size); - SB_DCHECK(written >= 0); - SB_DCHECK(written % (channels_ * GetSampleSize(sample_type_)) == 0); - written_frames_ += written / (channels_ * GetSampleSize(sample_type_)); - written_fully = (written == expected_written_frames); - } else { - SB_NOTREACHED(); - } - + int written_frames = WriteData( + env, + IncrementPointerByBytes(frame_buffer_, start_position * channels_ * + GetSampleSize(sample_type_)), + expected_written_frames); + written_frames_ += written_frames; + bool written_fully = (written_frames == expected_written_frames); auto unplayed_frames_in_time = written_frames_ * kSbTimeSecond / sampling_frequency_hz_ - (SbTimeGetMonotonicNow() - frames_consumed_at); @@ -346,7 +331,7 @@ SbThreadSleep(40 * kSbTimeMillisecond); } else if (!written_fully) { // Only sleep if the buffer is nearly full and the last write is partial. - SbThreadSleep(1 * kSbTimeMillisecond); + SbThreadSleep(10 * kSbTimeMillisecond); } } @@ -358,6 +343,38 @@ env->CallVoidMethodOrAbort(j_audio_track_bridge_, "flush", "()V"); } +int AudioTrackAudioSink::WriteData(JniEnvExt* env, + const void* buffer, + int expected_written_frames) { + if (sample_type_ == kSbMediaAudioSampleTypeFloat32) { + int expected_written_size = expected_written_frames * channels_; + env->SetFloatArrayRegion(static_cast<jfloatArray>(j_audio_data_), kNoOffset, + expected_written_size, + static_cast<const float*>(buffer)); + int written = + env->CallIntMethodOrAbort(j_audio_track_bridge_, "write", "([FI)I", + j_audio_data_, expected_written_size); + SB_DCHECK(written >= 0); + SB_DCHECK(written % channels_ == 0); + return written / channels_; + } + if (sample_type_ == kSbMediaAudioSampleTypeInt16Deprecated) { + int expected_written_size = + expected_written_frames * channels_ * GetSampleSize(sample_type_); + env->SetByteArrayRegion(static_cast<jbyteArray>(j_audio_data_), kNoOffset, + expected_written_size, + static_cast<const jbyte*>(buffer)); + int written = + env->CallIntMethodOrAbort(j_audio_track_bridge_, "write", "([BI)I", + j_audio_data_, expected_written_size); + SB_DCHECK(written >= 0); + SB_DCHECK(written % (channels_ * GetSampleSize(sample_type_)) == 0); + return written / (channels_ * GetSampleSize(sample_type_)); + } + SB_NOTREACHED(); + return 0; +} + void AudioTrackAudioSink::SetVolume(double volume) { auto* env = JniEnvExt::Get(); jint status = env->CallIntMethodOrAbort(j_audio_track_bridge_, "setVolume",
diff --git a/src/starboard/android/shared/gyp_configuration.py b/src/starboard/android/shared/gyp_configuration.py index e6d28d9..d674f72 100644 --- a/src/starboard/android/shared/gyp_configuration.py +++ b/src/starboard/android/shared/gyp_configuration.py
@@ -298,13 +298,10 @@ 'VideoDecoderTests/VideoDecoderTest.SingleInput/1', 'VideoDecoderTests/VideoDecoderTest.SingleInput/2', 'VideoDecoderTests/VideoDecoderTest.SingleInput/3', - - # On some platforms, and for some decoders (such as AVC), Android - # returns MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER for the test's - # invalid input frame instead of signaling an error, which the test is - # looking for. - 'VideoDecoderTests/VideoDecoderTest.SingleInvalidInput/0', - 'VideoDecoderTests/VideoDecoderTest.SingleInvalidInput/1', + 'VideoDecoderTests/VideoDecoderTest.SingleInvalidInput/*', + 'VideoDecoderTests/VideoDecoderTest' + '.MultipleValidInputsAfterInvalidKeyFrame/*', + 'VideoDecoderTests/VideoDecoderTest.MultipleInvalidInput/*', # Android currently does not support multi-video playback, which # the following tests depend upon.
diff --git a/src/starboard/android/shared/system_get_property.cc b/src/starboard/android/shared/system_get_property.cc index d4e6d84..d4412d4 100644 --- a/src/starboard/android/shared/system_get_property.cc +++ b/src/starboard/android/shared/system_get_property.cc
@@ -93,7 +93,7 @@ switch (property_id) { case kSbSystemPropertyBrandName: - return GetAndroidSystemProperty("ro.product.manufacturer", out_value, + return GetAndroidSystemProperty("ro.product.brand", out_value, value_length, kUnknownValue); case kSbSystemPropertyModelName: return GetAndroidSystemProperty("ro.product.model", out_value, @@ -105,8 +105,11 @@ return GetAndroidSystemProperty("ro.board.platform", out_value, value_length, kUnknownValue); case kSbSystemPropertyModelYear: + return false; case kSbSystemPropertyOriginalDesignManufacturerName: - return false; + return GetAndroidSystemProperty("ro.product.manufacturer", out_value, + value_length, kUnknownValue); + case kSbSystemPropertyFriendlyName: return CopyStringAndTestIfSuccess(out_value, value_length, kFriendlyName);
diff --git a/src/starboard/common/common.gyp b/src/starboard/common/common.gyp index c7cb5f6..4db427b 100644 --- a/src/starboard/common/common.gyp +++ b/src/starboard/common/common.gyp
@@ -29,7 +29,7 @@ 'condition_variable.cc', 'condition_variable.h', 'flat_map.h', - 'locked_ptr.h', + 'locked_ptr.h', 'log.cc', 'log.h', 'memory.cc',
diff --git a/src/starboard/cpu_features.h b/src/starboard/cpu_features.h index 6aed047..166bd74 100644 --- a/src/starboard/cpu_features.h +++ b/src/starboard/cpu_features.h
@@ -31,6 +31,10 @@ #if SB_API_VERSION >= 11 +#ifdef __cplusplus +extern "C" { +#endif + typedef enum SbCPUFeaturesArchitecture { kSbCPUFeaturesArchitectureArm, kSbCPUFeaturesArchitectureArm64, @@ -263,9 +267,12 @@ // under the key "model name" or "Processor". const char* brand; - // Processor cache line size in bytes. Queried from /proc/cpuinfo or + // Processor cache line size in bytes of Level 1 instruction cache and data + // cache. Queried by sysconf(_SC_LEVEL1_ICACHE_LINESIZE) and + // sysconf(_SC_LEVEL1_DCACHE_LINESIZE), or from files /proc/cpuinfo, // /proc/self/auxv, or CPUID with CLFLUSH instruction. - int32_t cache_size; + int32_t icache_line_size; + int32_t dcache_line_size; // Processor has floating-point unit on-chip. bool has_fpu; @@ -314,5 +321,9 @@ // all fields in |features| are invalid. SB_EXPORT bool SbCPUFeaturesGet(SbCPUFeatures* features); +#ifdef __cplusplus +} // extern "C" +#endif + #endif // SB_API_VERSION >= 11 #endif // STARBOARD_CPU_FEATURES_H_
diff --git a/src/starboard/elf_loader/dynamic_section.cc b/src/starboard/elf_loader/dynamic_section.cc new file mode 100644 index 0000000..b4d9422 --- /dev/null +++ b/src/starboard/elf_loader/dynamic_section.cc
@@ -0,0 +1,203 @@ +// Copyright 2019 The Cobalt Authors. 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 "starboard/elf_loader/dynamic_section.h" + +#include "starboard/common/log.h" + +namespace starboard { +namespace elf_loader { + +DynamicSection::DynamicSection(Addr base_memory_address, + Dyn* dynamic, + size_t dynamic_count, + Word dynamic_flags) + : base_memory_address_(base_memory_address), + soname_(NULL), + dynamic_(dynamic), + dynamic_count_(dynamic_count), + dynamic_flags_(dynamic_flags), + has_DT_SYMBOLIC_(false), + symbol_table_(NULL), + string_table_(NULL), + preinit_array_(NULL), + preinit_array_count_(0), + init_array_(NULL), + init_array_count_(0), + fini_array_(NULL), + fini_array_count_(0), + init_func_(NULL), + fini_func_(NULL) {} + +bool DynamicSection::InitDynamicSection() { + SB_LOG(INFO) << "Dynamic section count=" << dynamic_count_; + for (int i = 0; i < dynamic_count_; i++) { + Addr dyn_value = dynamic_[i].d_un.d_val; + uintptr_t dyn_addr = base_memory_address_ + dynamic_[i].d_un.d_ptr; + SB_LOG(INFO) << "Dynamic tag=" << dynamic_[i].d_tag; + switch (dynamic_[i].d_tag) { + case DT_DEBUG: + // TODO: implement. + break; + case DT_INIT: + SB_LOG(INFO) << " DT_INIT addr=0x" << std::hex << dyn_addr; + init_func_ = reinterpret_cast<linker_function_t>(dyn_addr); + break; + case DT_FINI: + SB_LOG(INFO) << " DT_FINI addr=0x" << std::hex << dyn_addr; + fini_func_ = reinterpret_cast<linker_function_t>(dyn_addr); + break; + case DT_INIT_ARRAY: + SB_LOG(INFO) << " DT_INIT_ARRAY addr=0x" << std::hex << dyn_addr; + init_array_ = reinterpret_cast<linker_function_t*>(dyn_addr); + break; + case DT_INIT_ARRAYSZ: + init_array_count_ = dyn_value / sizeof(Addr); + SB_LOG(INFO) << " DT_INIT_ARRAYSZ value=0x" << std::hex << dyn_value + << " count=" << std::dec << init_array_count_; + break; + case DT_FINI_ARRAY: + SB_LOG(INFO) << " DT_FINI_ARRAY addr=0x" << std::hex << dyn_addr; + fini_array_ = reinterpret_cast<linker_function_t*>(dyn_addr); + break; + case DT_FINI_ARRAYSZ: + fini_array_count_ = dyn_value / sizeof(Addr); + SB_LOG(INFO) << " DT_FINI_ARRAYSZ value=0x" << std::hex << dyn_value + << " count=" << fini_array_count_; + break; + case DT_PREINIT_ARRAY: + SB_LOG(INFO) << " DT_PREINIT_ARRAY addr=0x" << std::hex << dyn_addr; + preinit_array_ = reinterpret_cast<linker_function_t*>(dyn_addr); + break; + case DT_PREINIT_ARRAYSZ: + preinit_array_count_ = dyn_value / sizeof(Addr); + SB_LOG(INFO) << " DT_PREINIT_ARRAYSZ addr=" << dyn_addr + << " count=" << preinit_array_count_; + break; + case DT_SYMBOLIC: + SB_LOG(INFO) << " DT_SYMBOLIC"; + has_DT_SYMBOLIC_ = true; + break; + case DT_FLAGS: + if (dyn_value & DF_SYMBOLIC) + has_DT_SYMBOLIC_ = true; + break; + case DT_SONAME: + soname_ = string_table_ + dyn_value; + break; + default: + break; + } + } + return true; +} + +bool DynamicSection::InitDynamicSymbols() { + for (int i = 0; i < dynamic_count_; i++) { + Addr dyn_value = dynamic_[i].d_un.d_val; + uintptr_t dyn_addr = base_memory_address_ + dynamic_[i].d_un.d_ptr; + switch (dynamic_[i].d_tag) { + case DT_HASH: + SB_LOG(INFO) << " DT_HASH addr=0x" << std::hex << dyn_addr; + elf_hash_.Init(dyn_addr); + break; + case DT_GNU_HASH: + SB_LOG(INFO) << " DT_GNU_HASH addr=0x" << std::hex << dyn_addr; + gnu_hash_.Init(dyn_addr); + break; + case DT_STRTAB: + SB_LOG(INFO) << " DT_STRTAB addr=0x" << std::hex << dyn_addr; + string_table_ = reinterpret_cast<const char*>(dyn_addr); + break; + case DT_SYMTAB: + SB_LOG(INFO) << " DT_SYMTAB addr=0x" << std::hex << dyn_addr; + symbol_table_ = reinterpret_cast<Sym*>(dyn_addr); + break; + default: + break; + } + } + return true; +} + +const Dyn* DynamicSection::GetDynamicTable() { + return dynamic_; +} + +size_t DynamicSection::GetDynamicTableSize() { + return dynamic_count_; +} + +void DynamicSection::CallConstructors() { + CallFunction(init_func_, "DT_INIT"); + for (size_t n = 0; n < init_array_count_; ++n) + CallFunction(init_array_[n], "DT_INIT_ARRAY"); +} + +void DynamicSection::CallDestructors() { + for (size_t n = fini_array_count_; n > 0; --n) { + CallFunction(fini_array_[n - 1], "DT_FINI_ARRAY"); + } + CallFunction(fini_func_, "DT_FINI"); +} + +void DynamicSection::CallFunction(linker_function_t func, + const char* func_type) { + uintptr_t func_address = reinterpret_cast<uintptr_t>(func); + + // On some platforms the entries in the array can be 0 or -1, + // and should be ignored e.g. Android: + // https://android.googlesource.com/platform/bionic/+/android-4.2_r1/linker/README.TXT + if (func_address != 0 && func_address != uintptr_t(-1)) { + func(); + } +} + +const Sym* DynamicSection::LookupById(size_t symbol_id) const { + // TODO: Calculated the symbol_table size and validation check. + return &symbol_table_[symbol_id]; +} + +bool DynamicSection::IsWeakById(size_t symbol_id) const { + // TODO: Calculated the symbol_table size and validation check. + return ELF_ST_BIND(symbol_table_[symbol_id].st_info) == STB_WEAK; +} + +const char* DynamicSection::LookupNameById(size_t symbol_id) const { + const Sym* sym = LookupById(symbol_id); + // TODO: Confirm that LookupById actually can return NULL. + if (!sym) + return NULL; + return string_table_ + sym->st_name; +} + +const Sym* DynamicSection::LookupByName(const char* symbol_name) const { + const Sym* sym = + gnu_hash_.IsValid() + ? gnu_hash_.LookupByName(symbol_name, symbol_table_, string_table_) + : elf_hash_.LookupByName(symbol_name, symbol_table_, string_table_); + + // Ignore undefined symbols or those that are not global or weak definitions. + if (!sym || sym->st_shndx == SHN_UNDEF) + return NULL; + + uint8_t info = ELF_ST_BIND(sym->st_info); + if (info != STB_GLOBAL && info != STB_WEAK) + return NULL; + + return sym; +} + +} // namespace elf_loader +} // namespace starboard
diff --git a/src/starboard/elf_loader/dynamic_section.h b/src/starboard/elf_loader/dynamic_section.h new file mode 100644 index 0000000..eec44c2 --- /dev/null +++ b/src/starboard/elf_loader/dynamic_section.h
@@ -0,0 +1,106 @@ +// Copyright 2019 The Cobalt Authors. 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. + +#ifndef STARBOARD_ELF_LOADER_DYNAMIC_SECTION_H_ +#define STARBOARD_ELF_LOADER_DYNAMIC_SECTION_H_ + +#include "starboard/elf_loader/elf.h" +#include "starboard/elf_loader/elf_hash_table.h" +#include "starboard/elf_loader/exported_symbols.h" +#include "starboard/elf_loader/gnu_hash_table.h" +#include "starboard/elf_loader/program_table.h" + +namespace starboard { +namespace elf_loader { + +typedef void (*linker_function_t)(); + +// class representing the ELF dynamic +// section with dynamic symbols and a +// string tables. + +// The initialization requires calling: +// 1. InitDynamicSection() +// 2. InitDynamicSymbols() +// +class DynamicSection { + public: + DynamicSection(Addr base_memory_address, + Dyn* dynamic, + size_t dynamic_count, + Word dynamic_flags); + + // Initialize the dynamic section. + bool InitDynamicSection(); + + // Initialize all the dynamic symbol tables. + bool InitDynamicSymbols(); + + // Get pointer to the dynamic table. + const Dyn* GetDynamicTable(); + + // Get the size of the dynamic table + size_t GetDynamicTableSize(); + + // Call all the global constructors. + void CallConstructors(); + + // Call all the global destructors. + void CallDestructors(); + + // Call a function. + void CallFunction(linker_function_t func, const char* func_type); + + // Lookup a symbol using its name. + const Sym* LookupByName(const char* symbol_name) const; + + // Lookup a symbol using its id. + const Sym* LookupById(size_t symbol_id) const; + + // Checks if a symbols is weak. + bool IsWeakById(size_t symbol_id) const; + + // Lookup the name of a symbol by using its id. + const char* LookupNameById(size_t symbol_id) const; + + private: + Addr base_memory_address_; + const char* soname_; + + Dyn* dynamic_; + size_t dynamic_count_; + Word dynamic_flags_; + bool has_DT_SYMBOLIC_; + + Sym* symbol_table_; + const char* string_table_; + ElfHashTable elf_hash_; + GnuHashTable gnu_hash_; + + linker_function_t* preinit_array_; + size_t preinit_array_count_; + linker_function_t* init_array_; + size_t init_array_count_; + linker_function_t* fini_array_; + size_t fini_array_count_; + linker_function_t init_func_; + linker_function_t fini_func_; + + SB_DISALLOW_COPY_AND_ASSIGN(DynamicSection); +}; + +} // namespace elf_loader +} // namespace starboard + +#endif // STARBOARD_ELF_LOADER_DYNAMIC_SECTION_H_
diff --git a/src/starboard/elf_loader/dynamic_section_test.cc b/src/starboard/elf_loader/dynamic_section_test.cc new file mode 100644 index 0000000..9aa68be --- /dev/null +++ b/src/starboard/elf_loader/dynamic_section_test.cc
@@ -0,0 +1,38 @@ +// Copyright 2019 The Cobalt Authors. 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 "starboard/elf_loader/elf_loader_impl.h" + +#include "starboard/common/scoped_ptr.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace starboard { +namespace elf_loader { + +namespace { + +// TODO: implement +class DynamicSection : public ::testing::Test { + protected: + DynamicSection() {} + ~DynamicSection() {} +}; + +TEST_F(DynamicSection, Initialize) { + EXPECT_TRUE(true); +} + +} // namespace +} // namespace elf_loader +} // namespace starboard
diff --git a/src/starboard/elf_loader/elf.h b/src/starboard/elf_loader/elf.h new file mode 100644 index 0000000..1ecd908 --- /dev/null +++ b/src/starboard/elf_loader/elf.h
@@ -0,0 +1,651 @@ +// Copyright 2019 The Cobalt Authors. 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. + +#ifndef STARBOARD_ELF_LOADER_ELF_H_ +#define STARBOARD_ELF_LOADER_ELF_H_ + +// Subset of the ELF specification for loading Dynamic Shared Libraries. +// System V Application Binary Interface - DRAFT - 10 June 2013 +// http://www.sco.com/developers/gabi/latest/contents.html + +#ifndef __cplusplus +#error "Only C++ files can include this header." +#endif + +#include "starboard/types.h" + +namespace starboard { +namespace elf_loader { + +// 32 bit data types + +// Unsigned program address - 4 bytes. +typedef uint32_t Elf32_Addr; + +// Unsigned medium integer - 2 bytes. +typedef uint16_t Elf32_Half; + +// Unsigned file offset - 4 bytes. +typedef uint32_t Elf32_Off; + +// Signed large integer - 4 bytes. +typedef int32_t Elf32_Sword; + +// Unsigned large integer - 4 bytes. +typedef uint32_t Elf32_Word; + +// 64 bit data types + +// Unsigned program address - 8 bytes. +typedef uint64_t Elf64_Addr; + +// Unsigned file offset - 8 bytes. +typedef uint64_t Elf64_Off; + +// Unsigned medium intege 2 - bytes. +typedef uint16_t Elf64_Half; + +// Unsigned integer - 4 bytes. +typedef uint32_t Elf64_Word; + +// Signed integer - 4 bytes. +typedef int32_t Elf64_Sword; + +// Unsigned long integer - 8 bytes. +typedef uint64_t Elf64_Xword; + +// Signed long integer - 8 bytes. +typedef int64_t Elf64_Sxword; + +#define EI_NIDENT (16) + +// Pack all the structs at 1 byte alignment. +#pragma pack(push) +#pragma pack(1) + +// 32 bit ELF file header. +typedef struct { + // The initial bytes mark the file as an object file and provide + // machine-independent data. + unsigned char e_ident[EI_NIDENT]; + + // The object file type. We support only ET_DYN. + Elf32_Half e_type; + + // Architecture of the file. + Elf32_Half e_machine; + + // Object file version. The value should be 1. + Elf32_Word e_version; + + // Virtual address to which the system first transfers + // control, thus starting the process. + Elf32_Addr e_entry; + + // Program header table's file offset in bytes. + Elf32_Off e_phoff; + + // Section header table's file offset in bytes. + Elf32_Off e_shoff; + + // Processor-specific flags associated with the file. + Elf32_Word e_flags; + + // ELF header's size in bytes. + Elf32_Half e_ehsize; + + // Size in bytes of one entry in the file's program header table + Elf32_Half e_phentsize; + + // The number of entries in the program header table. + Elf32_Half e_phnum; + + // Section header's size in bytes. + Elf32_Half e_shentsize; + + // The number of entries in the section header table. + Elf32_Half e_shnum; + + // The section header table index of the entry associated + // with the section name string table. + Elf32_Half e_shstrndx; +} Elf32_Ehdr; + +// 64 bit ELF file header. +typedef struct { + // The initial bytes mark the file as an object file and provide + // machine-independent data. + unsigned char e_ident[EI_NIDENT]; + + // The object file type. We support only ET_DYN. + Elf64_Half e_type; + + // Architecture of the file. + Elf64_Half e_machine; + + // Object file version. The value should be 1. + Elf64_Word e_version; + + // Virtual address to which the system first transfers + // control, thus starting the process. + Elf64_Addr e_entry; + + // Program header table's file offset in bytes. + Elf64_Off e_phoff; + + // Section header table's file offset in bytes. + Elf64_Off e_shoff; + + // Processor-specific flags associated with the file. + Elf64_Word e_flags; + + // This member holds the ELF header's size in bytes. + Elf64_Half e_ehsize; + + // Size in bytes of one entry in the file's program header table + Elf64_Half e_phentsize; + + // The number of entries in the section header table. + Elf64_Half e_phnum; + + // Section header's size in bytes. + Elf64_Half e_shentsize; + + // The number of entries in the section header table. + Elf64_Half e_shnum; + + // The section header table index of the entry associated + // with the section name string table. + Elf64_Half e_shstrndx; +} Elf64_Ehdr; + +// 32 bit Program header. +typedef struct { + // The kind of segment this array element describes. + Elf32_Word p_type; + + // The offset from the beginning of the file at which the + // first byte of the segment resides. + Elf32_Off p_offset; + + // The virtual address at which the first byte of the + // segment resides in memory. + Elf32_Addr p_vaddr; + + // Segment's physical address. Unused for shared libraries. + Elf32_Addr p_paddr; + + // The number of bytes in the file image of the segment. May be zero. + Elf32_Word p_filesz; + + // The number of bytes in the memory image of the segment. May be zero. + Elf32_Word p_memsz; + + // Segment flags + Elf32_Word p_flags; + + // Segment alignment constraint. + Elf32_Word p_align; +} Elf32_Phdr; + +// 64 bit Program header. +typedef struct { + // The kind of segment this array element describes. + Elf64_Word p_type; + + // Segment flags + Elf64_Word p_flags; + + // The offset from the beginning of the file at which the + // first byte of the segment resides. + Elf64_Off p_offset; + + // The virtual address at which the first byte of the + // segment resides in memory. + Elf64_Addr p_vaddr; + + // Segment's physical address. Unused for shared libraries. + Elf64_Addr p_paddr; + + // The number of bytes in the file image of the segment. May be zero. + Elf64_Xword p_filesz; + + // The number of bytes in the memory image of the segment. May be zero. + Elf64_Xword p_memsz; + + // Segment alignment constraint + Elf64_Xword p_align; +} Elf64_Phdr; + +// 32 bit Dynamic Section Entry +typedef struct { + // Controls the interpretation of d_un. + Elf32_Sword d_tag; + union { + // These objects represent integer values with various interpretations. + Elf32_Word d_val; + // These objects represent program virtual addresses. + Elf32_Addr d_ptr; + } d_un; +} Elf32_Dyn; + +// 64 bit Dynamic Section Entry +typedef struct { + // Controls the interpretation of d_un. + Elf64_Sxword d_tag; + union { + // These objects represent integer values with various interpretations. + Elf64_Xword d_val; + // These objects represent program virtual addresses. + Elf64_Addr d_ptr; + } d_un; +} Elf64_Dyn; + +// 32 bit Symbol Table Entry +typedef struct { + // An index into the object file's symbol string table, + // which holds the character representations of the symbol names. If the value + // is non-zero, it represents a string table index that gives the symbol name. + // Otherwise, the symbol table entry has no name. + Elf32_Word st_name; + + // The value of the associated symbol. Depending on the + // context, this may be an absolute value, an address, and so on; + Elf32_Addr st_value; + + // Many symbols have associated sizes. For example, a data object's size is + // the number of bytes contained in the object. + Elf32_Word st_size; + + // The symbol's type and binding attributes. + unsigned char st_info; + + // Symbol's visibility. + unsigned char st_other; + + // Every symbol table entry is defined in relation to some section. This + // member holds the relevant section header table index. + Elf32_Half st_shndx; +} Elf32_Sym; + +// 64 bit Symbol Table Entry +typedef struct { + // An index into the object file's symbol string table, + // which holds the character representations of the symbol names. If the value + // is non-zero, it represents a string table index that gives the symbol name. + // Otherwise, the symbol table entry has no name. + Elf64_Word st_name; + + // The symbol's type and binding attributes. + unsigned char st_info; + + // Symbol's visibility. + unsigned char st_other; + + // Every symbol table entry is defined in relation to some section. This + // member holds the relevant section header table index. + Elf64_Half st_shndx; + + // The value of the associated symbol. Depending on the + // context, this may be an absolute value, an address, and so on; + Elf64_Addr st_value; + + // Many symbols have associated sizes. For example, a data object's size is + // the number of bytes contained in the object. + Elf64_Xword st_size; +} Elf64_Sym; + +// 32 bit Relocation Entry +typedef struct { + // The location at which to apply the relocation action. For a relocatable + // file, the value is the byte offset from the beginning of the section to + // the storage unit affected by the relocation. For an executable file or a + // shared object, the value is the virtual address of the storage unit + // affected by the relocation. + Elf32_Addr r_offset; + // The symbol table index with respect to which the + // relocation must be made, and the type of relocation to apply. + Elf32_Word r_info; +} Elf32_Rel; + +// 64 bit Relocation Entry +typedef struct { + // The location at which to apply the relocation action. For + // a relocatable file, the value is the byte offset from the beginning of the + // section to the storage unit affected by the relocation. For an executable + // file or a shared object, the value is the virtual address of the storage + // unit affected by the relocation. + Elf64_Addr r_offset; + + // The symbol table index with respect to which the + // relocation must be made, and the type of relocation to apply. + Elf64_Xword r_info; +} Elf64_Rel; + +// 32 bit Relocation Entry with Addend. +typedef struct { + // The location at which to apply the relocation action. For + // a relocatable file, the value is the byte offset from the beginning of the + // section to the storage unit affected by the relocation. For an executable + // file or a shared object, the value is the virtual address of the storage + // unit affected by the relocation. + Elf32_Addr r_offset; + + // The symbol table index with respect to which the + // relocation must be made, and the type of relocation to apply. + Elf32_Word r_info; + + // A constant addend used to compute the value to be stored into the + // relocatable field. + Elf32_Sword r_addend; +} Elf32_Rela; + +// 64 bit Relocation Entry with Addend. +typedef struct { + // The location at which to apply the relocation action. For a relocatable + // file, the value is the byte offset from the beginning of the section to the + // storage unit affected by the relocation. For an executable file or a shared + // object, the value is the virtual address of the storage unit affected by + // the relocation. + Elf64_Addr r_offset; + + // The symbol table index with respect to which the + // relocation must be made, and the type of relocation to apply. + Elf64_Xword r_info; + + // A constant addend used to compute the value to be stored into the + // relocatable field. + Elf64_Sxword r_addend; +} Elf64_Rela; + +#pragma pack(pop) + +#define EI_CLASS 4 +#define ELFCLASS32 1 +#define ELFCLASS64 2 +#define EI_DATA 5 +#define ELFDATA2LSB 1 +#define ET_DYN 3 +#define EV_CURRENT 1 + +#if SB_HAS(32_BIT_POINTERS) +typedef Elf32_Ehdr Ehdr; +typedef Elf32_Phdr Phdr; +typedef Elf32_Addr Addr; +typedef Elf32_Dyn Dyn; +typedef Elf32_Word Word; +typedef Elf32_Sym Sym; +typedef Elf32_Rel Rel; +typedef Elf32_Rela Rela; +typedef Elf32_Word Relr; +typedef Elf32_Sword Sword; +#define ELF_BITS 32 +#define ELF_R_TYPE ELF32_R_TYPE +#define ELF_R_SYM ELF32_R_SYM +#define ELF_CLASS_VALUE ELFCLASS32 +#elif SB_HAS(64_BIT_POINTERS) +typedef Elf64_Ehdr Ehdr; +typedef Elf64_Phdr Phdr; +typedef Elf64_Addr Addr; +typedef Elf64_Dyn Dyn; +typedef Elf64_Word Word; +typedef Elf64_Sym Sym; +typedef Elf64_Rel Rel; +typedef Elf64_Rela Rela; +typedef Elf64_Word Relr; +typedef Elf64_Sword Sword; +#define ELF_BITS 64 +#define ELF_R_TYPE ELF64_R_TYPE +#define ELF_R_SYM ELF64_R_SYM +#define ELF_CLASS_VALUE ELFCLASS64 +#else +#error "Unsupported pointer size" +#endif + +#define ELF32_R_SYM(val) ((val) >> 8) +#define ELF32_R_TYPE(val) ((val)&0xff) +#define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type)&0xff)) + +#define ELF64_R_SYM(i) ((i) >> 32) +#define ELF64_R_TYPE(i) ((i)&0xffffffff) +#define ELF64_R_INFO(sym, type) ((((Elf64_Xword)(sym)) << 32) + (type)) + +#define ELFMAG "\177ELF" +#define SELFMAG 4 + +// TODO: Refactor the code to detect it at runtime +// using DT_PLTREL. +#if (SB_IS(ARCH_ARM) || SB_IS(ARCH_X86)) && SB_IS(64_BIT) +#define USE_RELA +#endif + +#if defined(USE_RELA) +typedef Rela rel_t; +#else +typedef Rel rel_t; +#endif + +#if SB_IS(ARCH_ARM) && SB_IS(32_BIT) +#define ELF_MACHINE 40 +#elif SB_IS(ARCH_X86) && SB_IS(32_BIT) +#define ELF_MACHINE 3 +#elif SB_IS(ARCH_X86) && SB_IS(64_BIT) +#define ELF_MACHINE 62 +#elif SB_IS(ARCH_ARM) && SB_IS(64_BIT) +#define ELF_MACHINE 183 +#else +#error "Unsupported target CPU architecture" +#endif + +// Segment types. +typedef enum SegmentTypes { + // Unused segment. + PT_NULL = 0, + + // Loadable segment. + PT_LOAD = 1, + + // Dynamic linking information. + PT_DYNAMIC = 2, + + // Interpreter pathname. + PT_INTERP = 3, + + // Auxiliary information. + PT_NOTE = 4, + + // Reserved. + PT_SHLIB = 5, + + // The program header table itself. + PT_PHDR = 6, + + // The thread-local storage template. + PT_TLS = 7 +} SegmentTypes; + +// Symbol bindings. +typedef enum SymbolBindings { + // Local symbol, not visible outside obj file containing def + STB_LOCAL = 0, + + // Global symbol, visible to all object files being combined + STB_GLOBAL = 1, + + // Weak symbol, like global but lower-precedence + STB_WEAK = 2, + + STB_GNU_UNIQUE = 10, + + // Lowest operating system-specific binding type + STB_LOOS = 10, + + // Highest operating system-specific binding type + STB_HIOS = 12, + + // Lowest processor-specific binding type + STB_LOPROC = 13, + + // Highest processor-specific binding type + STB_HIPROC = 15 +} SymbolBindings; + +#define ELF_ST_BIND(x) ((x) >> 4) +#define ELF32_ST_BIND(x) ELF_ST_BIND(x) +#define ELF64_ST_BIND(x) ELF_ST_BIND(x) + +#define PF_X (1 << 0) +#define PF_W (1 << 1) +#define PF_R (1 << 2) +#define PF_MASKOS 0x0ff00000 +#define PF_MASKPROC 0xf0000000 + +// Dynamic table tags. +typedef enum DynamicTags { + DT_NULL = 0, + DT_NEEDED = 1, + DT_PLTRELSZ = 2, + DT_PLTGOT = 3, + DT_HASH = 4, + DT_STRTAB = 5, + DT_SYMTAB = 6, + DT_RELA = 7, + DT_RELASZ = 8, + DT_RELAENT = 9, + DT_STRSZ = 10, + DT_SYMENT = 11, + DT_INIT = 12, + DT_FINI = 13, + DT_SONAME = 14, + DT_RPATH = 15, + DT_SYMBOLIC = 16, + DT_REL = 17, + DT_RELSZ = 18, + DT_RELENT = 19, + DT_PLTREL = 20, + DT_DEBUG = 21, + DT_TEXTREL = 22, + DT_JMPREL = 23, + DT_BIND_NOW = 24, + DT_INIT_ARRAY = 25, + DT_FINI_ARRAY = 26, + DT_INIT_ARRAYSZ = 27, + DT_FINI_ARRAYSZ = 28, + DT_RUNPATH = 29, + DT_FLAGS = 30, + DT_ENCODING = 32, + DT_PREINIT_ARRAY = 32, + DT_PREINIT_ARRAYSZ = 33, + DT_SYMTAB_SHNDX = 34, + DT_RELRSZ = 35, + DT_RELR = 36, + DT_RELRENT = 37, + DT_LOOS = 0x6000000D, + DT_ANDROID_REL = 0x6000000F, + DT_ANDROID_RELSZ = 0x60000010, + DT_ANDROID_RELA = 0x60000011, + DT_ANDROID_RELASZ = 0x60000012, + DT_HIOS = 0x6ffff000, + DT_ANDROID_RELR = 0x6fffe000, + DT_ANDROID_RELRSZ = 0x6fffe001, + DT_ANDROID_RELRENT = 0x6fffe003, + DT_GNU_HASH = 0x6ffffef5, + DT_LOPROC = 0x70000000, + DT_HIPROC = 0x7fffffff, +} DynamicTags; + +typedef enum DynamicFlags { + // This flag signifies that the object being loaded may make reference to the + DF_ORIGIN = 0x00000001, + + // If this flag is set in a shared object library, the dynamic linker's symbol + // resolution algorithm for references within the library is changed. Instead + // of starting a symbol search with the executable file, the dynamic linker + // starts from the shared object itself. If the shared object fails to supply + // the referenced symbol, the dynamic linker then searches the executable file + // and other shared objects as usual. + DF_SYMBOLIC = 0x00000002, + + // This flag is not set, no relocation entry should cause a modification to a + // non-writable segment, as specified by the segment permissions in the + // program header table. + DF_TEXTREL = 0x00000004, + + // If set in a shared object or executable, this flag instructs the dynamic + // linker to process all relocations for the object containing this entry + // before transferring control to the program. + DF_BIND_NOW = 0x00000008, + + // If set in a shared object or executable, this flag instructs the dynamic + // linker to reject attempts to load this file dynamically. It indicates that + // the shared object or executable contains code using a static thread-local + // storage scheme. Implementations need not support any form of thread-local + // storage. + DF_STATIC_TLS = 0x00000010, +} DynamicFalgs; + +// Relocation types per CPU architecture +#if SB_IS(ARCH_ARM) && SB_IS(32_BIT) +typedef enum RelocationTypes { + R_ARM_ABS32 = 2, + R_ARM_REL32 = 3, + R_ARM_GLOB_DAT = 21, + R_ARM_JUMP_SLOT = 22, + R_ARM_COPY = 20, + R_ARM_RELATIVE = 23, +} RelocationTypes; +#elif SB_IS(ARCH_ARM) && SB_IS(64_BIT) +typedef enum RelocationTypes { + R_AARCH64_ABS64 = 257, + R_AARCH64_COPY = 1024, + R_AARCH64_GLOB_DAT = 1025, + R_AARCH64_JUMP_SLOT = 1026, + R_AARCH64_RELATIVE = 1027, +} RelocationTypes; +#elif SB_IS(ARCH_X86) && SB_IS(32_BIT) +typedef enum RelocationTypes { + R_386_32 = 1, + R_386_PC32 = 2, + R_386_GLOB_DAT = 6, + R_386_JMP_SLOT = 7, + R_386_RELATIVE = 8, +} RelocationTypes; +#elif SB_IS(ARCH_X86) && SB_IS(64_BIT) +typedef enum RelocationTypes { + R_X86_64_64 = 1, + R_X86_64_PC32 = 2, + R_X86_64_GLOB_DAT = 6, + R_X86_64_JMP_SLOT = 7, + R_X86_64_RELATIVE = 8, +} RelocationTypes; +#else +#error "Unsupported architecture for relocations." +#endif + +// Helper macros for memory page computations. +#ifndef PAGE_SIZE +#define PAGE_SHIFT 12 +#define PAGE_SIZE (1UL << PAGE_SHIFT) +#define PAGE_MASK (~(PAGE_SIZE - 1)) +#endif + +#define PAGE_START(x) ((x)&PAGE_MASK) +#define PAGE_OFFSET(x) ((x) & ~PAGE_MASK) +#define PAGE_END(x) PAGE_START((x) + (PAGE_SIZE - 1)) + +#define SHN_UNDEF 0 + +} // namespace elf_loader +} // namespace starboard +#endif // STARBOARD_ELF_LOADER_ELF_H_
diff --git a/src/starboard/elf_loader/elf_hash_table.cc b/src/starboard/elf_loader/elf_hash_table.cc new file mode 100644 index 0000000..b6b6c70 --- /dev/null +++ b/src/starboard/elf_loader/elf_hash_table.cc
@@ -0,0 +1,69 @@ +// Copyright 2019 The Cobalt Authors. 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 "starboard/elf_loader/elf_hash_table.h" +#include "starboard/string.h" + +namespace starboard { +namespace elf_loader { + +// Compute the ELF hash of a given symbol. +// Defined in +// https://refspecs.linuxfoundation.org/elf/gabi4+/ch5.dynamic.html#hash +static unsigned ElfHash(const char* name) { + const uint8_t* ptr = reinterpret_cast<const uint8_t*>(name); + unsigned h = 0; + while (*ptr) { + h = (h << 4) + *ptr++; + unsigned g = h & 0xf0000000; + h ^= g; + h ^= g >> 24; + } + return h; +} + +ElfHashTable::ElfHashTable() + : hash_bucket_(NULL), + hash_bucket_size_(0), + hash_chain_(NULL), + hash_chain_size_(0) {} +void ElfHashTable::Init(uintptr_t dt_elf_hash) { + const Word* data = reinterpret_cast<const Word*>(dt_elf_hash); + hash_bucket_size_ = data[0]; + hash_bucket_ = data + 2; + hash_chain_size_ = data[1]; + hash_chain_ = hash_bucket_ + hash_bucket_size_; +} + +bool ElfHashTable::IsValid() const { + return hash_bucket_size_ > 0; +} + +const Sym* ElfHashTable::LookupByName(const char* symbol_name, + const Sym* symbol_table, + const char* string_table) const { + unsigned hash = ElfHash(symbol_name); + + for (unsigned n = hash_bucket_[hash % hash_bucket_size_]; n != 0; + n = hash_chain_[n]) { + const Sym* symbol = &symbol_table[n]; + // Check that the symbol has the appropriate name. + if (!SbStringCompareAll(string_table + symbol->st_name, symbol_name)) + return symbol; + } + return NULL; +} + +} // namespace elf_loader +} // namespace starboard
diff --git a/src/starboard/elf_loader/elf_hash_table.h b/src/starboard/elf_loader/elf_hash_table.h new file mode 100644 index 0000000..14bb9ca --- /dev/null +++ b/src/starboard/elf_loader/elf_hash_table.h
@@ -0,0 +1,62 @@ +// Copyright 2019 The Cobalt Authors. 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. + +#ifndef STARBOARD_ELF_LOADER_ELF_HASH_TABLE_H_ +#define STARBOARD_ELF_LOADER_ELF_HASH_TABLE_H_ + +#include <stddef.h> +#include "starboard/elf_loader/elf.h" + +namespace starboard { +namespace elf_loader { + +// Models the hash table used to map symbol names to symbol entries using +// the standard ELF format. +class ElfHashTable { + public: + ElfHashTable(); + // Initialize instance. |dt_elf_hash| should be the address that the + // DT_HASH entry points to in the input ELF dynamic section. Call IsValid() + // to determine whether the table was well-formed. + void Init(uintptr_t dt_elf_hash); + + // Returns true iff the content of the table is valid. + bool IsValid() const; + + // Index of the first dynamic symbol within the ELF symbol table. + size_t dyn_symbols_offset() const { return 1; } + + // Number of dynamic symbols in the ELF symbol table. + size_t dyn_symbols_count() const { return hash_chain_size_ - 1; } + + // Lookup |symbol_name| in the table. |symbol_table| should point to the + // ELF symbol table, and |string_table| to the start of its string table. + // Returns NULL on failure. + const Sym* LookupByName(const char* symbol_name, + const Sym* symbol_table, + const char* string_table) const; + + private: + const Word* hash_bucket_; + size_t hash_bucket_size_; + const Word* hash_chain_; + size_t hash_chain_size_; + + SB_DISALLOW_COPY_AND_ASSIGN(ElfHashTable); +}; + +} // namespace elf_loader +} // namespace starboard + +#endif // STARBOARD_ELF_LOADER_ELF_HASH_TABLE_H_
diff --git a/src/starboard/elf_loader/elf_header.cc b/src/starboard/elf_loader/elf_header.cc new file mode 100644 index 0000000..bb3c07b --- /dev/null +++ b/src/starboard/elf_loader/elf_header.cc
@@ -0,0 +1,75 @@ +// Copyright 2019 The Cobalt Authors. 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 "starboard/elf_loader/elf_header.h" + +#include "starboard/common/log.h" +#include "starboard/memory.h" + +namespace starboard { +namespace elf_loader { + +ElfHeader::ElfHeader() { + elf_header_.reset(new Ehdr()); +} + +bool ElfHeader::LoadElfHeader(File* file) { + SB_LOG(INFO) << "LoadElfHeader"; + if (!file->ReadFromOffset(0, reinterpret_cast<char*>(elf_header_.get()), + sizeof(Ehdr))) { + SB_LOG(ERROR) << "Failed to read file"; + return false; + } + + if (SbMemoryCompare(elf_header_->e_ident, ELFMAG, SELFMAG) != 0) { + SB_LOG(ERROR) << "Bad ELF magic: " << elf_header_->e_ident; + return false; + } + + if (elf_header_->e_ident[EI_CLASS] != ELF_CLASS_VALUE) { + SB_LOG(ERROR) << "Not a " << ELF_BITS + << "-bit class: " << elf_header_->e_ident[EI_CLASS]; + return false; + } + if (elf_header_->e_ident[EI_DATA] != ELFDATA2LSB) { + SB_LOG(ERROR) << "Not little-endian class" << elf_header_->e_ident[EI_DATA]; + return false; + } + + if (elf_header_->e_type != ET_DYN) { + SB_LOG(ERROR) << "Not a shared library type:" << std::hex + << elf_header_->e_type; + return false; + } + + if (elf_header_->e_version != EV_CURRENT) { + SB_LOG(ERROR) << "Unexpected ELF version: " << elf_header_->e_version; + return false; + } + + if (elf_header_->e_machine != ELF_MACHINE) { + SB_LOG(ERROR) << "Unexpected ELF machine type: " << std::hex + << elf_header_->e_machine; + return false; + } + + return true; +} + +const Ehdr* ElfHeader::GetHeader() { + return elf_header_.get(); +} + +} // namespace elf_loader +} // namespace starboard
diff --git a/src/starboard/elf_loader/elf_header.h b/src/starboard/elf_loader/elf_header.h new file mode 100644 index 0000000..a8b666c --- /dev/null +++ b/src/starboard/elf_loader/elf_header.h
@@ -0,0 +1,45 @@ +// Copyright 2019 The Cobalt Authors. 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. + +#ifndef STARBOARD_ELF_LOADER_ELF_HEADER_H_ +#define STARBOARD_ELF_LOADER_ELF_HEADER_H_ + +#include "starboard/elf_loader/elf.h" + +#include "starboard/common/scoped_ptr.h" +#include "starboard/elf_loader/file.h" + +namespace starboard { +namespace elf_loader { + +// Class for loading, parsing and validating the ELF header section. +class ElfHeader { + public: + ElfHeader(); + + // Load, parse and validate the ELF header. + bool LoadElfHeader(File* file); + + // Get the actual header data. + const Ehdr* GetHeader(); + + private: + scoped_ptr<Ehdr> elf_header_; + SB_DISALLOW_COPY_AND_ASSIGN(ElfHeader); +}; + +} // namespace elf_loader +} // namespace starboard + +#endif // STARBOARD_ELF_LOADER_ELF_HEADER_H_
diff --git a/src/starboard/elf_loader/elf_header_test.cc b/src/starboard/elf_loader/elf_header_test.cc new file mode 100644 index 0000000..c129af7 --- /dev/null +++ b/src/starboard/elf_loader/elf_header_test.cc
@@ -0,0 +1,125 @@ +// Copyright 2019 The Cobalt Authors. 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 "starboard/elf_loader/elf_header.h" + +#include "starboard/common/scoped_ptr.h" +#include "starboard/elf_loader/file.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace starboard { +namespace elf_loader { + +namespace { + +class DummyFile : public File { + public: + DummyFile(const char* buffer, int size) : buffer_(buffer), size_(size) {} + + bool Open(const char* name) { return true; } + bool ReadFromOffset(int64_t offset, char* buffer, int size) { + SB_LOG(INFO) << "ReadFromOffset"; + if (offset != 0) { + SB_LOG(ERROR) << "ReadFromOffset: Invalid offset " << offset; + return false; + } + if (size < size_) { + SB_LOG(ERROR) << "ReadFromOffset: Invalid size " << size; + return false; + } + SbMemoryCopy(buffer, buffer_, size); + return true; + } + void Close() {} + + private: + const char* buffer_; + int size_; +}; + +class ElfHeaderTest : public ::testing::Test { + protected: + ElfHeaderTest() { + elf_header_.reset(new ElfHeader()); + SbMemorySet(reinterpret_cast<char*>(&ehdr_data_), 0, sizeof(ehdr_data_)); + ehdr_data_.e_machine = ELF_MACHINE; + ehdr_data_.e_ident[0] = 0x7F; + ehdr_data_.e_ident[1] = 'E'; + ehdr_data_.e_ident[2] = 'L'; + ehdr_data_.e_ident[3] = 'F'; + ehdr_data_.e_ident[EI_CLASS] = ELF_CLASS_VALUE; + ehdr_data_.e_ident[EI_DATA] = ELFDATA2LSB; + ehdr_data_.e_type = ET_DYN; + ehdr_data_.e_version = EV_CURRENT; + ehdr_data_.e_machine = ELF_MACHINE; + + dummy_file_.reset(new DummyFile(reinterpret_cast<const char*>(&ehdr_data_), + sizeof(ehdr_data_))); + } + ~ElfHeaderTest() {} + + scoped_ptr<ElfHeader> elf_header_; + Ehdr ehdr_data_; + scoped_ptr<DummyFile> dummy_file_; +}; + +TEST_F(ElfHeaderTest, Initialize) { + EXPECT_TRUE(elf_header_->LoadElfHeader(dummy_file_.get())); +} + +TEST_F(ElfHeaderTest, NegativeBadImage) { + ehdr_data_.e_ident[1] = 'F'; + dummy_file_.reset(new DummyFile(reinterpret_cast<const char*>(&ehdr_data_), + sizeof(ehdr_data_))); + EXPECT_FALSE(elf_header_->LoadElfHeader(dummy_file_.get())); +} + +TEST_F(ElfHeaderTest, NegativeBadClass) { + ehdr_data_.e_ident[EI_CLASS] = 0; + dummy_file_.reset(new DummyFile(reinterpret_cast<const char*>(&ehdr_data_), + sizeof(ehdr_data_))); + EXPECT_FALSE(elf_header_->LoadElfHeader(dummy_file_.get())); +} + +TEST_F(ElfHeaderTest, NegativeWrongGulliverLilliput) { + ehdr_data_.e_type = 2; + dummy_file_.reset(new DummyFile(reinterpret_cast<const char*>(&ehdr_data_), + sizeof(ehdr_data_))); + EXPECT_FALSE(elf_header_->LoadElfHeader(dummy_file_.get())); +} + +TEST_F(ElfHeaderTest, NegativeBadType) { + ehdr_data_.e_type = 2; + dummy_file_.reset(new DummyFile(reinterpret_cast<const char*>(&ehdr_data_), + sizeof(ehdr_data_))); + EXPECT_FALSE(elf_header_->LoadElfHeader(dummy_file_.get())); +} + +TEST_F(ElfHeaderTest, NegativeBadVersion) { + ehdr_data_.e_version = 2; + dummy_file_.reset(new DummyFile(reinterpret_cast<const char*>(&ehdr_data_), + sizeof(ehdr_data_))); + EXPECT_FALSE(elf_header_->LoadElfHeader(dummy_file_.get())); +} + +TEST_F(ElfHeaderTest, NegativeBadMachine) { + ehdr_data_.e_machine = 0; + dummy_file_.reset(new DummyFile(reinterpret_cast<const char*>(&ehdr_data_), + sizeof(ehdr_data_))); + EXPECT_FALSE(elf_header_->LoadElfHeader(dummy_file_.get())); +} +} // namespace +} // namespace elf_loader +} // namespace starboard
diff --git a/src/starboard/elf_loader/elf_loader.cc b/src/starboard/elf_loader/elf_loader.cc new file mode 100644 index 0000000..d62d07a --- /dev/null +++ b/src/starboard/elf_loader/elf_loader.cc
@@ -0,0 +1,38 @@ +// Copyright 2019 The Cobalt Authors. 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 "starboard/elf_loader/elf_loader.h" +#include "starboard/common/log.h" +#include "starboard/elf_loader/elf_loader_impl.h" +#include "starboard/elf_loader/file_impl.h" + +namespace starboard { +namespace elf_loader { + +ElfLoader::~ElfLoader() {} + +bool ElfLoader::Load(const char* file_name) { + return impl_->Load(file_name); +} + +void* ElfLoader::LookupSymbol(const char* symbol) { + return impl_->LookupSymbol(symbol); +} + +ElfLoader::ElfLoader() { + impl_.reset(new ElfLoaderImpl()); +} + +} // namespace elf_loader +} // namespace starboard
diff --git a/src/starboard/elf_loader/elf_loader.gyp b/src/starboard/elf_loader/elf_loader.gyp new file mode 100644 index 0000000..7860e03 --- /dev/null +++ b/src/starboard/elf_loader/elf_loader.gyp
@@ -0,0 +1,84 @@ +# Copyright 2019 The Cobalt Authors. 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. + +{ + 'targets': [ + { + 'target_name': 'elf_loader', + 'type': 'static_library', + 'include_dirs': [ + 'src/include', + 'src/src/', + ], + 'dependencies': [ + '<(DEPTH)/starboard/starboard.gyp:starboard', + ], + 'sources': [ + 'elf_header.h', + 'elf_header.cc', + 'elf_hash_table.h', + 'elf_hash_table.cc', + 'elf_loader.h', + 'elf_loader.cc', + 'elf_loader_impl.h', + 'elf_loader_impl.cc', + 'exported_symbols.cc', + 'file.h', + 'file_impl.h', + 'file_impl.cc', + 'gnu_hash_table.h', + 'gnu_hash_table.cc', + 'dynamic_section.h', + 'dynamic_section.cc', + 'program_table.h', + 'program_table.cc', + 'relocations.h', + 'relocations.cc', + ], + }, + { + 'target_name': 'elf_loader_sandbox', + 'type': '<(final_executable_type)', + 'include_dirs': [ + 'src/include', + 'src/src/', + ], + 'dependencies': [ + 'elf_loader', + '<(DEPTH)/starboard/starboard.gyp:starboard_full', + ], + 'sources': [ + 'sandbox.cc', + ], + }, + { + 'target_name': 'elf_loader_test', + 'type': '<(gtest_target_type)', + 'sources': [ + '<(DEPTH)/starboard/common/test_main.cc', + 'elf_loader_test.cc', + 'elf_header_test.cc', + 'dynamic_section_test.cc', + 'program_table_test.cc', + 'relocations_test.cc', + ], + 'dependencies': [ + 'elf_loader', + '<(DEPTH)/starboard/starboard.gyp:starboard_full', + '<(DEPTH)/testing/gmock.gyp:gmock', + '<(DEPTH)/testing/gtest.gyp:gtest', + ], + }, + ] +}
diff --git a/src/starboard/elf_loader/elf_loader.h b/src/starboard/elf_loader/elf_loader.h new file mode 100644 index 0000000..7bda25d --- /dev/null +++ b/src/starboard/elf_loader/elf_loader.h
@@ -0,0 +1,47 @@ +// Copyright 2019 The Cobalt Authors. 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. + +#ifndef STARBOARD_ELF_LOADER_ELF_LOADER_H_ +#define STARBOARD_ELF_LOADER_ELF_LOADER_H_ + +#include "starboard/common/scoped_ptr.h" + +namespace starboard { +namespace elf_loader { + +class ElfLoaderImpl; + +// A loader for ELF dynamic shared library. +class ElfLoader { + public: + ElfLoader(); + + // Loads the shared library + bool Load(const char* file_name); + + // Looks up the symbol address in the + // shared library. + void* LookupSymbol(const char* symbol); + + ~ElfLoader(); + + private: + scoped_ptr<ElfLoaderImpl> impl_; + + SB_DISALLOW_COPY_AND_ASSIGN(ElfLoader); +}; + +} // namespace elf_loader +} // namespace starboard +#endif // STARBOARD_ELF_LOADER_ELF_LOADER_H_
diff --git a/src/starboard/elf_loader/elf_loader_impl.cc b/src/starboard/elf_loader/elf_loader_impl.cc new file mode 100644 index 0000000..f81db05 --- /dev/null +++ b/src/starboard/elf_loader/elf_loader_impl.cc
@@ -0,0 +1,136 @@ +// Copyright 2019 The Cobalt Authors. 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 "starboard/elf_loader/elf_loader_impl.h" +#include "starboard/common/log.h" +#include "starboard/elf_loader/elf.h" +#include "starboard/elf_loader/file_impl.h" +#include "starboard/memory.h" +#include "starboard/string.h" + +namespace starboard { +namespace elf_loader { + +ElfLoaderImpl::ElfLoaderImpl() {} + +bool ElfLoaderImpl::Load(const char* name) { + SB_LOG(INFO) << "Loading: " << name; + elf_file_.reset(new FileImpl()); + elf_file_->Open(name); + + elf_header_loader_.reset(new ElfHeader()); + if (!elf_header_loader_->LoadElfHeader(elf_file_.get())) { + SB_LOG(ERROR) << "Failed to loaded ELF header"; + return false; + } + + SB_LOG(INFO) << "Loaded ELF header"; + + program_table_.reset(new ProgramTable()); + program_table_->LoadProgramHeader(elf_header_loader_->GetHeader(), + elf_file_.get()); + + SB_LOG(INFO) << "Loaded Program header"; + + if (!program_table_->ReserveLoadMemory()) { + SB_LOG(ERROR) << "Failed to reserve memory space"; + return false; + } + + SB_LOG(INFO) << "Reserved address space"; + + if (!program_table_->LoadSegments(elf_file_.get())) { + SB_LOG(ERROR) << "Failed to load segments"; + return false; + } + SB_LOG(INFO) << "Loaded segments"; + + Dyn* dynamic = NULL; + size_t dynamic_count = 0; + Word dynamic_flags = 0; + program_table_->GetDynamicSection(&dynamic, &dynamic_count, &dynamic_flags); + if (!dynamic) { + SB_LOG(ERROR) << "No PT_DYNAMIC section!"; + return false; + } + dynamic_section_.reset( + new DynamicSection(program_table_->GetBaseMemoryAddress(), dynamic, + dynamic_count, dynamic_flags)); + if (!dynamic_section_->InitDynamicSection()) { + SB_LOG(ERROR) << "Failed to initialize dynamic section"; + return false; + } + SB_LOG(INFO) << "Initialized dynamic section"; + if (!dynamic_section_->InitDynamicSymbols()) { + SB_LOG(ERROR) << "Failed to load dynamic symbols"; + return false; + } + SB_LOG(INFO) << "Initialized dynamic symbols"; + + exported_symbols_.reset(new ExportedSymbols()); + relocations_.reset(new Relocations(program_table_->GetBaseMemoryAddress(), + dynamic_section_.get(), + exported_symbols_.get())); + if (!relocations_->InitRelocations()) { + SB_LOG(ERROR) << "Failed to initialize relocations"; + return false; + } + if (relocations_->HasTextRelocations()) { + SB_LOG(INFO) << "HasTextRelocations"; + // Adjust the memory protection to its to allow modifications. + if (program_table_->AdjustMemoryProtectionOfReadOnlySegments( + kSbMemoryMapProtectWrite) < 0) { + SB_LOG(ERROR) << "Unable to make segments writable"; + return false; + } + } + SB_LOG(INFO) << "Loaded relocations"; + if (!relocations_->ApplyAllRelocations()) { + SB_LOG(ERROR) << "Failed to apply relocations"; + return false; + } + + if (relocations_->HasTextRelocations()) { + // Restores the memory protection to its original state. + if (program_table_->AdjustMemoryProtectionOfReadOnlySegments( + kSbMemoryMapProtectReserved) < 0) { + SB_LOG(ERROR) << "Unable to restore segment protection"; + return false; + } + } + + SB_LOG(INFO) << "Applied relocations"; + + SB_LOG(INFO) << "Call constructors"; + dynamic_section_->CallConstructors(); + + SB_LOG(INFO) << "Finished loading"; + + return true; +} +void* ElfLoaderImpl::LookupSymbol(const char* symbol) { + const Sym* sym = dynamic_section_->LookupByName(symbol); + void* address = NULL; + if (sym) { + address = reinterpret_cast<void*>(program_table_->GetBaseMemoryAddress() + + sym->st_value); + } + return address; +} + +ElfLoaderImpl::~ElfLoaderImpl() { + dynamic_section_->CallDestructors(); +} +} // namespace elf_loader +} // namespace starboard
diff --git a/src/starboard/elf_loader/elf_loader_impl.h b/src/starboard/elf_loader/elf_loader_impl.h new file mode 100644 index 0000000..b317ecf --- /dev/null +++ b/src/starboard/elf_loader/elf_loader_impl.h
@@ -0,0 +1,53 @@ +// Copyright 2019 The Cobalt Authors. 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. + +#ifndef STARBOARD_ELF_LOADER_ELF_LOADER_IMPL_H_ +#define STARBOARD_ELF_LOADER_ELF_LOADER_IMPL_H_ + +#include "starboard/common/scoped_ptr.h" +#include "starboard/elf_loader/dynamic_section.h" +#include "starboard/elf_loader/elf.h" +#include "starboard/elf_loader/elf_hash_table.h" +#include "starboard/elf_loader/elf_header.h" +#include "starboard/elf_loader/exported_symbols.h" +#include "starboard/elf_loader/file.h" +#include "starboard/elf_loader/gnu_hash_table.h" +#include "starboard/elf_loader/program_table.h" +#include "starboard/elf_loader/relocations.h" + +namespace starboard { +namespace elf_loader { + +// Implementation of the elf loader. +class ElfLoaderImpl { + public: + ElfLoaderImpl(); + bool Load(const char* file_name); + void* LookupSymbol(const char* symbol); + ~ElfLoaderImpl(); + + private: + scoped_ptr<File> elf_file_; + scoped_ptr<ElfHeader> elf_header_loader_; + scoped_ptr<ProgramTable> program_table_; + scoped_ptr<DynamicSection> dynamic_section_; + scoped_ptr<ExportedSymbols> exported_symbols_; + scoped_ptr<Relocations> relocations_; + + SB_DISALLOW_COPY_AND_ASSIGN(ElfLoaderImpl); +}; + +} // namespace elf_loader +} // namespace starboard +#endif // STARBOARD_ELF_LOADER_ELF_LOADER_IMPL_H_
diff --git a/src/starboard/elf_loader/elf_loader_test.cc b/src/starboard/elf_loader/elf_loader_test.cc new file mode 100644 index 0000000..d3351f3 --- /dev/null +++ b/src/starboard/elf_loader/elf_loader_test.cc
@@ -0,0 +1,38 @@ +// Copyright 2019 The Cobalt Authors. 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 "starboard/elf_loader/elf_loader_impl.h" + +#include "starboard/common/scoped_ptr.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace starboard { +namespace elf_loader { + +namespace { + +// TODO: implement using real shared library fro the file system. +class ElfLoaderTest : public ::testing::Test { + protected: + ElfLoaderTest() {} + ~ElfLoaderTest() {} +}; + +TEST_F(ElfLoaderTest, Initialize) { + EXPECT_TRUE(true); +} + +} // namespace +} // namespace elf_loader +} // namespace starboard
diff --git a/src/starboard/elf_loader/exported_symbols.cc b/src/starboard/elf_loader/exported_symbols.cc new file mode 100644 index 0000000..a4c4539 --- /dev/null +++ b/src/starboard/elf_loader/exported_symbols.cc
@@ -0,0 +1,512 @@ +// Copyright 2019 The Cobalt Authors. 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 "starboard/elf_loader/exported_symbols.h" + +// TODO: Remove these once the API leaks are fixed. +//#define LOCAL_TEST_WITH_API_LEAKS +#ifdef LOCAL_TEST_WITH_API_LEAKS +#include <dlfcn.h> +#include <fcntl.h> +#include <nl_types.h> +#include <setjmp.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> +#endif + +#include "starboard/accessibility.h" +#include "starboard/audio_sink.h" +#include "starboard/byte_swap.h" +#include "starboard/character.h" +#include "starboard/condition_variable.h" +#include "starboard/cpu_features.h" +#include "starboard/decode_target.h" +#include "starboard/directory.h" +#include "starboard/double.h" +#include "starboard/egl.h" +#include "starboard/event.h" +#include "starboard/file.h" +#include "starboard/gles.h" +#include "starboard/image.h" +#include "starboard/log.h" +#include "starboard/memory.h" +#include "starboard/microphone.h" +#include "starboard/mutex.h" +#include "starboard/once.h" +#include "starboard/player.h" +#include "starboard/socket.h" +#include "starboard/socket_waiter.h" +#include "starboard/speech_recognizer.h" +#include "starboard/speech_synthesis.h" +#include "starboard/storage.h" +#include "starboard/string.h" +#include "starboard/system.h" +#include "starboard/thread.h" +#include "starboard/time_zone.h" +#include "starboard/ui_navigation.h" + +// TODO: cleanup these hack as we fix the API leaks + +void tmp_dl_iterate_phdr() { + SB_LOG(INFO) << "tmp_dl_iterate_phdr"; +} + +void tmp__cxa_thread_atexit_impl() { + SB_LOG(INFO) << "tmp__cxa_thread_atexit_impl"; +} + +namespace starboard { +namespace elf_loader { + +ExportedSymbols::ExportedSymbols() { + map_["SbAccessibilityGetDisplaySettings"] = + reinterpret_cast<const void*>(SbAccessibilityGetDisplaySettings); + map_["SbAccessibilityGetTextToSpeechSettings"] = + reinterpret_cast<const void*>(SbAccessibilityGetTextToSpeechSettings); + map_["SbAudioSinkCreate"] = reinterpret_cast<const void*>(SbAudioSinkCreate); + map_["SbAudioSinkDestroy"] = + reinterpret_cast<const void*>(SbAudioSinkDestroy); + map_["SbAudioSinkGetNearestSupportedSampleFrequency"] = + reinterpret_cast<const void*>( + SbAudioSinkGetNearestSupportedSampleFrequency); + map_["SbAudioSinkIsAudioFrameStorageTypeSupported"] = + reinterpret_cast<const void*>( + SbAudioSinkIsAudioFrameStorageTypeSupported); + map_["SbAudioSinkIsAudioSampleTypeSupported"] = + reinterpret_cast<const void*>(SbAudioSinkIsAudioSampleTypeSupported); + map_["SbAudioSinkIsValid"] = + reinterpret_cast<const void*>(SbAudioSinkIsValid); + map_["SbByteSwapU16"] = reinterpret_cast<const void*>(SbByteSwapU16); + map_["SbByteSwapU32"] = reinterpret_cast<const void*>(SbByteSwapU32); + map_["SbByteSwapU64"] = reinterpret_cast<const void*>(SbByteSwapU64); + map_["SbCharacterIsDigit"] = + reinterpret_cast<const void*>(SbCharacterIsDigit); + map_["SbCharacterIsHexDigit"] = + reinterpret_cast<const void*>(SbCharacterIsHexDigit); + map_["SbCharacterIsSpace"] = + reinterpret_cast<const void*>(SbCharacterIsSpace); + map_["SbCharacterToLower"] = + reinterpret_cast<const void*>(SbCharacterToLower); + map_["SbCharacterToUpper"] = + reinterpret_cast<const void*>(SbCharacterToUpper); + map_["SbConditionVariableBroadcast"] = + reinterpret_cast<const void*>(SbConditionVariableBroadcast); + map_["SbConditionVariableCreate"] = + reinterpret_cast<const void*>(SbConditionVariableCreate); + map_["SbConditionVariableDestroy"] = + reinterpret_cast<const void*>(SbConditionVariableDestroy); + map_["SbConditionVariableSignal"] = + reinterpret_cast<const void*>(SbConditionVariableSignal); + map_["SbConditionVariableWait"] = + reinterpret_cast<const void*>(SbConditionVariableWait); + map_["SbConditionVariableWaitTimed"] = + reinterpret_cast<const void*>(SbConditionVariableWaitTimed); + map_["SbCPUFeaturesGet"] = reinterpret_cast<const void*>(SbCPUFeaturesGet); + map_["SbDecodeTargetGetInfo"] = + reinterpret_cast<const void*>(SbDecodeTargetGetInfo); + map_["SbDecodeTargetRelease"] = + reinterpret_cast<const void*>(SbDecodeTargetRelease); + map_["SbDirectoryCanOpen"] = + reinterpret_cast<const void*>(SbDirectoryCanOpen); + map_["SbDirectoryClose"] = reinterpret_cast<const void*>(SbDirectoryClose); + map_["SbDirectoryCreate"] = reinterpret_cast<const void*>(SbDirectoryCreate); + map_["SbDirectoryGetNext"] = + reinterpret_cast<const void*>(SbDirectoryGetNext); + map_["SbDirectoryOpen"] = reinterpret_cast<const void*>(SbDirectoryOpen); + map_["SbDoubleAbsolute"] = reinterpret_cast<const void*>(SbDoubleAbsolute); + map_["SbDoubleExponent"] = reinterpret_cast<const void*>(SbDoubleExponent); + map_["SbDoubleFloor"] = reinterpret_cast<const void*>(SbDoubleFloor); + map_["SbDoubleIsFinite"] = reinterpret_cast<const void*>(SbDoubleIsFinite); + map_["SbDoubleIsNan"] = reinterpret_cast<const void*>(SbDoubleIsNan); + map_["SbDrmCloseSession"] = reinterpret_cast<const void*>(SbDrmCloseSession); + map_["SbDrmCreateSystem"] = reinterpret_cast<const void*>(SbDrmCreateSystem); + map_["SbDrmDestroySystem"] = + reinterpret_cast<const void*>(SbDrmDestroySystem); + map_["SbDrmGenerateSessionUpdateRequest"] = + reinterpret_cast<const void*>(SbDrmGenerateSessionUpdateRequest); + map_["SbDrmIsServerCertificateUpdatable"] = + reinterpret_cast<const void*>(SbDrmIsServerCertificateUpdatable); + map_["SbDrmUpdateServerCertificate"] = + reinterpret_cast<const void*>(SbDrmUpdateServerCertificate); + map_["SbDrmUpdateSession"] = + reinterpret_cast<const void*>(SbDrmUpdateSession); + map_["SbEventCancel"] = reinterpret_cast<const void*>(SbEventCancel); + map_["SbEventSchedule"] = reinterpret_cast<const void*>(SbEventSchedule); + map_["SbFileCanOpen"] = reinterpret_cast<const void*>(SbFileCanOpen); + map_["SbFileClose"] = reinterpret_cast<const void*>(SbFileClose); + map_["SbFileDelete"] = reinterpret_cast<const void*>(SbFileDelete); + map_["SbFileExists"] = reinterpret_cast<const void*>(SbFileExists); + map_["SbFileFlush"] = reinterpret_cast<const void*>(SbFileFlush); + map_["SbFileGetInfo"] = reinterpret_cast<const void*>(SbFileGetInfo); + map_["SbFileGetPathInfo"] = reinterpret_cast<const void*>(SbFileGetPathInfo); + map_["SbFileModeStringToFlags"] = + reinterpret_cast<const void*>(SbFileModeStringToFlags); + map_["SbFileOpen"] = reinterpret_cast<const void*>(SbFileOpen); + map_["SbFileRead"] = reinterpret_cast<const void*>(SbFileRead); + map_["SbFileSeek"] = reinterpret_cast<const void*>(SbFileSeek); + map_["SbFileTruncate"] = reinterpret_cast<const void*>(SbFileTruncate); + map_["SbFileWrite"] = reinterpret_cast<const void*>(SbFileWrite); + map_["SbGetEglInterface"] = reinterpret_cast<const void*>(SbGetEglInterface); + map_["SbGetGlesInterface"] = + reinterpret_cast<const void*>(SbGetGlesInterface); + map_["SbImageDecode"] = reinterpret_cast<const void*>(SbImageDecode); + map_["SbImageIsDecodeSupported"] = + reinterpret_cast<const void*>(SbImageIsDecodeSupported); + map_["SbLog"] = reinterpret_cast<const void*>(SbLog); + map_["SbLogFlush"] = reinterpret_cast<const void*>(SbLogFlush); + map_["SbLogFormat"] = reinterpret_cast<const void*>(SbLogFormat); + map_["SbLogIsTty"] = reinterpret_cast<const void*>(SbLogIsTty); + map_["SbLogRaw"] = reinterpret_cast<const void*>(SbLogRaw); + map_["SbLogRawFormat"] = reinterpret_cast<const void*>(SbLogRawFormat); + map_["SbMediaCanPlayMimeAndKeySystem"] = + reinterpret_cast<const void*>(SbMediaCanPlayMimeAndKeySystem); + map_["SbMediaGetAudioBufferBudget"] = + reinterpret_cast<const void*>(SbMediaGetAudioBufferBudget); + map_["SbMediaGetBufferAlignment"] = + reinterpret_cast<const void*>(SbMediaGetBufferAlignment); + map_["SbMediaGetBufferAllocationUnit"] = + reinterpret_cast<const void*>(SbMediaGetBufferAllocationUnit); + map_["SbMediaGetBufferGarbageCollectionDurationThreshold"] = + reinterpret_cast<const void*>( + SbMediaGetBufferGarbageCollectionDurationThreshold); + map_["SbMediaGetBufferPadding"] = + reinterpret_cast<const void*>(SbMediaGetBufferPadding); + map_["SbMediaGetInitialBufferCapacity"] = + reinterpret_cast<const void*>(SbMediaGetInitialBufferCapacity); + map_["SbMediaGetMaxBufferCapacity"] = + reinterpret_cast<const void*>(SbMediaGetMaxBufferCapacity); + map_["SbMediaGetProgressiveBufferBudget"] = + reinterpret_cast<const void*>(SbMediaGetProgressiveBufferBudget); + map_["SbMediaGetVideoBufferBudget"] = + reinterpret_cast<const void*>(SbMediaGetVideoBufferBudget); + map_["SbMediaIsBufferPoolAllocateOnDemand"] = + reinterpret_cast<const void*>(SbMediaIsBufferPoolAllocateOnDemand); + map_["SbMediaIsBufferUsingMemoryPool"] = + reinterpret_cast<const void*>(SbMediaIsBufferUsingMemoryPool); + map_["SbMediaSetAudioWriteDuration"] = + reinterpret_cast<const void*>(SbMediaSetAudioWriteDuration); + map_["SbMemoryAllocateAlignedUnchecked"] = + reinterpret_cast<const void*>(SbMemoryAllocateAlignedUnchecked); + map_["SbMemoryAllocateUnchecked"] = + reinterpret_cast<const void*>(SbMemoryAllocateUnchecked); + map_["SbMemoryCompare"] = reinterpret_cast<const void*>(SbMemoryCompare); + map_["SbMemoryCopy"] = reinterpret_cast<const void*>(SbMemoryCopy); + map_["SbMemoryFindByte"] = reinterpret_cast<const void*>(SbMemoryFindByte); + map_["SbMemoryFree"] = reinterpret_cast<const void*>(SbMemoryFree); + map_["SbMemoryFreeAligned"] = + reinterpret_cast<const void*>(SbMemoryFreeAligned); + map_["SbMemoryMap"] = reinterpret_cast<const void*>(SbMemoryMap); + map_["SbMemoryMove"] = reinterpret_cast<const void*>(SbMemoryMove); + map_["SbMemoryProtect"] = reinterpret_cast<const void*>(SbMemoryProtect); + map_["SbMemoryReallocateUnchecked"] = + reinterpret_cast<const void*>(SbMemoryReallocateUnchecked); + map_["SbMemorySet"] = reinterpret_cast<const void*>(SbMemorySet); + map_["SbMemoryUnmap"] = reinterpret_cast<const void*>(SbMemoryUnmap); + +#if SB_HAS(MICROPHONE) + map_["SbMicrophoneClose"] = reinterpret_cast<const void*>(SbMicrophoneClose); + map_["SbMicrophoneCreate"] = + reinterpret_cast<const void*>(SbMicrophoneCreate); + map_["SbMicrophoneDestroy"] = + reinterpret_cast<const void*>(SbMicrophoneDestroy); + map_["SbMicrophoneGetAvailable"] = + reinterpret_cast<const void*>(SbMicrophoneGetAvailable); + map_["SbMicrophoneIsSampleRateSupported"] = + reinterpret_cast<const void*>(SbMicrophoneIsSampleRateSupported); + map_["SbMicrophoneOpen"] = reinterpret_cast<const void*>(SbMicrophoneOpen); + map_["SbMicrophoneRead"] = reinterpret_cast<const void*>(SbMicrophoneRead); +#endif + + map_["SbMutexAcquire"] = reinterpret_cast<const void*>(SbMutexAcquire); + map_["SbMutexAcquireTry"] = reinterpret_cast<const void*>(SbMutexAcquireTry); + map_["SbMutexCreate"] = reinterpret_cast<const void*>(SbMutexCreate); + map_["SbMutexDestroy"] = reinterpret_cast<const void*>(SbMutexDestroy); + map_["SbMutexRelease"] = reinterpret_cast<const void*>(SbMutexRelease); + map_["SbOnce"] = reinterpret_cast<const void*>(SbOnce); + + map_["SbPlayerCreate"] = reinterpret_cast<const void*>(SbPlayerCreate); + map_["SbPlayerDestroy"] = reinterpret_cast<const void*>(SbPlayerDestroy); + map_["SbPlayerGetCurrentFrame"] = + reinterpret_cast<const void*>(SbPlayerGetCurrentFrame); + map_["SbPlayerGetInfo2"] = reinterpret_cast<const void*>(SbPlayerGetInfo2); + map_["SbPlayerGetMaximumNumberOfSamplesPerWrite"] = + reinterpret_cast<const void*>(SbPlayerGetMaximumNumberOfSamplesPerWrite); + map_["SbPlayerOutputModeSupported"] = + reinterpret_cast<const void*>(SbPlayerOutputModeSupported); + map_["SbPlayerSeek2"] = reinterpret_cast<const void*>(SbPlayerSeek2); + map_["SbPlayerSetBounds"] = reinterpret_cast<const void*>(SbPlayerSetBounds); + map_["SbPlayerSetPlaybackRate"] = + reinterpret_cast<const void*>(SbPlayerSetPlaybackRate); + map_["SbPlayerSetVolume"] = reinterpret_cast<const void*>(SbPlayerSetVolume); + map_["SbPlayerWriteEndOfStream"] = + reinterpret_cast<const void*>(SbPlayerWriteEndOfStream); + map_["SbPlayerWriteSample2"] = + reinterpret_cast<const void*>(SbPlayerWriteSample2); + map_["SbSocketAccept"] = reinterpret_cast<const void*>(SbSocketAccept); + map_["SbSocketBind"] = reinterpret_cast<const void*>(SbSocketBind); + map_["SbSocketClearLastError"] = reinterpret_cast<const void*>(SbSocketClearLastError); + map_["SbSocketConnect"] = reinterpret_cast<const void*>(SbSocketConnect); + map_["SbSocketCreate"] = reinterpret_cast<const void*>(SbSocketCreate); + map_["SbSocketDestroy"] = reinterpret_cast<const void*>(SbSocketDestroy); + map_["SbSocketFreeResolution"] = + reinterpret_cast<const void*>(SbSocketFreeResolution); + map_["SbSocketGetInterfaceAddress"] = + reinterpret_cast<const void*>(SbSocketGetInterfaceAddress); + map_["SbSocketGetLastError"] = + reinterpret_cast<const void*>(SbSocketGetLastError); + map_["SbSocketGetLocalAddress"] = + reinterpret_cast<const void*>(SbSocketGetLocalAddress); + map_["SbSocketIsConnected"] = + reinterpret_cast<const void*>(SbSocketIsConnected); + map_["SbSocketIsConnectedAndIdle"] = + reinterpret_cast<const void*>(SbSocketIsConnectedAndIdle); + map_["SbSocketJoinMulticastGroup"] = + reinterpret_cast<const void*>(SbSocketJoinMulticastGroup); + map_["SbSocketListen"] = reinterpret_cast<const void*>(SbSocketListen); + map_["SbSocketReceiveFrom"] = + reinterpret_cast<const void*>(SbSocketReceiveFrom); + map_["SbSocketResolve"] = reinterpret_cast<const void*>(SbSocketResolve); + map_["SbSocketSendTo"] = reinterpret_cast<const void*>(SbSocketSendTo); + map_["SbSocketSetBroadcast"] = + reinterpret_cast<const void*>(SbSocketSetBroadcast); + map_["SbSocketSetReceiveBufferSize"] = + reinterpret_cast<const void*>(SbSocketSetReceiveBufferSize); + map_["SbSocketSetReuseAddress"] = + reinterpret_cast<const void*>(SbSocketSetReuseAddress); + map_["SbSocketSetSendBufferSize"] = + reinterpret_cast<const void*>(SbSocketSetSendBufferSize); + map_["SbSocketSetTcpKeepAlive"] = + reinterpret_cast<const void*>(SbSocketSetTcpKeepAlive); + map_["SbSocketSetTcpNoDelay"] = + reinterpret_cast<const void*>(SbSocketSetTcpNoDelay); + map_["SbSocketSetTcpWindowScaling"] = + reinterpret_cast<const void*>(SbSocketSetTcpWindowScaling); + map_["SbSocketWaiterAdd"] = reinterpret_cast<const void*>(SbSocketWaiterAdd); + map_["SbSocketWaiterCreate"] = + reinterpret_cast<const void*>(SbSocketWaiterCreate); + map_["SbSocketWaiterDestroy"] = + reinterpret_cast<const void*>(SbSocketWaiterDestroy); + map_["SbSocketWaiterRemove"] = + reinterpret_cast<const void*>(SbSocketWaiterRemove); + map_["SbSocketWaiterWait"] = + reinterpret_cast<const void*>(SbSocketWaiterWait); + map_["SbSocketWaiterWaitTimed"] = + reinterpret_cast<const void*>(SbSocketWaiterWaitTimed); + map_["SbSocketWaiterWakeUp"] = + reinterpret_cast<const void*>(SbSocketWaiterWakeUp); + +#if SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5 + map_["SbSpeechRecognizerCreate"] = + reinterpret_cast<const void*>(SbSpeechRecognizerCreate); + map_["SbSpeechRecognizerDestroy"] = + reinterpret_cast<const void*>(SbSpeechRecognizerDestroy); + map_["SbSpeechRecognizerStart"] = + reinterpret_cast<const void*>(SbSpeechRecognizerStart); + map_["SbSpeechRecognizerStop"] = + reinterpret_cast<const void*>(SbSpeechRecognizerStop); + map_["SbSpeechSynthesisCancel"] = + reinterpret_cast<const void*>(SbSpeechSynthesisCancel); + map_["SbSpeechSynthesisSpeak"] = + reinterpret_cast<const void*>(SbSpeechSynthesisSpeak); +#endif + + map_["SbStorageCloseRecord"] = + reinterpret_cast<const void*>(SbStorageCloseRecord); + map_["SbStorageDeleteRecord"] = + reinterpret_cast<const void*>(SbStorageDeleteRecord); + map_["SbStorageGetRecordSize"] = + reinterpret_cast<const void*>(SbStorageGetRecordSize); + map_["SbStorageOpenRecord"] = + reinterpret_cast<const void*>(SbStorageOpenRecord); + map_["SbStorageReadRecord"] = + reinterpret_cast<const void*>(SbStorageReadRecord); + map_["SbStorageWriteRecord"] = + reinterpret_cast<const void*>(SbStorageWriteRecord); + map_["SbStringCompare"] = reinterpret_cast<const void*>(SbStringCompare); + map_["SbStringCompareAll"] = + reinterpret_cast<const void*>(SbStringCompareAll); + map_["SbStringCompareNoCase"] = + reinterpret_cast<const void*>(SbStringCompareNoCase); + map_["SbStringCompareNoCaseN"] = + reinterpret_cast<const void*>(SbStringCompareNoCaseN); + map_["SbStringConcat"] = reinterpret_cast<const void*>(SbStringConcat); + map_["SbStringCopy"] = reinterpret_cast<const void*>(SbStringCopy); + map_["SbStringDuplicate"] = reinterpret_cast<const void*>(SbStringDuplicate); + map_["SbStringFindCharacter"] = + reinterpret_cast<const void*>(SbStringFindCharacter); + map_["SbStringFindLastCharacter"] = + reinterpret_cast<const void*>(SbStringFindLastCharacter); + map_["SbStringFindString"] = + reinterpret_cast<const void*>(SbStringFindString); + map_["SbStringFormat"] = reinterpret_cast<const void*>(SbStringFormat); + map_["SbStringFormatWide"] = + reinterpret_cast<const void*>(SbStringFormatWide); + map_["SbStringGetLength"] = reinterpret_cast<const void*>(SbStringGetLength); + map_["SbStringParseDouble"] = + reinterpret_cast<const void*>(SbStringParseDouble); + map_["SbStringParseSignedInteger"] = + reinterpret_cast<const void*>(SbStringParseSignedInteger); + map_["SbStringParseUInt64"] = + reinterpret_cast<const void*>(SbStringParseUInt64); + map_["SbStringParseUnsignedInteger"] = + reinterpret_cast<const void*>(SbStringParseUnsignedInteger); + map_["SbStringScan"] = reinterpret_cast<const void*>(SbStringScan); + map_["SbSystemBinarySearch"] = + reinterpret_cast<const void*>(SbSystemBinarySearch); + map_["SbSystemBreakIntoDebugger"] = + reinterpret_cast<const void*>(SbSystemBreakIntoDebugger); + map_["SbSystemClearLastError"] = + reinterpret_cast<const void*>(SbSystemClearLastError); + map_["SbSystemGetConnectionType"] = + reinterpret_cast<const void*>(SbSystemGetConnectionType); + map_["SbSystemGetDeviceType"] = + reinterpret_cast<const void*>(SbSystemGetDeviceType); + map_["SbSystemGetErrorString"] = + reinterpret_cast<const void*>(SbSystemGetErrorString); + map_["SbSystemGetExtension"] = + reinterpret_cast<const void*>(SbSystemGetExtension); + map_["SbSystemGetLastError"] = + reinterpret_cast<const void*>(SbSystemGetLastError); + map_["SbSystemGetLocaleId"] = + reinterpret_cast<const void*>(SbSystemGetLocaleId); + map_["SbSystemGetNumberOfProcessors"] = + reinterpret_cast<const void*>(SbSystemGetNumberOfProcessors); + map_["SbSystemGetPath"] = reinterpret_cast<const void*>(SbSystemGetPath); + map_["SbSystemGetProperty"] = + reinterpret_cast<const void*>(SbSystemGetProperty); + map_["SbSystemGetRandomData"] = + reinterpret_cast<const void*>(SbSystemGetRandomData); + map_["SbSystemGetRandomUInt64"] = + reinterpret_cast<const void*>(SbSystemGetRandomUInt64); + map_["SbSystemGetStack"] = reinterpret_cast<const void*>(SbSystemGetStack); + map_["SbSystemGetTotalCPUMemory"] = + reinterpret_cast<const void*>(SbSystemGetTotalCPUMemory); + map_["SbSystemGetTotalGPUMemory"] = + reinterpret_cast<const void*>(SbSystemGetTotalGPUMemory); + map_["SbSystemGetUsedCPUMemory"] = + reinterpret_cast<const void*>(SbSystemGetUsedCPUMemory); + map_["SbSystemGetUsedGPUMemory"] = + reinterpret_cast<const void*>(SbSystemGetUsedGPUMemory); + map_["SbSystemHasCapability"] = + reinterpret_cast<const void*>(SbSystemHasCapability); + map_["SbSystemHideSplashScreen"] = + reinterpret_cast<const void*>(SbSystemHideSplashScreen); + map_["SbSystemIsDebuggerAttached"] = + reinterpret_cast<const void*>(SbSystemIsDebuggerAttached); + map_["SbSystemRaisePlatformError"] = + reinterpret_cast<const void*>(SbSystemRaisePlatformError); + map_["SbSystemRequestPause"] = + reinterpret_cast<const void*>(SbSystemRequestPause); + map_["SbSystemRequestStop"] = + reinterpret_cast<const void*>(SbSystemRequestStop); + map_["SbSystemRequestSuspend"] = + reinterpret_cast<const void*>(SbSystemRequestSuspend); + map_["SbSystemRequestUnpause"] = + reinterpret_cast<const void*>(SbSystemRequestUnpause); + map_["SbSystemSort"] = reinterpret_cast<const void*>(SbSystemSort); + map_["SbSystemSupportsResume"] = + reinterpret_cast<const void*>(SbSystemSupportsResume); + map_["SbSystemSymbolize"] = reinterpret_cast<const void*>(SbSystemSymbolize); + map_["SbThreadContextGetPointer"] = + reinterpret_cast<const void*>(SbThreadContextGetPointer); + map_["SbThreadCreate"] = reinterpret_cast<const void*>(SbThreadCreate); + map_["SbThreadCreateLocalKey"] = + reinterpret_cast<const void*>(SbThreadCreateLocalKey); + map_["SbThreadDestroyLocalKey"] = + reinterpret_cast<const void*>(SbThreadDestroyLocalKey); + map_["SbThreadDetach"] = reinterpret_cast<const void*>(SbThreadDetach); + map_["SbThreadGetCurrent"] = + reinterpret_cast<const void*>(SbThreadGetCurrent); + map_["SbThreadGetId"] = reinterpret_cast<const void*>(SbThreadGetId); + map_["SbThreadGetLocalValue"] = + reinterpret_cast<const void*>(SbThreadGetLocalValue); + map_["SbThreadIsEqual"] = reinterpret_cast<const void*>(SbThreadIsEqual); + map_["SbThreadJoin"] = reinterpret_cast<const void*>(SbThreadJoin); + map_["SbThreadSamplerCreate"] = + reinterpret_cast<const void*>(SbThreadSamplerCreate); + map_["SbThreadSamplerDestroy"] = + reinterpret_cast<const void*>(SbThreadSamplerDestroy); + map_["SbThreadSamplerFreeze"] = + reinterpret_cast<const void*>(SbThreadSamplerFreeze); + map_["SbThreadSamplerThaw"] = + reinterpret_cast<const void*>(SbThreadSamplerThaw); + map_["SbThreadSetLocalValue"] = + reinterpret_cast<const void*>(SbThreadSetLocalValue); + map_["SbThreadSetName"] = reinterpret_cast<const void*>(SbThreadSetName); + map_["SbThreadSleep"] = reinterpret_cast<const void*>(SbThreadSleep); + map_["SbThreadYield"] = reinterpret_cast<const void*>(SbThreadYield); + map_["SbTimeGetMonotonicNow"] = + reinterpret_cast<const void*>(SbTimeGetMonotonicNow); + map_["SbTimeGetMonotonicThreadNow"] = + reinterpret_cast<const void*>(SbTimeGetMonotonicThreadNow); + map_["SbTimeGetNow"] = reinterpret_cast<const void*>(SbTimeGetNow); + map_["SbTimeZoneGetCurrent"] = + reinterpret_cast<const void*>(SbTimeZoneGetCurrent); + map_["SbTimeZoneGetName"] = reinterpret_cast<const void*>(SbTimeZoneGetName); +#if SB_API_VERSION >= SB_UI_NAVIGATION_VERSION + map_["SbUiNavGetInterface"] = + reinterpret_cast<const void*>(SbUiNavGetInterface); +#endif + map_["SbUserGetCurrent"] = reinterpret_cast<const void*>(SbUserGetCurrent); + map_["SbUserGetProperty"] = reinterpret_cast<const void*>(SbUserGetProperty); + map_["SbUserGetPropertySize"] = + reinterpret_cast<const void*>(SbUserGetPropertySize); + map_["SbWindowCreate"] = reinterpret_cast<const void*>(SbWindowCreate); + map_["SbWindowDestroy"] = reinterpret_cast<const void*>(SbWindowDestroy); + map_["SbWindowGetDiagonalSizeInInches"] = + reinterpret_cast<const void*>(SbWindowGetDiagonalSizeInInches); + map_["SbWindowGetPlatformHandle"] = + reinterpret_cast<const void*>(SbWindowGetPlatformHandle); + map_["SbWindowGetSize"] = reinterpret_cast<const void*>(SbWindowGetSize); + map_["SbWindowSetDefaultOptions"] = + reinterpret_cast<const void*>(SbWindowSetDefaultOptions); +#ifdef LOCAL_TEST_WITH_API_LEAKS + map_["atexit"] = reinterpret_cast<const void*>(atexit); + map_["btowc"] = reinterpret_cast<const void*>(btowc); + map_["__ctype_get_mb_cur_max"] = + map_["__cxa_thread_atexit_impl"] = + reinterpret_cast<const void*>(tmp__cxa_thread_atexit_impl); + map_["dladdr"] = reinterpret_cast<const void*>(dladdr); + map_["dl_iterate_phdr"] = reinterpret_cast<const void*>(tmp_dl_iterate_phdr); + map_["longjmp"] = reinterpret_cast<const void*>(longjmp); + map_["mbrlen"] = reinterpret_cast<const void*>(mbrlen); + map_["mbrtowc"] = reinterpret_cast<const void*>(mbrtowc); + map_["mbsnrtowcs"] = reinterpret_cast<const void*>(mbsnrtowcs); + map_["mbsrtowcs"] = reinterpret_cast<const void*>(mbsrtowcs); + map_["mbtowc"] = reinterpret_cast<const void*>(mbtowc); + + map_["setjmp"] = reinterpret_cast<const void*>(setjmp); + map_["wcrtomb"] = reinterpret_cast<const void*>(wcrtomb); + map_["wcsnrtombs"] = reinterpret_cast<const void*>(wcsnrtombs); + map_["wcstod"] = reinterpret_cast<const void*>(wcstod); + map_["wcstof"] = reinterpret_cast<const void*>(wcstof); + map_["wcstol"] = reinterpret_cast<const void*>(wcstol); + map_["wcstold"] = reinterpret_cast<const void*>(wcstold); + map_["wcstoll"] = reinterpret_cast<const void*>(wcstoll); + map_["wcstoul"] = reinterpret_cast<const void*>(wcstoul); + map_["wcstoull"] = reinterpret_cast<const void*>(wcstoull); + map_["wcsxfrm_l"] = reinterpret_cast<const void*>(wcsxfrm_l); + map_["wctob"] = reinterpret_cast<const void*>(wctob); +#endif +} + +const void* ExportedSymbols::Lookup(const char* name) { + const void* ret = map_[name]; + SB_CHECK(ret); + return ret; +} +} // namespace elf_loader +} // namespace starboard
diff --git a/src/starboard/elf_loader/exported_symbols.h b/src/starboard/elf_loader/exported_symbols.h new file mode 100644 index 0000000..a28c583 --- /dev/null +++ b/src/starboard/elf_loader/exported_symbols.h
@@ -0,0 +1,46 @@ +// Copyright 2019 The Cobalt Authors. 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. + +#ifndef STARBOARD_ELF_LOADER_EXPORTED_SYMBOLS_H_ +#define STARBOARD_ELF_LOADER_EXPORTED_SYMBOLS_H_ + +#include <map> +#include <string> + +#include "starboard/elf_loader/elf_hash_table.h" +#include "starboard/elf_loader/gnu_hash_table.h" +#include "starboard/file.h" + +namespace starboard { +namespace elf_loader { + +// class representing all exported symbols +// by the starboard layer. + +// The elf_loader will not use any other symbols +// outside of the set represented in this class. +class ExportedSymbols { + public: + ExportedSymbols(); + const void* Lookup(const char* name); + + private: + std::map<std::string, const void*> map_; + + SB_DISALLOW_COPY_AND_ASSIGN(ExportedSymbols); +}; + +} // namespace elf_loader +} // namespace starboard +#endif // STARBOARD_ELF_LOADER_EXPORTED_SYMBOLS_H_
diff --git a/src/starboard/elf_loader/file.h b/src/starboard/elf_loader/file.h new file mode 100644 index 0000000..90296e7 --- /dev/null +++ b/src/starboard/elf_loader/file.h
@@ -0,0 +1,44 @@ +// Copyright 2019 The Cobalt Authors. 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. + +#ifndef STARBOARD_ELF_LOADER_FILE_H_ +#define STARBOARD_ELF_LOADER_FILE_H_ + +#include "starboard/elf_loader/elf.h" + +namespace starboard { +namespace elf_loader { + +// File abstraction to be used by the ELF loader. +// The main reason to introduce this class is to allow for +// easy testing. +class File { + public: + // Opens the file specified for reading. + virtual bool Open(const char* name) = 0; + + // Reads a buffer from the file using the specified offset from the beginning + // of the file. + virtual bool ReadFromOffset(int64_t offset, char* buffer, int size) = 0; + + // Closes the underlying file. + virtual void Close() = 0; + + virtual ~File() {} +}; + +} // namespace elf_loader +} // namespace starboard + +#endif // STARBOARD_ELF_LOADER_FILE_H_
diff --git a/src/starboard/elf_loader/file_impl.cc b/src/starboard/elf_loader/file_impl.cc new file mode 100644 index 0000000..8250e8f --- /dev/null +++ b/src/starboard/elf_loader/file_impl.cc
@@ -0,0 +1,71 @@ +// Copyright 2019 The Cobalt Authors. 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 "starboard/elf_loader/file_impl.h" + +#include "starboard/common/log.h" + +namespace { +void LogLastError(const char* msg) { + const int kErrorMessageBufferSize = 256; + char msgbuf[kErrorMessageBufferSize]; + SbSystemError error_code = SbSystemGetLastError(); + if (SbSystemGetErrorString(error_code, msgbuf, kErrorMessageBufferSize) > 0) { + SB_LOG(ERROR) << msg << ": " << msgbuf; + } +} +} // namespace + +namespace starboard { +namespace elf_loader { + +FileImpl::FileImpl() : file_(NULL) {} + +bool FileImpl::Open(const char* name) { + SB_LOG(INFO) << "Loading: " << name; + file_ = SbFileOpen(name, kSbFileOpenOnly | kSbFileRead, NULL, NULL); + if (!file_) { + return false; + } + return true; +} + +bool FileImpl::ReadFromOffset(int64_t offset, char* buffer, int size) { + if (!file_) { + return false; + } + int64_t ret = SbFileSeek(file_, kSbFileFromBegin, offset); + SB_LOG(INFO) << "SbFileSeek: ret=" << ret; + if (ret == -1) { + SB_LOG(INFO) << "SbFileSeek: failed"; + return false; + } + + int count = SbFileReadAll(file_, buffer, size); + SB_LOG(INFO) << "SbFileReadAll: count=" << count; + if (count == -1) { + LogLastError("SbFileReadAll failed"); + return false; + } + return true; +} + +void FileImpl::Close() { + if (file_) { + SbFileClose(file_); + } +} + +} // namespace elf_loader +} // namespace starboard
diff --git a/src/starboard/elf_loader/file_impl.h b/src/starboard/elf_loader/file_impl.h new file mode 100644 index 0000000..2a923be --- /dev/null +++ b/src/starboard/elf_loader/file_impl.h
@@ -0,0 +1,43 @@ +// Copyright 2019 The Cobalt Authors. 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. + +#ifndef STARBOARD_ELF_LOADER_FILE_IMPL_H_ +#define STARBOARD_ELF_LOADER_FILE_IMPL_H_ + +#include "starboard/elf_loader/elf.h" + +#include "starboard/elf_loader/file.h" +#include "starboard/file.h" + +namespace starboard { +namespace elf_loader { + +// Starboard implementation for reading a file. +class FileImpl : public File { + public: + FileImpl(); + bool Open(const char* name); + bool ReadFromOffset(int64_t offset, char* buffer, int size); + void Close(); + + private: + SbFile file_; + + SB_DISALLOW_COPY_AND_ASSIGN(FileImpl); +}; + +} // namespace elf_loader +} // namespace starboard + +#endif // STARBOARD_ELF_LOADER_FILE_IMPL_H_
diff --git a/src/starboard/elf_loader/gnu_hash_table.cc b/src/starboard/elf_loader/gnu_hash_table.cc new file mode 100644 index 0000000..37db118 --- /dev/null +++ b/src/starboard/elf_loader/gnu_hash_table.cc
@@ -0,0 +1,142 @@ +// Copyright 2019 The Cobalt Authors. 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 "starboard/elf_loader/gnu_hash_table.h" +#include "starboard/common/log.h" +#include "starboard/string.h" + +namespace starboard { +namespace elf_loader { + +// Compute the GNU hash of a given symbol. +// For more details on the hash function: +// https://blogs.oracle.com/solaris/gnu-hash-elf-sections-v2 +static uint32_t GnuHash(const char* name) { + uint32_t h = 5381; + const uint8_t* ptr = reinterpret_cast<const uint8_t*>(name); + while (*ptr) { + h = h * 33 + *ptr++; + } + return h; +} + +GnuHashTable::GnuHashTable() + : num_buckets_(0), + sym_offset_(0), + sym_count_(0), + bloom_word_mask_(0), + bloom_shift_(0), + bloom_filter_(NULL), + buckets_(NULL), + chain_(NULL) {} +void GnuHashTable::Init(uintptr_t dt_gnu_hash) { + SB_LOG(INFO) << "GnuHashTable::Init 0x" << std::hex << dt_gnu_hash; + sym_count_ = 0; + + const uint32_t* data = reinterpret_cast<const uint32_t*>(dt_gnu_hash); + num_buckets_ = data[0]; + sym_offset_ = data[1]; + + SB_LOG(INFO) << "GnuHashTable::Init num_buckets_=" << num_buckets_ + << " sym_offset_" << sym_offset_; + if (!num_buckets_) + return; + + const uint32_t bloom_size = data[2]; + SB_LOG(INFO) << "GnuHashTable::Init bloom_size=" << bloom_size; + if ((bloom_size & (bloom_size - 1U)) != 0) // must be a power of 2 + return; + + bloom_word_mask_ = bloom_size - 1U; + bloom_shift_ = data[3]; + + SB_LOG(INFO) << "GnuHashTable::Init bloom_word_mask_=" << bloom_word_mask_; + SB_LOG(INFO) << "GnuHashTable::Init bloom_shift_=" << bloom_shift_; + bloom_filter_ = reinterpret_cast<const Addr*>(data + 4); + SB_LOG(INFO) << "GnuHashTable::Init bloom_filter_=0x" << std::hex + << bloom_filter_; + buckets_ = reinterpret_cast<const uint32_t*>(bloom_filter_ + bloom_size); + + SB_LOG(INFO) << "GnuHashTable::Init buckets_=0x" << std::hex << buckets_; + chain_ = buckets_ + num_buckets_; + + // Compute number of dynamic symbols by parsing the table. + if (num_buckets_ > 0) { + // First find the maximum index in the buckets table. + uint32_t max_index = buckets_[0]; + for (size_t n = 1; n < num_buckets_; ++n) { + uint32_t sym_index = buckets_[n]; + if (sym_index > max_index) + max_index = sym_index; + } + // Now start to look at the chain_ table from (max_index - sym_offset_) + // until there is a value with LSB set to 1, indicating the end of the + // last chain. + while ((chain_[max_index - sym_offset_] & 1) == 0) + max_index++; + + sym_count_ = (max_index - sym_offset_) + 1; + } +} + +bool GnuHashTable::IsValid() const { + return sym_count_ > 0; +} + +const Sym* GnuHashTable::LookupByName(const char* symbol_name, + const Sym* symbol_table, + const char* string_table) const { + SB_LOG(INFO) << "GnuHashTable::LookupByName: " << symbol_name; + uint32_t hash = GnuHash(symbol_name); + + SB_LOG(INFO) << "GnuHashTable::LookupByName: hash=" << hash; + SB_LOG(INFO) << "GnuHashTable::LookupByName: ELF_BITS=" << ELF_BITS; + + // First, bloom filter test. + Addr word = bloom_filter_[(hash / ELF_BITS) & bloom_word_mask_]; + + SB_LOG(INFO) << "GnuHashTable::LookupByName: word=" << word; + Addr mask = (Addr(1) << (hash % ELF_BITS)) | + (Addr(1) << ((hash >> bloom_shift_) % ELF_BITS)); + + SB_LOG(INFO) << "GnuHashTable::LookupByName: mask=" << mask; + if ((word & mask) != mask) + return NULL; + + uint32_t sym_index = buckets_[hash % num_buckets_]; + if (sym_index < sym_offset_) + return NULL; + + // TODO: add validations of the syn_index + while (true) { + const Sym* sym = symbol_table + sym_index; + const uint32_t sym_hash = chain_[sym_index - sym_offset_]; + const char* sym_name = string_table + sym->st_name; + + if ((sym_hash | 1) == (hash | 1) && + !SbStringCompareAll(sym_name, symbol_name)) { + return sym; + } + + if (sym_hash & 1) + break; + + sym_index++; + } + + return NULL; +} + +} // namespace elf_loader +} // namespace starboard
diff --git a/src/starboard/elf_loader/gnu_hash_table.h b/src/starboard/elf_loader/gnu_hash_table.h new file mode 100644 index 0000000..5bdf199 --- /dev/null +++ b/src/starboard/elf_loader/gnu_hash_table.h
@@ -0,0 +1,66 @@ +// Copyright 2019 The Cobalt Authors. 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. + +#ifndef STARBOARD_ELF_LOADER_GNU_HASH_TABLE_H_ +#define STARBOARD_ELF_LOADER_GNU_HASH_TABLE_H_ + +#include <stddef.h> +#include "starboard/elf_loader/elf.h" + +namespace starboard { +namespace elf_loader { + +// Models the hash table used to map symbol names to symbol entries using +// the GNU format. This one is smaller and faster than the standard ELF one. +class GnuHashTable { + public: + GnuHashTable(); + // Initialize instance. |dt_gnu_hash| should be the address that the + // DT_GNU_HASH entry points to in the input ELF dynamic section. Call + // IsValid() to determine whether the table was well-formed. + void Init(uintptr_t dt_gnu_hash); + + // Returns true iff the content of the table is valid. + bool IsValid() const; + + // Return the index of the first dynamic symbol within the ELF symbol table. + size_t dyn_symbols_offset() const { return sym_offset_; } + + // Number of dynamic symbols in the ELF symbol table. + size_t dyn_symbols_count() const { return sym_count_; } + + // Lookup |symbol_name| in the table. |symbol_table| should point to the + // ELF symbol table, and |string_table| to the start of its string table. + // Returns NULL on failure. + const Sym* LookupByName(const char* symbol_name, + const Sym* symbol_table, + const char* string_table) const; + + private: + uint32_t num_buckets_; + uint32_t sym_offset_; + uint32_t sym_count_; + uint32_t bloom_word_mask_; + uint32_t bloom_shift_; + const Addr* bloom_filter_; + const uint32_t* buckets_; + const uint32_t* chain_; + + SB_DISALLOW_COPY_AND_ASSIGN(GnuHashTable); +}; + +} // namespace elf_loader +} // namespace starboard + +#endif // STARBOARD_ELF_LOADER_GNU_HASH_TABLE_H_
diff --git a/src/starboard/elf_loader/program_table.cc b/src/starboard/elf_loader/program_table.cc new file mode 100644 index 0000000..7542604 --- /dev/null +++ b/src/starboard/elf_loader/program_table.cc
@@ -0,0 +1,329 @@ +// Copyright 2019 The Cobalt Authors. 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 "starboard/elf_loader/program_table.h" + +#include "starboard/common/log.h" +#include "starboard/memory.h" + +#define MAYBE_MAP_FLAG(x, from, to) (((x) & (from)) ? (to) : 0) +#define PFLAGS_TO_PROT(x) \ + (MAYBE_MAP_FLAG((x), PF_X, kSbMemoryMapProtectExec) | \ + MAYBE_MAP_FLAG((x), PF_R, kSbMemoryMapProtectRead) | \ + MAYBE_MAP_FLAG((x), PF_W, kSbMemoryMapProtectWrite)) + +#define MAP_FAILED ((void*)-1) + +namespace starboard { +namespace elf_loader { + +ProgramTable::ProgramTable() + : phdr_num_(0), + phdr_mmap_(NULL), + phdr_table_(NULL), + phdr_size_(0), + load_start_(NULL), + load_size_(0), + base_memory_address_(0) {} + +bool ProgramTable::LoadProgramHeader(const Ehdr* elf_header, File* elf_file) { + if (!elf_header) { + SB_LOG(ERROR) << "Ehdr is required"; + return false; + } + if (!elf_file) { + SB_LOG(ERROR) << "File is required"; + return false; + } + phdr_num_ = elf_header->e_phnum; + + SB_LOG(INFO) << "Program Header count=" << phdr_num_; + // Like the kernel, only accept program header tables smaller than 64 KB. + if (phdr_num_ < 1 || phdr_num_ > 65536 / elf_header->e_phentsize) { + SB_LOG(ERROR) << "Invalid program header count: " << phdr_num_; + return false; + } + + SB_LOG(INFO) << "elf_header->e_phoff=" << elf_header->e_phoff; + SB_LOG(INFO) << "elf_header->e_phnum=" << elf_header->e_phnum; + + Addr page_min = PAGE_START(elf_header->e_phoff); + Addr page_max = PAGE_END(elf_header->e_phoff + (phdr_num_ * elf_header->e_phentsize)); + Addr page_offset = PAGE_OFFSET(elf_header->e_phoff); + + SB_LOG(INFO) << "page_min=" << page_min; + SB_LOG(INFO) << "page_max=" << page_max; + + phdr_size_ = page_max - page_min; + + SB_LOG(INFO) << "page_max - page_min=" << page_max - page_min; + + phdr_mmap_ = + SbMemoryMap(phdr_size_, kSbMemoryMapProtectWrite, "program_header"); + if (!phdr_mmap_) { + SB_LOG(ERROR) << "Failed to allocate memory"; + return false; + } + + SB_LOG(INFO) << "Allocated address=" << phdr_mmap_; + + if (!elf_file->ReadFromOffset(page_min, reinterpret_cast<char*>(phdr_mmap_), + phdr_size_)) { + SB_LOG(ERROR) << "Failed to read program header from file offset: " + << page_min; + return false; + } + + bool mp_result = + SbMemoryProtect(phdr_mmap_, phdr_size_, kSbMemoryMapProtectRead); + SB_LOG(INFO) << "mp_result=" << mp_result; + if (!mp_result) { + SB_LOG(ERROR) << "Failed to protect program header"; + return false; + } + phdr_table_ = reinterpret_cast<Phdr*>(reinterpret_cast<char*>(phdr_mmap_) + + page_offset); + + return true; +} + +bool ProgramTable::LoadSegments(File* elf_file) { + for (size_t i = 0; i < phdr_num_; ++i) { + const Phdr* phdr = &phdr_table_[i]; + + if (phdr->p_type != PT_LOAD) { + continue; + } + + // Segment byte addresses in memory. + Addr seg_start = phdr->p_vaddr + base_memory_address_; + Addr seg_end = seg_start + phdr->p_memsz; + + // Segment page addresses in memory. + Addr seg_page_start = PAGE_START(seg_start); + Addr seg_page_end = PAGE_END(seg_end); + + // File offsets. + Addr seg_file_end = seg_start + phdr->p_filesz; + Addr file_start = phdr->p_offset; + Addr file_end = file_start + phdr->p_filesz; + + SB_LOG(INFO) << " phdr->p_offset=" << phdr->p_offset + << " phdr->p_filesz=" << phdr->p_filesz; + + Addr file_page_start = PAGE_START(file_start); + Addr file_length = file_end - file_page_start; + + SB_LOG(INFO) << "Mapping segment: " + << " file_page_start=" << file_page_start + << " file_length=" << file_length << " seg_page_start=0x" + << std::hex << seg_page_start; + + if (file_length != 0) { + const int prot_flags = PFLAGS_TO_PROT(phdr->p_flags); + SB_LOG(INFO) << "segment prot_flags=" << std::hex << prot_flags; + + void* seg_addr = reinterpret_cast<void*>(seg_page_start); + bool mp_ret = + SbMemoryProtect(seg_addr, file_length, kSbMemoryMapProtectWrite); + SB_LOG(INFO) << "segment vaddress=" << seg_addr; + + if (!mp_ret) { + SB_LOG(ERROR) << "Failed to unprotect segment"; + return false; + } + if (!elf_file->ReadFromOffset(file_page_start, + reinterpret_cast<char*>(seg_addr), + file_length)) { + SB_LOG(INFO) << "Failed to read segment from file offset: " + << file_page_start; + return false; + } + + mp_ret = SbMemoryProtect(seg_addr, file_length, prot_flags); + SB_LOG(INFO) << "mp_ret=" << mp_ret; + if (!mp_ret) { + SB_LOG(ERROR) << "Failed to protect segment"; + return false; + } + if (!seg_addr) { + SB_LOG(ERROR) << "Could not map segment " << i; + return false; + } + } + + // if the segment is writable, and does not end on a page boundary, + // zero-fill it until the page limit. + if ((phdr->p_flags & PF_W) != 0 && PAGE_OFFSET(seg_file_end) > 0) { + SbMemorySet(reinterpret_cast<void*>(seg_file_end), 0, + PAGE_SIZE - PAGE_OFFSET(seg_file_end)); + } + + seg_file_end = PAGE_END(seg_file_end); + + // seg_file_end is now the first page address after the file + // content. If seg_page_end is larger, we need to zero anything + // between them. This is done by using a private anonymous + // map for all extra pages. + if (seg_page_end > seg_file_end) { + bool mprotect_fix = SbMemoryProtect(reinterpret_cast<void*>(seg_file_end), + seg_page_end - seg_file_end, + kSbMemoryMapProtectWrite); + SB_LOG(INFO) << "mprotect_fix=" << mprotect_fix; + if (!mprotect_fix) { + SB_LOG(ERROR) << "Failed to unprotect end of segment"; + return false; + } + SbMemorySet(reinterpret_cast<void*>(seg_file_end), 0, + seg_page_end - seg_file_end); + SbMemoryProtect(reinterpret_cast<void*>(seg_file_end), + seg_page_end - seg_file_end, + PFLAGS_TO_PROT(phdr->p_flags)); + SB_LOG(INFO) << "mprotect_fix=" << mprotect_fix; + if (!mprotect_fix) { + SB_LOG(ERROR) << "Failed to protect end of segment"; + return false; + } + } + } + return true; +} + +size_t ProgramTable::GetLoadMemorySize() { + Addr min_vaddr = ~static_cast<Addr>(0); + Addr max_vaddr = 0x00000000U; + + bool found_pt_load = false; + for (size_t i = 0; i < phdr_num_; ++i) { + const Phdr* phdr = &phdr_table_[i]; + + if (phdr->p_type != PT_LOAD) { + SB_LOG(INFO) << "GetLoadMemorySize: ignoring segment with type: " + << phdr->p_type; + continue; + } + found_pt_load = true; + + if (phdr->p_vaddr < min_vaddr) { + SB_LOG(INFO) << "p_vaddr=" << std::hex << phdr->p_vaddr; + min_vaddr = phdr->p_vaddr; + } + + if (phdr->p_vaddr + phdr->p_memsz > max_vaddr) { + max_vaddr = phdr->p_vaddr + phdr->p_memsz; + SB_LOG(INFO) << "phdr->p_vaddr=" << phdr->p_vaddr + << " phdr->p_memsz=" << phdr->p_memsz; + SB_LOG(INFO) << " max_vaddr=0x" << std::hex << max_vaddr; + } + } + if (!found_pt_load) { + min_vaddr = 0x00000000U; + } + + min_vaddr = PAGE_START(min_vaddr); + max_vaddr = PAGE_END(max_vaddr); + + return max_vaddr - min_vaddr; +} + +void ProgramTable::GetDynamicSection(Dyn** dynamic, + size_t* dynamic_count, + Word* dynamic_flags) { + const Phdr* phdr = phdr_table_; + const Phdr* phdr_limit = phdr + phdr_num_; + + for (phdr = phdr_table_; phdr < phdr_limit; phdr++) { + if (phdr->p_type != PT_DYNAMIC) { + SB_LOG(INFO) << "Ignore section with type: " << phdr->p_type; + continue; + } + + SB_LOG(INFO) << "Reading at vaddr: " << phdr->p_vaddr; + *dynamic = reinterpret_cast<Dyn*>(base_memory_address_ + phdr->p_vaddr); + if (dynamic_count) { + *dynamic_count = (size_t)(phdr->p_memsz / sizeof(Dyn)); + } + if (dynamic_flags) { + *dynamic_flags = phdr->p_flags; + } + return; + } + *dynamic = NULL; + if (dynamic_count) { + *dynamic_count = 0; + } +} + +int ProgramTable::AdjustMemoryProtectionOfReadOnlySegments( + int extra_prot_flags) { + const Phdr* phdr = phdr_table_; + const Phdr* phdr_limit = phdr + phdr_num_; + + for (; phdr < phdr_limit; phdr++) { + if (phdr->p_type != PT_LOAD || (phdr->p_flags & PF_W) != 0) + continue; + + Addr seg_page_start = PAGE_START(phdr->p_vaddr) + base_memory_address_; + Addr seg_page_end = + PAGE_END(phdr->p_vaddr + phdr->p_memsz) + base_memory_address_; + + int ret = SbMemoryProtect(reinterpret_cast<void*>(seg_page_start), + seg_page_end - seg_page_start, + PFLAGS_TO_PROT(phdr->p_flags) | extra_prot_flags); + if (ret < 0) { + return -1; + } + } + return 0; +} + +bool ProgramTable::ReserveLoadMemory() { + load_size_ = GetLoadMemorySize(); + if (load_size_ == 0) { + SB_LOG(ERROR) << "No loadable segments"; + return false; + } + + SB_LOG(INFO) << "Load size=" << load_size_; + + load_start_ = + SbMemoryMap(load_size_, kSbMemoryMapProtectReserved, "reserved_mem"); + if (load_start_ == MAP_FAILED) { + SB_LOG(ERROR) << "Could not reserve " << load_size_ + << " bytes of address space"; + return false; + } + + base_memory_address_ = reinterpret_cast<Addr>(load_start_); + + SB_LOG(INFO) << "Load start=" << std::hex << load_start_ + << " base_memory_address=0x" << base_memory_address_; + return true; +} + +Addr ProgramTable::GetBaseMemoryAddress() { + return base_memory_address_; +} + +ProgramTable::~ProgramTable() { + if (load_start_) { + SbMemoryUnmap(load_start_, load_size_); + } + if (phdr_mmap_) { + SbMemoryUnmap(phdr_mmap_, phdr_size_); + } +} + +} // namespace elf_loader +} // namespace starboard
diff --git a/src/starboard/elf_loader/program_table.h b/src/starboard/elf_loader/program_table.h new file mode 100644 index 0000000..c4229e7 --- /dev/null +++ b/src/starboard/elf_loader/program_table.h
@@ -0,0 +1,91 @@ +// Copyright 2019 The Cobalt Authors. 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. + +#ifndef STARBOARD_ELF_LOADER_PROGRAM_TABLE_H_ +#define STARBOARD_ELF_LOADER_PROGRAM_TABLE_H_ + +#include "starboard/elf_loader/elf.h" +#include "starboard/elf_loader/file.h" + +namespace starboard { +namespace elf_loader { + +// Loads the ELF's binary program table and memory maps +// the loadable segments. +// +// To properly initialize the program table and the segments +// the following calls are required: +// 1. LoadProgramHeader() +// 2. LoadSegments() +// +// After those calls the ProgramTable class is fully functional and +// the segments properly loaded. + +class ProgramTable { + public: + ProgramTable(); + + // Loads the program header. + bool LoadProgramHeader(const Ehdr* elf_header, File* elf_file); + + // Loads the segments. + bool LoadSegments(File* elf_file); + + // Retrieves the dynamic section table. + void GetDynamicSection(Dyn** dynamic, + size_t* dynamic_count, + Word* dynamic_flags); + + // Adjusts the memory protection of read only segments. + // This call is used to make text segments writable in order + // to apply relocations. After the relocations are done the + // protection is restored to its original read only state. + int AdjustMemoryProtectionOfReadOnlySegments(int extra_prot_flags); + + // Reserves a contiguous block of memory, page aligned for mapping all + // the segments of the binary. + bool ReserveLoadMemory(); + + // Retrieves the base load address for the binary. + Addr GetBaseMemoryAddress(); + + ~ProgramTable(); + + private: + // Calculates the memory size of the binary. + size_t GetLoadMemorySize(); + + private: + size_t phdr_num_; + void* phdr_mmap_; + Phdr* phdr_table_; + Addr phdr_size_; + + // First page of reserved address space. + void* load_start_; + + // Size in bytes of reserved address space. + Addr load_size_; + + // The base memory address. All virtual addresses + // from the ELF file are offsets from this address. + Addr base_memory_address_; + + SB_DISALLOW_COPY_AND_ASSIGN(ProgramTable); +}; + +} // namespace elf_loader +} // namespace starboard + +#endif // STARBOARD_ELF_LOADER_PROGRAM_TABLE_H_
diff --git a/src/starboard/elf_loader/program_table_test.cc b/src/starboard/elf_loader/program_table_test.cc new file mode 100644 index 0000000..da15cae --- /dev/null +++ b/src/starboard/elf_loader/program_table_test.cc
@@ -0,0 +1,182 @@ +// Copyright 2019 The Cobalt Authors. 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 "starboard/elf_loader/program_table.h" + +#include <vector> + +#include "starboard/common/scoped_ptr.h" +#include "starboard/elf_loader/file.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace starboard { +namespace elf_loader { + +namespace { + +class DummyFile : public File { + public: + typedef struct FileChunk { + FileChunk(int file_offset, const char* buffer, int size) + : file_offset_(file_offset), buffer_(buffer), size_(size) {} + int file_offset_; + const char* buffer_; + int size_; + } FileChunk; + + explicit DummyFile(const std::vector<FileChunk>& file_chunks) + : file_chunks_(file_chunks), read_index_(0) {} + + bool Open(const char* name) { return true; } + bool ReadFromOffset(int64_t offset, char* buffer, int size) { + SB_LOG(INFO) << "ReadFromOffset offset=" << offset << " size=" << size + << " read_index_=" << read_index_; + if (read_index_ >= file_chunks_.size()) { + SB_LOG(INFO) << "ReadFromOffset EOF"; + return false; + } + const FileChunk& file_chunk = file_chunks_[read_index_++]; + if (offset != file_chunk.file_offset_) { + SB_LOG(ERROR) << "ReadFromOffset: Invalid offset " << offset + << " expected " << file_chunk.file_offset_; + return false; + } + if (size > file_chunk.size_) { + SB_LOG(ERROR) << "ReadFromOffset: Invalid size " << size << " expected < " + << file_chunk.size_; + return false; + } + SbMemoryCopy(buffer, file_chunk.buffer_, size); + return true; + } + void Close() {} + + private: + int file_offset_; + const char* buffer_; + int size_; + std::vector<FileChunk> file_chunks_; + int read_index_; +}; + +class ProgramTableTest : public ::testing::Test { + protected: + ProgramTableTest() { program_table_.reset(new ProgramTable()); } + ~ProgramTableTest() {} + + void HelperMethod() {} + + protected: + scoped_ptr<ProgramTable> program_table_; +}; + +TEST_F(ProgramTableTest, LoadSegments) { + // File structure + // [Phdr1] + // [Phdr2] + // [200, 300) sement for phdr1 + // [250, 300) dyanmic section in segment for phdr1 + // [400, 500) sement for phdr2 + Ehdr ehdr; + ehdr.e_phnum = 3; + ehdr.e_phoff = 0; + + Phdr ent1; + Phdr ent2; + Phdr ent3; + SbMemorySet(&ent1, 0, sizeof(Phdr)); + SbMemorySet(&ent2, 0, sizeof(Phdr)); + SbMemorySet(&ent3, 0, sizeof(Phdr)); + + ent1.p_type = PT_LOAD; + ent1.p_vaddr = 0; + ent1.p_memsz = 2 * PAGE_SIZE; + ent1.p_offset = 200; + ent1.p_filesz = 100; + ent1.p_flags = kSbMemoryMapProtectRead; + + ent2.p_type = PT_LOAD; + ent2.p_vaddr = 2 * PAGE_SIZE; + ent2.p_memsz = 3 * PAGE_SIZE; + ent2.p_offset = 400; + ent2.p_filesz = 100; + ent1.p_flags = kSbMemoryMapProtectRead | kSbMemoryMapProtectExec; + + ent3.p_type = PT_DYNAMIC; + ent3.p_vaddr = 250; + ent3.p_memsz = 3 * sizeof(Dyn); + ent3.p_offset = 250; + ent3.p_filesz = 5 * sizeof(Dyn); + ent3.p_flags = 0x42; + + Phdr program_table_data[3]; + program_table_data[0] = ent1; + program_table_data[1] = ent2; + program_table_data[2] = ent3; + + Dyn dynamic_table_data[3]; + dynamic_table_data[0].d_tag = DT_DEBUG; + dynamic_table_data[1].d_tag = DT_DEBUG; + dynamic_table_data[2].d_tag = DT_DEBUG; + + char program_table_page[PAGE_SIZE]; + SbMemorySet(program_table_page, 0, sizeof(program_table_page)); + SbMemoryCopy(program_table_page, program_table_data, + sizeof(program_table_data)); + + char segment_file_data1[2 * PAGE_SIZE]; + char segment_file_data2[3 * PAGE_SIZE]; + + SbMemoryCopy(segment_file_data1 + 250, dynamic_table_data, + sizeof(dynamic_table_data)); + + std::vector<DummyFile::FileChunk> file_chunks; + file_chunks.push_back( + DummyFile::FileChunk(0, program_table_page, sizeof(program_table_page))); + file_chunks.push_back( + DummyFile::FileChunk(0, segment_file_data1, sizeof(segment_file_data1))); + file_chunks.push_back( + DummyFile::FileChunk(0, segment_file_data2, sizeof(segment_file_data2))); + + DummyFile file(file_chunks); + + EXPECT_TRUE(program_table_->LoadProgramHeader(&ehdr, &file)); + + EXPECT_EQ(program_table_->GetBaseMemoryAddress(), 0); + + EXPECT_TRUE(program_table_->ReserveLoadMemory()); + + EXPECT_NE(program_table_->GetBaseMemoryAddress(), 0); + + EXPECT_TRUE(program_table_->LoadSegments(&file)); + + Dyn* dynamic = NULL; + size_t dynamic_count = 0; + Word dynamic_flags = 0; + + program_table_->GetDynamicSection(&dynamic, &dynamic_count, &dynamic_flags); + Dyn* expected_dyn = reinterpret_cast<Dyn*>( + program_table_->GetBaseMemoryAddress() + ent3.p_vaddr); + EXPECT_TRUE(dynamic != NULL); + EXPECT_EQ(dynamic[0].d_tag, DT_DEBUG); + EXPECT_EQ(dynamic[1].d_tag, DT_DEBUG); + EXPECT_EQ(dynamic[2].d_tag, DT_DEBUG); + EXPECT_EQ(dynamic_count, 3); + EXPECT_EQ(dynamic_flags, 0x42); +} + +} // namespace +} // namespace elf_loader +} // namespace starboard
diff --git a/src/starboard/elf_loader/relocations.cc b/src/starboard/elf_loader/relocations.cc new file mode 100644 index 0000000..4b7131c --- /dev/null +++ b/src/starboard/elf_loader/relocations.cc
@@ -0,0 +1,551 @@ +// Copyright 2019 The Cobalt Authors. 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 "starboard/elf_loader/relocations.h" + +#include "starboard/common/log.h" + +namespace starboard { +namespace elf_loader { + +Relocations::Relocations(Addr base_memory_address, + DynamicSection* dynamic_section, + ExportedSymbols* exported_symbols) + : base_memory_address_(base_memory_address), + dynamic_section_(dynamic_section), + plt_relocations_(0), + plt_relocations_size_(0), + plt_got_(NULL), + relocations_(0), + relocations_size_(0), + android_relocations_(NULL), + android_relocations_size_(0), + has_text_relocations_(false), + has_symbolic_(false), + exported_symbols_(exported_symbols) {} + +bool Relocations::HasTextRelocations() { + return has_text_relocations_; +} + +bool Relocations::InitRelocations() { + SB_LOG(INFO) << "InitRelocations: dynamic_count=" + << dynamic_section_->GetDynamicTableSize(); + const Dyn* dynamic = dynamic_section_->GetDynamicTable(); + for (int i = 0; i < dynamic_section_->GetDynamicTableSize(); i++) { + Addr dyn_value = dynamic[i].d_un.d_val; + uintptr_t dyn_addr = base_memory_address_ + dynamic[i].d_un.d_ptr; + Addr tag = dynamic[i].d_tag; + SB_LOG(INFO) << "InitRelocations: tag=" << tag; + switch (tag) { +#if defined(USE_RELA) + case DT_REL: + case DT_RELSZ: + case DT_ANDROID_REL: + case DT_ANDROID_RELSZ: +#else + case DT_RELA: + case DT_RELASZ: + case DT_ANDROID_RELA: + case DT_ANDROID_RELASZ: +#endif + SB_LOG(ERROR) << "unsupported relocation type"; + return false; + case DT_PLTREL: + SB_LOG(INFO) << " DT_PLTREL value=" << dyn_value; +#if defined(USE_RELA) + if (dyn_value != DT_RELA) { + SB_LOG(ERROR) << "unsupported DT_PLTREL expected DT_RELA"; + return false; + } +#else + if (dyn_value != DT_REL) { + SB_LOG(ERROR) << "unsupported DT_PLTREL expected DT_REL"; + return false; + } +#endif + break; + case DT_JMPREL: + SB_LOG(INFO) << " DT_JMPREL addr=0x" << std::hex + << (dyn_addr - base_memory_address_); + plt_relocations_ = dyn_addr; + break; + case DT_PLTRELSZ: + plt_relocations_size_ = dyn_value; + SB_LOG(INFO) << " DT_PLTRELSZ size=" << dyn_value; + break; +#if defined(USE_RELA) + case DT_RELA: +#else + case DT_REL: +#endif + SB_LOG(INFO) << " " << ((tag == DT_RELA) ? "DT_RELA" : "DT_REL") + << " addr=" << std::hex + << (dyn_addr - base_memory_address_); + if (relocations_) { + SB_LOG(ERROR) + << "Unsupported DT_RELA/DT_REL combination in dynamic section"; + return false; + } + relocations_ = dyn_addr; + break; +#if defined(USE_RELA) + case DT_RELASZ: +#else + case DT_RELSZ: +#endif + SB_LOG(INFO) << " " << ((tag == DT_RELASZ) ? "DT_RELASZ" : "DT_RELSZ") + << " size=" << dyn_value; + relocations_size_ = dyn_value; + break; +#if defined(USE_RELA) + case DT_ANDROID_RELA: +#else + case DT_ANDROID_REL: +#endif + SB_LOG(INFO) << " " + << ((tag == DT_ANDROID_REL) ? "DT_ANDROID_REL" + : "DT_ANDROID_RELA") + << " addr=" << std::hex + << (dyn_addr - base_memory_address_); + if (android_relocations_) { + SB_LOG(ERROR) << "Multiple DT_ANDROID_* sections defined."; + return false; + } + android_relocations_ = reinterpret_cast<uint8_t*>(dyn_addr); + break; +#if defined(USE_RELA) + case DT_ANDROID_RELASZ: +#else + case DT_ANDROID_RELSZ: +#endif + SB_LOG(ERROR) << " DT_ANDROID_RELSZ NOT IMPELMENTED"; + android_relocations_size_ = dyn_value; + break; + case DT_RELR: + case DT_ANDROID_RELR: + SB_LOG(ERROR) << " DT_RELR NOT IMPELMENTED"; + break; + case DT_ANDROID_RELRSZ: + case DT_RELRSZ: + SB_LOG(ERROR) << " DT_RELRSZ NOT IMPELMENTED"; + break; + case DT_RELRENT: + case DT_ANDROID_RELRENT: + if (dyn_value != sizeof(Relr)) { + SB_LOG(ERROR) << "Invalid DT_RELRENT value=" << std::hex + << static_cast<int>(dyn_value) + << " expected=" << static_cast<int>(sizeof(Relr)); + return false; + } + break; + case DT_PLTGOT: + SB_LOG(INFO) << "DT_PLTGOT addr=0x" << std::hex + << (dyn_addr - base_memory_address_); + plt_got_ = reinterpret_cast<Addr*>(dyn_addr); + break; + case DT_TEXTREL: + SB_LOG(INFO) << " DT_TEXTREL"; + has_text_relocations_ = true; + break; + case DT_SYMBOLIC: + SB_LOG(INFO) << " DT_SYMBOLIC"; + has_symbolic_ = true; + break; + case DT_FLAGS: + if (dyn_value & DF_TEXTREL) + has_text_relocations_ = true; + if (dyn_value & DF_SYMBOLIC) + has_symbolic_ = true; + + SB_LOG(INFO) << " DT_FLAGS has_text_relocations=" + << has_text_relocations_ + << " has_symbolic=" << has_symbolic_; + + break; + default: + break; + } + } + + return true; +} + +bool Relocations::ApplyAllRelocations() { + SB_LOG(INFO) << "Applying regular relocations"; + if (!ApplyRelocations(reinterpret_cast<rel_t*>(relocations_), + relocations_size_ / sizeof(rel_t))) { + SB_LOG(ERROR) << "regular relocations failed"; + return false; + } + + SB_LOG(INFO) << "Applying PLT relocations"; + if (!ApplyRelocations(reinterpret_cast<rel_t*>(plt_relocations_), + plt_relocations_size_ / sizeof(rel_t))) { + SB_LOG(ERROR) << "PLT relocations failed"; + return false; + } + return true; +} + +bool Relocations::ApplyRelocations(const rel_t* rel, size_t rel_count) { + SB_LOG(INFO) << "rel=" << std::hex << rel << std::dec + << " rel_count=" << rel_count; + + if (!rel) + return true; + + for (size_t rel_n = 0; rel_n < rel_count; rel++, rel_n++) { + SB_LOG(INFO) << " Relocation " << rel_n + 1 << " of " << rel_count; + + if (!ApplyRelocation(rel)) + return false; + } + + return true; +} + +bool Relocations::ApplyRelocation(const rel_t* rel) { + const Word rel_type = ELF_R_TYPE(rel->r_info); + const Word rel_symbol = ELF_R_SYM(rel->r_info); + + Addr sym_addr = 0; + Addr reloc = static_cast<Addr>(rel->r_offset + base_memory_address_); + SB_LOG(INFO) << " offset=0x" << std::hex << rel->r_offset + << " type=" << std::dec << rel_type << " reloc=0x" << std::hex + << reloc << " symbol=" << rel_symbol; + + if (rel_type == 0) + return true; + + if (rel_symbol != 0) { + if (!ResolveSymbol(rel_type, rel_symbol, reloc, &sym_addr)) { + SB_LOG(ERROR) << "Failed to resolve symbol: " << rel_symbol; + return false; + } + } + + return ApplyResolvedReloc(rel, sym_addr); +} + +#if defined(USE_RELA) +bool Relocations::ApplyResolvedReloc(const Rela* rela, Addr sym_addr) { + const Word rela_type = ELF_R_TYPE(rela->r_info); + const Word rela_symbol = ELF_R_SYM(rela->r_info); + const Sword addend = rela->r_addend; + const Addr reloc = static_cast<Addr>(rela->r_offset + base_memory_address_); + + SB_LOG(INFO) << " rela reloc=0x" << std::hex << reloc << " offset=0x" + << rela->r_offset << " type=" << std::dec << rela_type + << " addend=0x" << std::hex << addend; + Addr* target = reinterpret_cast<Addr*>(reloc); + switch (rela_type) { +#if SB_IS(ARCH_ARM) && SB_IS(64_BIT) + case R_AARCH64_JUMP_SLOT: + SB_LOG(INFO) << " R_AARCH64_JUMP_SLOT target=" << std::hex << target + << " addr=" << (sym_addr + addend); + *target = sym_addr + addend; + break; + + case R_AARCH64_GLOB_DAT: + SB_LOG(INFO) << " R_AARCH64_GLOB_DAT target=" << std::hex << target + << " addr=" << (sym_addr + addend); + *target = sym_addr + addend; + break; + + case R_AARCH64_ABS64: + SB_LOG(INFO) << " R_AARCH64_ABS64 target=" << std::hex << target << " " + << *target << " addr=" << sym_addr + addend; + *target += sym_addr + addend; + break; + + case R_AARCH64_RELATIVE: + SB_LOG(INFO) << " R_AARCH64_RELATIVE target=" << std::hex << target + << " " << *target + << " bias=" << base_memory_address_ + addend; + if (!rela_symbol) { + SB_LOG(ERROR) << "Invalid relative relocation with symbol"; + return false; + } + *target = base_memory_address_ + addend; + break; + + case R_AARCH64_COPY: + // NOTE: These relocations are forbidden in shared libraries. + SB_LOG(ERROR) << "Invalid R_AARCH64_COPY relocation in shared library"; + return false; +#endif + +#if SB_IS(ARCH_X86) && SB_IS(64_BIT) + case R_X86_64_JMP_SLOT: + SB_LOG(INFO) << " R_X86_64_JMP_SLOT target=" << std::hex << target + << " addr=" << (sym_addr + addend); + *target = sym_addr + addend; + break; + + case R_X86_64_GLOB_DAT: + SB_LOG(INFO) << " R_X86_64_GLOB_DAT target=" << std::hex << target + << " addr=" << (sym_addr + addend); + + *target = sym_addr + addend; + break; + + case R_X86_64_RELATIVE: + if (rela_symbol) { + SB_LOG(ERROR) << "Invalid R_X86_64_RELATIVE"; + return false; + } + + SB_LOG(INFO) << " R_X86_64_RELATIVE target=" << std::hex << target << " " + << *target << " bias=" << base_memory_address_ + addend; + *target = base_memory_address_ + addend; + break; + + case R_X86_64_64: + *target = sym_addr + addend; + break; + + case R_X86_64_PC32: + *target = sym_addr + (addend - reloc); + break; +#endif + + default: + SB_LOG(ERROR) << "Invalid relocation type: " << rela_type; + return false; + } + + return true; +} +#else +bool Relocations::ApplyResolvedReloc(const Rel* rel, Addr sym_addr) { + const Word rel_type = ELF_R_TYPE(rel->r_info); + const Word rel_symbol = ELF_R_SYM(rel->r_info); + + const Addr reloc = static_cast<Addr>(rel->r_offset + base_memory_address_); + + SB_LOG(INFO) << " rel reloc=0x" << std::hex << reloc << " offset=0x" + << rel->r_offset << " type=" << std::dec << rel_type; + + Addr* target = reinterpret_cast<Addr*>(reloc); + switch (rel_type) { +#if SB_IS(ARCH_ARM) && SB_IS(32_BIT) + case R_ARM_JUMP_SLOT: + SB_LOG(INFO) << " R_ARM_JUMP_SLOT target=" << std::hex << target + << " addr=" << sym_addr; + *target = sym_addr; + break; + + case R_ARM_GLOB_DAT: + SB_LOG(INFO) << " R_ARM_GLOB_DAT target=" << std::hex << target + << " addr=" << sym_addr; + *target = sym_addr; + break; + + case R_ARM_ABS32: + SB_LOG(INFO) << " R_ARM_ABS32 target=" << std::hex << target << " " + << *target << " addr=" << sym_addr; + *target += sym_addr; + break; + + case R_ARM_REL32: + SB_LOG(INFO) << " R_ARM_REL32 target=" << std::hex << target << " " + << *target << " addr=" << sym_addr + << " offset=" << rel->r_offset; + *target += sym_addr - rel->r_offset; + break; + + case R_ARM_RELATIVE: + SB_LOG(INFO) << " RR_ARM_RELATIVE target=" << std::hex << target << " " + << *target << " bias=" << base_memory_address_; + if (!rel_symbol) { + SB_LOG(ERROR) << "Invalid relative relocation with symbol"; + return false; + } + *target += base_memory_address_; + break; + + case R_ARM_COPY: + // NOTE: These relocations are forbidden in shared libraries. + // The Android linker has special code to deal with this, which + // is not needed here. + SB_LOG(ERROR) << "Invalid R_ARM_COPY relocation in shared library"; + + return false; +#endif + +#if SB_IS(ARCH_X86) && SB_IS(32_BIT) + case R_386_JMP_SLOT: + SB_LOG(INFO) << " R_386_JMP_SLOT target=" << std::hex << target + << " addr=" << sym_addr; + + *target = sym_addr; + break; + + case R_386_GLOB_DAT: + SB_LOG(INFO) << " R_386_GLOB_DAT target=" << std::hex << target + << " addr=" << sym_addr; + *target = sym_addr; + + break; + + case R_386_RELATIVE: + if (rel_symbol) { + SB_LOG(ERROR) << "Invalid relative relocation with symbol"; + return false; + } + SB_LOG(INFO) << " R_386_RELATIVE target=" << std::hex << target << " " + << *target << " bias=" << base_memory_address_; + + *target += base_memory_address_; + break; + + case R_386_32: + SB_LOG(INFO) << " R_386_32 target=" << std::hex << target << " " + << *target << " addr=" << sym_addr; + *target += sym_addr; + break; + + case R_386_PC32: + SB_LOG(INFO) << " R_386_PC32 target=" << std::hex << target << " " + << *target << " addr=" << sym_addr << " reloc=" << reloc; + *target += (sym_addr - reloc); + break; +#endif + + default: + SB_LOG(ERROR) << "Invalid relocation type: " << rel_type; + return false; + } + + return true; +} +#endif + +RelocationType Relocations::GetRelocationType(Word r_type) { + switch (r_type) { +#if SB_IS(ARCH_ARM) && SB_IS(32_BIT) + case R_ARM_JUMP_SLOT: + case R_ARM_GLOB_DAT: + case R_ARM_ABS32: + return RELOCATION_TYPE_ABSOLUTE; + + case R_ARM_REL32: + case R_ARM_RELATIVE: + return RELOCATION_TYPE_RELATIVE; + + case R_ARM_COPY: + return RELOCATION_TYPE_COPY; +#endif + +#if SB_IS(ARCH_ARM) && SB_IS(64_BIT) + case R_AARCH64_JUMP_SLOT: + case R_AARCH64_GLOB_DAT: + case R_AARCH64_ABS64: + return RELOCATION_TYPE_ABSOLUTE; + + case R_AARCH64_RELATIVE: + return RELOCATION_TYPE_RELATIVE; + + case R_AARCH64_COPY: + return RELOCATION_TYPE_COPY; +#endif + +#if SB_IS(ARCH_X86) && SB_IS(32_BIT) + case R_386_JMP_SLOT: + case R_386_GLOB_DAT: + case R_386_32: + return RELOCATION_TYPE_ABSOLUTE; + + case R_386_RELATIVE: + return RELOCATION_TYPE_RELATIVE; + + case R_386_PC32: + return RELOCATION_TYPE_PC_RELATIVE; +#endif + +#if SB_IS(ARCH_X86) && SB_IS(64_BIT) + case R_X86_64_JMP_SLOT: + case R_X86_64_GLOB_DAT: + case R_X86_64_64: + return RELOCATION_TYPE_ABSOLUTE; + + case R_X86_64_RELATIVE: + return RELOCATION_TYPE_RELATIVE; + + case R_X86_64_PC32: + return RELOCATION_TYPE_PC_RELATIVE; +#endif + default: + return RELOCATION_TYPE_UNKNOWN; + } +} + +bool Relocations::ResolveSymbol(Word rel_type, + Word rel_symbol, + Addr reloc, + Addr* sym_addr) { + const char* sym_name = dynamic_section_->LookupNameById(rel_symbol); + SB_LOG(INFO) << "Resolve: " << sym_name; + const void* address = NULL; + + const Sym* sym = dynamic_section_->LookupByName(sym_name); + if (sym) { + address = reinterpret_cast<void*>(base_memory_address_ + sym->st_value); + } else { + address = exported_symbols_->Lookup(sym_name); + } + + SB_LOG(INFO) << "Resolve: address=0x" << std::hex << address; + + if (address) { + // The symbol was found, so compute its address. + *sym_addr = reinterpret_cast<Addr>(address); + return true; + } + + // The symbol was not found. Normally this is an error except + // if this is a weak reference. + if (!dynamic_section_->IsWeakById(rel_symbol)) { + SB_LOG(ERROR) << "Could not find symbol: " << sym_name; + return false; + } + + // IHI0044C AAELF 4.5.1.1: + // Libraries are not searched to resolve weak references. + // It is not an error for a weak reference to remain + // unsatisfied. + // + // During linking, the value of an undefined weak reference is: + // - Zero if the relocation type is absolute + // - The address of the place if the relocation is pc-relative + // - The address of nominal base address if the relocation + // type is base-relative. + RelocationType r = GetRelocationType(rel_type); + if (r == RELOCATION_TYPE_ABSOLUTE || r == RELOCATION_TYPE_RELATIVE) { + *sym_addr = 0; + return true; + } + + if (r == RELOCATION_TYPE_PC_RELATIVE) { + *sym_addr = reloc; + return true; + } + + SB_LOG(ERROR) << "Invalid weak relocation type (" << r + << ") for unknown symbol '" << sym_name << "'"; + return false; +} +} // namespace elf_loader +} // namespace starboard
diff --git a/src/starboard/elf_loader/relocations.h b/src/starboard/elf_loader/relocations.h new file mode 100644 index 0000000..b763c1b --- /dev/null +++ b/src/starboard/elf_loader/relocations.h
@@ -0,0 +1,96 @@ +// Copyright 2019 The Cobalt Authors. 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. + +#ifndef STARBOARD_ELF_LOADER_RELOCATIONS_H_ +#define STARBOARD_ELF_LOADER_RELOCATIONS_H_ + +#include "starboard/elf_loader/elf.h" + +#include "starboard/elf_loader/dynamic_section.h" +#include "starboard/elf_loader/program_table.h" + +namespace starboard { +namespace elf_loader { + +enum RelocationType { + RELOCATION_TYPE_UNKNOWN = 0, + RELOCATION_TYPE_ABSOLUTE = 1, + RELOCATION_TYPE_RELATIVE = 2, + RELOCATION_TYPE_PC_RELATIVE = 3, + RELOCATION_TYPE_COPY = 4, +}; + +// class representing the ELF relocations. +class Relocations { + public: + Relocations(Addr base_memory_adddress, + DynamicSection* dynamic_section, + ExportedSymbols* exported_symbols); + + // Initialize the relocation tables. + bool InitRelocations(); + + // Apply all the relocations. + bool ApplyAllRelocations(); + + // Apply a set of relocations. + bool ApplyRelocations(const rel_t* rel, size_t rel_count); + + // Apply an individual relocation. + bool ApplyRelocation(const rel_t* rel); + +// Apply a resolved symbol relocation. +#if defined(USE_RELA) + bool ApplyResolvedReloc(const Rela* rela, Addr sym_addr); +#else + bool ApplyResolvedReloc(const Rel* rel, Addr sym_addr); +#endif + + // Convert an ELF relocation type info a RelocationType value. + RelocationType GetRelocationType(Word r_type); + + // Resolve a symbol address. + bool ResolveSymbol(Word rel_type, + Word rel_symbol, + Addr reloc, + Addr* sym_addr); + + // Checks if there are any text relocations. + bool HasTextRelocations(); + + private: + Addr base_memory_address_; + DynamicSection* dynamic_section_; + Addr plt_relocations_; + size_t plt_relocations_size_; + Addr* plt_got_; + + Addr relocations_; + size_t relocations_size_; + + uint8_t* android_relocations_; + size_t android_relocations_size_; + + bool has_text_relocations_; + bool has_symbolic_; + + ExportedSymbols* exported_symbols_; + + SB_DISALLOW_COPY_AND_ASSIGN(Relocations); +}; + +} // namespace elf_loader +} // namespace starboard + +#endif // STARBOARD_ELF_LOADER_RELOCATIONS_H_
diff --git a/src/starboard/elf_loader/relocations_test.cc b/src/starboard/elf_loader/relocations_test.cc new file mode 100644 index 0000000..a95d7e5 --- /dev/null +++ b/src/starboard/elf_loader/relocations_test.cc
@@ -0,0 +1,74 @@ +// Copyright 2019 The Cobalt Authors. 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 "starboard/elf_loader/relocations.h" + +#include "starboard/common/scoped_ptr.h" +#include "starboard/elf_loader/elf.h" +#include "starboard/elf_loader/file_impl.h" +#include "starboard/string.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace starboard { +namespace elf_loader { + +namespace { + +// TODO: implement +class RelocationsTest : public ::testing::Test { + protected: + RelocationsTest() {} + ~RelocationsTest() {} + + scoped_ptr<Relocations> relocations_; +}; + +#if SB_IS(ARCH_X86) && SB_IS(64_BIT) +TEST_F(RelocationsTest, Initialize_X86_64) { + char buff[1024] = "AAAAAAAAAAAAAAAAAAA"; + Addr load_bias = reinterpret_cast<Addr>(&buff); + Dyn dynamic_table[10]; + Dyn entry1; + entry1.d_tag = DT_REL; + + dynamic_table[0] = entry1; + Dyn* dyn = dynamic_table; + size_t dyn_count = 1; + Word dyn_flags = 0; + + scoped_ptr<DynamicSection> dynamic_section( + new DynamicSection(load_bias, dyn, dyn_count, dyn_flags)); + dynamic_section->InitDynamicSection(); + dynamic_section->InitDynamicSymbols(); + + scoped_ptr<ExportedSymbols> exported_symbols(new ExportedSymbols()); + relocations_.reset(new Relocations(load_bias, dynamic_section.get(), + exported_symbols.get())); + Rela rela; + rela.r_offset = 2; + rela.r_info = R_X86_64_JMP_SLOT; + rela.r_addend = 5; + Addr sym_addr = 34; + + Addr target = rela.r_offset + load_bias; + SB_LOG(INFO) << "target= " << reinterpret_cast<char*>(target); + relocations_->ApplyResolvedReloc(&rela, sym_addr); + EXPECT_EQ(39, *reinterpret_cast<Elf64_Sxword*>(buff + 2)); + SB_LOG(INFO) << "buffer= " << *reinterpret_cast<Elf64_Sxword*>(buff + 2); +} +#endif + +} // namespace +} // namespace elf_loader +} // namespace starboard
diff --git a/src/starboard/elf_loader/sandbox.cc b/src/starboard/elf_loader/sandbox.cc new file mode 100644 index 0000000..86e0476 --- /dev/null +++ b/src/starboard/elf_loader/sandbox.cc
@@ -0,0 +1,52 @@ +// Copyright 2019 The Cobalt Authors. 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 "starboard/common/log.h" +#include "starboard/event.h" + +#include "starboard/elf_loader/elf_loader.h" + +starboard::elf_loader::ElfLoader g_elfLoader; + +void (*g_sb_event_func)(const SbEvent*) = NULL; + +void SbEventHandle(const SbEvent* event) { + switch (event->type) { + case kSbEventTypeStart: { + SbEventStartData* data = static_cast<SbEventStartData*>(event->data); + if (!g_sb_event_func && data->argument_count == 2) { + if (!g_elfLoader.Load(data->argument_values[1])) { + SB_LOG(INFO) << "Failed to load library"; + return; + } + + SB_LOG(INFO) << "Successfully loaded library\n"; + void* p = g_elfLoader.LookupSymbol("SbEventHandle"); + if (p != NULL) { + SB_LOG(INFO) << "Symbol Lookup succeeded address=0x" << std::hex << p; + g_sb_event_func = (void (*)(const SbEvent*))p; + g_sb_event_func(event); + } else { + SB_LOG(INFO) << "Symbol Lookup failed\n"; + } + } + break; + } + default: { + if (g_sb_event_func) { + g_sb_event_func(event); + } + } + } +}
diff --git a/src/starboard/linux/shared/audio_sink_type_dispatcher.cc b/src/starboard/linux/shared/audio_sink_type_dispatcher.cc index 22bc79b..2a0b581 100644 --- a/src/starboard/linux/shared/audio_sink_type_dispatcher.cc +++ b/src/starboard/linux/shared/audio_sink_type_dispatcher.cc
@@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "starboard/common/log.h" #include "starboard/shared/alsa/alsa_audio_sink_type.h" #include "starboard/shared/pulse/pulse_audio_sink_type.h" #include "starboard/shared/starboard/audio_sink/audio_sink_internal.h" @@ -23,7 +24,10 @@ // static void SbAudioSinkPrivate::PlatformInitialize() { starboard::shared::pulse::PlatformInitialize(); - if (!GetPrimaryType()) { + if (GetPrimaryType()) { + SB_LOG(INFO) << "Use PulseAudio"; + } else { + SB_LOG(INFO) << "Use ALSA"; starboard::shared::alsa::PlatformInitialize(); is_fallback_to_alsa = true; }
diff --git a/src/starboard/nplb/audio_sink_test.cc b/src/starboard/nplb/audio_sink_test.cc index 326fb8d..caa7870 100644 --- a/src/starboard/nplb/audio_sink_test.cc +++ b/src/starboard/nplb/audio_sink_test.cc
@@ -38,9 +38,10 @@ AudioSinkTestEnvironment environment(frame_buffers); ASSERT_TRUE(environment.is_valid()); + // Audio sink need to be fully filled once to ensure it can start working. int frames_to_append = frame_buffers.frames_per_channel(); + environment.AppendFrame(frames_to_append); - environment.AppendFrame(frames_to_append / 2); EXPECT_TRUE(environment.WaitUntilSomeFramesAreConsumed()); } @@ -50,8 +51,8 @@ ASSERT_TRUE(environment.is_valid()); int frames_to_append = frame_buffers.frames_per_channel(); - environment.AppendFrame(frames_to_append / 2); + EXPECT_TRUE(environment.WaitUntilAllFramesAreConsumed()); } @@ -60,11 +61,13 @@ AudioSinkTestEnvironment environment(frame_buffers); ASSERT_TRUE(environment.is_valid()); + // Audio sink need to be fully filled once to ensure it can start working. int frames_to_append = frame_buffers.frames_per_channel(); + environment.AppendFrame(frames_to_append); - environment.AppendFrame(frames_to_append / 2); EXPECT_TRUE(environment.WaitUntilSomeFramesAreConsumed()); - environment.AppendFrame(frames_to_append / 2); + ASSERT_GT(environment.GetFrameBufferFreeSpaceAmount(), 0); + environment.AppendFrame(environment.GetFrameBufferFreeSpaceAmount()); EXPECT_TRUE(environment.WaitUntilAllFramesAreConsumed()); } @@ -75,9 +78,10 @@ environment.SetIsPlaying(false); + // Audio sink need to be fully filled once to ensure it can start working. int frames_to_append = frame_buffers.frames_per_channel(); + environment.AppendFrame(frames_to_append); - environment.AppendFrame(frames_to_append / 2); int free_space = environment.GetFrameBufferFreeSpaceAmount(); EXPECT_TRUE(environment.WaitUntilUpdateStatusCalled()); EXPECT_TRUE(environment.WaitUntilUpdateStatusCalled()); @@ -91,12 +95,14 @@ AudioSinkTestEnvironment environment(frame_buffers); ASSERT_TRUE(environment.is_valid()); + // Audio sink need to be fully filled once to ensure it can start working. int frames_to_append = frame_buffers.frames_per_channel(); + environment.AppendFrame(frames_to_append); - environment.AppendFrame(frames_to_append / 2); EXPECT_TRUE(environment.WaitUntilSomeFramesAreConsumed()); SbThreadSleep(250 * kSbTimeMillisecond); - environment.AppendFrame(frames_to_append / 2); + ASSERT_GT(environment.GetFrameBufferFreeSpaceAmount(), 0); + environment.AppendFrame(environment.GetFrameBufferFreeSpaceAmount()); EXPECT_TRUE(environment.WaitUntilAllFramesAreConsumed()); }
diff --git a/src/starboard/nplb/cpu_features_get_test.cc b/src/starboard/nplb/cpu_features_get_test.cc index 87fa1ba..97c2271 100644 --- a/src/starboard/nplb/cpu_features_get_test.cc +++ b/src/starboard/nplb/cpu_features_get_test.cc
@@ -100,7 +100,8 @@ EXPECT_EQ(kSbCPUFeaturesArchitectureUnknown, features.architecture); EXPECT_NE(nullptr, features.brand); EXPECT_EQ(0, strlen(features.brand)); - EXPECT_EQ(kFeatureValueInvalid, features.cache_size); + EXPECT_EQ(kFeatureValueInvalid, features.icache_line_size); + EXPECT_EQ(kFeatureValueInvalid, features.dcache_line_size); EXPECT_FALSE(features.has_fpu); EXPECT_EQ(0, features.hwcap); EXPECT_EQ(0, features.hwcap2);
diff --git a/src/starboard/raspi/shared/gyp_configuration.py b/src/starboard/raspi/shared/gyp_configuration.py index 21e3c72..e7668ea 100644 --- a/src/starboard/raspi/shared/gyp_configuration.py +++ b/src/starboard/raspi/shared/gyp_configuration.py
@@ -106,6 +106,10 @@ 'player_filter_tests': [ # TODO: debug these failures. 'VideoDecoderTests/VideoDecoderTest.EndOfStreamWithoutAnyInput/0', - 'VideoDecoderTests/VideoDecoderTest.SingleInvalidInput/0', + 'VideoDecoderTests/VideoDecoderTest.MultipleResets/0', + 'VideoDecoderTests/VideoDecoderTest.SingleInvalidInput/*', + 'VideoDecoderTests/VideoDecoderTest' + '.MultipleValidInputsAfterInvalidKeyFrame/*', + 'VideoDecoderTests/VideoDecoderTest.MultipleInvalidInput/*', ], }
diff --git a/src/starboard/raspi/shared/starboard_platform.gypi b/src/starboard/raspi/shared/starboard_platform.gypi index 4a8b07e..b20edc6 100644 --- a/src/starboard/raspi/shared/starboard_platform.gypi +++ b/src/starboard/raspi/shared/starboard_platform.gypi
@@ -140,6 +140,7 @@ '<(DEPTH)/starboard/shared/libevent/socket_waiter_wait_timed.cc', '<(DEPTH)/starboard/shared/libevent/socket_waiter_wake_up.cc', '<(DEPTH)/starboard/shared/linux/byte_swap.cc', + '<(DEPTH)/starboard/shared/linux/cpu_features_get.cc', '<(DEPTH)/starboard/shared/linux/dev_input/dev_input.cc', '<(DEPTH)/starboard/shared/linux/get_home_directory.cc', '<(DEPTH)/starboard/shared/linux/memory_get_stack_bounds.cc', @@ -352,7 +353,6 @@ '<(DEPTH)/starboard/shared/starboard/window_set_default_options.cc', '<(DEPTH)/starboard/shared/stub/accessibility_get_display_settings.cc', '<(DEPTH)/starboard/shared/stub/accessibility_get_text_to_speech_settings.cc', - '<(DEPTH)/starboard/shared/stub/cpu_features_get.cc', '<(DEPTH)/starboard/shared/stub/cryptography_create_transformer.cc', '<(DEPTH)/starboard/shared/stub/cryptography_destroy_transformer.cc', '<(DEPTH)/starboard/shared/stub/cryptography_get_tag.cc',
diff --git a/src/starboard/raspi/shared/thread_create_priority.cc b/src/starboard/raspi/shared/thread_create_priority.cc index b068feb..981c9d6 100644 --- a/src/starboard/raspi/shared/thread_create_priority.cc +++ b/src/starboard/raspi/shared/thread_create_priority.cc
@@ -27,6 +27,19 @@ // This is the maximum priority that will be passed to SetRoundRobinScheduler(). const int kMaxRoundRobinPriority = 2; +// Permissions are needed to allow usage non-default thread schedulers and +// thread priorities. Specifically, /etc/security/limits.conf should set +// "rtprio" and "nice" limits. "rtprio" will allow use of the real-time +// schedulers, and "nice" will allow use of nice priorities as well as allow +// SCHED_IDLE threads to increase their priority. If the user is 'pi', then +// limits.conf should have the following lines: +// @pi hard rtprio 99 +// @pi soft rtprio 99 +// @pi hard nice -20 +// @pi soft nice -20 +const char kSchedulerErrorMessage[] = "Unable to set scheduler. Please update " + "limits.conf to set 'rtprio' limit to 99 and 'nice' limit to -20."; + // Note that use of sched_setscheduler() has been found to be more reliably // supported than pthread_setschedparam(), so we are using that. @@ -34,14 +47,14 @@ struct sched_param thread_sched_param; thread_sched_param.sched_priority = 0; int result = sched_setscheduler(0, SCHED_IDLE, &thread_sched_param); - SB_CHECK(result == 0); + SB_CHECK(result == 0) << kSchedulerErrorMessage; } void SetOtherScheduler() { struct sched_param thread_sched_param; thread_sched_param.sched_priority = 0; int result = sched_setscheduler(0, SCHED_OTHER, &thread_sched_param); - SB_CHECK(result == 0); + SB_CHECK(result == 0) << kSchedulerErrorMessage; } // Here |priority| is a number >= 0, where the higher the number, the @@ -83,7 +96,7 @@ std::min(min_priority + priority, static_cast<int>(rlimit_rtprio.rlim_cur)); int result = sched_setscheduler(0, SCHED_RR, &thread_sched_param); - SB_CHECK(result == 0); + SB_CHECK(result == 0) << kSchedulerErrorMessage; } void ThreadSetPriority(SbThreadPriority priority) {
diff --git a/src/starboard/shared/blittergles/blitter_create_default_device.cc b/src/starboard/shared/blittergles/blitter_create_default_device.cc index e7becb8..abec352 100644 --- a/src/starboard/shared/blittergles/blitter_create_default_device.cc +++ b/src/starboard/shared/blittergles/blitter_create_default_device.cc
@@ -22,6 +22,8 @@ #include "starboard/common/optional.h" #include "starboard/shared/blittergles/blitter_context.h" #include "starboard/shared/blittergles/blitter_internal.h" +#include "starboard/shared/blittergles/blitter_surface.h" +#include "starboard/shared/blittergles/color_shader_program.h" #include "starboard/shared/gles/gl_call.h" #include "starboard/shared/x11/application_x11.h" #include "starboard/window.h" @@ -79,6 +81,21 @@ return starboard::nullopt; } +// When using Xvfb, the selected drivers will leak memory on the 1st call to +// glDrawArrays(). We get that draw out of the way with a dummy draw here. +void DummyDraw(SbBlitterContext context) { + SbBlitterSurface dummy_surface = SbBlitterCreateRenderTargetSurface( + context->device, 1, 1, kSbBlitterSurfaceFormatRGBA8); + SbBlitterSetRenderTarget(context, dummy_surface->render_target); + SbBlitterContextPrivate::ScopedCurrentContext scoped_current_context(context); + const starboard::shared::blittergles::ColorShaderProgram& + color_shader_program = context->GetColorShaderProgram(); + color_shader_program.DummyDraw(dummy_surface->render_target); + context->current_render_target = kSbBlitterInvalidRenderTarget; + context->scissor = SbBlitterMakeRect(0, 0, 0, 0); + SbBlitterDestroySurface(dummy_surface); +} + } // namespace SbBlitterDevice SbBlitterCreateDefaultDevice() { @@ -97,8 +114,17 @@ SB_DLOG(ERROR) << ": Failed to get EGL display connection."; return kSbBlitterInvalidDevice; } - eglInitialize(device->display, NULL, NULL); - if (eglGetError() != EGL_SUCCESS) { + + // When running on Xvfb, sometimes ANGLE fails to open the default X display. + // By retrying, we increase the chances that eglInitialize() will succeed. + // This is a temporary fix. + int max_tries = 3, num_tries = 0; + bool initialized = false; + do { + initialized = eglInitialize(device->display, NULL, NULL); + ++num_tries; + } while (!initialized && num_tries < max_tries); + if (!initialized) { SB_DLOG(ERROR) << ": Failed to initialize device."; return kSbBlitterInvalidDevice; } @@ -120,5 +146,7 @@ starboard::ScopedLock context_lock(context_registry->mutex); context_registry->context = context.release(); + DummyDraw(context_registry->context); + return device_registry->default_device; }
diff --git a/src/starboard/shared/blittergles/blitter_create_render_target_surface.cc b/src/starboard/shared/blittergles/blitter_create_render_target_surface.cc index 7f5d2bf..6ed0927 100644 --- a/src/starboard/shared/blittergles/blitter_create_render_target_surface.cc +++ b/src/starboard/shared/blittergles/blitter_create_render_target_surface.cc
@@ -46,7 +46,9 @@ surface->info.height = height; surface->info.format = surface_format; surface->color_texture_handle = 0; - surface->SetTexture(NULL); + if (!surface->SetTexture(NULL)) { + return kSbBlitterInvalidSurface; + } std::unique_ptr<SbBlitterRenderTargetPrivate> render_target( new SbBlitterRenderTargetPrivate()); render_target->swap_chain = kSbBlitterInvalidSwapChain; @@ -56,7 +58,9 @@ render_target->device = device; render_target->framebuffer_handle = 0; surface->render_target = render_target.release(); - surface->render_target->SetFramebuffer(); + if (!surface->render_target->SetFramebuffer()) { + return kSbBlitterInvalidSurface; + } return surface.release(); }
diff --git a/src/starboard/shared/blittergles/blitter_download_surface_pixels.cc b/src/starboard/shared/blittergles/blitter_download_surface_pixels.cc index af006fb..2757b65 100644 --- a/src/starboard/shared/blittergles/blitter_download_surface_pixels.cc +++ b/src/starboard/shared/blittergles/blitter_download_surface_pixels.cc
@@ -101,7 +101,9 @@ dummy_render_target->width = surface->info.width; dummy_render_target->height = surface->info.height; dummy_render_target->device = surface->device; - dummy_render_target->SetFramebuffer(); + if (!dummy_render_target->SetFramebuffer()) { + return false; + } starboard::shared::blittergles::SbBlitterContextRegistry* context_registry = starboard::shared::blittergles::GetBlitterContextRegistry();
diff --git a/src/starboard/shared/blittergles/blitter_internal.cc b/src/starboard/shared/blittergles/blitter_internal.cc index fec01db..6661cbc 100644 --- a/src/starboard/shared/blittergles/blitter_internal.cc +++ b/src/starboard/shared/blittergles/blitter_internal.cc
@@ -150,22 +150,22 @@ } // namespace shared } // namespace starboard -void SbBlitterRenderTargetPrivate::SetFramebuffer() { +bool SbBlitterRenderTargetPrivate::SetFramebuffer() { if (surface->color_texture_handle == 0) { - return; + return false; } SbBlitterContextPrivate::ScopedCurrentContext scoped_current_context; glGenFramebuffers(1, &framebuffer_handle); if (framebuffer_handle == 0) { SB_DLOG(ERROR) << ": Error creating new framebuffer."; - return; + return false; } glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_handle); if (glGetError() != GL_NO_ERROR) { GL_CALL(glDeleteFramebuffers(1, &framebuffer_handle)); framebuffer_handle = 0; SB_DLOG(ERROR) << ": Error binding framebuffer."; - return; + return false; } GL_CALL(glBindTexture(GL_TEXTURE_2D, surface->color_texture_handle)); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, @@ -176,7 +176,7 @@ framebuffer_handle = 0; surface->color_texture_handle = 0; SB_DLOG(ERROR) << ": Error drawing empty image to framebuffer."; - return; + return false; } GL_CALL(glBindTexture(GL_TEXTURE_2D, 0)); @@ -186,7 +186,8 @@ framebuffer_handle = 0; surface->color_texture_handle = 0; SB_DLOG(ERROR) << ": Failed to create framebuffer."; - return; + return false; } GL_CALL(glBindFramebuffer(GL_FRAMEBUFFER, 0)); + return true; }
diff --git a/src/starboard/shared/blittergles/blitter_internal.h b/src/starboard/shared/blittergles/blitter_internal.h index f62d717..2cc517a 100644 --- a/src/starboard/shared/blittergles/blitter_internal.h +++ b/src/starboard/shared/blittergles/blitter_internal.h
@@ -91,8 +91,8 @@ GLuint framebuffer_handle; // Sets framebuffer_handle and binds the texture from the surface field to it. - // On failure, sets framebuffer_handle to 0. - void SetFramebuffer(); + // On failure, sets framebuffer_handle to 0 and returns false. + bool SetFramebuffer(); }; struct SbBlitterSwapChainPrivate {
diff --git a/src/starboard/shared/blittergles/blitter_surface.cc b/src/starboard/shared/blittergles/blitter_surface.cc index 25054fd..06edbd6 100644 --- a/src/starboard/shared/blittergles/blitter_surface.cc +++ b/src/starboard/shared/blittergles/blitter_surface.cc
@@ -29,22 +29,22 @@ } } -void SbBlitterSurfacePrivate::SetTexture(void* pixel_data) { +bool SbBlitterSurfacePrivate::SetTexture(void* pixel_data) { SbBlitterContextPrivate::ScopedCurrentContext scoped_current_context; if (scoped_current_context.InitializationError()) { - return; + return false; } glGenTextures(1, &color_texture_handle); if (color_texture_handle == 0) { SB_DLOG(ERROR) << ": Error creating new texture."; - return; + return false; } glBindTexture(GL_TEXTURE_2D, color_texture_handle); if (glGetError() != GL_NO_ERROR) { GL_CALL(glDeleteTextures(1, &color_texture_handle)); color_texture_handle = 0; SB_DLOG(ERROR) << ": Error binding new texture."; - return; + return false; } GL_CALL(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); GL_CALL(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); @@ -59,8 +59,9 @@ GL_CALL(glDeleteTextures(1, &color_texture_handle)); color_texture_handle = 0; SB_DLOG(ERROR) << ": Error allocating new texture backing."; - return; + return false; } GL_CALL(glBindTexture(GL_TEXTURE_2D, 0)); + return true; }
diff --git a/src/starboard/shared/blittergles/blitter_surface.h b/src/starboard/shared/blittergles/blitter_surface.h index c1d734b..cf0f29f 100644 --- a/src/starboard/shared/blittergles/blitter_surface.h +++ b/src/starboard/shared/blittergles/blitter_surface.h
@@ -36,8 +36,8 @@ GLuint color_texture_handle; // Sets the color_texture_handle field using given pixel_data. On failure, - // resets color_texture_handle to 0. - void SetTexture(void* pixel_data); + // resets color_texture_handle to 0 and returns false. + bool SetTexture(void* pixel_data); }; #endif // STARBOARD_SHARED_BLITTERGLES_BLITTER_SURFACE_H_
diff --git a/src/starboard/shared/blittergles/color_shader_program.cc b/src/starboard/shared/blittergles/color_shader_program.cc index d3978d0..38bbd83 100644 --- a/src/starboard/shared/blittergles/color_shader_program.cc +++ b/src/starboard/shared/blittergles/color_shader_program.cc
@@ -15,6 +15,18 @@ #include "starboard/shared/blittergles/color_shader_program.h" #include <GLES2/gl2.h> +#if defined(ADDRESS_SANITIZER) +// By default, Leak Sanitizer and Address Sanitizer is expected to exist +// together. However, this is not true for all platforms. +// HAS_LEAK_SANTIZIER=0 explicitly removes the Leak Sanitizer from code. +#ifndef HAS_LEAK_SANITIZER +#define HAS_LEAK_SANITIZER 1 +#endif // HAS_LEAK_SANITIZER +#endif // defined(ADDRESS_SANITIZER) + +#if HAS_LEAK_SANITIZER +#include <sanitizer/lsan_interface.h> +#endif // HAS_LEAK_SANITIZER #include "starboard/blitter.h" #include "starboard/shared/blittergles/blitter_internal.h" @@ -75,6 +87,29 @@ return success; } +void ColorShaderProgram::DummyDraw(SbBlitterRenderTarget render_target) const { + GL_CALL(glUseProgram(GetProgramHandle())); + + float vertices[8]; + SetNDC(SbBlitterMakeRect(0, 0, 1, 1), render_target->width, + render_target->height, vertices); + GL_CALL(glVertexAttribPointer(kPositionAttribute, 2, GL_FLOAT, GL_FALSE, 0, + vertices)); + GL_CALL(glEnableVertexAttribArray(kPositionAttribute)); + GL_CALL(glVertexAttrib4f(kColorAttribute, 0.0f, 0.0f, 0.0f, 0.0f)); + +#if HAS_LEAK_SANITIZER + __lsan_disable(); +#endif // HAS_LEAK_SANITIZER + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); +#if HAS_LEAK_SANITIZER + __lsan_enable(); +#endif // HAS_LEAK_SANITIZER + + GL_CALL(glDisableVertexAttribArray(kPositionAttribute)); + GL_CALL(glUseProgram(0)); +} + } // namespace blittergles } // namespace shared } // namespace starboard
diff --git a/src/starboard/shared/blittergles/color_shader_program.h b/src/starboard/shared/blittergles/color_shader_program.h index a682a5a..e99dfdd 100644 --- a/src/starboard/shared/blittergles/color_shader_program.h +++ b/src/starboard/shared/blittergles/color_shader_program.h
@@ -33,6 +33,10 @@ float (&color_rgba)[4], SbBlitterRect rect) const; + // Method that draws a 1x1 transparent rectangle and disables leak sanitizer + // around glDrawArrays(). + void DummyDraw(SbBlitterRenderTarget render_target) const; + private: // Location of the shader attribute "a_position" for the color shader. static const int kPositionAttribute = 0;
diff --git a/src/starboard/shared/linux/cpu_features_get.cc b/src/starboard/shared/linux/cpu_features_get.cc new file mode 100644 index 0000000..d8ce245 --- /dev/null +++ b/src/starboard/shared/linux/cpu_features_get.cc
@@ -0,0 +1,515 @@ +// Copyright 2019 The Cobalt Authors. 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 "starboard/cpu_features.h" + +#include <dlfcn.h> // dlsym, dlclose, dlopen +#include <linux/auxvec.h> // AT_HWCAP +#include <stdio.h> // fopen, fclose +#include <string.h> +#include <strings.h> // strcasecmp +#include <sys/auxv.h> +#include <unistd.h> // sysconf() +#include <memory> + +#include <cstdlib> + +#include "starboard/common/log.h" +#include "starboard/shared/starboard/cpu_features.h" + +#if SB_API_VERSION >= 11 + +namespace { + +// See <asm/hwcap.h> kernel header. +#define HWCAP_VFP (1 << 6) +#define HWCAP_IWMMXT (1 << 9) +#define HWCAP_NEON (1 << 12) +#define HWCAP_VFPv3 (1 << 13) +#define HWCAP_VFPv3D16 (1 << 14) /* also set for VFPv4-D16 */ +#define HWCAP_VFPv4 (1 << 16) +#define HWCAP_IDIVA (1 << 17) +#define HWCAP_IDIVT (1 << 18) +#define HWCAP_VFPD32 (1 << 19) /* set if VFP has 32 regs (not 16) */ +#define HWCAP_IDIV (HWCAP_IDIVA | HWCAP_IDIVT) + +// see <uapi/asm/hwcap.h> kernel header +#define HWCAP2_AES (1 << 0) +#define HWCAP2_PMULL (1 << 1) +#define HWCAP2_SHA1 (1 << 2) +#define HWCAP2_SHA2 (1 << 3) +#define HWCAP2_CRC32 (1 << 4) + +// Preset hwcap for Armv8 +#define HWCAP_SET_FOR_ARMV8 \ + (HWCAP_VFP | HWCAP_NEON | HWCAP_VFPv3 | HWCAP_VFPv4 | HWCAP_IDIV) + +using starboard::shared::SetX86FeaturesInvalid; +using starboard::shared::SetArmFeaturesInvalid; +using starboard::shared::SetGeneralFeaturesInvalid; + +// Checks if a space-separated list of items |list|, in the form of a string, +// contains one given item |item|. +bool HasItemInList(const char* list, const char* flag) { + ssize_t flag_length = strlen(flag); + const char* list_ptr = list; + if (list_ptr == nullptr) { + return false; + } + while (*list_ptr != '\0') { + // Skip whitespace. + while (isspace(*list_ptr)) + ++list_ptr; + + // Find end of current list flag. + const char* end_ptr = list_ptr; + while (*end_ptr != '\0' && !isspace(*end_ptr)) + ++end_ptr; + + if (flag_length == end_ptr - list_ptr && + memcmp(list_ptr, flag, flag_length) == 0) { + return true; + } + + // Continue to the next flag. + list_ptr = end_ptr; + } + return false; +} + +// Class that holds the information in system file /proc/cpuinfo. +class ProcCpuInfo { + // Raw data of the file /proc/cpuinfo + std::unique_ptr<char[]> file_data_; + // Size of the raw data + size_t file_data_size_; + + public: + explicit ProcCpuInfo(const char* file_path = "/proc/cpuinfo") { + file_data_size_ = 0; + // Get the size of the cpuinfo file by reading it until the end. This is + // required because files under /proc do not always return a valid size + // when using fseek(0, SEEK_END) + ftell(). Nor can the be mmap()-ed. + FILE* file = fopen(file_path, "r"); + if (file != nullptr) { + for (;;) { + char file_buffer[256]; + size_t data_size = fread(file_buffer, 1, sizeof(file_buffer), file); + if (data_size == 0) { + break; + } + file_data_size_ += data_size; + } + fclose(file); + } + + // Read the contents of the cpuinfo file. + file_data_ = std::unique_ptr<char[]>(new char[file_data_size_ + 1]); + char* file_data_ptr = file_data_.get(); + memset(file_data_ptr, 0, file_data_size_ + 1); + + file = fopen(file_path, "r"); + if (file != nullptr) { + for (size_t offset = 0; offset < file_data_size_;) { + size_t data_size = + fread(file_data_ptr + offset, 1, file_data_size_ - offset, file); + if (data_size == 0) { + break; + } + offset += data_size; + } + fclose(file); + } + + // Zero-terminate the data. + file_data_ptr[file_data_size_] = '\0'; + } + ~ProcCpuInfo() { file_data_.reset(); } + + // Extract the string feature data named by |feature| and store in + // |out_feature| whose size is |out_feature_size|. + bool ExtractStringFeature(const char* feature, + char* out_feature, + size_t out_feature_size) { + if (feature == nullptr) { + return false; + } + + // Look for first feature occurrence, and ensure it starts the line. + size_t feature_name_size = strlen(feature); + const char* feature_ptr = nullptr; + char* file_data_ptr = file_data_.get(); + + const char* line_start_ptr = file_data_.get(); + while (line_start_ptr < file_data_ptr + file_data_size_) { + // Find the end of the line. + const char* line_end_ptr = strchr(line_start_ptr, '\n'); + if (line_end_ptr == nullptr) { + line_end_ptr = file_data_ptr + file_data_size_; + } + + char line_buffer[line_end_ptr - line_start_ptr + + 1]; // NOLINT(runtime/arrays) + memset(line_buffer, 0, sizeof(line_buffer)); + memcpy(line_buffer, line_start_ptr, line_end_ptr - line_start_ptr); + line_buffer[line_end_ptr - line_start_ptr] = '\0'; + + // Find the colon + const char* colon_ptr = strchr(line_buffer, ':'); + if (colon_ptr == nullptr || !isspace(colon_ptr[1])) { + line_start_ptr = line_end_ptr + 1; + continue; + } + + line_buffer[colon_ptr - line_buffer] = '\0'; + + // Trim trailing white space of the line before colon + const char* feature_end_ptr = colon_ptr - 1; + while (feature_end_ptr >= line_buffer && + isspace(line_buffer[feature_end_ptr - line_buffer])) { + line_buffer[feature_end_ptr - line_buffer] = '\0'; + feature_end_ptr--; + } + // Out of boundary + if (feature_end_ptr < line_buffer) { + line_start_ptr = line_end_ptr + 1; + continue; + } + // Trim leading white space of the line + const char* feature_start_ptr = line_buffer; + while (feature_start_ptr <= feature_end_ptr && + isspace(line_buffer[feature_start_ptr - line_buffer])) { + line_buffer[feature_start_ptr - line_buffer] = '\0'; + feature_start_ptr++; + } + // There is no need to check feature_start_ptr out of boundary, because if + // feature_start_ptr > feature_end_ptr, it means the line before colon is + // all white space, and feature_end_ptr will be out of boundary already. + + if (strcmp(feature_start_ptr, feature) != 0) { + line_start_ptr = line_end_ptr + 1; + continue; + } + + feature_ptr = colon_ptr + 2 - line_buffer + line_start_ptr; + break; + } + + if (feature_ptr == nullptr) { + return false; + } + + // Find the end of the line. + const char* line_end_ptr = strchr(feature_ptr, '\n'); + if (line_end_ptr == nullptr) { + line_end_ptr = file_data_ptr + file_data_size_; + } + + // Get the size of the feature data + int feature_size = line_end_ptr - feature_ptr; + + if (out_feature_size < feature_size + 1) { + SB_LOG(WARNING) << "CPU Feature " << feature << " is truncated."; + feature_size = out_feature_size - 1; + } + memcpy(out_feature, feature_ptr, feature_size); + out_feature[feature_size] = '\0'; + + return true; + } + + // Extract a integer feature field identified by |feature| from /proc/cpuinfo + int ExtractIntegerFeature(const char* feature) { + int feature_data = -1; + // Allocate 128 bytes for an integer field. + char feature_buffer[128] = {0}; + if (!ExtractStringFeature( + feature, feature_buffer, + sizeof(feature_buffer) / sizeof(feature_buffer[0]))) { + return feature_data; + } + + char* end; + feature_data = static_cast<int>(strtol(feature_buffer, &end, 0)); + if (end == feature_buffer) { + feature_data = -1; + } + return feature_data; + } +}; + +// Check if getauxval() is supported +bool IsGetauxvalSupported() { + // TODO: figure out which linking flags are needed to use + // dl* functions. Currently the linker complains symbols + // like "__dlopen" undefined, even though "-ldl" and "-lc" + // are added to linker flags. + + // dlerror(); + // void* libc_handle = dlopen("libc.so", RTLD_NOW); + // if (!libc_handle) { + // printf("Could not dlopen() C library: %s\n", dlerror()); + // return false; + // } + + // typedef unsigned long getauxval_func_t(unsigned long); + // getauxval_func_t* func = (getauxval_func_t*) + // dlsym(libc_handle, "getauxval"); + // if (!func) { + // printf("Could not find getauxval() in C library\n"); + // return false; + // } + // dlclose(libc_handle); + return true; +} + +// Get hwcap bitmask by getauxval() or by reading /proc/self/auxv +uint32_t ReadElfHwcaps(uint32_t hwcap_type) { + uint32_t hwcap = 0; + if (IsGetauxvalSupported()) { + hwcap = static_cast<uint32_t>(getauxval(hwcap_type)); + } else { + // Read the ELF HWCAP flags by parsing /proc/self/auxv. + FILE* file_ptr = fopen("/proc/self/auxv", "r"); + if (file_ptr == nullptr) { + return hwcap; + } + struct { + uint32_t tag; + uint32_t value; + } entry; + for (;;) { + size_t n = fread(&entry, sizeof(entry), 1, file_ptr); + if (n == 0 || (entry.tag == 0 && entry.value == 0)) { + break; + } + if (entry.tag == hwcap_type) { + hwcap = entry.value; + break; + } + } + fclose(file_ptr); + } + return hwcap; +} + +// Construct hwcap bitmask by the feature flags in /proc/cpuinfo +uint32_t ConstructHwcapFromCPUInfo(ProcCpuInfo* cpu_info, + int16_t architecture_generation, + uint32_t hwcap_type) { + if (hwcap_type == AT_HWCAP && architecture_generation >= 8) { + // This is a 32-bit ARM binary running on a 64-bit ARM64 kernel. + // The 'Features' line only lists the optional features that the + // device's CPU supports, compared to its reference architecture + // which are of no use for this process. + SB_LOG(INFO) << "Faking 32-bit ARM HWCaps on ARMv" + << architecture_generation; + return HWCAP_SET_FOR_ARMV8; + } + + uint32_t hwcap_value = 0; + + // Allocate 1024 bytes for "Features", which is a list of flags. + char flags_buffer[1024] = {0}; + if (!cpu_info->ExtractStringFeature( + "Features", flags_buffer, + sizeof(flags_buffer) / sizeof(flags_buffer[0]))) { + return hwcap_value; + } + + if (hwcap_type == AT_HWCAP) { + hwcap_value |= HasItemInList(flags_buffer, "vfp") ? HWCAP_VFP : 0; + hwcap_value |= HasItemInList(flags_buffer, "vfpv3") ? HWCAP_VFPv3 : 0; + hwcap_value |= HasItemInList(flags_buffer, "vfpv3d16") ? HWCAP_VFPv3D16 : 0; + hwcap_value |= HasItemInList(flags_buffer, "vfpv4") ? HWCAP_VFPv4 : 0; + hwcap_value |= HasItemInList(flags_buffer, "neon") ? HWCAP_NEON : 0; + hwcap_value |= HasItemInList(flags_buffer, "idiva") ? HWCAP_IDIVA : 0; + hwcap_value |= HasItemInList(flags_buffer, "idivt") ? HWCAP_IDIVT : 0; + hwcap_value |= + HasItemInList(flags_buffer, "idiv") ? (HWCAP_IDIVA | HWCAP_IDIVT) : 0; + hwcap_value |= HasItemInList(flags_buffer, "iwmmxt") ? HWCAP_IWMMXT : 0; + } else if (hwcap_type == AT_HWCAP2) { + hwcap_value |= HasItemInList(flags_buffer, "aes") ? HWCAP2_AES : 0; + hwcap_value |= HasItemInList(flags_buffer, "pmull") ? HWCAP2_PMULL : 0; + hwcap_value |= HasItemInList(flags_buffer, "sha1") ? HWCAP2_SHA1 : 0; + hwcap_value |= HasItemInList(flags_buffer, "sha2") ? HWCAP2_SHA2 : 0; + hwcap_value |= HasItemInList(flags_buffer, "crc32") ? HWCAP2_CRC32 : 0; + } + return hwcap_value; +} + +bool SbCPUFeaturesGet_ARM(SbCPUFeatures* features) { + memset(features, 0, sizeof(*features)); + + // Raspi is a 32-bit ARM platform. + features->architecture = kSbCPUFeaturesArchitectureArm; + + // Set the default value of the features to be invalid, then fill them in + // if appropriate. + SetGeneralFeaturesInvalid(features); + SetArmFeaturesInvalid(features); + SetX86FeaturesInvalid(features); + + ProcCpuInfo cpu_info; + + // Extract CPU implementor, variant, revision and part information, which + // are all integers. + features->arm.implementer = cpu_info.ExtractIntegerFeature("CPU implementer"); + features->arm.variant = cpu_info.ExtractIntegerFeature("CPU variant"); + features->arm.revision = cpu_info.ExtractIntegerFeature("CPU revision"); + features->arm.part = cpu_info.ExtractIntegerFeature("CPU part"); + + // Extract CPU architecture generation from the "CPU Architecture" field. + // Allocate 128 bytes for "CPU architecture", which is an integer field. + char architecture_buffer[128] = {0}; + if (cpu_info.ExtractStringFeature( + "CPU architecture", architecture_buffer, + sizeof(architecture_buffer) / sizeof(architecture_buffer[0]))) { + char* end; + features->arm.architecture_generation = + static_cast<int>(strtol(architecture_buffer, &end, 10)); + if (end == architecture_buffer) { + // Kernels older than 3.18 report "CPU architecture: AArch64" on ARMv8. + if (strcasecmp(architecture_buffer, "AArch64") == 0) { + features->arm.architecture_generation = 8; + } else { + features->arm.architecture_generation = -1; + } + } + + // Unfortunately, it seems that certain ARMv6-based CPUs + // report an incorrect architecture number of 7! + // + // See http://code.google.com/p/android/issues/detail?id=10812 + // + // We try to correct this by looking at the 'elf_platform' + // feature reported by the 'Processor' field or 'model name' + // field in Linux v3.8, which is of the form of "(v7l)" for an + // ARMv7-based CPU, and "(v6l)" for an ARMv6-one. For example, + // the Raspberry Pi is one popular ARMv6 device that reports + // architecture 7. The 'Processor' or 'model name' fields + // also contain processor brand information. + + // Allocate 256 bytes for "Processor"/"model name" field. + static char brand_buffer[256] = {0}; + if (!cpu_info.ExtractStringFeature( + "Processor", brand_buffer, + sizeof(brand_buffer) / sizeof(brand_buffer[0]))) { + if (cpu_info.ExtractStringFeature( + "model name", brand_buffer, + sizeof(brand_buffer) / sizeof(brand_buffer[0]))) { + features->brand = brand_buffer; + if (features->arm.architecture_generation == 7 && + HasItemInList(features->brand, "(v6l)")) { + features->arm.architecture_generation = 6; + } + } + } + } + + // Get hwcap bitmask and extract the CPU feature flags from it. + features->hwcap = ReadElfHwcaps(AT_HWCAP); + if (features->hwcap == 0) { + features->hwcap = ConstructHwcapFromCPUInfo( + &cpu_info, features->arm.architecture_generation, AT_HWCAP); + } + + features->arm.has_idiva = (features->hwcap & HWCAP_IDIVA) != 0; + features->arm.has_neon = (features->hwcap & HWCAP_NEON) != 0; + features->arm.has_vfp = (features->hwcap & HWCAP_VFP) != 0; + features->arm.has_vfp3 = (features->hwcap & (HWCAP_VFPv3 | HWCAP_VFPv3D16 | + HWCAP_VFPv4 | HWCAP_NEON)) != 0; + features->arm.has_vfp3_d32 = + (features->arm.has_vfp3 && ((features->hwcap & HWCAP_VFPv3D16) == 0 || + (features->hwcap & HWCAP_VFPD32) != 0)); + features->arm.has_vfp3_d32 = + features->arm.has_vfp3_d32 || features->arm.has_neon; + + // Some old kernels will report vfp not vfpv3. Here we make an attempt + // to detect vfpv3 by checking for vfp *and* neon, since neon is only + // available on architectures with vfpv3. Checking neon on its own is + // not enough as it is possible to have neon without vfp. + if (features->arm.has_vfp && features->arm.has_neon) { + features->arm.has_vfp3 = true; + } + + // VFPv3 implies ARMv7, see ARM DDI 0406B, page A1-6. + if (features->arm.architecture_generation < 7 && features->arm.has_vfp3) { + features->arm.architecture_generation = 7; + } + + // ARMv7 implies Thumb2. + if (features->arm.architecture_generation >= 7) { + features->arm.has_thumb2 = true; + } + + // The earliest architecture with Thumb2 is ARMv6T2. + if (features->arm.has_thumb2 && features->arm.architecture_generation < 6) { + features->arm.architecture_generation = 6; + } + + // We don't support any FPUs other than VFP. + features->has_fpu = features->arm.has_vfp; + + // The following flags are always supported by ARMv8, as mandated by the ARM + // Architecture Reference Manual. + if (features->arm.architecture_generation >= 8) { + features->arm.has_idiva = true; + features->arm.has_neon = true; + features->arm.has_thumb2 = true; + features->arm.has_vfp = true; + features->arm.has_vfp3 = true; + } + + // Read hwcaps2 bitmask and extract the CPU feature flags from it. + features->hwcap2 = ReadElfHwcaps(AT_HWCAP2); + if (features->hwcap2 == 0) { + features->hwcap2 = ConstructHwcapFromCPUInfo( + &cpu_info, features->arm.architecture_generation, AT_HWCAP2); + } + + features->arm.has_aes = (features->hwcap2 & HWCAP2_AES) != 0; + features->arm.has_pmull = (features->hwcap2 & HWCAP2_PMULL) != 0; + features->arm.has_sha1 = (features->hwcap2 & HWCAP2_PMULL) != 0; + features->arm.has_sha2 = (features->hwcap2 & HWCAP2_SHA2) != 0; + features->arm.has_crc32 = (features->hwcap2 & HWCAP2_CRC32) != 0; + + // Get L1 ICACHE and DCACHE line size. + features->icache_line_size = sysconf(_SC_LEVEL1_ICACHE_LINESIZE); + features->dcache_line_size = sysconf(_SC_LEVEL1_DCACHE_LINESIZE); + + return true; +} + +} // namespace + +// TODO: Only ARM is currently implemented and tested +bool SbCPUFeaturesGet(SbCPUFeatures* features) { +#if SB_IS(ARCH_ARM) + return SbCPUFeaturesGet_ARM(features); +#else + SB_NOTIMPLEMENTED(); + + memset(features, 0, sizeof(*features)); + features->architecture = kSbCPUFeaturesArchitectureUnknown; + + SetGeneralFeaturesInvalid(features); + SetArmFeaturesInvalid(features); + SetX86FeaturesInvalid(features); + + return false; +#endif +} + +#endif // SB_API_VERSION >= 11
diff --git a/src/starboard/shared/starboard/audio_sink/audio_sink_create.cc b/src/starboard/shared/starboard/audio_sink/audio_sink_create.cc index 36fa34b..00605fc 100644 --- a/src/starboard/shared/starboard/audio_sink/audio_sink_create.cc +++ b/src/starboard/shared/starboard/audio_sink/audio_sink_create.cc
@@ -93,10 +93,14 @@ } if (auto type = SbAudioSinkPrivate::GetFallbackType()) { + SB_LOG(WARNING) << "Primary audio sink failed to create, use fallback."; return type->Create(channels, sampling_frequency_hz, audio_sample_type, audio_frame_storage_type, frame_buffers, frame_buffers_size_in_frames, update_source_status_func, consume_frames_func, context); + } else { + SB_LOG(WARNING) << "Primary audio sink failed to create," + << " fallback is not enabled."; } return kSbAudioSinkInvalid;
diff --git a/src/starboard/shared/starboard/cpu_features.h b/src/starboard/shared/starboard/cpu_features.h new file mode 100644 index 0000000..6641ee8 --- /dev/null +++ b/src/starboard/shared/starboard/cpu_features.h
@@ -0,0 +1,65 @@ +// Copyright 2019 The Cobalt Authors. 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. + +// Module Overview: Starboard CPU features API + +// Provide helper classes, macros and functions useful to the implementations of +// Starboard CPU features API on all platforms + +#ifndef STARBOARD_SHARED_STARBOARD_CPU_FEATURES_H_ +#define STARBOARD_SHARED_STARBOARD_CPU_FEATURES_H_ + +#include "starboard/cpu_features.h" + +#if SB_API_VERSION >= 11 + +namespace starboard { +namespace shared { + +// Set the general features of SbCPUFeatures to be invalid +inline void SetGeneralFeaturesInvalid(SbCPUFeatures* features) { + features->brand = ""; + features->icache_line_size = -1; + features->dcache_line_size = -1; + features->hwcap = 0; + features->hwcap2 = 0; +} + +// Set the features of SbCPUFeatures.x86 to be invalid +inline void SetX86FeaturesInvalid(SbCPUFeatures* features) { + features->x86.vendor = ""; + features->x86.family = -1; + features->x86.ext_family = -1; + features->x86.model = -1; + features->x86.ext_model = -1; + features->x86.stepping = -1; + features->x86.type = -1; + features->x86.signature = -1; +} + +// Set the features of SbCPUFeatures.arm to be invalid +inline void SetArmFeaturesInvalid(SbCPUFeatures* features) { + features->arm.implementer = -1; + features->arm.variant = -1; + features->arm.revision = -1; + features->arm.architecture_generation = -1; + features->arm.part = -1; +} + +} // namespace shared +} // namespace starboard + +#endif // SB_API_VERSION >= 11 + +#endif // STARBOARD_SHARED_STARBOARD_CPU_FEATURES_H_
diff --git a/src/starboard/shared/starboard/player/filter/adaptive_audio_decoder_internal.cc b/src/starboard/shared/starboard/player/filter/adaptive_audio_decoder_internal.cc index d85f33e..8b06d66 100644 --- a/src/starboard/shared/starboard/player/filter/adaptive_audio_decoder_internal.cc +++ b/src/starboard/shared/starboard/player/filter/adaptive_audio_decoder_internal.cc
@@ -14,6 +14,8 @@ #include "starboard/shared/starboard/player/filter/adaptive_audio_decoder_internal.h" +#include "starboard/audio_sink.h" +#include "starboard/common/log.h" #include "starboard/common/reset_and_return.h" namespace starboard { @@ -25,6 +27,33 @@ using common::ResetAndReturn; #if SB_API_VERSION >= 11 +SbMediaAudioSampleType GetDefaultSupportedAudioSampleType() { + if (SbAudioSinkIsAudioSampleTypeSupported(kSbMediaAudioSampleTypeFloat32)) { + return kSbMediaAudioSampleTypeFloat32; + } + if (SbAudioSinkIsAudioSampleTypeSupported( + kSbMediaAudioSampleTypeInt16Deprecated)) { + return kSbMediaAudioSampleTypeInt16Deprecated; + } + SB_NOTREACHED(); + return kSbMediaAudioSampleTypeFloat32; +} + +SbMediaAudioFrameStorageType GetDefaultSupportedAudioFrameStorageType() { + if (SbAudioSinkIsAudioFrameStorageTypeSupported( + kSbMediaAudioFrameStorageTypeInterleaved)) { + return kSbMediaAudioFrameStorageTypeInterleaved; + } + SB_NOTREACHED(); + return kSbMediaAudioFrameStorageTypeInterleaved; +} + +int GetDefaultSupportedAudioSamplesPerSecond() { + const int kDefaultOutputSamplesPerSecond = 48000; + return SbAudioSinkGetNearestSupportedSampleFrequency( + kDefaultOutputSamplesPerSecond); +} + bool IsResetDecoderNecessary(const SbMediaAudioSampleInfo& current_info, const SbMediaAudioSampleInfo& new_info) { if (current_info.codec != new_info.codec) { @@ -118,6 +147,16 @@ if (audio_decoder_) { audio_decoder_->WriteEndOfStream(); } else { + // It's possible that WriteEndOfStream() is called without any + // other input. In that case, we need to give |output_sample_type_|, + // |output_storage_type_| and |output_samples_per_second_| default + // value. + if (!first_output_received_) { + first_output_received_ = true; + output_sample_type_ = GetDefaultSupportedAudioSampleType(); + output_storage_type_ = GetDefaultSupportedAudioFrameStorageType(); + output_samples_per_second_ = GetDefaultSupportedAudioSamplesPerSecond(); + } decoded_audios_.push(new DecodedAudio); Schedule(output_cb_); }
diff --git a/src/starboard/shared/starboard/player/filter/audio_renderer_internal.cc b/src/starboard/shared/starboard/player/filter/audio_renderer_internal.cc index 479ce16..996f9aa 100644 --- a/src/starboard/shared/starboard/player/filter/audio_renderer_internal.cc +++ b/src/starboard/shared/starboard/player/filter/audio_renderer_internal.cc
@@ -518,6 +518,7 @@ max_cached_frames_, this); if (!audio_renderer_sink_->HasStarted()) { #if SB_HAS(PLAYER_ERROR_MESSAGE) + SB_LOG(ERROR) << "Failed to start audio sink."; error_cb_(kSbPlayerErrorDecode, "failed to start audio sink"); #else // SB_HAS(PLAYER_ERROR_MESSAGE) error_cb_(); @@ -721,7 +722,8 @@ << " time since last check, which is too frequently."; } - sink_callbacks_since_last_check_.store(0); + auto sink_callbacks_since_last_check = + sink_callbacks_since_last_check_.exchange(0); if (paused_ || playback_rate_ == 0.0) { return; @@ -735,7 +737,9 @@ << elapsed / kSbTimeSecond << " seconds, with " << total_frames_sent_to_sink_ - total_frames_consumed_by_sink_ - << " frames in sink."; + << " frames in sink, " << (underflow_ ? "underflow, " : "") + << sink_callbacks_since_last_check + << " callbacks since last check."; } Schedule(std::bind(&AudioRenderer::CheckAudioSinkStatus, this), kCheckAudioSinkStatusInterval);
diff --git a/src/starboard/shared/starboard/player/filter/player_components.cc b/src/starboard/shared/starboard/player/filter/player_components.cc new file mode 100644 index 0000000..74e3cb3 --- /dev/null +++ b/src/starboard/shared/starboard/player/filter/player_components.cc
@@ -0,0 +1,123 @@ +// Copyright 2019 The Cobalt Authors. 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 "starboard/shared/starboard/player/filter/player_components.h" + +#include "starboard/shared/starboard/application.h" +#include "starboard/shared/starboard/command_line.h" +#include "starboard/shared/starboard/player/filter/adaptive_audio_decoder_internal.h" +#include "starboard/shared/starboard/player/filter/audio_renderer_sink_impl.h" +#include "starboard/shared/starboard/player/filter/punchout_video_renderer_sink.h" +#include "starboard/shared/starboard/player/filter/stub_audio_decoder.h" +#include "starboard/shared/starboard/player/filter/stub_video_decoder.h" +#include "starboard/shared/starboard/player/filter/video_render_algorithm_impl.h" + +namespace starboard { +namespace shared { +namespace starboard { +namespace player { +namespace filter { + +scoped_ptr<AudioRenderer> PlayerComponents::CreateAudioRenderer( + const AudioParameters& audio_parameters) { + scoped_ptr<AudioDecoder> audio_decoder; + scoped_ptr<AudioRendererSink> audio_renderer_sink; + + auto command_line = shared::starboard::Application::Get()->GetCommandLine(); + if (command_line->HasSwitch("use_stub_audio_decoder")) { + CreateStubAudioComponents(audio_parameters, &audio_decoder, + &audio_renderer_sink); + } else { + CreateAudioComponents(audio_parameters, &audio_decoder, + &audio_renderer_sink); + } + if (!audio_decoder || !audio_renderer_sink) { + return scoped_ptr<AudioRenderer>(); + } + int max_cached_frames, max_frames_per_append; + GetAudioRendererParams(&max_cached_frames, &max_frames_per_append); + return make_scoped_ptr( + new AudioRenderer(audio_decoder.Pass(), audio_renderer_sink.Pass(), + audio_parameters.audio_sample_info, max_cached_frames, + max_frames_per_append)); +} + +scoped_ptr<VideoRenderer> PlayerComponents::CreateVideoRenderer( + const VideoParameters& video_parameters, + MediaTimeProvider* media_time_provider) { + scoped_ptr<VideoDecoder> video_decoder; + scoped_ptr<VideoRenderAlgorithm> video_render_algorithm; + scoped_refptr<VideoRendererSink> video_renderer_sink; + + auto command_line = shared::starboard::Application::Get()->GetCommandLine(); + if (command_line->HasSwitch("use_stub_video_decoder")) { + CreateStubVideoComponents(video_parameters, &video_decoder, + &video_render_algorithm, &video_renderer_sink); + } else { + CreateVideoComponents(video_parameters, &video_decoder, + &video_render_algorithm, &video_renderer_sink); + } + if (!video_decoder || !video_render_algorithm) { + return scoped_ptr<VideoRenderer>(); + } + return make_scoped_ptr( + new VideoRenderer(video_decoder.Pass(), media_time_provider, + video_render_algorithm.Pass(), video_renderer_sink)); +} + +void PlayerComponents::CreateStubAudioComponents( + const AudioParameters& audio_parameters, + scoped_ptr<AudioDecoder>* audio_decoder, + scoped_ptr<AudioRendererSink>* audio_renderer_sink) { + SB_DCHECK(audio_decoder); + SB_DCHECK(audio_renderer_sink); + +#if SB_API_VERSION >= 11 + auto decoder_creator = [](const SbMediaAudioSampleInfo& audio_sample_info, + SbDrmSystem drm_system) { + return scoped_ptr<AudioDecoder>( + new StubAudioDecoder(audio_sample_info.codec, audio_sample_info)); + }; + audio_decoder->reset( + new AdaptiveAudioDecoder(audio_parameters.audio_sample_info, + audio_parameters.drm_system, decoder_creator)); +#else // SB_API_VERSION >= 11 + audio_decoder->reset(new StubAudioDecoder( + audio_parameters.audio_codec, audio_parameters.audio_sample_info)); +#endif // SB_API_VERISON >= 11 + audio_renderer_sink->reset(new AudioRendererSinkImpl); +} + +void PlayerComponents::CreateStubVideoComponents( + const VideoParameters& video_parameters, + scoped_ptr<VideoDecoder>* video_decoder, + scoped_ptr<VideoRenderAlgorithm>* video_render_algorithm, + scoped_refptr<VideoRendererSink>* video_renderer_sink) { + const SbTime kVideoSinkRenderInterval = 10 * kSbTimeMillisecond; + + SB_DCHECK(video_decoder); + SB_DCHECK(video_render_algorithm); + SB_DCHECK(video_renderer_sink); + + video_decoder->reset(new StubVideoDecoder); + video_render_algorithm->reset(new VideoRenderAlgorithmImpl); + *video_renderer_sink = new PunchoutVideoRendererSink( + video_parameters.player, kVideoSinkRenderInterval); +} + +} // namespace filter +} // namespace player +} // namespace starboard +} // namespace shared +} // namespace starboard
diff --git a/src/starboard/shared/starboard/player/filter/player_components.h b/src/starboard/shared/starboard/player/filter/player_components.h index 983f207..a73ac46 100644 --- a/src/starboard/shared/starboard/player/filter/player_components.h +++ b/src/starboard/shared/starboard/player/filter/player_components.h
@@ -22,22 +22,14 @@ #include "starboard/media.h" #include "starboard/player.h" #include "starboard/shared/internal_only.h" -#include "starboard/shared/starboard/application.h" -#include "starboard/shared/starboard/command_line.h" #include "starboard/shared/starboard/player/filter/audio_decoder_internal.h" #include "starboard/shared/starboard/player/filter/audio_renderer_internal.h" #include "starboard/shared/starboard/player/filter/audio_renderer_sink.h" -#include "starboard/shared/starboard/player/filter/audio_renderer_sink_impl.h" #include "starboard/shared/starboard/player/filter/media_time_provider.h" -#include "starboard/shared/starboard/player/filter/punchout_video_renderer_sink.h" -#include "starboard/shared/starboard/player/filter/stub_audio_decoder.h" -#include "starboard/shared/starboard/player/filter/stub_video_decoder.h" #include "starboard/shared/starboard/player/filter/video_decoder_internal.h" #include "starboard/shared/starboard/player/filter/video_render_algorithm.h" -#include "starboard/shared/starboard/player/filter/video_render_algorithm_impl.h" #include "starboard/shared/starboard/player/filter/video_renderer_internal.h" #include "starboard/shared/starboard/player/filter/video_renderer_sink.h" -#include "starboard/shared/starboard/player/job_queue.h" namespace starboard { namespace shared { @@ -71,50 +63,11 @@ static scoped_ptr<PlayerComponents> Create(); scoped_ptr<AudioRenderer> CreateAudioRenderer( - const AudioParameters& audio_parameters) { - scoped_ptr<AudioDecoder> audio_decoder; - scoped_ptr<AudioRendererSink> audio_renderer_sink; + const AudioParameters& audio_parameters); - auto command_line = shared::starboard::Application::Get()->GetCommandLine(); - if (command_line->HasSwitch("use_stub_audio_decoder")) { - CreateStubAudioComponents(audio_parameters, &audio_decoder, - &audio_renderer_sink); - } else { - CreateAudioComponents(audio_parameters, &audio_decoder, - &audio_renderer_sink); - } - if (!audio_decoder || !audio_renderer_sink) { - return scoped_ptr<AudioRenderer>(); - } - int max_cached_frames, max_frames_per_append; - GetAudioRendererParams(&max_cached_frames, &max_frames_per_append); - return make_scoped_ptr( - new AudioRenderer(audio_decoder.Pass(), audio_renderer_sink.Pass(), - audio_parameters.audio_sample_info, max_cached_frames, - max_frames_per_append)); - } scoped_ptr<VideoRenderer> CreateVideoRenderer( const VideoParameters& video_parameters, - MediaTimeProvider* media_time_provider) { - scoped_ptr<VideoDecoder> video_decoder; - scoped_ptr<VideoRenderAlgorithm> video_render_algorithm; - scoped_refptr<VideoRendererSink> video_renderer_sink; - - auto command_line = shared::starboard::Application::Get()->GetCommandLine(); - if (command_line->HasSwitch("use_stub_video_decoder")) { - CreateStubVideoComponents(video_parameters, &video_decoder, - &video_render_algorithm, &video_renderer_sink); - } else { - CreateVideoComponents(video_parameters, &video_decoder, - &video_render_algorithm, &video_renderer_sink); - } - if (!video_decoder || !video_render_algorithm) { - return scoped_ptr<VideoRenderer>(); - } - return make_scoped_ptr( - new VideoRenderer(video_decoder.Pass(), media_time_provider, - video_render_algorithm.Pass(), video_renderer_sink)); - } + MediaTimeProvider* media_time_provider); #if COBALT_BUILD_TYPE_GOLD private: @@ -143,31 +96,13 @@ void CreateStubAudioComponents( const AudioParameters& audio_parameters, scoped_ptr<AudioDecoder>* audio_decoder, - scoped_ptr<AudioRendererSink>* audio_renderer_sink) { - SB_DCHECK(audio_decoder); - SB_DCHECK(audio_renderer_sink); - - audio_decoder->reset( - new StubAudioDecoder(audio_parameters.audio_sample_info)); - audio_renderer_sink->reset(new AudioRendererSinkImpl); - } + scoped_ptr<AudioRendererSink>* audio_renderer_sink); void CreateStubVideoComponents( const VideoParameters& video_parameters, scoped_ptr<VideoDecoder>* video_decoder, scoped_ptr<VideoRenderAlgorithm>* video_render_algorithm, - scoped_refptr<VideoRendererSink>* video_renderer_sink) { - const SbTime kVideoSinkRenderInterval = 10 * kSbTimeMillisecond; - - SB_DCHECK(video_decoder); - SB_DCHECK(video_render_algorithm); - SB_DCHECK(video_renderer_sink); - - video_decoder->reset(new StubVideoDecoder); - video_render_algorithm->reset(new VideoRenderAlgorithmImpl); - *video_renderer_sink = new PunchoutVideoRendererSink( - video_parameters.player, kVideoSinkRenderInterval); - } + scoped_refptr<VideoRendererSink>* video_renderer_sink); private: SB_DISALLOW_COPY_AND_ASSIGN(PlayerComponents);
diff --git a/src/starboard/shared/starboard/player/filter/player_filter.gypi b/src/starboard/shared/starboard/player/filter/player_filter.gypi index a3f40ba..b67a371 100644 --- a/src/starboard/shared/starboard/player/filter/player_filter.gypi +++ b/src/starboard/shared/starboard/player/filter/player_filter.gypi
@@ -42,6 +42,7 @@ '<(DEPTH)/starboard/shared/starboard/player/filter/media_time_provider_impl.h', '<(DEPTH)/starboard/shared/starboard/player/filter/mock_audio_decoder.h', '<(DEPTH)/starboard/shared/starboard/player/filter/mock_audio_renderer_sink.h', + '<(DEPTH)/starboard/shared/starboard/player/filter/player_components.cc', '<(DEPTH)/starboard/shared/starboard/player/filter/player_components.h', '<(DEPTH)/starboard/shared/starboard/player/filter/punchout_video_renderer_sink.cc', '<(DEPTH)/starboard/shared/starboard/player/filter/punchout_video_renderer_sink.h', @@ -61,4 +62,4 @@ '<(DEPTH)/starboard/shared/starboard/player/filter/wsola_internal.h', ], }, -} \ No newline at end of file +}
diff --git a/src/starboard/shared/starboard/player/filter/stub_audio_decoder.cc b/src/starboard/shared/starboard/player/filter/stub_audio_decoder.cc index 5358ae3..b5888c1 100644 --- a/src/starboard/shared/starboard/player/filter/stub_audio_decoder.cc +++ b/src/starboard/shared/starboard/player/filter/stub_audio_decoder.cc
@@ -35,8 +35,10 @@ } // namespace StubAudioDecoder::StubAudioDecoder( + SbMediaAudioCodec audio_codec, const SbMediaAudioSampleInfo& audio_sample_info) : sample_type_(GetSupportedSampleType()), + audio_codec_(audio_codec), audio_sample_info_(audio_sample_info), stream_ended_(false) {} @@ -67,10 +69,15 @@ size_t size = diff * GetSamplesPerSecond() * sample_size * audio_sample_info_.number_of_channels / kSbTimeSecond; size -= size % (sample_size * audio_sample_info_.number_of_channels); + if (audio_codec_ == kSbMediaAudioCodecAac) { + // Frame size for AAC is fixed at 1024, so fake the output size such that + // number of frames matches up. + size = sample_size * audio_sample_info_.number_of_channels * 1024; + } - decoded_audios_.push(new DecodedAudio(audio_sample_info_.number_of_channels, - GetSampleType(), GetStorageType(), - input_buffer->timestamp(), size)); + decoded_audios_.push(new DecodedAudio( + audio_sample_info_.number_of_channels, GetSampleType(), + GetStorageType(), last_input_buffer_->timestamp(), size)); if (fill_type == kSilence) { SbMemorySet(decoded_audios_.back()->buffer(), 0, size); @@ -100,9 +107,13 @@ size_t fake_size = 4 * last_input_buffer_->size(); size_t sample_size = GetSampleType() == kSbMediaAudioSampleTypeInt16Deprecated ? 2 : 4; - fake_size += + fake_size -= fake_size % (sample_size * audio_sample_info_.number_of_channels); - + if (audio_codec_ == kSbMediaAudioCodecAac) { + // Frame size for AAC is fixed at 1024, so fake the output size such that + // number of frames matches up. + fake_size = sample_size * audio_sample_info_.number_of_channels * 1024; + } decoded_audios_.push(new DecodedAudio( audio_sample_info_.number_of_channels, GetSampleType(), GetStorageType(), last_input_buffer_->timestamp(), fake_size));
diff --git a/src/starboard/shared/starboard/player/filter/stub_audio_decoder.h b/src/starboard/shared/starboard/player/filter/stub_audio_decoder.h index bcfdf8f..d42ecd0 100644 --- a/src/starboard/shared/starboard/player/filter/stub_audio_decoder.h +++ b/src/starboard/shared/starboard/player/filter/stub_audio_decoder.h
@@ -30,7 +30,8 @@ class StubAudioDecoder : public AudioDecoder, private JobQueue::JobOwner { public: - explicit StubAudioDecoder(const SbMediaAudioSampleInfo& audio_sample_info); + StubAudioDecoder(SbMediaAudioCodec audio_codec, + const SbMediaAudioSampleInfo& audio_sample_info); void Initialize(const OutputCB& output_cb, const ErrorCB& error_cb) override; @@ -52,6 +53,7 @@ private: OutputCB output_cb_; SbMediaAudioSampleType sample_type_; + SbMediaAudioCodec audio_codec_; SbMediaAudioSampleInfo audio_sample_info_; bool stream_ended_; std::queue<scoped_refptr<DecodedAudio> > decoded_audios_;
diff --git a/src/starboard/shared/starboard/player/filter/stub_player_components_impl.cc b/src/starboard/shared/starboard/player/filter/stub_player_components_impl.cc index baa83fa..2947df4 100644 --- a/src/starboard/shared/starboard/player/filter/stub_player_components_impl.cc +++ b/src/starboard/shared/starboard/player/filter/stub_player_components_impl.cc
@@ -12,7 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "starboard/common/log.h" +#include "starboard/shared/starboard/player/filter/stub_player_components_impl.h" + #include "starboard/shared/starboard/player/filter/player_components.h" namespace starboard { @@ -21,37 +22,9 @@ namespace player { namespace filter { -class PlayerComponentsImpl : public PlayerComponents { - void CreateAudioComponents( - const AudioParameters& audio_parameters, - scoped_ptr<AudioDecoder>* audio_decoder, - scoped_ptr<AudioRendererSink>* audio_renderer_sink) override { - CreateStubAudioComponents(audio_parameters, audio_decoder, - audio_renderer_sink); - } - - void CreateVideoComponents( - const VideoParameters& video_parameters, - scoped_ptr<VideoDecoder>* video_decoder, - scoped_ptr<VideoRenderAlgorithm>* video_render_algorithm, - scoped_refptr<VideoRendererSink>* video_renderer_sink) override { - CreateStubVideoComponents(video_parameters, video_decoder, - video_render_algorithm, video_renderer_sink); - } - - void GetAudioRendererParams(int* max_cached_frames, - int* max_frames_per_append) const override { - SB_DCHECK(max_cached_frames); - SB_DCHECK(max_frames_per_append); - - *max_cached_frames = 128 * 1024; - *max_frames_per_append = 16384; - } -}; - // static scoped_ptr<PlayerComponents> PlayerComponents::Create() { - return make_scoped_ptr<PlayerComponents>(new PlayerComponentsImpl); + return make_scoped_ptr<PlayerComponents>(new StubPlayerComponentsImpl); } // static
diff --git a/src/starboard/shared/starboard/player/filter/stub_player_components_impl.h b/src/starboard/shared/starboard/player/filter/stub_player_components_impl.h new file mode 100644 index 0000000..3e2013a --- /dev/null +++ b/src/starboard/shared/starboard/player/filter/stub_player_components_impl.h
@@ -0,0 +1,61 @@ +// Copyright 2017 The Cobalt Authors. 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. + +#ifndef STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_STUB_PLAYER_COMPONENTS_IMPL_H_ +#define STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_STUB_PLAYER_COMPONENTS_IMPL_H_ + +#include "starboard/shared/starboard/player/filter/player_components.h" + +namespace starboard { +namespace shared { +namespace starboard { +namespace player { +namespace filter { + +class StubPlayerComponentsImpl : public PlayerComponents { + public: + void CreateAudioComponents( + const AudioParameters& audio_parameters, + scoped_ptr<AudioDecoder>* audio_decoder, + scoped_ptr<AudioRendererSink>* audio_renderer_sink) override { + CreateStubAudioComponents(audio_parameters, audio_decoder, + audio_renderer_sink); + } + + void CreateVideoComponents( + const VideoParameters& video_parameters, + scoped_ptr<VideoDecoder>* video_decoder, + scoped_ptr<VideoRenderAlgorithm>* video_render_algorithm, + scoped_refptr<VideoRendererSink>* video_renderer_sink) override { + CreateStubVideoComponents(video_parameters, video_decoder, + video_render_algorithm, video_renderer_sink); + } + + void GetAudioRendererParams(int* max_cached_frames, + int* max_frames_per_append) const override { + SB_DCHECK(max_cached_frames); + SB_DCHECK(max_frames_per_append); + + *max_cached_frames = 128 * 1024; + *max_frames_per_append = 16384; + } +}; + +} // namespace filter +} // namespace player +} // namespace starboard +} // namespace shared +} // namespace starboard + +#endif // STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_STUB_PLAYER_COMPONENTS_IMPL_H_
diff --git a/src/starboard/shared/starboard/player/filter/stub_video_decoder.cc b/src/starboard/shared/starboard/player/filter/stub_video_decoder.cc index 344d364..38b84a6 100644 --- a/src/starboard/shared/starboard/player/filter/stub_video_decoder.cc +++ b/src/starboard/shared/starboard/player/filter/stub_video_decoder.cc
@@ -52,17 +52,40 @@ video_sample_info_.value() != video_sample_info) { SB_LOG(INFO) << "New video sample info: " << video_sample_info; video_sample_info_ = video_sample_info; +#if SB_API_VERSION < 11 + color_metadata_ = *video_sample_info.color_metadata; + video_sample_info_->color_metadata = &color_metadata_; +#endif // SB_API_VERSION < 11 } } - decoder_status_cb_(kNeedMoreInput, new VideoFrame(input_buffer->timestamp())); + output_event_frame_times_.insert(input_buffer->timestamp()); + // Defer sending frames out until we've accumulated a reasonable number. + // This allows for input buffers to be out of order, and we expect that + // after buffering 8 (arbitrarily chosen) that the first timestamp in the + // sorted buffer will be the "correct" timestamp to send out. + const int kMaxFramesToDelay = 8; + scoped_refptr<VideoFrame> output_frame = NULL; + if (output_event_frame_times_.size() > kMaxFramesToDelay) { + output_frame = new VideoFrame(*output_event_frame_times_.begin()); + output_event_frame_times_.erase(output_event_frame_times_.begin()); + } + decoder_status_cb_(kNeedMoreInput, output_frame); } void StubVideoDecoder::WriteEndOfStream() { + // If there are any remaining frames we need to output, send them all out + // before writing EOS. + for (const auto& time : output_event_frame_times_) { + decoder_status_cb_(kBufferFull, new VideoFrame(time)); + } decoder_status_cb_(kBufferFull, VideoFrame::CreateEOSFrame()); } -void StubVideoDecoder::Reset() {} +void StubVideoDecoder::Reset() { + output_event_frame_times_.clear(); + video_sample_info_ = nullopt; +} SbDecodeTarget StubVideoDecoder::GetCurrentDecodeTarget() { return kSbDecodeTargetInvalid;
diff --git a/src/starboard/shared/starboard/player/filter/stub_video_decoder.h b/src/starboard/shared/starboard/player/filter/stub_video_decoder.h index fd64fdc..b320b32 100644 --- a/src/starboard/shared/starboard/player/filter/stub_video_decoder.h +++ b/src/starboard/shared/starboard/player/filter/stub_video_decoder.h
@@ -15,6 +15,8 @@ #ifndef STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_STUB_VIDEO_DECODER_H_ #define STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_STUB_VIDEO_DECODER_H_ +#include <set> + #include "starboard/common/optional.h" #include "starboard/shared/internal_only.h" #include "starboard/shared/starboard/player/filter/video_decoder_internal.h" @@ -50,6 +52,12 @@ private: DecoderStatusCB decoder_status_cb_; optional<SbMediaVideoSampleInfo> video_sample_info_; +#if SB_API_VERSION < 11 + SbMediaColorMetadata color_metadata_; +#endif // SB_API_VERSION < 11 + + // std::set<> keeps frame timestamps sorted in ascending order. + std::set<SbTime> output_event_frame_times_; }; } // namespace filter
diff --git a/src/starboard/shared/starboard/player/filter/testing/adaptive_audio_decoder_test.cc b/src/starboard/shared/starboard/player/filter/testing/adaptive_audio_decoder_test.cc index 4730e34..c68e925 100644 --- a/src/starboard/shared/starboard/player/filter/testing/adaptive_audio_decoder_test.cc +++ b/src/starboard/shared/starboard/player/filter/testing/adaptive_audio_decoder_test.cc
@@ -21,6 +21,7 @@ #include "starboard/shared/starboard/media/media_support_internal.h" #include "starboard/shared/starboard/player/filter/audio_decoder_internal.h" #include "starboard/shared/starboard/player/filter/player_components.h" +#include "starboard/shared/starboard/player/filter/stub_player_components_impl.h" #include "starboard/shared/starboard/player/video_dmp_reader.h" #include "starboard/thread.h" #include "testing/gtest/include/gtest/gtest.h" @@ -37,6 +38,8 @@ namespace testing { namespace { +using ::testing::Bool; +using ::testing::Combine; using ::testing::ValuesIn; using std::vector; using std::string; @@ -88,13 +91,14 @@ // TODO: Avoid reading same dmp file repeatly. class AdaptiveAudioDecoderTest - : public ::testing::TestWithParam<vector<const char*>> { + : public ::testing::TestWithParam<std::tuple<vector<const char*>, bool>> { protected: enum Event { kConsumed, kOutput, kError }; - AdaptiveAudioDecoderTest() { - vector<const char*> params = GetParam(); - for (auto filename : params) { + AdaptiveAudioDecoderTest() + : test_filenames_(std::get<0>(GetParam())), + using_stub_decoder_(std::get<1>(GetParam())) { + for (auto filename : test_filenames_) { dmp_readers_.emplace_back( new VideoDmpReader(ResolveTestFileName(filename).c_str())); } @@ -105,9 +109,11 @@ } return std::move(accumulated) + "->" + str; }; - string description = std::accumulate(params.begin(), params.end(), string(), - accumulate_operation); - SB_LOG(INFO) << "Testing: " << description; + string description = + std::accumulate(test_filenames_.begin(), test_filenames_.end(), + string(), accumulate_operation); + SB_LOG(INFO) << "Testing: " << description + << (using_stub_decoder_ ? " (with stub decoder)." : "."); } void SetUp() override { @@ -121,8 +127,14 @@ dmp_readers_[0]->audio_codec(), dmp_readers_[0]->audio_sample_info(), kSbDrmSystemInvalid}; - scoped_ptr<PlayerComponents> components = PlayerComponents::Create(); scoped_ptr<AudioRendererSink> audio_renderer_sink; + scoped_ptr<PlayerComponents> components; + if (using_stub_decoder_) { + components = make_scoped_ptr<StubPlayerComponentsImpl>( + new StubPlayerComponentsImpl); + } else { + components = PlayerComponents::Create(); + } components->CreateAudioComponents(audio_parameters, &audio_decoder_, &audio_renderer_sink); ASSERT_TRUE(audio_decoder_); @@ -202,6 +214,16 @@ } } + void AssertExpectedAndOutputFramesMatch(int expected_output_frames) { + if (using_stub_decoder_) { + // The number of output frames is not applicable in the case of the + // StubAudioDecoder, because it is not actually doing any decoding work. + return; + } + ASSERT_LE(abs(expected_output_frames - num_of_output_frames_), + dmp_readers_.size()); + } + vector<std::unique_ptr<VideoDmpReader>> dmp_readers_; scoped_refptr<DecodedAudio> last_decoded_audio_; int num_of_output_frames_ = 0; @@ -262,6 +284,13 @@ num_of_output_frames_ += last_decoded_audio_->frames(); } + // Test parameter for the filenames to load with the VideoDmpReader. + std::vector<const char*> test_filenames_; + + // Test parameter to configure whether the test is run with the + // StubAudioDecoder, or the platform-specific AudioDecoderImpl. + bool using_stub_decoder_; + JobQueue job_queue_; scoped_ptr<AudioDecoder> audio_decoder_; @@ -300,8 +329,7 @@ // |expected_output_frames|. Each time to switch decoder, it may have one // sample difference in output due to integer conversion. The total difference // should not exceed the length of |dmp_readers_|. - ASSERT_LE(abs(expected_output_frames - num_of_output_frames_), - dmp_readers_.size()); + AssertExpectedAndOutputFramesMatch(expected_output_frames); } TEST_P(AdaptiveAudioDecoderTest, MultipleInput) { @@ -334,8 +362,7 @@ // |expected_output_frames|. Each time to switch decoder, it may have one // sample difference in ouput due to integer conversion. The total difference // should not exceed the length of |dmp_readers_|. - ASSERT_LE(abs(expected_output_frames - num_of_output_frames_), - dmp_readers_.size()); + AssertExpectedAndOutputFramesMatch(expected_output_frames); } vector<vector<const char*>> GetSupportedTests() { @@ -391,7 +418,7 @@ INSTANTIATE_TEST_CASE_P(AdaptiveAudioDecoderTests, AdaptiveAudioDecoderTest, - ValuesIn(GetSupportedTests())); + Combine(ValuesIn(GetSupportedTests()), Bool())); } // namespace } // namespace testing
diff --git a/src/starboard/shared/starboard/player/filter/testing/audio_decoder_test.cc b/src/starboard/shared/starboard/player/filter/testing/audio_decoder_test.cc index cd73cfc..9b8e5ce 100644 --- a/src/starboard/shared/starboard/player/filter/testing/audio_decoder_test.cc +++ b/src/starboard/shared/starboard/player/filter/testing/audio_decoder_test.cc
@@ -25,6 +25,7 @@ #include "starboard/shared/starboard/media/media_support_internal.h" #include "starboard/shared/starboard/media/media_util.h" #include "starboard/shared/starboard/player/filter/player_components.h" +#include "starboard/shared/starboard/player/filter/stub_player_components_impl.h" #include "starboard/shared/starboard/player/video_dmp_reader.h" #include "starboard/thread.h" #include "testing/gtest/include/gtest/gtest.h" @@ -40,6 +41,8 @@ namespace testing { namespace { +using ::testing::Bool; +using ::testing::Combine; using ::testing::ValuesIn; using video_dmp::VideoDmpReader; @@ -74,10 +77,15 @@ return GetTestInputDirectory() + SB_FILE_SEP_CHAR + filename; } -class AudioDecoderTest : public ::testing::TestWithParam<const char*> { +class AudioDecoderTest + : public ::testing::TestWithParam<std::tuple<const char*, bool> > { public: - AudioDecoderTest() : dmp_reader_(ResolveTestFileName(GetParam()).c_str()) { - SB_LOG(INFO) << "Testing " << GetParam(); + AudioDecoderTest() + : test_filename_(std::get<0>(GetParam())), + using_stub_decoder_(std::get<1>(GetParam())), + dmp_reader_(ResolveTestFileName(test_filename_).c_str()) { + SB_LOG(INFO) << "Testing " << test_filename_ + << (using_stub_decoder_ ? " with stub audio decoder." : "."); } void SetUp() override { ASSERT_NE(dmp_reader_.audio_codec(), kSbMediaAudioCodecNone); @@ -87,7 +95,13 @@ dmp_reader_.audio_codec(), dmp_reader_.audio_sample_info(), kSbDrmSystemInvalid}; - scoped_ptr<PlayerComponents> components = PlayerComponents::Create(); + scoped_ptr<PlayerComponents> components; + if (using_stub_decoder_) { + components = make_scoped_ptr<StubPlayerComponentsImpl>( + new StubPlayerComponentsImpl); + } else { + components = PlayerComponents::Create(); + } components->CreateAudioComponents(audio_parameters, &audio_decoder_, &audio_renderer_sink_); ASSERT_TRUE(audio_decoder_); @@ -151,6 +165,8 @@ last_input_buffer_ = GetAudioInputBuffer(index); + outstanding_inputs_.insert(last_input_buffer_->timestamp()); + audio_decoder_->Decode(last_input_buffer_, consumed_cb()); } @@ -265,6 +281,8 @@ can_accept_more_input_ = true; last_input_buffer_ = NULL; last_decoded_audio_ = NULL; + outstanding_inputs_.clear(); + eos_written_ = false; } void WaitForDecodedAudio() { @@ -296,9 +314,38 @@ #endif // SB_API_VERSION >= 11 } + void WriteEndOfStream() { + SB_DCHECK(!eos_written_); + audio_decoder_->WriteEndOfStream(); + eos_written_ = true; + } + + void AssertInvalidOutputFormat() { + SbMediaAudioSampleType output_sample_type = audio_decoder_->GetSampleType(); + ASSERT_TRUE(output_sample_type == kSbMediaAudioSampleTypeFloat32 || + output_sample_type == kSbMediaAudioSampleTypeInt16Deprecated); + + SbMediaAudioFrameStorageType output_storage_type = + audio_decoder_->GetStorageType(); + ASSERT_TRUE(output_storage_type == + kSbMediaAudioFrameStorageTypeInterleaved || + output_storage_type == kSbMediaAudioFrameStorageTypePlanar); + + int output_samples_per_second = audio_decoder_->GetSamplesPerSecond(); + ASSERT_TRUE(output_samples_per_second > 0 && + output_samples_per_second <= 480000); + } + Mutex event_queue_mutex_; std::deque<Event> event_queue_; + // Test parameter for the filename to load with the VideoDmpReader. + const char* test_filename_; + + // Test parameter to configure whether the test is run with the + // StubAudioDecoder, or the platform-specific AudioDecoderImpl + bool using_stub_decoder_; + JobQueue job_queue_; VideoDmpReader dmp_reader_; scoped_ptr<AudioDecoder> audio_decoder_; @@ -307,6 +354,12 @@ bool can_accept_more_input_ = true; scoped_refptr<InputBuffer> last_input_buffer_; scoped_refptr<DecodedAudio> last_decoded_audio_; + + // List of timestamps of InputBuffers provided to the Decoder so far, sorted + // in ascending order. + std::set<SbTime> outstanding_inputs_; + + bool eos_written_ = false; }; TEST_P(AudioDecoderTest, ThreeMoreDecoders) { @@ -332,10 +385,11 @@ TEST_P(AudioDecoderTest, SingleInput) { ASSERT_NO_FATAL_FAILURE(WriteSingleInput(0)); - audio_decoder_->WriteEndOfStream(); + WriteEndOfStream(); ASSERT_NO_FATAL_FAILURE(DrainOutputs()); ASSERT_TRUE(last_decoded_audio_); + ASSERT_NO_FATAL_FAILURE(AssertInvalidOutputFormat()); } TEST_P(AudioDecoderTest, SingleInputHEAAC) { @@ -346,10 +400,11 @@ } ASSERT_NO_FATAL_FAILURE(WriteSingleInput(0)); - audio_decoder_->WriteEndOfStream(); + WriteEndOfStream(); ASSERT_NO_FATAL_FAILURE(DrainOutputs()); ASSERT_TRUE(last_decoded_audio_); + ASSERT_NO_FATAL_FAILURE(AssertInvalidOutputFormat()); if (last_decoded_audio_->frames() == kAacFrameSize) { return; } @@ -367,7 +422,7 @@ static_cast<int>(content.size())); audio_decoder_->Decode(last_input_buffer_, consumed_cb()); - audio_decoder_->WriteEndOfStream(); + WriteEndOfStream(); bool error_occurred = false; ASSERT_NO_FATAL_FAILURE(DrainOutputs(&error_occurred)); @@ -381,20 +436,22 @@ } TEST_P(AudioDecoderTest, EndOfStreamWithoutAnyInput) { - audio_decoder_->WriteEndOfStream(); + WriteEndOfStream(); ASSERT_NO_FATAL_FAILURE(DrainOutputs()); ASSERT_FALSE(last_decoded_audio_); + ASSERT_NO_FATAL_FAILURE(AssertInvalidOutputFormat()); } TEST_P(AudioDecoderTest, ResetBeforeInput) { ResetDecoder(); ASSERT_NO_FATAL_FAILURE(WriteSingleInput(0)); - audio_decoder_->WriteEndOfStream(); + WriteEndOfStream(); ASSERT_NO_FATAL_FAILURE(DrainOutputs()); ASSERT_TRUE(last_decoded_audio_); + ASSERT_NO_FATAL_FAILURE(AssertInvalidOutputFormat()); } TEST_P(AudioDecoderTest, MultipleInputs) { @@ -404,10 +461,11 @@ ASSERT_NO_FATAL_FAILURE(WriteMultipleInputs(0, number_of_inputs_to_write)); - audio_decoder_->WriteEndOfStream(); + WriteEndOfStream(); ASSERT_NO_FATAL_FAILURE(DrainOutputs()); ASSERT_TRUE(last_decoded_audio_); + ASSERT_NO_FATAL_FAILURE(AssertInvalidOutputFormat()); } #if SB_API_VERSION >= 11 @@ -421,7 +479,7 @@ ASSERT_NO_FATAL_FAILURE(WriteTimeLimitedInputs(&start_index, duration)); if (start_index >= dmp_reader_.number_of_audio_buffers()) { - audio_decoder_->WriteEndOfStream(); + WriteEndOfStream(); } // Wait for decoded audio. @@ -456,9 +514,10 @@ ASSERT_FALSE(decoded_audio->is_end_of_stream()); } } - audio_decoder_->WriteEndOfStream(); + WriteEndOfStream(); ASSERT_NO_FATAL_FAILURE(DrainOutputs()); ASSERT_TRUE(last_decoded_audio_); + ASSERT_NO_FATAL_FAILURE(AssertInvalidOutputFormat()); } #endif // SB_API_VERSION >= 11 @@ -488,7 +547,7 @@ INSTANTIATE_TEST_CASE_P(AudioDecoderTests, AudioDecoderTest, - ValuesIn(GetSupportedTests())); + Combine(ValuesIn(GetSupportedTests()), Bool())); } // namespace } // namespace testing
diff --git a/src/starboard/shared/starboard/player/filter/testing/video_decoder_test.cc b/src/starboard/shared/starboard/player/filter/testing/video_decoder_test.cc index 19f8fcc..c977332 100644 --- a/src/starboard/shared/starboard/player/filter/testing/video_decoder_test.cc +++ b/src/starboard/shared/starboard/player/filter/testing/video_decoder_test.cc
@@ -17,6 +17,7 @@ #include <algorithm> #include <deque> #include <functional> +#include <map> #include <set> #include "starboard/common/condition_variable.h" @@ -28,7 +29,7 @@ #include "starboard/memory.h" #include "starboard/shared/starboard/media/media_support_internal.h" #include "starboard/shared/starboard/media/media_util.h" -#include "starboard/shared/starboard/player/filter/player_components.h" +#include "starboard/shared/starboard/player/filter/stub_player_components_impl.h" #include "starboard/shared/starboard/player/job_queue.h" #include "starboard/shared/starboard/player/video_dmp_reader.h" #include "starboard/testing/fake_graphics_context_provider.h" @@ -55,6 +56,8 @@ using ::testing::AssertionFailure; using ::testing::AssertionResult; using ::testing::AssertionSuccess; +using ::testing::Bool; +using ::testing::Combine; using ::testing::ValuesIn; using video_dmp::VideoDmpReader; @@ -102,11 +105,16 @@ << "time " << time1 << " doesn't match with time " << time2; } -class VideoDecoderTest : public ::testing::TestWithParam<TestParam> { +class VideoDecoderTest + : public ::testing::TestWithParam<std::tuple<TestParam, bool>> { public: VideoDecoderTest() - : dmp_reader_(ResolveTestFileName(GetParam().filename).c_str()) { - SB_LOG(INFO) << "Testing " << GetParam().filename; + : test_filename_(std::get<0>(GetParam()).filename), + output_mode_(std::get<0>(GetParam()).output_mode), + using_stub_decoder_(std::get<1>(GetParam())), + dmp_reader_(ResolveTestFileName(test_filename_).c_str()) { + SB_LOG(INFO) << "Testing " << test_filename_ + << (using_stub_decoder_ ? " with stub video decoder." : "."); } ~VideoDecoderTest() { video_decoder_->Reset(); } @@ -116,7 +124,7 @@ ASSERT_GT(dmp_reader_.number_of_video_buffers(), 0); ASSERT_TRUE(GetVideoInputBuffer(0)->video_sample_info().is_key_frame); - SbPlayerOutputMode output_mode = GetParam().output_mode; + SbPlayerOutputMode output_mode = output_mode_; ASSERT_TRUE(VideoDecoder::OutputModeSupported( output_mode, dmp_reader_.video_codec(), kSbDrmSystemInvalid)); @@ -127,7 +135,13 @@ output_mode, fake_graphics_context_provider_.decoder_target_provider()}; - scoped_ptr<PlayerComponents> components = PlayerComponents::Create(); + scoped_ptr<PlayerComponents> components; + if (using_stub_decoder_) { + components = make_scoped_ptr<StubPlayerComponentsImpl>( + new StubPlayerComponentsImpl); + } else { + components = PlayerComponents::Create(); + } components->CreateVideoComponents(video_parameters, &video_decoder_, &video_render_algorithm_, &video_renderer_sink_); @@ -172,7 +186,7 @@ #if SB_HAS(GLES2) void AssertInvalidDecodeTarget() { - if (GetParam().output_mode == kSbPlayerOutputModeDecodeToTexture) { + if (output_mode_ == kSbPlayerOutputModeDecodeToTexture) { auto decode_target = video_decoder_->GetCurrentDecodeTarget(); ASSERT_FALSE(SbDecodeTargetIsValid(decode_target)); fake_graphics_context_provider_.ReleaseDecodeTarget(decode_target); @@ -239,10 +253,20 @@ return !event_queue_.empty(); } + void GetDecodeTargetWhenSupported() { +#if SB_HAS(GLES2) + if (output_mode_ == kSbPlayerOutputModeDecodeToTexture) { + SbDecodeTarget decode_target = video_decoder_->GetCurrentDecodeTarget(); + fake_graphics_context_provider_.ReleaseDecodeTarget(decode_target); + } +#endif // SB_HAS(GLES2) + } + void AssertValidDecodeTargetWhenSupported() { #if SB_HAS(GLES2) - if (GetParam().output_mode == kSbPlayerOutputModeDecodeToTexture) { - auto decode_target = video_decoder_->GetCurrentDecodeTarget(); + if (output_mode_ == kSbPlayerOutputModeDecodeToTexture && + !using_stub_decoder_) { + SbDecodeTarget decode_target = video_decoder_->GetCurrentDecodeTarget(); ASSERT_TRUE(SbDecodeTargetIsValid(decode_target)); fake_graphics_context_provider_.ReleaseDecodeTarget(decode_target); } @@ -290,6 +314,14 @@ ASSERT_NO_FATAL_FAILURE(WriteSingleInput(start_index)); ++start_index; --number_of_inputs_to_write; + } else if (event.status == kError) { + // Assume that the caller does't expect an error when |event_cb| isn't + // provided. + ASSERT_TRUE(event_cb); + bool continue_process = true; + event_cb(event, &continue_process); + ASSERT_FALSE(continue_process); + return; } else { ASSERT_EQ(event.status, kBufferFull); } @@ -335,7 +367,16 @@ if (event.frame) { if (event.frame->is_end_of_stream()) { end_of_stream_decoded = true; - ASSERT_TRUE(outstanding_inputs_.empty()); + if (!outstanding_inputs_.empty()) { + if (error_occurred) { + *error_occurred = true; + } else { + // |error_occurred| is NULL indicates that the caller doesn't + // expect an error, use the following redundant ASSERT to trigger + // a failure. + ASSERT_TRUE(outstanding_inputs_.empty()); + } + } } else { if (!decoded_frames_.empty()) { ASSERT_LT(decoded_frames_.back()->timestamp(), @@ -371,11 +412,24 @@ auto video_sample_info = dmp_reader_.GetPlayerSampleInfo(kSbMediaTypeVideo, index); #if SB_API_VERSION >= 11 - return new InputBuffer(DeallocateSampleFunc, NULL, NULL, video_sample_info); + auto input_buffer = + new InputBuffer(DeallocateSampleFunc, NULL, NULL, video_sample_info); #else // SB_API_VERSION >= 11 - return new InputBuffer(kSbMediaTypeVideo, DeallocateSampleFunc, NULL, NULL, - video_sample_info, NULL); + auto input_buffer = new InputBuffer(kSbMediaTypeVideo, DeallocateSampleFunc, + NULL, NULL, video_sample_info, NULL); #endif // SB_API_VERSION >= 11 + auto iter = invalid_inputs_.find(index); + if (iter != invalid_inputs_.end()) { + std::vector<uint8_t> content(input_buffer->size(), iter->second); + // Replace the content with invalid data. + input_buffer->SetDecryptedContent(content.data(), + static_cast<int>(content.size())); + } + return input_buffer; + } + + void UseInvalidDataForInput(size_t index, uint8_t byte_to_fill) { + invalid_inputs_[index] = byte_to_fill; } JobQueue job_queue_; @@ -383,6 +437,16 @@ Mutex mutex_; std::deque<Event> event_queue_; + // Test parameter filename for the VideoDmpReader to load and test with. + const char* test_filename_; + + // Test parameter for OutputMode. + SbPlayerOutputMode output_mode_; + + // Test parameter for whether or not to use the StubVideoDecoder, or the + // platform-specific VideoDecoderImpl. + bool using_stub_decoder_; + FakeGraphicsContextProvider fake_graphics_context_provider_; VideoDmpReader dmp_reader_; scoped_ptr<VideoDecoder> video_decoder_; @@ -397,6 +461,8 @@ scoped_refptr<VideoRendererSink> video_renderer_sink_; bool end_of_stream_written_ = false; + + std::map<size_t, uint8_t> invalid_inputs_; }; TEST_P(VideoDecoderTest, PrerollFrameCount) { @@ -440,8 +506,11 @@ #if SB_HAS(GLES2) TEST_P(VideoDecoderTest, GetCurrentDecodeTargetBeforeWriteInputBuffer) { - if (GetParam().output_mode == kSbPlayerOutputModeDecodeToTexture) { + if (output_mode_ == kSbPlayerOutputModeDecodeToTexture) { AssertInvalidDecodeTarget(); + SbDecodeTarget decode_target = video_decoder_->GetCurrentDecodeTarget(); + EXPECT_FALSE(SbDecodeTargetIsValid(decode_target)); + fake_graphics_context_provider_.ReleaseDecodeTarget(decode_target); } } #endif // SB_HAS(GLES2) @@ -529,28 +598,81 @@ ASSERT_FALSE(error_occurred); } -TEST_P(VideoDecoderTest, SingleInvalidInput) { - need_more_input_ = false; - auto input_buffer = GetVideoInputBuffer(0); - outstanding_inputs_.insert(input_buffer->timestamp()); - std::vector<uint8_t> content(input_buffer->size(), 0xab); - // Replace the content with invalid data. - input_buffer->SetDecryptedContent(content.data(), - static_cast<int>(content.size())); - video_decoder_->WriteInputBuffer(input_buffer); +TEST_P(VideoDecoderTest, SingleInvalidKeyFrame) { + UseInvalidDataForInput(0, 0xab); + WriteSingleInput(0); WriteEndOfStream(); bool error_occurred = true; ASSERT_NO_FATAL_FAILURE(DrainOutputs(&error_occurred)); - if (error_occurred) { - ASSERT_TRUE(decoded_frames_.empty()); - } else { - // We don't expect the video decoder to recover from a bad input but some - // decoders may just return an empty frame. - ASSERT_FALSE(decoded_frames_.empty()); - AssertValidDecodeTargetWhenSupported(); + // We don't expect the video decoder can always recover from a bad key frame + // and to raise an error, but it shouldn't crash or hang. + GetDecodeTargetWhenSupported(); +} + +TEST_P(VideoDecoderTest, MultipleValidInputsAfterInvalidKeyFrame) { + const size_t kMaxNumberOfInputToWrite = 10; + const size_t number_of_input_to_write = + std::min(kMaxNumberOfInputToWrite, dmp_reader_.number_of_video_buffers()); + + UseInvalidDataForInput(0, 0xab); + + bool error_occurred = false; + + // Write first few frames. The first one is invalid and the rest are valid. + WriteMultipleInputs(0, number_of_input_to_write, + [&](const Event& event, bool* continue_process) { + if (event.status == kError) { + error_occurred = true; + *continue_process = false; + return; + } + + *continue_process = event.status != kBufferFull; + }); + + if (!error_occurred) { + GetDecodeTargetWhenSupported(); + WriteEndOfStream(); + ASSERT_NO_FATAL_FAILURE(DrainOutputs(&error_occurred)); } + // We don't expect the video decoder can always recover from a bad key frame + // and to raise an error, but it shouldn't crash or hang. + GetDecodeTargetWhenSupported(); +} + +TEST_P(VideoDecoderTest, MultipleInvalidInput) { + const size_t kMaxNumberOfInputToWrite = 128; + const size_t number_of_input_to_write = + std::min(kMaxNumberOfInputToWrite, dmp_reader_.number_of_video_buffers()); + // Replace the content of the first few input buffers with invalid data. + // Every test instance loads its own copy of data so this won't affect other + // tests. + for (size_t i = 0; i < number_of_input_to_write; ++i) { + UseInvalidDataForInput(i, static_cast<uint8_t>(0xab + i)); + } + + bool error_occurred = false; + WriteMultipleInputs(0, number_of_input_to_write, + [&](const Event& event, bool* continue_process) { + if (event.status == kError) { + error_occurred = true; + *continue_process = false; + return; + } + + *continue_process = event.status != kBufferFull; + }); + + if (!error_occurred) { + GetDecodeTargetWhenSupported(); + WriteEndOfStream(); + ASSERT_NO_FATAL_FAILURE(DrainOutputs(&error_occurred)); + } + // We don't expect the video decoder can always recover from a bad key frame + // and to raise an error, but it shouldn't crash or hang. + GetDecodeTargetWhenSupported(); } TEST_P(VideoDecoderTest, EndOfStreamWithoutAnyInput) { @@ -744,7 +866,7 @@ INSTANTIATE_TEST_CASE_P(VideoDecoderTests, VideoDecoderTest, - ValuesIn(GetSupportedTests())); + Combine(ValuesIn(GetSupportedTests()), Bool())); } // namespace } // namespace testing
diff --git a/src/starboard/shared/starboard/player/testdata/beneath_the_canopy_avc_aac.dmp b/src/starboard/shared/starboard/player/testdata/beneath_the_canopy_avc_aac.dmp deleted file mode 100644 index bec6752..0000000 --- a/src/starboard/shared/starboard/player/testdata/beneath_the_canopy_avc_aac.dmp +++ /dev/null Binary files differ
diff --git a/src/starboard/shared/starboard/player/testdata/beneath_the_canopy_vp9_opus.dmp b/src/starboard/shared/starboard/player/testdata/beneath_the_canopy_vp9_opus.dmp deleted file mode 100644 index 4d663f9..0000000 --- a/src/starboard/shared/starboard/player/testdata/beneath_the_canopy_vp9_opus.dmp +++ /dev/null Binary files differ
diff --git a/src/starboard/shared/starboard/player/testdata/heaac.dmp b/src/starboard/shared/starboard/player/testdata/heaac.dmp deleted file mode 100644 index 133a9c1..0000000 --- a/src/starboard/shared/starboard/player/testdata/heaac.dmp +++ /dev/null Binary files differ
diff --git a/src/starboard/shared/starboard/player/video_dmp_reader.cc b/src/starboard/shared/starboard/player/video_dmp_reader.cc index 2ae52a0..250a0f7 100644 --- a/src/starboard/shared/starboard/player/video_dmp_reader.cc +++ b/src/starboard/shared/starboard/player/video_dmp_reader.cc
@@ -120,13 +120,13 @@ switch (type) { case kSbMediaTypeAudio: { SB_DCHECK(index < audio_access_units_.size()); - const AudioAccessUnit& aau = audio_access_units_[index]; - return ConvertToPlayerSampleInfo(aau); + const AudioAccessUnit& audio_au = audio_access_units_[index]; + return ConvertToPlayerSampleInfo(audio_au); } case kSbMediaTypeVideo: { SB_DCHECK(index < video_access_units_.size()); - const VideoAccessUnit& vau = video_access_units_[index]; - return ConvertToPlayerSampleInfo(vau); + const VideoAccessUnit& video_au = video_access_units_[index]; + return ConvertToPlayerSampleInfo(video_au); } } SB_NOTREACHED() << "Unhandled SbMediaType";
diff --git a/src/starboard/shared/stub/cpu_features_get.cc b/src/starboard/shared/stub/cpu_features_get.cc index 21c289f..a550da2 100644 --- a/src/starboard/shared/stub/cpu_features_get.cc +++ b/src/starboard/shared/stub/cpu_features_get.cc
@@ -13,34 +13,23 @@ // limitations under the License. #include "starboard/cpu_features.h" +#include "starboard/shared/starboard/cpu_features.h" #include <string.h> #if SB_API_VERSION >= 11 +using starboard::shared::SetArmFeaturesInvalid; +using starboard::shared::SetGeneralFeaturesInvalid; +using starboard::shared::SetX86FeaturesInvalid; + bool SbCPUFeaturesGet(SbCPUFeatures* features) { memset(features, 0, sizeof(*features)); features->architecture = kSbCPUFeaturesArchitectureUnknown; - features->brand = ""; - features->cache_size = -1; - features->has_fpu = false; - features->hwcap = 0; - features->hwcap2 = 0; - features->arm.implementer = -1; - features->arm.variant = -1; - features->arm.revision = -1; - features->arm.architecture_generation = -1; - features->arm.part = -1; - - features->x86.vendor = ""; - features->x86.family = -1; - features->x86.ext_family = -1; - features->x86.model = -1; - features->x86.ext_model = -1; - features->x86.stepping = -1; - features->x86.type = -1; - features->x86.signature = -1; + SetGeneralFeaturesInvalid(features); + SetArmFeaturesInvalid(features); + SetX86FeaturesInvalid(features); return false; }
diff --git a/src/starboard/tools/testing/test_runner.py b/src/starboard/tools/testing/test_runner.py index f5af1ca..ee3b7d7 100755 --- a/src/starboard/tools/testing/test_runner.py +++ b/src/starboard/tools/testing/test_runner.py
@@ -473,6 +473,11 @@ total_flaky_failed_count = 0 total_filtered_count = 0 + print # Explicit print for empty formatting line. + logging.info("TEST RUN COMPLETE.") + if results: + print # Explicit print for empty formatting line. + # If the number of run tests from a test binary cannot be # determined, assume an error occurred while running it. error = False @@ -513,8 +518,7 @@ for test_case in flaky_failed_tests: for retry in range(_FLAKY_RETRY_LIMIT): retry_result = self._RunTest(target_name, test_case) - # Explicit print used to have an empty newline for formatting. - print + print # Explicit print for empty formatting line. if retry_result[2] == 1: flaky_passed_tests.append(test_case) logging.info("%s succeeded on run #%d!\n", test_case, retry + 2) @@ -529,20 +533,17 @@ else: logging.info("") # formatting newline. - logging.info("TEST RUN COMPLETE. RESULTS BELOW:") - logging.info("") # formatting newline. - test_status = "SUCCEEDED" - # If |return_code| is non-zero, the tests either crashed or failed. - if return_code != 0: - # If |run_count| is zero the tests crashed. - if run_count == 0 or actual_failed_count > 0 or flaky_failed_count > 0: - error = True - test_status = "FAILED" + + # Always mark as FAILED if we have a non-zero return code, or failing + # test. + if return_code != 0 or actual_failed_count > 0 or flaky_failed_count > 0: + error = True + test_status = "FAILED" failed_test_groups.append(target_name) logging.info("%s: %s.", target_name, test_status) - if return_code != 0 and run_count == 0: + if return_code != 0 and run_count == 0 and filtered_count == 0: logging.info(" Results not available. Did the test crash?") logging.info("") # formatting newline. continue @@ -579,6 +580,8 @@ for line in filtered_tests: logging.info(" %s", line) logging.info("") # formatting newline. + logging.info(" RETURN CODE: %d", return_code) + logging.info("") # formatting newline. overall_status = "SUCCEEDED" result = True
diff --git a/src/third_party/boringssl/boringssl.gyp b/src/third_party/boringssl/boringssl.gyp index 1edb8cd..a6cd7c8 100644 --- a/src/third_party/boringssl/boringssl.gyp +++ b/src/third_party/boringssl/boringssl.gyp
@@ -44,6 +44,7 @@ ], 'sources': [ '<(boringssl_root)/crypto/rand_extra/starboard.c', + '<(boringssl_root)/crypto/cpu-starboard.c', ], 'sources!': [ '<(boringssl_root)/crypto/bio/connect.c',
diff --git a/src/third_party/boringssl/boringssl.gypi b/src/third_party/boringssl/boringssl.gypi index e8c5445..c1e4e2e 100644 --- a/src/third_party/boringssl/boringssl.gypi +++ b/src/third_party/boringssl/boringssl.gypi
@@ -105,6 +105,7 @@ '<(boringssl_root)/crypto/chacha/chacha.c', '<(boringssl_root)/crypto/cipher_extra/cipher_extra.c', '<(boringssl_root)/crypto/cipher_extra/derive_key.c', + '<(boringssl_root)/crypto/cipher_extra/e_aesccm.c', '<(boringssl_root)/crypto/cipher_extra/e_aesctrhmac.c', '<(boringssl_root)/crypto/cipher_extra/e_aesgcmsiv.c', '<(boringssl_root)/crypto/cipher_extra/e_chacha20poly1305.c',
diff --git a/src/third_party/boringssl/boringssl_tool.gyp b/src/third_party/boringssl/boringssl_tool.gyp new file mode 100644 index 0000000..8397b22 --- /dev/null +++ b/src/third_party/boringssl/boringssl_tool.gyp
@@ -0,0 +1,47 @@ +# Copyright 2019 Google Inc. All Rights Reserved. +{ + 'variables': { + 'boringssl_root%': '<(DEPTH)/third_party/boringssl/src', + }, + 'targets': [ + { + 'target_name': 'crypto_tool', + 'type': '<(final_executable_type)', + 'include_dirs': [ + '<(boringssl_root)/include', + ], + 'defines': [ + 'OPENSSL_NO_SOCK' + ], + 'sources' : [ + '<(boringssl_root)/tool/args.cc', + '<(boringssl_root)/tool/ciphers.cc', + '<(boringssl_root)/tool/const.cc', + '<(boringssl_root)/tool/digest.cc', + '<(boringssl_root)/tool/file.cc', + '<(boringssl_root)/tool/generate_ed25519.cc', + '<(boringssl_root)/tool/genrsa.cc', + '<(boringssl_root)/tool/pkcs12.cc', + '<(boringssl_root)/tool/rand.cc', + '<(boringssl_root)/tool/sign.cc', + '<(boringssl_root)/tool/speed.cc', + '<(boringssl_root)/tool/tool.cc', + ], + 'dependencies' : [ + '<(DEPTH)/third_party/boringssl/boringssl.gyp:crypto', + '<(DEPTH)/starboard/starboard.gyp:starboard' + ] + }, + { + 'target_name': 'crypto_tool_deploy', + 'type': 'none', + 'dependencies': [ + 'crypto_tool', + ], + 'variables': { + 'executable_name': 'crypto_tool', + }, + 'includes': [ '../../starboard/build/deploy.gypi' ], + }, + ], +}
diff --git a/src/third_party/boringssl/src/config/starboard/openssl/opensslconf.h b/src/third_party/boringssl/src/config/starboard/openssl/opensslconf.h index 3734c4d..6edf989 100644 --- a/src/third_party/boringssl/src/config/starboard/openssl/opensslconf.h +++ b/src/third_party/boringssl/src/config/starboard/openssl/opensslconf.h
@@ -36,9 +36,10 @@ # define OPENSSL_NO_POSIX_IO #endif -#ifndef OPENSSL_NO_FP_API -# define OPENSSL_NO_FP_API -#endif +// Benchmarking tool requires FP API to read certs and keys +//#ifndef OPENSSL_NO_FP_API +// # define OPENSSL_NO_FP_API +//#endif #ifndef OPENSSL_NO_DSO # define OPENSSL_NO_DSO
diff --git a/src/third_party/boringssl/src/crypto/cpu-starboard.c b/src/third_party/boringssl/src/crypto/cpu-starboard.c new file mode 100644 index 0000000..2f7609c --- /dev/null +++ b/src/third_party/boringssl/src/crypto/cpu-starboard.c
@@ -0,0 +1,124 @@ +// Copyright 2019 The Cobalt Authors. 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 <openssl/opensslconf.h> +#include <openssl/cpu.h> +#include "../../crypto/internal.h" +#include <starboard/cpu_features.h> +#include <starboard/string.h> + +#if defined(STARBOARD) && (SB_API_VERSION >= 11) + +#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64) + +#define CPUID_01_REG_EDX 0 +#define CPUID_01_REG_ECX 1 +#define CPUID_07_REG_EBX 2 +#define CPUID_07_REG_ECX 3 + +#define ID_01_EDX_IS_INTEL_BIT 30 +#define ID_01_ECX_SSSE3_BIT 9 +#define ID_01_ECX_AESNI_BIT 25 +#define ID_01_ECX_AVX_BIT 28 + +static bool starboard_cpuid_setup_x86(void) { + OPENSSL_ia32cap_P[CPUID_01_REG_EDX] = 0; + OPENSSL_ia32cap_P[CPUID_01_REG_ECX] = 0; + OPENSSL_ia32cap_P[CPUID_07_REG_EBX] = 0; + OPENSSL_ia32cap_P[CPUID_07_REG_ECX] = 0; + + SbCPUFeatures features; + if (!SbCPUFeaturesGet(&features)) { + return false; + } + + if(features.architecture != kSbCPUFeaturesArchitectureX86_64 && + features.architecture != kSbCPUFeaturesArchitectureX86) { + return false; + } + + // OpenSSL has optimized AVX codepath enabled only on Intel CPUs + // The flag is passed as a "synthetic" value in reserved bit, i.e. CPUID + // never returns it. See https://github.com/openssl/openssl/commit/0c14980 + if (!SbStringCompareAll(features.x86.vendor,"GenuineIntel")) { + OPENSSL_ia32cap_P[CPUID_01_REG_EDX] |= (1 << ID_01_EDX_IS_INTEL_BIT); + } + + // Enables AESNI acceleration + if (features.x86.has_aesni) + OPENSSL_ia32cap_P[CPUID_01_REG_ECX] |= (1 << ID_01_ECX_AESNI_BIT); + // Enables AESNI and SHAx acceleration + if (features.x86.has_avx) + OPENSSL_ia32cap_P[CPUID_01_REG_ECX] |= (1 << ID_01_ECX_AVX_BIT); + // Enables alternate SHA acceleration + if (features.x86.has_ssse3) + OPENSSL_ia32cap_P[CPUID_01_REG_ECX] |= (1 << ID_01_ECX_SSSE3_BIT); + + return true; +} + +#else +static bool starboard_cpuid_setup_x86(void) { return true; } +#endif // defined(OPENSSL_X86 || OPENSSL_X86_64) + +#if defined(OPENSSL_ARM) + +#include <openssl/arm_arch.h> + +// This global provides ARM assembly routines capability flags +extern uint32_t OPENSSL_armcap_P; + +static bool starboard_cpuid_setup_arm() { + OPENSSL_armcap_P = 0; // Reset the flags + + SbCPUFeatures features; + if (!SbCPUFeaturesGet(&features)) { + return false; + } + + if(features.architecture != kSbCPUFeaturesArchitectureArm64 && + features.architecture != kSbCPUFeaturesArchitectureArm) { + return false; + } + + if (features.arm.has_aes) + OPENSSL_armcap_P |= ARMV8_AES; + if (features.arm.has_sha1) + OPENSSL_armcap_P |= ARMV8_SHA1; + if (features.arm.has_sha2) + OPENSSL_armcap_P |= ARMV8_SHA256; + if (features.arm.has_pmull) + OPENSSL_armcap_P |= ARMV8_PMULL; + if (features.arm.has_neon) + OPENSSL_armcap_P |= ARMV7_NEON; + + return true; +} + +#else +static bool starboard_cpuid_setup_arm(void) { return true; } +#endif // OPENSSL_ARM + +void OPENSSL_cpuid_setup_starboard(void) { + if (!starboard_cpuid_setup_arm() || + !starboard_cpuid_setup_x86() ) { +#if !SB_IS(EVERGREEN) + // Fall back on original implementation if the platform + // does not yet support Starboard CPU detection + OPENSSL_cpuid_setup(); +#endif + } +} + +#endif // STARBOARD
diff --git a/src/third_party/boringssl/src/crypto/crypto.c b/src/third_party/boringssl/src/crypto/crypto.c index 93e2f82..4e9d316 100644 --- a/src/third_party/boringssl/src/crypto/crypto.c +++ b/src/third_party/boringssl/src/crypto/crypto.c
@@ -148,8 +148,12 @@ // WARNING: this function may only configure the capability variables. See the // note above about the linker bug. #if defined(NEED_CPUID) +#if defined(STARBOARD) && (SB_API_VERSION >= 11) + OPENSSL_cpuid_setup_starboard(); +#else OPENSSL_cpuid_setup(); #endif +#endif } void CRYPTO_library_init(void) {
diff --git a/src/third_party/boringssl/src/crypto/internal.h b/src/third_party/boringssl/src/crypto/internal.h index 643c389..4b88bcf 100644 --- a/src/third_party/boringssl/src/crypto/internal.h +++ b/src/third_party/boringssl/src/crypto/internal.h
@@ -155,6 +155,9 @@ defined(OPENSSL_AARCH64) || defined(OPENSSL_PPC64LE) // OPENSSL_cpuid_setup initializes the platform-specific feature cache. void OPENSSL_cpuid_setup(void); +#if defined(STARBOARD) +void OPENSSL_cpuid_setup_starboard(void); +#endif #endif
diff --git a/src/third_party/boringssl/src/tool/digest.cc b/src/third_party/boringssl/src/tool/digest.cc index 7b6c88b..6020c99 100644 --- a/src/third_party/boringssl/src/tool/digest.cc +++ b/src/third_party/boringssl/src/tool/digest.cc
@@ -37,8 +37,10 @@ OPENSSL_MSVC_PRAGMA(warning(pop)) #include <io.h> #define PATH_MAX MAX_PATH +#if !defined(STARBOARD) typedef int ssize_t; #endif +#endif #include <openssl/digest.h>
diff --git a/src/third_party/boringssl/src/tool/pkcs12.cc b/src/third_party/boringssl/src/tool/pkcs12.cc index a8ddb0e..8440096 100644 --- a/src/third_party/boringssl/src/tool/pkcs12.cc +++ b/src/third_party/boringssl/src/tool/pkcs12.cc
@@ -111,7 +111,7 @@ off < sizeof(password) - 1) || (n == -1 && errno == EINTR)); - char *newline = reinterpret_cast<char *>(OPENSSL_memchr(password, '\n', off)); + char *newline = const_cast<char *>(reinterpret_cast<const char *>(OPENSSL_memchr(password, '\n', off))); if (newline == NULL) { return false; }
diff --git a/src/third_party/boringssl/src/tool/speed.cc b/src/third_party/boringssl/src/tool/speed.cc index 2175baa..194b618 100644 --- a/src/third_party/boringssl/src/tool/speed.cc +++ b/src/third_party/boringssl/src/tool/speed.cc
@@ -32,6 +32,7 @@ #include <openssl/ecdsa.h> #include <openssl/ec_key.h> #include <openssl/evp.h> +#include <openssl/mem.h> #include <openssl/nid.h> #include <openssl/rand.h> #include <openssl/rsa.h>
diff --git a/src/third_party/boringssl/src/tool/tool.cc b/src/third_party/boringssl/src/tool/tool.cc index 670d4e7..313da33 100644 --- a/src/third_party/boringssl/src/tool/tool.cc +++ b/src/third_party/boringssl/src/tool/tool.cc
@@ -19,12 +19,18 @@ #include <openssl/err.h> #include <openssl/ssl.h> +#ifdef STARBOARD +#include <starboard/client_porting/wrap_main/wrap_main.h> +#endif + #if defined(OPENSSL_WINDOWS) #include <fcntl.h> #include <io.h> #else +#if defined(_POSIX_C_SOURCE) || defined(__ANDROID_API_) #include <libgen.h> #endif +#endif #include "internal.h" @@ -43,16 +49,20 @@ static const Tool kTools[] = { { "ciphers", Ciphers }, +#ifndef OPENSSL_NO_SOCK { "client", Client }, +#endif { "isfips", IsFIPS }, { "generate-ed25519", GenerateEd25519Key }, { "genrsa", GenerateRSAKey }, { "md5sum", MD5Sum }, { "pkcs12", DoPKCS12 }, { "rand", Rand }, +#ifndef OPENSSL_NO_SOCK { "s_client", Client }, { "s_server", Server }, { "server", Server }, +#endif { "sha1sum", SHA1Sum }, { "sha224sum", SHA224Sum }, { "sha256sum", SHA256Sum }, @@ -86,7 +96,11 @@ } } +#ifdef STARBOARD +int crypto_tool_main(int argc, char **argv) { +#else int main(int argc, char **argv) { +#endif #if defined(OPENSSL_WINDOWS) // Read and write in binary mode. This makes bssl on Windows consistent with // bssl on other platforms, and also makes it consistent with MSYS's commands @@ -111,8 +125,10 @@ int starting_arg = 1; tool_func_t tool = nullptr; #if !defined(OPENSSL_WINDOWS) +#if defined(_POSIX_C_SOURCE) || defined(__ANDROID_API_) tool = FindTool(basename(argv[0])); #endif +#endif if (tool == nullptr) { starting_arg++; if (argc > 1) { @@ -136,3 +152,7 @@ return 0; } + +#ifdef STARBOARD +STARBOARD_WRAP_SIMPLE_MAIN(crypto_tool_main); +#endif
diff --git a/src/third_party/llvm-project/libcxxabi/libcxxabi.gyp b/src/third_party/llvm-project/libcxxabi/libcxxabi.gyp index 7133871..bcf2e83 100644 --- a/src/third_party/llvm-project/libcxxabi/libcxxabi.gyp +++ b/src/third_party/llvm-project/libcxxabi/libcxxabi.gyp
@@ -47,9 +47,6 @@ '-Wno-unused-command-line-argument', ], 'defines' : [ - # If not defined, this symbol is used to detect this function's presence in the C library - # at runtime. - 'HAVE___CXA_THREAD_ATEXIT_IMPL', # This macro is used to disable extern template declarations in the libc++ # headers. The intended use case is for clients who wish to use the libc++ # headers without taking a dependency on the libc++ library itself. @@ -75,7 +72,6 @@ 'src/cxa_handlers.cpp', 'src/cxa_handlers.hpp', 'src/cxa_personality.cpp', - 'src/cxa_thread_atexit.cpp', 'src/cxa_unexpected.cpp', 'src/cxa_vector.cpp', 'src/cxa_virtual.cpp', @@ -96,6 +92,9 @@ 'sources!': [ # We utilize exception handling and the following file breaks the build. 'src/cxa_noexception.cpp', + + # Not needed and leaks __cxa_thread_atexit_impl. + 'src/cxa_thread_atexit.cpp', ], 'all_dependent_settings': { 'defines': [
diff --git a/src/third_party/llvm-project/libunwind/libunwind.gyp b/src/third_party/llvm-project/libunwind/libunwind.gyp index 0802c24..833ca4a 100644 --- a/src/third_party/llvm-project/libunwind/libunwind.gyp +++ b/src/third_party/llvm-project/libunwind/libunwind.gyp
@@ -53,6 +53,9 @@ # Build libunwind with concurrency built upon Starboard mutexes and # condition variables. '_LIBUNWIND_HAS_STARBOARD_THREADS', + 'LIBUNWIND_PRINT_APIS', + 'LIBUNWIND_PRINT_DWARF', + 'LIBUNWIND_PRINT_UNWINDING', 'LLVM_PATH="<(DEPTH)/third_party/llvm-project/llvm/"', ], 'sources': [
diff --git a/src/third_party/llvm-project/libunwind/src/libunwind.cpp b/src/third_party/llvm-project/libunwind/src/libunwind.cpp index 3bd8ef1..a0fdecb 100644 --- a/src/third_party/llvm-project/libunwind/src/libunwind.cpp +++ b/src/third_party/llvm-project/libunwind/src/libunwind.cpp
@@ -374,7 +374,12 @@ static bool checked = false; static bool log = false; if (!checked) { - log = (getenv("LIBUNWIND_PRINT_APIS") != NULL); + log = +#if defined(LIBUNWIND_PRINT_APIS) + true; +#else // !defined(LIBUNWIND_PRINT_APIS) + false; +#endif // defined(LIBUNWIND_PRINT_APIS) checked = true; } return log; @@ -386,7 +391,12 @@ static bool checked = false; static bool log = false; if (!checked) { - log = (getenv("LIBUNWIND_PRINT_UNWINDING") != NULL); + log = +#if defined(LIBUNWIND_PRINT_UNWINDING) + true; +#else // !defined(LIBUNWIND_PRINT_UNWINDING) + false; +#endif // defined(LIBUNWIND_PRINT_UNWINDING) checked = true; } return log; @@ -398,7 +408,12 @@ static bool checked = false; static bool log = false; if (!checked) { - log = (getenv("LIBUNWIND_PRINT_DWARF") != NULL); + log = +#if defined(LIBUNWIND_PRINT_DWARF) + true; +#else // !defined(LIBUNWIND_PRINT_DWARF) + false; +#endif // defined(LIBUNWIND_PRINT_DWARF) checked = true; } return log;
diff --git a/src/third_party/musl/musl.gyp b/src/third_party/musl/musl.gyp index f2ac88a..58afe2f 100644 --- a/src/third_party/musl/musl.gyp +++ b/src/third_party/musl/musl.gyp
@@ -116,6 +116,7 @@ 'include_dirs+': [ 'src/starboard/internal', 'src/errno', + 'src/multibyte', 'src/time', ], 'sources': [ @@ -144,8 +145,13 @@ 'src/starboard/time/__tz.c', 'src/starboard/time/clock_gettime.c', + 'src/ctype/iswspace.c', 'src/errno/strerror.c', 'src/exit/assert.c', + 'src/exit/atexit.c', + 'src/internal/floatscan.c', + 'src/internal/intscan.c', + 'src/internal/shgetc.c', 'src/locale/strcoll.c', 'src/locale/strcoll.c', 'src/locale/strxfrm.c', @@ -154,7 +160,24 @@ 'src/locale/wcscoll.c', 'src/locale/wcsxfrm.c', 'src/locale/wcsxfrm.c', + 'src/math/copysignl.c', + 'src/math/scalbnl.c', + 'src/multibyte/btowc.c', + 'src/multibyte/internal.c', + 'src/multibyte/mbrlen.c', + 'src/multibyte/mbrtowc.c', + 'src/multibyte/mbsnrtowcs.c', + 'src/multibyte/mbsrtowcs.c', + 'src/multibyte/mbtowc.c', + 'src/multibyte/wcrtomb.c', + 'src/multibyte/wcsnrtombs.c', + 'src/multibyte/wcsrtombs.c', + 'src/multibyte/wcstombs.c', + 'src/multibyte/wctob.c', + 'src/stdio/__toread.c', + 'src/stdio/__uflow.c', 'src/stdio/fprintf.c', + 'src/stdio/fwrite.c', 'src/stdio/printf.c', 'src/stdio/snprintf.c', 'src/stdio/sscanf.c', @@ -164,6 +187,8 @@ 'src/stdlib/abs.c', 'src/stdlib/labs.c', 'src/stdlib/llabs.c', + 'src/stdlib/wcstod.c', + 'src/stdlib/wcstol.c', 'src/string/strerror_r.c', 'src/time/__month_to_secs.c', 'src/time/__tm_to_secs.c',
diff --git a/src/third_party/musl/src/exit/atexit.c b/src/third_party/musl/src/exit/atexit.c index cd3b0a6..5b51b4b 100644 --- a/src/third_party/musl/src/exit/atexit.c +++ b/src/third_party/musl/src/exit/atexit.c
@@ -2,6 +2,13 @@ #include <stdint.h> #include "libc.h" +#ifdef STARBOARD +#include "starboard/common/log.h" +#include "starboard/mutex.h" +#include "starboard/thread_types.h" +#include "starboard/types.h" +#endif // STARBOARD + /* Ensure that at least 32 atexit handlers can be registered without malloc */ #define COUNT 32 @@ -13,7 +20,19 @@ } builtin, *head; static int slot; +#ifdef STARBOARD +static SbMutex lock = SB_MUTEX_INITIALIZER; +#define LOCK(x) \ + do { \ + SB_DCHECK(SbMutexAcquire(&x) == kSbMutexAcquired); \ + } while (0) +#define UNLOCK(x) \ + do { \ + SB_DCHECK(SbMutexRelease(&x)); \ + } while (0) +#else // !STARBOARD static volatile int lock[1]; +#endif // STARBOARD void __funcs_on_exit() {
diff --git a/src/third_party/musl/src/internal/libc.h b/src/third_party/musl/src/internal/libc.h index 5e14518..1fa9243 100644 --- a/src/third_party/musl/src/internal/libc.h +++ b/src/third_party/musl/src/internal/libc.h
@@ -51,8 +51,10 @@ void __unlock(volatile int *) ATTR_LIBC_VISIBILITY; int __lockfile(FILE *) ATTR_LIBC_VISIBILITY; void __unlockfile(FILE *) ATTR_LIBC_VISIBILITY; +#ifndef STARBOARD #define LOCK(x) __lock(x) #define UNLOCK(x) __unlock(x) +#endif // STARBOARD void __synccall(void (*)(void *), void *); int __setxid(int, int, int, int);
diff --git a/src/third_party/musl/src/internal/stdio_impl.h b/src/third_party/musl/src/internal/stdio_impl.h index 1127a49..d3ce332 100644 --- a/src/third_party/musl/src/internal/stdio_impl.h +++ b/src/third_party/musl/src/internal/stdio_impl.h
@@ -2,14 +2,20 @@ #define _STDIO_IMPL_H #include <stdio.h> -#include "syscall.h" #include "libc.h" +// When STARBOARD is defined we only want to include the definition of _IO_FILE, +// a.k.a. FILE, along with a few constants used when working with wide strings. + +#ifndef STARBOARD +#include "syscall.h" + #define UNGET 8 #define FFINALLOCK(f) ((f)->lock>=0 ? __lockfile((f)) : 0) #define FLOCK(f) int __need_unlock = ((f)->lock>=0 ? __lockfile((f)) : 0) #define FUNLOCK(f) do { if (__need_unlock) __unlockfile((f)); } while (0) +#endif // STARBOARD #define F_PERM 1 #define F_NORD 4 @@ -50,6 +56,7 @@ struct __locale_struct *locale; }; +#ifndef STARBOARD size_t __stdio_read(FILE *, unsigned char *, size_t); size_t __stdio_write(FILE *, const unsigned char *, size_t); size_t __stdout_write(FILE *, const unsigned char *, size_t); @@ -93,5 +100,6 @@ /* Caller-allocated FILE * operations */ FILE *__fopen_rb_ca(const char *, FILE *, unsigned char *, size_t); int __fclose_ca(FILE *); +#endif // STARBOARD #endif
diff --git a/src/third_party/musl/src/starboard/internal/stdio_impl.h b/src/third_party/musl/src/starboard/internal/stdio_impl.h deleted file mode 100644 index 57133a2..0000000 --- a/src/third_party/musl/src/starboard/internal/stdio_impl.h +++ /dev/null
@@ -1,41 +0,0 @@ -#ifndef _STDIO_IMPL_H -#define _STDIO_IMPL_H - -#include <stdio.h> -#include "libc.h" - -// Slimmed version of stdio_impl.h that only provides the definition of -// _IO_FILE, a.k.a. FILE. - -struct _IO_FILE { - unsigned flags; - unsigned char *rpos, *rend; - int (*close)(FILE *); - unsigned char *wend, *wpos; - unsigned char *mustbezero_1; - unsigned char *wbase; - size_t (*read)(FILE *, unsigned char *, size_t); - size_t (*write)(FILE *, const unsigned char *, size_t); - off_t (*seek)(FILE *, off_t, int); - unsigned char *buf; - size_t buf_size; - FILE *prev, *next; - int fd; - int pipe_pid; - long lockcount; - short dummy3; - signed char mode; - signed char lbf; - volatile int lock; - volatile int waiters; - void *cookie; - off_t off; - char *getln_buf; - void *mustbezero_2; - unsigned char *shend; - off_t shlim, shcnt; - FILE *prev_locked, *next_locked; - struct __locale_struct *locale; -}; - -#endif
diff --git a/src/third_party/musl/src/stdio/__toread.c b/src/third_party/musl/src/stdio/__toread.c index 35f67b8..20fef0a 100644 --- a/src/third_party/musl/src/stdio/__toread.c +++ b/src/third_party/musl/src/stdio/__toread.c
@@ -13,9 +13,12 @@ return (f->flags & F_EOF) ? EOF : 0; } +// This function is unused, and leaks __stdio_exit_needed. +#ifndef STARBOARD void __stdio_exit_needed(void); void __toread_needs_stdio_exit() { __stdio_exit_needed(); } +#endif // STARBOARD
diff --git a/src/third_party/musl/src/stdio/fwrite.c b/src/third_party/musl/src/stdio/fwrite.c index 7a567b2..8a5d9c5 100644 --- a/src/third_party/musl/src/stdio/fwrite.c +++ b/src/third_party/musl/src/stdio/fwrite.c
@@ -1,6 +1,11 @@ #include "stdio_impl.h" #include <string.h> +#ifdef STARBOARD +#include "starboard/common/log.h" +#endif // STARBOARD + +#ifndef STARBOARD size_t __fwritex(const unsigned char *restrict s, size_t l, FILE *restrict f) { size_t i=0; @@ -24,15 +29,21 @@ f->wpos += l; return l+i; } +#endif size_t fwrite(const void *restrict src, size_t size, size_t nmemb, FILE *restrict f) { +#ifdef STARBOARD + SB_NOTREACHED(); + return 0; +#else // !STARBOARD size_t k, l = size*nmemb; if (!size) nmemb = 0; FLOCK(f); k = __fwritex(src, l, f); FUNLOCK(f); return k==l ? nmemb : k/size; +#endif // STARBOARD } weak_alias(fwrite, fwrite_unlocked);
diff --git a/src/third_party/openssl/openssl/Makefile b/src/third_party/openssl/openssl/Makefile deleted file mode 100644 index d5db11b..0000000 --- a/src/third_party/openssl/openssl/Makefile +++ /dev/null
@@ -1,685 +0,0 @@ -### Generated automatically from Makefile.org by Configure. - -## -## Makefile for OpenSSL -## - -VERSION=1.0.1c -MAJOR=1 -MINOR=0.1 -SHLIB_VERSION_NUMBER=1.0.0 -SHLIB_VERSION_HISTORY= -SHLIB_MAJOR=1 -SHLIB_MINOR=0.0 -SHLIB_EXT= -PLATFORM=dist -OPTIONS= no-ec_nistp_64_gcc_128 no-gmp no-jpake no-krb5 no-md2 no-rc5 no-rfc3779 no-sctp no-shared no-store no-zlib no-zlib-dynamic static-engine -CONFIGURE_ARGS=dist -SHLIB_TARGET= - -# HERE indicates where this Makefile lives. This can be used to indicate -# where sub-Makefiles are expected to be. Currently has very limited usage, -# and should probably not be bothered with at all. -HERE=. - -# INSTALL_PREFIX is for package builders so that they can configure -# for, say, /usr/ and yet have everything installed to /tmp/somedir/usr/. -# Normally it is left empty. -INSTALL_PREFIX= -INSTALLTOP=/usr/local/ssl - -# Do not edit this manually. Use Configure --openssldir=DIR do change this! -OPENSSLDIR=/usr/local/ssl - -# NO_IDEA - Define to build without the IDEA algorithm -# NO_RC4 - Define to build without the RC4 algorithm -# NO_RC2 - Define to build without the RC2 algorithm -# THREADS - Define when building with threads, you will probably also need any -# system defines as well, i.e. _REENTERANT for Solaris 2.[34] -# TERMIO - Define the termio terminal subsystem, needed if sgtty is missing. -# TERMIOS - Define the termios terminal subsystem, Silicon Graphics. -# LONGCRYPT - Define to use HPUX 10.x's long password modification to crypt(3). -# DEVRANDOM - Give this the value of the 'random device' if your OS supports -# one. 32 bytes will be read from this when the random -# number generator is initalised. -# SSL_FORBID_ENULL - define if you want the server to be not able to use the -# NULL encryption ciphers. -# -# LOCK_DEBUG - turns on lots of lock debug output :-) -# REF_CHECK - turn on some xyz_free() assertions. -# REF_PRINT - prints some stuff on structure free. -# CRYPTO_MDEBUG - turns on my 'memory leak' detecting stuff -# MFUNC - Make all Malloc/Free/Realloc calls call -# CRYPTO_malloc/CRYPTO_free/CRYPTO_realloc which can be setup to -# call application defined callbacks via CRYPTO_set_mem_functions() -# MD5_ASM needs to be defined to use the x86 assembler for MD5 -# SHA1_ASM needs to be defined to use the x86 assembler for SHA1 -# RMD160_ASM needs to be defined to use the x86 assembler for RIPEMD160 -# Do not define B_ENDIAN or L_ENDIAN if 'unsigned long' == 8. It must -# equal 4. -# PKCS1_CHECK - pkcs1 tests. - -CC= cc -CFLAG= -O -DEPFLAG= -DOPENSSL_NO_EC_NISTP_64_GCC_128 -DOPENSSL_NO_GMP -DOPENSSL_NO_JPAKE -DOPENSSL_NO_MD2 -DOPENSSL_NO_RC5 -DOPENSSL_NO_RFC3779 -DOPENSSL_NO_SCTP -DOPENSSL_NO_STORE -PEX_LIBS= -EX_LIBS= -EXE_EXT= -ARFLAGS= -AR= ar $(ARFLAGS) r -RANLIB= /usr/bin/ranlib -NM= nm -PERL= /usr/bin/perl -TAR= tar -TARFLAGS= --no-recursion -MAKEDEPPROG=makedepend -LIBDIR=lib - -# We let the C compiler driver to take care of .s files. This is done in -# order to be excused from maintaining a separate set of architecture -# dependent assembler flags. E.g. if you throw -mcpu=ultrasparc at SPARC -# gcc, then the driver will automatically translate it to -xarch=v8plus -# and pass it down to assembler. -AS=$(CC) -c -ASFLAG=$(CFLAG) - -# For x86 assembler: Set PROCESSOR to 386 if you want to support -# the 80386. -PROCESSOR= - -# CPUID module collects small commonly used assembler snippets -CPUID_OBJ= mem_clr.o -BN_ASM= bn_asm.o -DES_ENC= des_enc.o fcrypt_b.o -AES_ENC= aes_core.o aes_cbc.o -BF_ENC= bf_enc.o -CAST_ENC= c_enc.o -RC4_ENC= rc4_enc.o rc4_skey.o -RC5_ENC= rc5_enc.o -MD5_ASM_OBJ= -SHA1_ASM_OBJ= -RMD160_ASM_OBJ= -WP_ASM_OBJ= wp_block.o -CMLL_ENC= camellia.o cmll_misc.o cmll_cbc.o -MODES_ASM_OBJ= -ENGINES_ASM_OBJ= -PERLASM_SCHEME= - -# KRB5 stuff -KRB5_INCLUDES= -LIBKRB5= - -# Zlib stuff -ZLIB_INCLUDE= -LIBZLIB= - -# TOP level FIPS install directory. -FIPSDIR=/usr/local/ssl/fips-2.0 - -# This is the location of fipscanister.o and friends. -# The FIPS module build will place it $(INSTALLTOP)/lib -# but since $(INSTALLTOP) can only take the default value -# when the module is built it will be in /usr/local/ssl/lib -# $(INSTALLTOP) for this build may be different so hard -# code the path. - -FIPSLIBDIR= - -# The location of the library which contains fipscanister.o -# normally it will be libcrypto unless fipsdso is set in which -# case it will be libfips. If not compiling in FIPS mode at all -# this is empty making it a useful test for a FIPS compile. - -FIPSCANLIB= - -# Shared library base address. Currently only used on Windows. -# - -BASEADDR=0xFB00000 - -DIRS= crypto ssl engines apps test tools -ENGDIRS= ccgost -SHLIBDIRS= crypto ssl - -# dirs in crypto to build -SDIRS= \ - objects \ - md4 md5 sha mdc2 hmac ripemd whrlpool \ - des aes rc2 rc4 idea bf cast camellia seed modes \ - bn ec rsa dsa ecdsa dh ecdh dso engine \ - buffer bio stack lhash rand err \ - evp asn1 pem x509 x509v3 conf txt_db pkcs7 pkcs12 comp ocsp ui krb5 \ - cms pqueue ts srp cmac -# keep in mind that the above list is adjusted by ./Configure -# according to no-xxx arguments... - -# tests to perform. "alltests" is a special word indicating that all tests -# should be performed. -TESTS = alltests - -MAKEFILE= Makefile - -MANDIR=$(OPENSSLDIR)/man -MAN1=1 -MAN3=3 -MANSUFFIX= -HTMLSUFFIX=html -HTMLDIR=$(OPENSSLDIR)/html -SHELL=/bin/sh - -TOP= . -ONEDIRS=out tmp -EDIRS= times doc bugs util include certs ms shlib mt demos perl sf dep VMS -WDIRS= windows -LIBS= libcrypto.a libssl.a -SHARED_CRYPTO=libcrypto$(SHLIB_EXT) -SHARED_SSL=libssl$(SHLIB_EXT) -SHARED_LIBS= -SHARED_LIBS_LINK_EXTS= -SHARED_LDFLAGS= - -GENERAL= Makefile -BASENAME= openssl -NAME= $(BASENAME)-$(VERSION) -TARFILE= $(NAME).tar -WTARFILE= $(NAME)-win.tar -EXHEADER= e_os2.h -HEADER= e_os.h - -all: Makefile build_all openssl.pc libssl.pc libcrypto.pc - -# as we stick to -e, CLEARENV ensures that local variables in lower -# Makefiles remain local and variable. $${VAR+VAR} is tribute to Korn -# shell, which [annoyingly enough] terminates unset with error if VAR -# is not present:-( TOP= && unset TOP is tribute to HP-UX /bin/sh, -# which terminates unset with error if no variable was present:-( -CLEARENV= TOP= && unset TOP $${LIB+LIB} $${LIBS+LIBS} \ - $${INCLUDE+INCLUDE} $${INCLUDES+INCLUDES} \ - $${DIR+DIR} $${DIRS+DIRS} $${SRC+SRC} \ - $${LIBSRC+LIBSRC} $${LIBOBJ+LIBOBJ} $${ALL+ALL} \ - $${EXHEADER+EXHEADER} $${HEADER+HEADER} \ - $${GENERAL+GENERAL} $${CFLAGS+CFLAGS} \ - $${ASFLAGS+ASFLAGS} $${AFLAGS+AFLAGS} \ - $${LDCMD+LDCMD} $${LDFLAGS+LDFLAGS} $${SCRIPTS+SCRIPTS} \ - $${SHAREDCMD+SHAREDCMD} $${SHAREDFLAGS+SHAREDFLAGS} \ - $${SHARED_LIB+SHARED_LIB} $${LIBEXTRAS+LIBEXTRAS} - -BUILDENV= PLATFORM='$(PLATFORM)' PROCESSOR='$(PROCESSOR)' \ - CC='$(CC)' CFLAG='$(CFLAG)' \ - AS='$(CC)' ASFLAG='$(CFLAG) -c' \ - AR='$(AR)' NM='$(NM)' RANLIB='$(RANLIB)' \ - CROSS_COMPILE='$(CROSS_COMPILE)' \ - PERL='$(PERL)' ENGDIRS='$(ENGDIRS)' \ - SDIRS='$(SDIRS)' LIBRPATH='$(INSTALLTOP)/$(LIBDIR)' \ - INSTALL_PREFIX='$(INSTALL_PREFIX)' \ - INSTALLTOP='$(INSTALLTOP)' OPENSSLDIR='$(OPENSSLDIR)' \ - LIBDIR='$(LIBDIR)' \ - MAKEDEPEND='$$$${TOP}/util/domd $$$${TOP} -MD $(MAKEDEPPROG)' \ - DEPFLAG='-DOPENSSL_NO_DEPRECATED $(DEPFLAG)' \ - MAKEDEPPROG='$(MAKEDEPPROG)' \ - SHARED_LDFLAGS='$(SHARED_LDFLAGS)' \ - KRB5_INCLUDES='$(KRB5_INCLUDES)' LIBKRB5='$(LIBKRB5)' \ - ZLIB_INCLUDE='$(ZLIB_INCLUDE)' LIBZLIB='$(LIBZLIB)' \ - EXE_EXT='$(EXE_EXT)' SHARED_LIBS='$(SHARED_LIBS)' \ - SHLIB_EXT='$(SHLIB_EXT)' SHLIB_TARGET='$(SHLIB_TARGET)' \ - PEX_LIBS='$(PEX_LIBS)' EX_LIBS='$(EX_LIBS)' \ - CPUID_OBJ='$(CPUID_OBJ)' \ - BN_ASM='$(BN_ASM)' DES_ENC='$(DES_ENC)' \ - AES_ENC='$(AES_ENC)' CMLL_ENC='$(CMLL_ENC)' \ - BF_ENC='$(BF_ENC)' CAST_ENC='$(CAST_ENC)' \ - RC4_ENC='$(RC4_ENC)' RC5_ENC='$(RC5_ENC)' \ - SHA1_ASM_OBJ='$(SHA1_ASM_OBJ)' \ - MD5_ASM_OBJ='$(MD5_ASM_OBJ)' \ - RMD160_ASM_OBJ='$(RMD160_ASM_OBJ)' \ - WP_ASM_OBJ='$(WP_ASM_OBJ)' \ - MODES_ASM_OBJ='$(MODES_ASM_OBJ)' \ - ENGINES_ASM_OBJ='$(ENGINES_ASM_OBJ)' \ - PERLASM_SCHEME='$(PERLASM_SCHEME)' \ - FIPSLIBDIR='${FIPSLIBDIR}' \ - FIPSDIR='${FIPSDIR}' \ - FIPSCANLIB="$${FIPSCANLIB:-$(FIPSCANLIB)}" \ - THIS=$${THIS:-$@} MAKEFILE=Makefile MAKEOVERRIDES= -# MAKEOVERRIDES= effectively "equalizes" GNU-ish and SysV-ish make flavors, -# which in turn eliminates ambiguities in variable treatment with -e. - -# BUILD_CMD is a generic macro to build a given target in a given -# subdirectory. The target must be given through the shell variable -# `target' and the subdirectory to build in must be given through `dir'. -# This macro shouldn't be used directly, use RECURSIVE_BUILD_CMD or -# BUILD_ONE_CMD instead. -# -# BUILD_ONE_CMD is a macro to build a given target in a given -# subdirectory if that subdirectory is part of $(DIRS). It requires -# exactly the same shell variables as BUILD_CMD. -# -# RECURSIVE_BUILD_CMD is a macro to build a given target in all -# subdirectories defined in $(DIRS). It requires that the target -# is given through the shell variable `target'. -BUILD_CMD= if [ -d "$$dir" ]; then \ - ( cd $$dir && echo "making $$target in $$dir..." && \ - $(CLEARENV) && $(MAKE) -e $(BUILDENV) TOP=.. DIR=$$dir $$target \ - ) || exit 1; \ - fi -RECURSIVE_BUILD_CMD=for dir in $(DIRS); do $(BUILD_CMD); done -BUILD_ONE_CMD=\ - if expr " $(DIRS) " : ".* $$dir " >/dev/null 2>&1; then \ - $(BUILD_CMD); \ - fi - -reflect: - @[ -n "$(THIS)" ] && $(CLEARENV) && $(MAKE) $(THIS) -e $(BUILDENV) - -sub_all: build_all -build_all: build_libs build_apps build_tests build_tools - -build_libs: build_crypto build_ssl build_engines - -build_crypto: - @dir=crypto; target=all; $(BUILD_ONE_CMD) -build_ssl: - @dir=ssl; target=all; $(BUILD_ONE_CMD) -build_engines: - @dir=engines; target=all; $(BUILD_ONE_CMD) -build_apps: - @dir=apps; target=all; $(BUILD_ONE_CMD) -build_tests: - @dir=test; target=all; $(BUILD_ONE_CMD) -build_tools: - @dir=tools; target=all; $(BUILD_ONE_CMD) - -all_testapps: build_libs build_testapps -build_testapps: - @dir=crypto; target=testapps; $(BUILD_ONE_CMD) - -fips_premain_dso$(EXE_EXT): libcrypto.a - [ -z "$(FIPSCANLIB)" ] || $(CC) $(CFLAG) -Iinclude \ - -DFINGERPRINT_PREMAIN_DSO_LOAD -o $@ \ - $(FIPSLIBDIR)fips_premain.c $(FIPSLIBDIR)fipscanister.o \ - libcrypto.a $(EX_LIBS) - -libcrypto$(SHLIB_EXT): libcrypto.a fips_premain_dso$(EXE_EXT) - @if [ "$(SHLIB_TARGET)" != "" ]; then \ - if [ "$(FIPSCANLIB)" = "libcrypto" ]; then \ - FIPSLD_LIBCRYPTO=libcrypto.a ; \ - FIPSLD_CC="$(CC)"; CC=$(FIPSDIR)/bin/fipsld; \ - export CC FIPSLD_CC FIPSLD_LIBCRYPTO; \ - fi; \ - $(MAKE) -e SHLIBDIRS=crypto build-shared; \ - else \ - echo "There's no support for shared libraries on this platform" >&2; \ - exit 1; \ - fi - -libssl$(SHLIB_EXT): libcrypto$(SHLIB_EXT) libssl.a - @if [ "$(SHLIB_TARGET)" != "" ]; then \ - $(MAKE) SHLIBDIRS=ssl SHLIBDEPS='-lcrypto' build-shared; \ - else \ - echo "There's no support for shared libraries on this platform" >&2; \ - exit 1; \ - fi - -clean-shared: - @set -e; for i in $(SHLIBDIRS); do \ - if [ -n "$(SHARED_LIBS_LINK_EXTS)" ]; then \ - tmp="$(SHARED_LIBS_LINK_EXTS)"; \ - for j in $${tmp:-x}; do \ - ( set -x; rm -f lib$$i$$j ); \ - done; \ - fi; \ - ( set -x; rm -f lib$$i$(SHLIB_EXT) ); \ - if [ "$(PLATFORM)" = "Cygwin" ]; then \ - ( set -x; rm -f cyg$$i$(SHLIB_EXT) lib$$i$(SHLIB_EXT).a ); \ - fi; \ - done - -link-shared: - @ set -e; for i in $(SHLIBDIRS); do \ - $(MAKE) -f $(HERE)/Makefile.shared -e $(BUILDENV) \ - LIBNAME=$$i LIBVERSION=$(SHLIB_MAJOR).$(SHLIB_MINOR) \ - LIBCOMPATVERSIONS=";$(SHLIB_VERSION_HISTORY)" \ - symlink.$(SHLIB_TARGET); \ - libs="$$libs -l$$i"; \ - done - -build-shared: do_$(SHLIB_TARGET) link-shared - -do_$(SHLIB_TARGET): - @ set -e; libs='-L. $(SHLIBDEPS)'; for i in $(SHLIBDIRS); do \ - if [ "$$i" = "ssl" -a -n "$(LIBKRB5)" ]; then \ - libs="$(LIBKRB5) $$libs"; \ - fi; \ - $(CLEARENV) && $(MAKE) -f Makefile.shared -e $(BUILDENV) \ - LIBNAME=$$i LIBVERSION=$(SHLIB_MAJOR).$(SHLIB_MINOR) \ - LIBCOMPATVERSIONS=";$(SHLIB_VERSION_HISTORY)" \ - LIBDEPS="$$libs $(EX_LIBS)" \ - link_a.$(SHLIB_TARGET); \ - libs="-l$$i $$libs"; \ - done - -libcrypto.pc: Makefile - @ ( echo 'prefix=$(INSTALLTOP)'; \ - echo 'exec_prefix=$${prefix}'; \ - echo 'libdir=$${exec_prefix}/$(LIBDIR)'; \ - echo 'includedir=$${prefix}/include'; \ - echo ''; \ - echo 'Name: OpenSSL-libcrypto'; \ - echo 'Description: OpenSSL cryptography library'; \ - echo 'Version: '$(VERSION); \ - echo 'Requires: '; \ - echo 'Libs: -L$${libdir} -lcrypto'; \ - echo 'Libs.private: $(EX_LIBS)'; \ - echo 'Cflags: -I$${includedir} $(KRB5_INCLUDES)' ) > libcrypto.pc - -libssl.pc: Makefile - @ ( echo 'prefix=$(INSTALLTOP)'; \ - echo 'exec_prefix=$${prefix}'; \ - echo 'libdir=$${exec_prefix}/$(LIBDIR)'; \ - echo 'includedir=$${prefix}/include'; \ - echo ''; \ - echo 'Name: OpenSSL'; \ - echo 'Description: Secure Sockets Layer and cryptography libraries'; \ - echo 'Version: '$(VERSION); \ - echo 'Requires: '; \ - echo 'Libs: -L$${libdir} -lssl -lcrypto'; \ - echo 'Libs.private: $(EX_LIBS)'; \ - echo 'Cflags: -I$${includedir} $(KRB5_INCLUDES)' ) > libssl.pc - -openssl.pc: Makefile - @ ( echo 'prefix=$(INSTALLTOP)'; \ - echo 'exec_prefix=$${prefix}'; \ - echo 'libdir=$${exec_prefix}/$(LIBDIR)'; \ - echo 'includedir=$${prefix}/include'; \ - echo ''; \ - echo 'Name: OpenSSL'; \ - echo 'Description: Secure Sockets Layer and cryptography libraries and tools'; \ - echo 'Version: '$(VERSION); \ - echo 'Requires: '; \ - echo 'Libs: -L$${libdir} -lssl -lcrypto'; \ - echo 'Libs.private: $(EX_LIBS)'; \ - echo 'Cflags: -I$${includedir} $(KRB5_INCLUDES)' ) > openssl.pc - -Makefile: Makefile.org Configure config - @echo "Makefile is older than Makefile.org, Configure or config." - @echo "Reconfigure the source tree (via './config' or 'perl Configure'), please." - @false - -libclean: - rm -f *.map *.so *.so.* *.dylib *.dll engines/*.so engines/*.dll engines/*.dylib *.a engines/*.a */lib */*/lib - -clean: libclean - rm -f shlib/*.o *.o core a.out fluff rehash.time testlog make.log cctest cctest.c - @set -e; target=clean; $(RECURSIVE_BUILD_CMD) - rm -f $(LIBS) - rm -f openssl.pc libssl.pc libcrypto.pc - rm -f speed.* .pure - rm -f $(TARFILE) - @set -e; for i in $(ONEDIRS) ;\ - do \ - rm -fr $$i/*; \ - done - -makefile.one: files - $(PERL) util/mk1mf.pl >makefile.one; \ - sh util/do_ms.sh - -files: - $(PERL) $(TOP)/util/files.pl Makefile > $(TOP)/MINFO - @set -e; target=files; $(RECURSIVE_BUILD_CMD) - -links: - @$(PERL) $(TOP)/util/mkdir-p.pl include/openssl - @$(PERL) $(TOP)/util/mklink.pl include/openssl $(EXHEADER) - @set -e; target=links; $(RECURSIVE_BUILD_CMD) - -gentests: - @(cd test && echo "generating dummy tests (if needed)..." && \ - $(CLEARENV) && $(MAKE) -e $(BUILDENV) TESTS='$(TESTS)' OPENSSL_DEBUG_MEMORY=on generate ); - -dclean: - rm -rf *.bak include/openssl certs/.0 - @set -e; target=dclean; $(RECURSIVE_BUILD_CMD) - -rehash: rehash.time -rehash.time: certs apps - @if [ -z "$(CROSS_COMPILE)" ]; then \ - (OPENSSL="`pwd`/util/opensslwrap.sh"; \ - [ -x "apps/openssl.exe" ] && OPENSSL="apps/openssl.exe" || :; \ - OPENSSL_DEBUG_MEMORY=on; \ - export OPENSSL OPENSSL_DEBUG_MEMORY; \ - $(PERL) tools/c_rehash certs) && \ - touch rehash.time; \ - else :; fi - -test: tests - -tests: rehash - @(cd test && echo "testing..." && \ - $(CLEARENV) && $(MAKE) -e $(BUILDENV) TOP=.. TESTS='$(TESTS)' OPENSSL_DEBUG_MEMORY=on OPENSSL_CONF=../apps/openssl.cnf tests ); - OPENSSL_CONF=apps/openssl.cnf util/opensslwrap.sh version -a - -report: - @$(PERL) util/selftest.pl - -depend: - @set -e; target=depend; $(RECURSIVE_BUILD_CMD) - -lint: - @set -e; target=lint; $(RECURSIVE_BUILD_CMD) - -tags: - rm -f TAGS - find . -name '[^.]*.[ch]' | xargs etags -a - -errors: - $(PERL) util/ck_errf.pl -strict */*.c */*/*.c - $(PERL) util/mkerr.pl -recurse -write - (cd engines; $(MAKE) PERL=$(PERL) errors) - -stacks: - $(PERL) util/mkstack.pl -write - -util/libeay.num:: - $(PERL) util/mkdef.pl crypto update - -util/ssleay.num:: - $(PERL) util/mkdef.pl ssl update - -crypto/objects/obj_dat.h: crypto/objects/obj_dat.pl crypto/objects/obj_mac.h - $(PERL) crypto/objects/obj_dat.pl crypto/objects/obj_mac.h crypto/objects/obj_dat.h -crypto/objects/obj_mac.h: crypto/objects/objects.pl crypto/objects/objects.txt crypto/objects/obj_mac.num - $(PERL) crypto/objects/objects.pl crypto/objects/objects.txt crypto/objects/obj_mac.num crypto/objects/obj_mac.h -crypto/objects/obj_xref.h: crypto/objects/objxref.pl crypto/objects/obj_xref.txt crypto/objects/obj_mac.num - $(PERL) crypto/objects/objxref.pl crypto/objects/obj_mac.num crypto/objects/obj_xref.txt >crypto/objects/obj_xref.h - -apps/openssl-vms.cnf: apps/openssl.cnf - $(PERL) VMS/VMSify-conf.pl < apps/openssl.cnf > apps/openssl-vms.cnf - -crypto/bn/bn_prime.h: crypto/bn/bn_prime.pl - $(PERL) crypto/bn/bn_prime.pl >crypto/bn/bn_prime.h - - -TABLE: Configure - (echo 'Output of `Configure TABLE'"':"; \ - $(PERL) Configure TABLE) > TABLE - -update: errors stacks util/libeay.num util/ssleay.num crypto/objects/obj_dat.h crypto/objects/obj_xref.h apps/openssl-vms.cnf crypto/bn/bn_prime.h TABLE depend - -# Build distribution tar-file. As the list of files returned by "find" is -# pretty long, on several platforms a "too many arguments" error or similar -# would occur. Therefore the list of files is temporarily stored into a file -# and read directly, requiring GNU-Tar. Call "make TAR=gtar dist" if the normal -# tar does not support the --files-from option. -tar: - find . -type d -print | xargs chmod 755 - find . -type f -print | xargs chmod a+r - find . -type f -perm -0100 -print | xargs chmod a+x - find * \! -path CVS/\* \! -path \*/CVS/\* \! -name CVS \! -name .cvsignore \! -name STATUS \! -name TABLE | sort > ../$(TARFILE).list; \ - $(TAR) $(TARFLAGS) --files-from ../$(TARFILE).list -cvf - | \ - tardy --user_number=0 --user_name=openssl \ - --group_number=0 --group_name=openssl \ - --prefix=openssl-$(VERSION) - |\ - gzip --best >../$(TARFILE).gz; \ - rm -f ../$(TARFILE).list; \ - ls -l ../$(TARFILE).gz - -tar-snap: - @$(TAR) $(TARFLAGS) -cvf - \ - `find * \! -path CVS/\* \! -path \*/CVS/\* \! -name CVS \! -name .cvsignore \! -name STATUS \! -name TABLE \! -name '*.o' \! -name '*.a' \! -name '*.so' \! -name '*.so.*' \! -name 'openssl' \! -name '*test' \! -name '.#*' \! -name '*~' | sort` |\ - tardy --user_number=0 --user_name=openssl \ - --group_number=0 --group_name=openssl \ - --prefix=openssl-$(VERSION) - > ../$(TARFILE);\ - ls -l ../$(TARFILE) - -dist: - $(PERL) Configure dist - @$(MAKE) dist_pem_h - @$(MAKE) SDIRS='$(SDIRS)' clean - @$(MAKE) TAR='$(TAR)' TARFLAGS='$(TARFLAGS)' tar - -dist_pem_h: - (cd crypto/pem; $(MAKE) -e $(BUILDENV) pem.h; $(MAKE) clean) - -install: all install_docs install_sw - -install_sw: - @$(PERL) $(TOP)/util/mkdir-p.pl $(INSTALL_PREFIX)$(INSTALLTOP)/bin \ - $(INSTALL_PREFIX)$(INSTALLTOP)/$(LIBDIR) \ - $(INSTALL_PREFIX)$(INSTALLTOP)/$(LIBDIR)/engines \ - $(INSTALL_PREFIX)$(INSTALLTOP)/$(LIBDIR)/pkgconfig \ - $(INSTALL_PREFIX)$(INSTALLTOP)/include/openssl \ - $(INSTALL_PREFIX)$(OPENSSLDIR)/misc \ - $(INSTALL_PREFIX)$(OPENSSLDIR)/certs \ - $(INSTALL_PREFIX)$(OPENSSLDIR)/private - @set -e; headerlist="$(EXHEADER)"; for i in $$headerlist;\ - do \ - (cp $$i $(INSTALL_PREFIX)$(INSTALLTOP)/include/openssl/$$i; \ - chmod 644 $(INSTALL_PREFIX)$(INSTALLTOP)/include/openssl/$$i ); \ - done; - @set -e; target=install; $(RECURSIVE_BUILD_CMD) - @set -e; liblist="$(LIBS)"; for i in $$liblist ;\ - do \ - if [ -f "$$i" ]; then \ - ( echo installing $$i; \ - cp $$i $(INSTALL_PREFIX)$(INSTALLTOP)/$(LIBDIR)/$$i.new; \ - $(RANLIB) $(INSTALL_PREFIX)$(INSTALLTOP)/$(LIBDIR)/$$i.new; \ - chmod 644 $(INSTALL_PREFIX)$(INSTALLTOP)/$(LIBDIR)/$$i.new; \ - mv -f $(INSTALL_PREFIX)$(INSTALLTOP)/$(LIBDIR)/$$i.new $(INSTALL_PREFIX)$(INSTALLTOP)/$(LIBDIR)/$$i ); \ - fi; \ - done; - @set -e; if [ -n "$(SHARED_LIBS)" ]; then \ - tmp="$(SHARED_LIBS)"; \ - for i in $${tmp:-x}; \ - do \ - if [ -f "$$i" -o -f "$$i.a" ]; then \ - ( echo installing $$i; \ - if [ "$(PLATFORM)" != "Cygwin" ]; then \ - cp $$i $(INSTALL_PREFIX)$(INSTALLTOP)/$(LIBDIR)/$$i.new; \ - chmod 555 $(INSTALL_PREFIX)$(INSTALLTOP)/$(LIBDIR)/$$i.new; \ - mv -f $(INSTALL_PREFIX)$(INSTALLTOP)/$(LIBDIR)/$$i.new $(INSTALL_PREFIX)$(INSTALLTOP)/$(LIBDIR)/$$i; \ - else \ - c=`echo $$i | sed 's/^lib\(.*\)\.dll\.a/cyg\1-$(SHLIB_VERSION_NUMBER).dll/'`; \ - cp $$c $(INSTALL_PREFIX)$(INSTALLTOP)/bin/$$c.new; \ - chmod 755 $(INSTALL_PREFIX)$(INSTALLTOP)/bin/$$c.new; \ - mv -f $(INSTALL_PREFIX)$(INSTALLTOP)/bin/$$c.new $(INSTALL_PREFIX)$(INSTALLTOP)/bin/$$c; \ - cp $$i $(INSTALL_PREFIX)$(INSTALLTOP)/$(LIBDIR)/$$i.new; \ - chmod 644 $(INSTALL_PREFIX)$(INSTALLTOP)/$(LIBDIR)/$$i.new; \ - mv -f $(INSTALL_PREFIX)$(INSTALLTOP)/$(LIBDIR)/$$i.new $(INSTALL_PREFIX)$(INSTALLTOP)/$(LIBDIR)/$$i; \ - fi ); \ - if expr $(PLATFORM) : 'mingw' > /dev/null; then \ - ( case $$i in \ - *crypto*) i=libeay32.dll;; \ - *ssl*) i=ssleay32.dll;; \ - esac; \ - echo installing $$i; \ - cp $$i $(INSTALL_PREFIX)$(INSTALLTOP)/bin/$$i.new; \ - chmod 755 $(INSTALL_PREFIX)$(INSTALLTOP)/bin/$$i.new; \ - mv -f $(INSTALL_PREFIX)$(INSTALLTOP)/bin/$$i.new $(INSTALL_PREFIX)$(INSTALLTOP)/bin/$$i ); \ - fi; \ - fi; \ - done; \ - ( here="`pwd`"; \ - cd $(INSTALL_PREFIX)$(INSTALLTOP)/$(LIBDIR); \ - $(MAKE) -f $$here/Makefile HERE="$$here" link-shared ); \ - if [ "$(INSTALLTOP)" != "/usr" ]; then \ - echo 'OpenSSL shared libraries have been installed in:'; \ - echo ' $(INSTALLTOP)'; \ - echo ''; \ - sed -e '1,/^$$/d' doc/openssl-shared.txt; \ - fi; \ - fi - cp libcrypto.pc $(INSTALL_PREFIX)$(INSTALLTOP)/$(LIBDIR)/pkgconfig - chmod 644 $(INSTALL_PREFIX)$(INSTALLTOP)/$(LIBDIR)/pkgconfig/libcrypto.pc - cp libssl.pc $(INSTALL_PREFIX)$(INSTALLTOP)/$(LIBDIR)/pkgconfig - chmod 644 $(INSTALL_PREFIX)$(INSTALLTOP)/$(LIBDIR)/pkgconfig/libssl.pc - cp openssl.pc $(INSTALL_PREFIX)$(INSTALLTOP)/$(LIBDIR)/pkgconfig - chmod 644 $(INSTALL_PREFIX)$(INSTALLTOP)/$(LIBDIR)/pkgconfig/openssl.pc - -install_html_docs: - here="`pwd`"; \ - for subdir in apps crypto ssl; do \ - mkdir -p $(INSTALL_PREFIX)$(HTMLDIR)/$$subdir; \ - for i in doc/$$subdir/*.pod; do \ - fn=`basename $$i .pod`; \ - echo "installing html/$$fn.$(HTMLSUFFIX)"; \ - cat $$i \ - | sed -r 's/L<([^)]*)(\([0-9]\))?\|([^)]*)(\([0-9]\))?>/L<\1|\3>/g' \ - | pod2html --podroot=doc --htmlroot=.. --podpath=apps:crypto:ssl \ - | sed -r 's/<!DOCTYPE.*//g' \ - > $(INSTALL_PREFIX)$(HTMLDIR)/$$subdir/$$fn.$(HTMLSUFFIX); \ - $(PERL) util/extract-names.pl < $$i | \ - grep -v $$filecase "^$$fn\$$" | \ - (cd $(INSTALL_PREFIX)$(HTMLDIR)/$$subdir; \ - while read n; do \ - PLATFORM=$(PLATFORM) $$here/util/point.sh $$fn.$(HTMLSUFFIX) "$$n".$(HTMLSUFFIX); \ - done); \ - done; \ - done - -install_docs: - @$(PERL) $(TOP)/util/mkdir-p.pl \ - $(INSTALL_PREFIX)$(MANDIR)/man1 \ - $(INSTALL_PREFIX)$(MANDIR)/man3 \ - $(INSTALL_PREFIX)$(MANDIR)/man5 \ - $(INSTALL_PREFIX)$(MANDIR)/man7 - @pod2man="`cd ./util; ./pod2mantest $(PERL)`"; \ - here="`pwd`"; \ - filecase=; \ - if [ "$(PLATFORM)" = "DJGPP" -o "$(PLATFORM)" = "Cygwin" -o "$(PLATFORM)" = "mingw" ]; then \ - filecase=-i; \ - fi; \ - set -e; for i in doc/apps/*.pod; do \ - fn=`basename $$i .pod`; \ - sec=`$(PERL) util/extract-section.pl 1 < $$i`; \ - echo "installing man$$sec/$$fn.$${sec}$(MANSUFFIX)"; \ - (cd `$(PERL) util/dirname.pl $$i`; \ - sh -c "$$pod2man \ - --section=$$sec --center=OpenSSL \ - --release=$(VERSION) `basename $$i`") \ - > $(INSTALL_PREFIX)$(MANDIR)/man$$sec/$$fn.$${sec}$(MANSUFFIX); \ - $(PERL) util/extract-names.pl < $$i | \ - (grep -v $$filecase "^$$fn\$$"; true) | \ - (grep -v "[ ]"; true) | \ - (cd $(INSTALL_PREFIX)$(MANDIR)/man$$sec/; \ - while read n; do \ - PLATFORM=$(PLATFORM) $$here/util/point.sh $$fn.$${sec}$(MANSUFFIX) "$$n".$${sec}$(MANSUFFIX); \ - done); \ - done; \ - set -e; for i in doc/crypto/*.pod doc/ssl/*.pod; do \ - fn=`basename $$i .pod`; \ - sec=`$(PERL) util/extract-section.pl 3 < $$i`; \ - echo "installing man$$sec/$$fn.$${sec}$(MANSUFFIX)"; \ - (cd `$(PERL) util/dirname.pl $$i`; \ - sh -c "$$pod2man \ - --section=$$sec --center=OpenSSL \ - --release=$(VERSION) `basename $$i`") \ - > $(INSTALL_PREFIX)$(MANDIR)/man$$sec/$$fn.$${sec}$(MANSUFFIX); \ - $(PERL) util/extract-names.pl < $$i | \ - (grep -v $$filecase "^$$fn\$$"; true) | \ - (grep -v "[ ]"; true) | \ - (cd $(INSTALL_PREFIX)$(MANDIR)/man$$sec/; \ - while read n; do \ - PLATFORM=$(PLATFORM) $$here/util/point.sh $$fn.$${sec}$(MANSUFFIX) "$$n".$${sec}$(MANSUFFIX); \ - done); \ - done - -# DO NOT DELETE THIS LINE -- make depend depends on it.
diff --git a/src/third_party/openssl/openssl/apps/CA.pl b/src/third_party/openssl/openssl/apps/CA.pl deleted file mode 100644 index a3965ec..0000000 --- a/src/third_party/openssl/openssl/apps/CA.pl +++ /dev/null
@@ -1,189 +0,0 @@ -#!/usr/bin/perl -# -# CA - wrapper around ca to make it easier to use ... basically ca requires -# some setup stuff to be done before you can use it and this makes -# things easier between now and when Eric is convinced to fix it :-) -# -# CA -newca ... will setup the right stuff -# CA -newreq[-nodes] ... will generate a certificate request -# CA -sign ... will sign the generated request and output -# -# At the end of that grab newreq.pem and newcert.pem (one has the key -# and the other the certificate) and cat them together and that is what -# you want/need ... I'll make even this a little cleaner later. -# -# -# 12-Jan-96 tjh Added more things ... including CA -signcert which -# converts a certificate to a request and then signs it. -# 10-Jan-96 eay Fixed a few more bugs and added the SSLEAY_CONFIG -# environment variable so this can be driven from -# a script. -# 25-Jul-96 eay Cleaned up filenames some more. -# 11-Jun-96 eay Fixed a few filename missmatches. -# 03-May-96 eay Modified to use 'ssleay cmd' instead of 'cmd'. -# 18-Apr-96 tjh Original hacking -# -# Tim Hudson -# tjh@cryptsoft.com -# - -# 27-Apr-98 snh Translation into perl, fix existing CA bug. -# -# -# Steve Henson -# shenson@bigfoot.com - -# default openssl.cnf file has setup as per the following -# demoCA ... where everything is stored - -my $openssl; -if(defined $ENV{OPENSSL}) { - $openssl = $ENV{OPENSSL}; -} else { - $openssl = "openssl"; - $ENV{OPENSSL} = $openssl; -} - -$SSLEAY_CONFIG=$ENV{"SSLEAY_CONFIG"}; -$DAYS="-days 365"; # 1 year -$CADAYS="-days 1095"; # 3 years -$REQ="$openssl req $SSLEAY_CONFIG"; -$CA="$openssl ca $SSLEAY_CONFIG"; -$VERIFY="$openssl verify"; -$X509="$openssl x509"; -$PKCS12="$openssl pkcs12"; - -$CATOP="./demoCA"; -$CAKEY="cakey.pem"; -$CAREQ="careq.pem"; -$CACERT="cacert.pem"; - -$DIRMODE = 0777; - -$RET = 0; - -foreach (@ARGV) { - if ( /^(-\?|-h|-help)$/ ) { - print STDERR "usage: CA -newcert|-newreq|-newreq-nodes|-newca|-sign|-verify\n"; - exit 0; - } elsif (/^-newcert$/) { - # create a certificate - system ("$REQ -new -x509 -keyout newkey.pem -out newcert.pem $DAYS"); - $RET=$?; - print "Certificate is in newcert.pem, private key is in newkey.pem\n" - } elsif (/^-newreq$/) { - # create a certificate request - system ("$REQ -new -keyout newkey.pem -out newreq.pem $DAYS"); - $RET=$?; - print "Request is in newreq.pem, private key is in newkey.pem\n"; - } elsif (/^-newreq-nodes$/) { - # create a certificate request - system ("$REQ -new -nodes -keyout newkey.pem -out newreq.pem $DAYS"); - $RET=$?; - print "Request is in newreq.pem, private key is in newkey.pem\n"; - } elsif (/^-newca$/) { - # if explicitly asked for or it doesn't exist then setup the - # directory structure that Eric likes to manage things - $NEW="1"; - if ( "$NEW" || ! -f "${CATOP}/serial" ) { - # create the directory hierarchy - mkdir $CATOP, $DIRMODE; - mkdir "${CATOP}/certs", $DIRMODE; - mkdir "${CATOP}/crl", $DIRMODE ; - mkdir "${CATOP}/newcerts", $DIRMODE; - mkdir "${CATOP}/private", $DIRMODE; - open OUT, ">${CATOP}/index.txt"; - close OUT; - open OUT, ">${CATOP}/crlnumber"; - print OUT "01\n"; - close OUT; - } - if ( ! -f "${CATOP}/private/$CAKEY" ) { - print "CA certificate filename (or enter to create)\n"; - $FILE = <STDIN>; - - chop $FILE; - - # ask user for existing CA certificate - if ($FILE) { - cp_pem($FILE,"${CATOP}/private/$CAKEY", "PRIVATE"); - cp_pem($FILE,"${CATOP}/$CACERT", "CERTIFICATE"); - $RET=$?; - } else { - print "Making CA certificate ...\n"; - system ("$REQ -new -keyout " . - "${CATOP}/private/$CAKEY -out ${CATOP}/$CAREQ"); - system ("$CA -create_serial " . - "-out ${CATOP}/$CACERT $CADAYS -batch " . - "-keyfile ${CATOP}/private/$CAKEY -selfsign " . - "-extensions v3_ca " . - "-infiles ${CATOP}/$CAREQ "); - $RET=$?; - } - } - } elsif (/^-pkcs12$/) { - my $cname = $ARGV[1]; - $cname = "My Certificate" unless defined $cname; - system ("$PKCS12 -in newcert.pem -inkey newkey.pem " . - "-certfile ${CATOP}/$CACERT -out newcert.p12 " . - "-export -name \"$cname\""); - $RET=$?; - print "PKCS #12 file is in newcert.p12\n"; - exit $RET; - } elsif (/^-xsign$/) { - system ("$CA -policy policy_anything -infiles newreq.pem"); - $RET=$?; - } elsif (/^(-sign|-signreq)$/) { - system ("$CA -policy policy_anything -out newcert.pem " . - "-infiles newreq.pem"); - $RET=$?; - print "Signed certificate is in newcert.pem\n"; - } elsif (/^(-signCA)$/) { - system ("$CA -policy policy_anything -out newcert.pem " . - "-extensions v3_ca -infiles newreq.pem"); - $RET=$?; - print "Signed CA certificate is in newcert.pem\n"; - } elsif (/^-signcert$/) { - system ("$X509 -x509toreq -in newreq.pem -signkey newreq.pem " . - "-out tmp.pem"); - system ("$CA -policy policy_anything -out newcert.pem " . - "-infiles tmp.pem"); - $RET = $?; - print "Signed certificate is in newcert.pem\n"; - } elsif (/^-verify$/) { - if (shift) { - foreach $j (@ARGV) { - system ("$VERIFY -CAfile $CATOP/$CACERT $j"); - $RET=$? if ($? != 0); - } - exit $RET; - } else { - system ("$VERIFY -CAfile $CATOP/$CACERT newcert.pem"); - $RET=$?; - exit 0; - } - } else { - print STDERR "Unknown arg $_\n"; - print STDERR "usage: CA -newcert|-newreq|-newreq-nodes|-newca|-sign|-verify\n"; - exit 1; - } -} - -exit $RET; - -sub cp_pem { -my ($infile, $outfile, $bound) = @_; -open IN, $infile; -open OUT, ">$outfile"; -my $flag = 0; -while (<IN>) { - $flag = 1 if (/^-----BEGIN.*$bound/) ; - print OUT $_ if ($flag); - if (/^-----END.*$bound/) { - close IN; - close OUT; - return; - } -} -} -
diff --git a/src/third_party/openssl/openssl/apps/md4.c b/src/third_party/openssl/openssl/apps/md4.c deleted file mode 120000 index 7f457b2..0000000 --- a/src/third_party/openssl/openssl/apps/md4.c +++ /dev/null
@@ -1 +0,0 @@ -../crypto/md4/md4.c \ No newline at end of file
diff --git a/src/third_party/openssl/openssl/crypto/opensslconf.h b/src/third_party/openssl/openssl/crypto/opensslconf.h deleted file mode 100644 index f17eaa9..0000000 --- a/src/third_party/openssl/openssl/crypto/opensslconf.h +++ /dev/null
@@ -1,262 +0,0 @@ -/* opensslconf.h */ -/* WARNING: Generated automatically from opensslconf.h.in by Configure. */ - -/* OpenSSL was configured with the following options: */ -#ifndef OPENSSL_DOING_MAKEDEPEND - - -#ifndef OPENSSL_NO_CAST -# define OPENSSL_NO_CAST -#endif -#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 -# define OPENSSL_NO_EC_NISTP_64_GCC_128 -#endif -#ifndef OPENSSL_NO_GMP -# define OPENSSL_NO_GMP -#endif -#ifndef OPENSSL_NO_IDEA -# define OPENSSL_NO_IDEA -#endif -#ifndef OPENSSL_NO_JPAKE -# define OPENSSL_NO_JPAKE -#endif -#ifndef OPENSSL_NO_KRB5 -# define OPENSSL_NO_KRB5 -#endif -#ifndef OPENSSL_NO_MD2 -# define OPENSSL_NO_MD2 -#endif -#ifndef OPENSSL_NO_RC5 -# define OPENSSL_NO_RC5 -#endif -#ifndef OPENSSL_NO_RFC3779 -# define OPENSSL_NO_RFC3779 -#endif -#ifndef OPENSSL_NO_SCTP -# define OPENSSL_NO_SCTP -#endif -#ifndef OPENSSL_NO_SEED -# define OPENSSL_NO_SEED -#endif -#ifndef OPENSSL_NO_SHA0 -# define OPENSSL_NO_SHA0 -#endif -#ifndef OPENSSL_NO_STORE -# define OPENSSL_NO_STORE -#endif -#ifndef OPENSSL_NO_WHRLPOOL -# define OPENSSL_NO_WHRLPOOL -#endif - -#endif /* OPENSSL_DOING_MAKEDEPEND */ - -#ifndef OPENSSL_THREADS -# define OPENSSL_THREADS -#endif -#ifndef OPENSSL_NO_DYNAMIC_ENGINE -# define OPENSSL_NO_DYNAMIC_ENGINE -#endif - -/* The OPENSSL_NO_* macros are also defined as NO_* if the application - asks for it. This is a transient feature that is provided for those - who haven't had the time to do the appropriate changes in their - applications. */ -#ifdef OPENSSL_ALGORITHM_DEFINES -# if defined(OPENSSL_NO_CAST) && !defined(NO_CAST) -# define NO_CAST -# endif -# if defined(OPENSSL_NO_EC_NISTP_64_GCC_128) && !defined(NO_EC_NISTP_64_GCC_128) -# define NO_EC_NISTP_64_GCC_128 -# endif -# if defined(OPENSSL_NO_GMP) && !defined(NO_GMP) -# define NO_GMP -# endif -# if defined(OPENSSL_NO_IDEA) && !defined(NO_IDEA) -# define NO_IDEA -# endif -# if defined(OPENSSL_NO_JPAKE) && !defined(NO_JPAKE) -# define NO_JPAKE -# endif -# if defined(OPENSSL_NO_KRB5) && !defined(NO_KRB5) -# define NO_KRB5 -# endif -# if defined(OPENSSL_NO_MD2) && !defined(NO_MD2) -# define NO_MD2 -# endif -# if defined(OPENSSL_NO_RC5) && !defined(NO_RC5) -# define NO_RC5 -# endif -# if defined(OPENSSL_NO_RFC3779) && !defined(NO_RFC3779) -# define NO_RFC3779 -# endif -# if defined(OPENSSL_NO_SCTP) && !defined(NO_SCTP) -# define NO_SCTP -# endif -# if defined(OPENSSL_NO_SEED) && !defined(NO_SEED) -# define NO_SEED -# endif -# if defined(OPENSSL_NO_SHA0) && !defined(NO_SHA0) -# define NO_SHA0 -# endif -# if defined(OPENSSL_NO_STORE) && !defined(NO_STORE) -# define NO_STORE -# endif -# if defined(OPENSSL_NO_WHRLPOOL) && !defined(NO_WHRLPOOL) -# define NO_WHRLPOOL -# endif -#endif - -/* crypto/opensslconf.h.in */ - -/* Generate 80386 code? */ -#undef I386_ONLY - -#if !(defined(VMS) || defined(__VMS)) /* VMS uses logical names instead */ -#if defined(HEADER_CRYPTLIB_H) && !defined(OPENSSLDIR) -#define ENGINESDIR "/usr/local/ssl/lib/engines" -#define OPENSSLDIR "/usr/local/ssl" -#endif -#endif - -#undef OPENSSL_UNISTD -#define OPENSSL_UNISTD <unistd.h> - -#undef OPENSSL_EXPORT_VAR_AS_FUNCTION - -#if defined(HEADER_IDEA_H) && !defined(IDEA_INT) -#define IDEA_INT unsigned int -#endif - -#if defined(HEADER_MD2_H) && !defined(MD2_INT) -#define MD2_INT unsigned int -#endif - -#if defined(HEADER_RC2_H) && !defined(RC2_INT) -/* I need to put in a mod for the alpha - eay */ -#define RC2_INT unsigned int -#endif - -#if defined(HEADER_RC4_H) -#if !defined(RC4_INT) -/* using int types make the structure larger but make the code faster - * on most boxes I have tested - up to %20 faster. */ -/* - * I don't know what does "most" mean, but declaring "int" is a must on: - * - Intel P6 because partial register stalls are very expensive; - * - elder Alpha because it lacks byte load/store instructions; - */ -#define RC4_INT unsigned char -#endif -#if !defined(RC4_CHUNK) -/* - * This enables code handling data aligned at natural CPU word - * boundary. See crypto/rc4/rc4_enc.c for further details. - */ -#define RC4_CHUNK unsigned long -#endif -#endif - -#if (defined(HEADER_NEW_DES_H) || defined(HEADER_DES_H)) && !defined(DES_LONG) -/* If this is set to 'unsigned int' on a DEC Alpha, this gives about a - * %20 speed up (longs are 8 bytes, int's are 4). */ -#ifndef DES_LONG -#define DES_LONG unsigned int -#endif -#endif - -#if defined(HEADER_BN_H) && !defined(CONFIG_HEADER_BN_H) -#define CONFIG_HEADER_BN_H -#define BN_LLONG - -/* Should we define BN_DIV2W here? */ - -/* Only one for the following should be defined */ -#undef SIXTY_FOUR_BIT_LONG -#undef SIXTY_FOUR_BIT -#define THIRTY_TWO_BIT -#endif - -#if defined(HEADER_RC4_LOCL_H) && !defined(CONFIG_HEADER_RC4_LOCL_H) -#define CONFIG_HEADER_RC4_LOCL_H -/* if this is defined data[i] is used instead of *data, this is a %20 - * speedup on x86 */ -#undef RC4_INDEX -#endif - -#if defined(HEADER_BF_LOCL_H) && !defined(CONFIG_HEADER_BF_LOCL_H) -#define CONFIG_HEADER_BF_LOCL_H -#define BF_PTR -#endif /* HEADER_BF_LOCL_H */ - -#if defined(HEADER_DES_LOCL_H) && !defined(CONFIG_HEADER_DES_LOCL_H) -#define CONFIG_HEADER_DES_LOCL_H -#ifndef DES_DEFAULT_OPTIONS -/* the following is tweaked from a config script, that is why it is a - * protected undef/define */ -#ifndef DES_PTR -#undef DES_PTR -#endif - -/* This helps C compiler generate the correct code for multiple functional - * units. It reduces register dependancies at the expense of 2 more - * registers */ -#ifndef DES_RISC1 -#undef DES_RISC1 -#endif - -#ifndef DES_RISC2 -#undef DES_RISC2 -#endif - -#if defined(DES_RISC1) && defined(DES_RISC2) -YOU SHOULD NOT HAVE BOTH DES_RISC1 AND DES_RISC2 DEFINED!!!!! -#endif - -/* Unroll the inner loop, this sometimes helps, sometimes hinders. - * Very mucy CPU dependant */ -#ifndef DES_UNROLL -#define DES_UNROLL -#endif - -/* These default values were supplied by - * Peter Gutman <pgut001@cs.auckland.ac.nz> - * They are only used if nothing else has been defined */ -#if !defined(DES_PTR) && !defined(DES_RISC1) && !defined(DES_RISC2) && !defined(DES_UNROLL) -/* Special defines which change the way the code is built depending on the - CPU and OS. For SGI machines you can use _MIPS_SZLONG (32 or 64) to find - even newer MIPS CPU's, but at the moment one size fits all for - optimization options. Older Sparc's work better with only UNROLL, but - there's no way to tell at compile time what it is you're running on */ - -#if defined( sun ) /* Newer Sparc's */ -# define DES_PTR -# define DES_RISC1 -# define DES_UNROLL -#elif defined( __ultrix ) /* Older MIPS */ -# define DES_PTR -# define DES_RISC2 -# define DES_UNROLL -#elif defined( __osf1__ ) /* Alpha */ -# define DES_PTR -# define DES_RISC2 -#elif defined ( _AIX ) /* RS6000 */ - /* Unknown */ -#elif defined( __hpux ) /* HP-PA */ - /* Unknown */ -#elif defined( __aux ) /* 68K */ - /* Unknown */ -#elif defined( __dgux ) /* 88K (but P6 in latest boxes) */ -# define DES_UNROLL -#elif defined( __sgi ) /* Newer MIPS */ -# define DES_PTR -# define DES_RISC2 -# define DES_UNROLL -#elif defined(i386) || defined(__i386__) /* x86 boxes, should be gcc */ -# define DES_PTR -# define DES_RISC1 -# define DES_UNROLL -#endif /* Systems-specific speed defines */ -#endif - -#endif /* DES_DEFAULT_OPTIONS */ -#endif /* HEADER_DES_LOCL_H */
diff --git a/src/third_party/openssl/openssl/include/openssl/aes.h b/src/third_party/openssl/openssl/include/openssl/aes.h deleted file mode 100644 index f646d41..0000000 --- a/src/third_party/openssl/openssl/include/openssl/aes.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/aes/aes.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/asn1.h b/src/third_party/openssl/openssl/include/openssl/asn1.h deleted file mode 100644 index 5432ed8..0000000 --- a/src/third_party/openssl/openssl/include/openssl/asn1.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/asn1/asn1.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/asn1_mac.h b/src/third_party/openssl/openssl/include/openssl/asn1_mac.h deleted file mode 100644 index 214787c..0000000 --- a/src/third_party/openssl/openssl/include/openssl/asn1_mac.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/asn1/asn1_mac.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/asn1t.h b/src/third_party/openssl/openssl/include/openssl/asn1t.h deleted file mode 100644 index 4de87a9..0000000 --- a/src/third_party/openssl/openssl/include/openssl/asn1t.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/asn1/asn1t.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/bio.h b/src/third_party/openssl/openssl/include/openssl/bio.h deleted file mode 100644 index 34f8a2d..0000000 --- a/src/third_party/openssl/openssl/include/openssl/bio.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/bio/bio.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/blowfish.h b/src/third_party/openssl/openssl/include/openssl/blowfish.h deleted file mode 100644 index 8d515fe..0000000 --- a/src/third_party/openssl/openssl/include/openssl/blowfish.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/bf/blowfish.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/bn.h b/src/third_party/openssl/openssl/include/openssl/bn.h deleted file mode 100644 index f47d65a..0000000 --- a/src/third_party/openssl/openssl/include/openssl/bn.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/bn/bn.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/buffer.h b/src/third_party/openssl/openssl/include/openssl/buffer.h deleted file mode 100644 index 1d2c2a2..0000000 --- a/src/third_party/openssl/openssl/include/openssl/buffer.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/buffer/buffer.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/camellia.h b/src/third_party/openssl/openssl/include/openssl/camellia.h deleted file mode 100644 index 5a0a141..0000000 --- a/src/third_party/openssl/openssl/include/openssl/camellia.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/camellia/camellia.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/cast.h b/src/third_party/openssl/openssl/include/openssl/cast.h deleted file mode 100644 index 12cf92c..0000000 --- a/src/third_party/openssl/openssl/include/openssl/cast.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/cast/cast.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/cmac.h b/src/third_party/openssl/openssl/include/openssl/cmac.h deleted file mode 100644 index a7579ae..0000000 --- a/src/third_party/openssl/openssl/include/openssl/cmac.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/cmac/cmac.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/cms.h b/src/third_party/openssl/openssl/include/openssl/cms.h deleted file mode 100644 index 8687c7f..0000000 --- a/src/third_party/openssl/openssl/include/openssl/cms.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/cms/cms.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/comp.h b/src/third_party/openssl/openssl/include/openssl/comp.h deleted file mode 100644 index d14e36c..0000000 --- a/src/third_party/openssl/openssl/include/openssl/comp.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/comp/comp.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/conf.h b/src/third_party/openssl/openssl/include/openssl/conf.h deleted file mode 100644 index 3882c82..0000000 --- a/src/third_party/openssl/openssl/include/openssl/conf.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/conf/conf.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/conf_api.h b/src/third_party/openssl/openssl/include/openssl/conf_api.h deleted file mode 100644 index 0393357..0000000 --- a/src/third_party/openssl/openssl/include/openssl/conf_api.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/conf/conf_api.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/crypto.h b/src/third_party/openssl/openssl/include/openssl/crypto.h deleted file mode 100644 index 7e3d91e..0000000 --- a/src/third_party/openssl/openssl/include/openssl/crypto.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/crypto.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/des.h b/src/third_party/openssl/openssl/include/openssl/des.h deleted file mode 100644 index 1d6631e..0000000 --- a/src/third_party/openssl/openssl/include/openssl/des.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/des/des.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/des_old.h b/src/third_party/openssl/openssl/include/openssl/des_old.h deleted file mode 100644 index e582873..0000000 --- a/src/third_party/openssl/openssl/include/openssl/des_old.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/des/des_old.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/dh.h b/src/third_party/openssl/openssl/include/openssl/dh.h deleted file mode 100644 index f70a767..0000000 --- a/src/third_party/openssl/openssl/include/openssl/dh.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/dh/dh.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/dsa.h b/src/third_party/openssl/openssl/include/openssl/dsa.h deleted file mode 100644 index 0365acf..0000000 --- a/src/third_party/openssl/openssl/include/openssl/dsa.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/dsa/dsa.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/dso.h b/src/third_party/openssl/openssl/include/openssl/dso.h deleted file mode 100644 index f3c8de2..0000000 --- a/src/third_party/openssl/openssl/include/openssl/dso.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/dso/dso.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/dtls1.h b/src/third_party/openssl/openssl/include/openssl/dtls1.h deleted file mode 100644 index ac8ab57..0000000 --- a/src/third_party/openssl/openssl/include/openssl/dtls1.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../ssl/dtls1.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/e_os2.h b/src/third_party/openssl/openssl/include/openssl/e_os2.h deleted file mode 100644 index ab3f1ee..0000000 --- a/src/third_party/openssl/openssl/include/openssl/e_os2.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../e_os2.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/ebcdic.h b/src/third_party/openssl/openssl/include/openssl/ebcdic.h deleted file mode 100644 index 6dedc70..0000000 --- a/src/third_party/openssl/openssl/include/openssl/ebcdic.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/ebcdic.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/ec.h b/src/third_party/openssl/openssl/include/openssl/ec.h deleted file mode 100644 index 7d20614..0000000 --- a/src/third_party/openssl/openssl/include/openssl/ec.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/ec/ec.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/ecdh.h b/src/third_party/openssl/openssl/include/openssl/ecdh.h deleted file mode 100644 index ad6e3dc..0000000 --- a/src/third_party/openssl/openssl/include/openssl/ecdh.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/ecdh/ecdh.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/ecdsa.h b/src/third_party/openssl/openssl/include/openssl/ecdsa.h deleted file mode 100644 index da45123..0000000 --- a/src/third_party/openssl/openssl/include/openssl/ecdsa.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/ecdsa/ecdsa.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/engine.h b/src/third_party/openssl/openssl/include/openssl/engine.h deleted file mode 100644 index 2dceaac..0000000 --- a/src/third_party/openssl/openssl/include/openssl/engine.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/engine/engine.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/err.h b/src/third_party/openssl/openssl/include/openssl/err.h deleted file mode 100644 index caf89a9..0000000 --- a/src/third_party/openssl/openssl/include/openssl/err.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/err/err.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/evp.h b/src/third_party/openssl/openssl/include/openssl/evp.h deleted file mode 100644 index dd7bcda..0000000 --- a/src/third_party/openssl/openssl/include/openssl/evp.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/evp/evp.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/hmac.h b/src/third_party/openssl/openssl/include/openssl/hmac.h deleted file mode 100644 index 202128b..0000000 --- a/src/third_party/openssl/openssl/include/openssl/hmac.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/hmac/hmac.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/idea.h b/src/third_party/openssl/openssl/include/openssl/idea.h deleted file mode 100644 index bdf697d..0000000 --- a/src/third_party/openssl/openssl/include/openssl/idea.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/idea/idea.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/krb5_asn.h b/src/third_party/openssl/openssl/include/openssl/krb5_asn.h deleted file mode 100644 index 0d3feea..0000000 --- a/src/third_party/openssl/openssl/include/openssl/krb5_asn.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/krb5/krb5_asn.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/kssl.h b/src/third_party/openssl/openssl/include/openssl/kssl.h deleted file mode 100644 index 719634a..0000000 --- a/src/third_party/openssl/openssl/include/openssl/kssl.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../ssl/kssl.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/lhash.h b/src/third_party/openssl/openssl/include/openssl/lhash.h deleted file mode 100644 index 2d3db87..0000000 --- a/src/third_party/openssl/openssl/include/openssl/lhash.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/lhash/lhash.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/md2.h b/src/third_party/openssl/openssl/include/openssl/md2.h deleted file mode 100644 index 4c3398c..0000000 --- a/src/third_party/openssl/openssl/include/openssl/md2.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/md2/md2.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/md4.h b/src/third_party/openssl/openssl/include/openssl/md4.h deleted file mode 100644 index 611806e..0000000 --- a/src/third_party/openssl/openssl/include/openssl/md4.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/md4/md4.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/md5.h b/src/third_party/openssl/openssl/include/openssl/md5.h deleted file mode 100644 index aa8cd0b..0000000 --- a/src/third_party/openssl/openssl/include/openssl/md5.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/md5/md5.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/mdc2.h b/src/third_party/openssl/openssl/include/openssl/mdc2.h deleted file mode 100644 index ac284a1..0000000 --- a/src/third_party/openssl/openssl/include/openssl/mdc2.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/mdc2/mdc2.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/modes.h b/src/third_party/openssl/openssl/include/openssl/modes.h deleted file mode 100644 index f57fcfe..0000000 --- a/src/third_party/openssl/openssl/include/openssl/modes.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/modes/modes.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/obj_mac.h b/src/third_party/openssl/openssl/include/openssl/obj_mac.h deleted file mode 100644 index 3890fa9..0000000 --- a/src/third_party/openssl/openssl/include/openssl/obj_mac.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/objects/obj_mac.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/objects.h b/src/third_party/openssl/openssl/include/openssl/objects.h deleted file mode 100644 index 5365a04..0000000 --- a/src/third_party/openssl/openssl/include/openssl/objects.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/objects/objects.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/ocsp.h b/src/third_party/openssl/openssl/include/openssl/ocsp.h deleted file mode 100644 index 50e2885..0000000 --- a/src/third_party/openssl/openssl/include/openssl/ocsp.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/ocsp/ocsp.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/opensslv.h b/src/third_party/openssl/openssl/include/openssl/opensslv.h deleted file mode 100644 index c39a0c3..0000000 --- a/src/third_party/openssl/openssl/include/openssl/opensslv.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/opensslv.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/ossl_typ.h b/src/third_party/openssl/openssl/include/openssl/ossl_typ.h deleted file mode 100644 index ddd7e58..0000000 --- a/src/third_party/openssl/openssl/include/openssl/ossl_typ.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/ossl_typ.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/pem.h b/src/third_party/openssl/openssl/include/openssl/pem.h deleted file mode 100644 index 5bcc5c5..0000000 --- a/src/third_party/openssl/openssl/include/openssl/pem.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/pem/pem.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/pem2.h b/src/third_party/openssl/openssl/include/openssl/pem2.h deleted file mode 100644 index bcd3acf..0000000 --- a/src/third_party/openssl/openssl/include/openssl/pem2.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/pem/pem2.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/pkcs12.h b/src/third_party/openssl/openssl/include/openssl/pkcs12.h deleted file mode 100644 index 0b5fbbf..0000000 --- a/src/third_party/openssl/openssl/include/openssl/pkcs12.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/pkcs12/pkcs12.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/pkcs7.h b/src/third_party/openssl/openssl/include/openssl/pkcs7.h deleted file mode 100644 index 2e19d7c..0000000 --- a/src/third_party/openssl/openssl/include/openssl/pkcs7.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/pkcs7/pkcs7.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/pqueue.h b/src/third_party/openssl/openssl/include/openssl/pqueue.h deleted file mode 100644 index 9681ff5..0000000 --- a/src/third_party/openssl/openssl/include/openssl/pqueue.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/pqueue/pqueue.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/rand.h b/src/third_party/openssl/openssl/include/openssl/rand.h deleted file mode 100644 index 9d1521b..0000000 --- a/src/third_party/openssl/openssl/include/openssl/rand.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/rand/rand.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/rc2.h b/src/third_party/openssl/openssl/include/openssl/rc2.h deleted file mode 100644 index f2f2bd1..0000000 --- a/src/third_party/openssl/openssl/include/openssl/rc2.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/rc2/rc2.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/rc4.h b/src/third_party/openssl/openssl/include/openssl/rc4.h deleted file mode 100644 index 306de2f..0000000 --- a/src/third_party/openssl/openssl/include/openssl/rc4.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/rc4/rc4.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/ripemd.h b/src/third_party/openssl/openssl/include/openssl/ripemd.h deleted file mode 100644 index 11351fc..0000000 --- a/src/third_party/openssl/openssl/include/openssl/ripemd.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/ripemd/ripemd.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/rsa.h b/src/third_party/openssl/openssl/include/openssl/rsa.h deleted file mode 100644 index 975e5d3..0000000 --- a/src/third_party/openssl/openssl/include/openssl/rsa.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/rsa/rsa.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/safestack.h b/src/third_party/openssl/openssl/include/openssl/safestack.h deleted file mode 100644 index 8a282b8..0000000 --- a/src/third_party/openssl/openssl/include/openssl/safestack.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/stack/safestack.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/seed.h b/src/third_party/openssl/openssl/include/openssl/seed.h deleted file mode 100644 index bbbf596..0000000 --- a/src/third_party/openssl/openssl/include/openssl/seed.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/seed/seed.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/sha.h b/src/third_party/openssl/openssl/include/openssl/sha.h deleted file mode 100644 index ab9d94c..0000000 --- a/src/third_party/openssl/openssl/include/openssl/sha.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/sha/sha.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/srp.h b/src/third_party/openssl/openssl/include/openssl/srp.h deleted file mode 100644 index 8217476..0000000 --- a/src/third_party/openssl/openssl/include/openssl/srp.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/srp/srp.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/srtp.h b/src/third_party/openssl/openssl/include/openssl/srtp.h deleted file mode 100644 index e185494..0000000 --- a/src/third_party/openssl/openssl/include/openssl/srtp.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../ssl/srtp.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/ssl.h b/src/third_party/openssl/openssl/include/openssl/ssl.h deleted file mode 100644 index 0b0589c..0000000 --- a/src/third_party/openssl/openssl/include/openssl/ssl.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../ssl/ssl.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/ssl2.h b/src/third_party/openssl/openssl/include/openssl/ssl2.h deleted file mode 100644 index 11b2205..0000000 --- a/src/third_party/openssl/openssl/include/openssl/ssl2.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../ssl/ssl2.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/ssl23.h b/src/third_party/openssl/openssl/include/openssl/ssl23.h deleted file mode 100644 index fe4dae6..0000000 --- a/src/third_party/openssl/openssl/include/openssl/ssl23.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../ssl/ssl23.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/ssl3.h b/src/third_party/openssl/openssl/include/openssl/ssl3.h deleted file mode 100644 index 0fb66a6..0000000 --- a/src/third_party/openssl/openssl/include/openssl/ssl3.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../ssl/ssl3.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/stack.h b/src/third_party/openssl/openssl/include/openssl/stack.h deleted file mode 100644 index 295968c..0000000 --- a/src/third_party/openssl/openssl/include/openssl/stack.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/stack/stack.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/store.h b/src/third_party/openssl/openssl/include/openssl/store.h deleted file mode 100644 index 84dc39f..0000000 --- a/src/third_party/openssl/openssl/include/openssl/store.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/store/store.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/symhacks.h b/src/third_party/openssl/openssl/include/openssl/symhacks.h deleted file mode 100644 index f946f4f..0000000 --- a/src/third_party/openssl/openssl/include/openssl/symhacks.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/symhacks.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/tls1.h b/src/third_party/openssl/openssl/include/openssl/tls1.h deleted file mode 100644 index c43a70f..0000000 --- a/src/third_party/openssl/openssl/include/openssl/tls1.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../ssl/tls1.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/ts.h b/src/third_party/openssl/openssl/include/openssl/ts.h deleted file mode 100644 index fe8a2cb..0000000 --- a/src/third_party/openssl/openssl/include/openssl/ts.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/ts/ts.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/txt_db.h b/src/third_party/openssl/openssl/include/openssl/txt_db.h deleted file mode 100644 index 167621b..0000000 --- a/src/third_party/openssl/openssl/include/openssl/txt_db.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/txt_db/txt_db.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/ui.h b/src/third_party/openssl/openssl/include/openssl/ui.h deleted file mode 100644 index 43dd3ae..0000000 --- a/src/third_party/openssl/openssl/include/openssl/ui.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/ui/ui.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/ui_compat.h b/src/third_party/openssl/openssl/include/openssl/ui_compat.h deleted file mode 100644 index c83f160..0000000 --- a/src/third_party/openssl/openssl/include/openssl/ui_compat.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/ui/ui_compat.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/whrlpool.h b/src/third_party/openssl/openssl/include/openssl/whrlpool.h deleted file mode 100644 index e2424fa..0000000 --- a/src/third_party/openssl/openssl/include/openssl/whrlpool.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/whrlpool/whrlpool.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/x509.h b/src/third_party/openssl/openssl/include/openssl/x509.h deleted file mode 100644 index a4651a2..0000000 --- a/src/third_party/openssl/openssl/include/openssl/x509.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/x509/x509.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/x509_vfy.h b/src/third_party/openssl/openssl/include/openssl/x509_vfy.h deleted file mode 100644 index b897aa0..0000000 --- a/src/third_party/openssl/openssl/include/openssl/x509_vfy.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/x509/x509_vfy.h"
diff --git a/src/third_party/openssl/openssl/include/openssl/x509v3.h b/src/third_party/openssl/openssl/include/openssl/x509v3.h deleted file mode 100644 index 363795e..0000000 --- a/src/third_party/openssl/openssl/include/openssl/x509v3.h +++ /dev/null
@@ -1 +0,0 @@ -#include "../../crypto/x509v3/x509v3.h"
diff --git a/src/third_party/openssl/openssl/test/bftest.c b/src/third_party/openssl/openssl/test/bftest.c deleted file mode 120000 index 78b1749..0000000 --- a/src/third_party/openssl/openssl/test/bftest.c +++ /dev/null
@@ -1 +0,0 @@ -../crypto/bf/bftest.c \ No newline at end of file
diff --git a/src/third_party/openssl/openssl/test/bntest.c b/src/third_party/openssl/openssl/test/bntest.c deleted file mode 120000 index 03f54a2..0000000 --- a/src/third_party/openssl/openssl/test/bntest.c +++ /dev/null
@@ -1 +0,0 @@ -../crypto/bn/bntest.c \ No newline at end of file
diff --git a/src/third_party/openssl/openssl/test/casttest.c b/src/third_party/openssl/openssl/test/casttest.c deleted file mode 120000 index ac7ede8..0000000 --- a/src/third_party/openssl/openssl/test/casttest.c +++ /dev/null
@@ -1 +0,0 @@ -../crypto/cast/casttest.c \ No newline at end of file
diff --git a/src/third_party/openssl/openssl/test/destest.c b/src/third_party/openssl/openssl/test/destest.c deleted file mode 120000 index 5988c73..0000000 --- a/src/third_party/openssl/openssl/test/destest.c +++ /dev/null
@@ -1 +0,0 @@ -../crypto/des/destest.c \ No newline at end of file
diff --git a/src/third_party/openssl/openssl/test/dhtest.c b/src/third_party/openssl/openssl/test/dhtest.c deleted file mode 120000 index 9a67f91..0000000 --- a/src/third_party/openssl/openssl/test/dhtest.c +++ /dev/null
@@ -1 +0,0 @@ -../crypto/dh/dhtest.c \ No newline at end of file
diff --git a/src/third_party/openssl/openssl/test/dsatest.c b/src/third_party/openssl/openssl/test/dsatest.c deleted file mode 120000 index 16a1b5a..0000000 --- a/src/third_party/openssl/openssl/test/dsatest.c +++ /dev/null
@@ -1 +0,0 @@ -../crypto/dsa/dsatest.c \ No newline at end of file
diff --git a/src/third_party/openssl/openssl/test/ecdhtest.c b/src/third_party/openssl/openssl/test/ecdhtest.c deleted file mode 120000 index 206d986..0000000 --- a/src/third_party/openssl/openssl/test/ecdhtest.c +++ /dev/null
@@ -1 +0,0 @@ -../crypto/ecdh/ecdhtest.c \ No newline at end of file
diff --git a/src/third_party/openssl/openssl/test/ecdsatest.c b/src/third_party/openssl/openssl/test/ecdsatest.c deleted file mode 120000 index 441082b..0000000 --- a/src/third_party/openssl/openssl/test/ecdsatest.c +++ /dev/null
@@ -1 +0,0 @@ -../crypto/ecdsa/ecdsatest.c \ No newline at end of file
diff --git a/src/third_party/openssl/openssl/test/ectest.c b/src/third_party/openssl/openssl/test/ectest.c deleted file mode 120000 index df1831f..0000000 --- a/src/third_party/openssl/openssl/test/ectest.c +++ /dev/null
@@ -1 +0,0 @@ -../crypto/ec/ectest.c \ No newline at end of file
diff --git a/src/third_party/openssl/openssl/test/enginetest.c b/src/third_party/openssl/openssl/test/enginetest.c deleted file mode 120000 index 5c74a6f..0000000 --- a/src/third_party/openssl/openssl/test/enginetest.c +++ /dev/null
@@ -1 +0,0 @@ -../crypto/engine/enginetest.c \ No newline at end of file
diff --git a/src/third_party/openssl/openssl/test/evp_test.c b/src/third_party/openssl/openssl/test/evp_test.c deleted file mode 120000 index 0741628..0000000 --- a/src/third_party/openssl/openssl/test/evp_test.c +++ /dev/null
@@ -1 +0,0 @@ -../crypto/evp/evp_test.c \ No newline at end of file
diff --git a/src/third_party/openssl/openssl/test/evptests.txt b/src/third_party/openssl/openssl/test/evptests.txt deleted file mode 100644 index c273707..0000000 --- a/src/third_party/openssl/openssl/test/evptests.txt +++ /dev/null
@@ -1,334 +0,0 @@ -#cipher:key:iv:plaintext:ciphertext:0/1(decrypt/encrypt) -#digest:::input:output - -# SHA(1) tests (from shatest.c) -SHA1:::616263:a9993e364706816aba3e25717850c26c9cd0d89d - -# MD5 tests (from md5test.c) -MD5::::d41d8cd98f00b204e9800998ecf8427e -MD5:::61:0cc175b9c0f1b6a831c399e269772661 -MD5:::616263:900150983cd24fb0d6963f7d28e17f72 -MD5:::6d65737361676520646967657374:f96b697d7cb7938d525a2f31aaf161d0 -MD5:::6162636465666768696a6b6c6d6e6f707172737475767778797a:c3fcd3d76192e4007dfb496cca67e13b -MD5:::4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a30313233343536373839:d174ab98d277d9f5a5611c2c9f419d9f -MD5:::3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930:57edf4a22be3c955ac49da2e2107b67a - -# AES 128 ECB tests (from FIPS-197 test vectors, encrypt) - -AES-128-ECB:000102030405060708090A0B0C0D0E0F::00112233445566778899AABBCCDDEEFF:69C4E0D86A7B0430D8CDB78070B4C55A:1 - -# AES 192 ECB tests (from FIPS-197 test vectors, encrypt) - -AES-192-ECB:000102030405060708090A0B0C0D0E0F1011121314151617::00112233445566778899AABBCCDDEEFF:DDA97CA4864CDFE06EAF70A0EC0D7191:1 - -# AES 256 ECB tests (from FIPS-197 test vectors, encrypt) - -AES-256-ECB:000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F::00112233445566778899AABBCCDDEEFF:8EA2B7CA516745BFEAFC49904B496089:1 - -# AES 128 ECB tests (from NIST test vectors, encrypt) - -#AES-128-ECB:00000000000000000000000000000000::00000000000000000000000000000000:C34C052CC0DA8D73451AFE5F03BE297F:1 - -# AES 128 ECB tests (from NIST test vectors, decrypt) - -#AES-128-ECB:00000000000000000000000000000000::44416AC2D1F53C583303917E6BE9EBE0:00000000000000000000000000000000:0 - -# AES 192 ECB tests (from NIST test vectors, decrypt) - -#AES-192-ECB:000000000000000000000000000000000000000000000000::48E31E9E256718F29229319C19F15BA4:00000000000000000000000000000000:0 - -# AES 256 ECB tests (from NIST test vectors, decrypt) - -#AES-256-ECB:0000000000000000000000000000000000000000000000000000000000000000::058CCFFDBBCB382D1F6F56585D8A4ADE:00000000000000000000000000000000:0 - -# AES 128 CBC tests (from NIST test vectors, encrypt) - -#AES-128-CBC:00000000000000000000000000000000:00000000000000000000000000000000:00000000000000000000000000000000:8A05FC5E095AF4848A08D328D3688E3D:1 - -# AES 192 CBC tests (from NIST test vectors, encrypt) - -#AES-192-CBC:000000000000000000000000000000000000000000000000:00000000000000000000000000000000:00000000000000000000000000000000:7BD966D53AD8C1BB85D2ADFAE87BB104:1 - -# AES 256 CBC tests (from NIST test vectors, encrypt) - -#AES-256-CBC:0000000000000000000000000000000000000000000000000000000000000000:00000000000000000000000000000000:00000000000000000000000000000000:FE3C53653E2F45B56FCD88B2CC898FF0:1 - -# AES 128 CBC tests (from NIST test vectors, decrypt) - -#AES-128-CBC:00000000000000000000000000000000:00000000000000000000000000000000:FACA37E0B0C85373DF706E73F7C9AF86:00000000000000000000000000000000:0 - -# AES tests from NIST document SP800-38A -# For all ECB encrypts and decrypts, the transformed sequence is -# AES-bits-ECB:key::plaintext:ciphertext:encdec -# ECB-AES128.Encrypt and ECB-AES128.Decrypt -AES-128-ECB:2B7E151628AED2A6ABF7158809CF4F3C::6BC1BEE22E409F96E93D7E117393172A:3AD77BB40D7A3660A89ECAF32466EF97 -AES-128-ECB:2B7E151628AED2A6ABF7158809CF4F3C::AE2D8A571E03AC9C9EB76FAC45AF8E51:F5D3D58503B9699DE785895A96FDBAAF -AES-128-ECB:2B7E151628AED2A6ABF7158809CF4F3C::30C81C46A35CE411E5FBC1191A0A52EF:43B1CD7F598ECE23881B00E3ED030688 -AES-128-ECB:2B7E151628AED2A6ABF7158809CF4F3C::F69F2445DF4F9B17AD2B417BE66C3710:7B0C785E27E8AD3F8223207104725DD4 -# ECB-AES192.Encrypt and ECB-AES192.Decrypt -AES-192-ECB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B::6BC1BEE22E409F96E93D7E117393172A:BD334F1D6E45F25FF712A214571FA5CC -AES-192-ECB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B::AE2D8A571E03AC9C9EB76FAC45AF8E51:974104846D0AD3AD7734ECB3ECEE4EEF -AES-192-ECB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B::30C81C46A35CE411E5FBC1191A0A52EF:EF7AFD2270E2E60ADCE0BA2FACE6444E -AES-192-ECB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B::F69F2445DF4F9B17AD2B417BE66C3710:9A4B41BA738D6C72FB16691603C18E0E -# ECB-AES256.Encrypt and ECB-AES256.Decrypt -AES-256-ECB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4::6BC1BEE22E409F96E93D7E117393172A:F3EED1BDB5D2A03C064B5A7E3DB181F8 -AES-256-ECB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4::AE2D8A571E03AC9C9EB76FAC45AF8E51:591CCB10D410ED26DC5BA74A31362870 -AES-256-ECB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4::30C81C46A35CE411E5FBC1191A0A52EF:B6ED21B99CA6F4F9F153E7B1BEAFED1D -AES-256-ECB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4::F69F2445DF4F9B17AD2B417BE66C3710:23304B7A39F9F3FF067D8D8F9E24ECC7 -# For all CBC encrypts and decrypts, the transformed sequence is -# AES-bits-CBC:key:IV/ciphertext':plaintext:ciphertext:encdec -# CBC-AES128.Encrypt and CBC-AES128.Decrypt -AES-128-CBC:2B7E151628AED2A6ABF7158809CF4F3C:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:7649ABAC8119B246CEE98E9B12E9197D -AES-128-CBC:2B7E151628AED2A6ABF7158809CF4F3C:7649ABAC8119B246CEE98E9B12E9197D:AE2D8A571E03AC9C9EB76FAC45AF8E51:5086CB9B507219EE95DB113A917678B2 -AES-128-CBC:2B7E151628AED2A6ABF7158809CF4F3C:5086CB9B507219EE95DB113A917678B2:30C81C46A35CE411E5FBC1191A0A52EF:73BED6B8E3C1743B7116E69E22229516 -AES-128-CBC:2B7E151628AED2A6ABF7158809CF4F3C:73BED6B8E3C1743B7116E69E22229516:F69F2445DF4F9B17AD2B417BE66C3710:3FF1CAA1681FAC09120ECA307586E1A7 -# CBC-AES192.Encrypt and CBC-AES192.Decrypt -AES-192-CBC:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:4F021DB243BC633D7178183A9FA071E8 -AES-192-CBC:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:4F021DB243BC633D7178183A9FA071E8:AE2D8A571E03AC9C9EB76FAC45AF8E51:B4D9ADA9AD7DEDF4E5E738763F69145A -AES-192-CBC:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:B4D9ADA9AD7DEDF4E5E738763F69145A:30C81C46A35CE411E5FBC1191A0A52EF:571B242012FB7AE07FA9BAAC3DF102E0 -AES-192-CBC:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:571B242012FB7AE07FA9BAAC3DF102E0:F69F2445DF4F9B17AD2B417BE66C3710:08B0E27988598881D920A9E64F5615CD -# CBC-AES256.Encrypt and CBC-AES256.Decrypt -AES-256-CBC:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:F58C4C04D6E5F1BA779EABFB5F7BFBD6 -AES-256-CBC:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:F58C4C04D6E5F1BA779EABFB5F7BFBD6:AE2D8A571E03AC9C9EB76FAC45AF8E51:9CFC4E967EDB808D679F777BC6702C7D -AES-256-CBC:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:9CFC4E967EDB808D679F777BC6702C7D:30C81C46A35CE411E5FBC1191A0A52EF:39F23369A9D9BACFA530E26304231461 -AES-256-CBC:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:39F23369A9D9BACFA530E26304231461:F69F2445DF4F9B17AD2B417BE66C3710:B2EB05E2C39BE9FCDA6C19078C6A9D1B -# We don't support CFB{1,8}-AESxxx.{En,De}crypt -# For all CFB128 encrypts and decrypts, the transformed sequence is -# AES-bits-CFB:key:IV/ciphertext':plaintext:ciphertext:encdec -# CFB128-AES128.Encrypt -AES-128-CFB:2B7E151628AED2A6ABF7158809CF4F3C:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:3B3FD92EB72DAD20333449F8E83CFB4A:1 -AES-128-CFB:2B7E151628AED2A6ABF7158809CF4F3C:3B3FD92EB72DAD20333449F8E83CFB4A:AE2D8A571E03AC9C9EB76FAC45AF8E51:C8A64537A0B3A93FCDE3CDAD9F1CE58B:1 -AES-128-CFB:2B7E151628AED2A6ABF7158809CF4F3C:C8A64537A0B3A93FCDE3CDAD9F1CE58B:30C81C46A35CE411E5FBC1191A0A52EF:26751F67A3CBB140B1808CF187A4F4DF:1 -AES-128-CFB:2B7E151628AED2A6ABF7158809CF4F3C:26751F67A3CBB140B1808CF187A4F4DF:F69F2445DF4F9B17AD2B417BE66C3710:C04B05357C5D1C0EEAC4C66F9FF7F2E6:1 -# CFB128-AES128.Decrypt -AES-128-CFB:2B7E151628AED2A6ABF7158809CF4F3C:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:3B3FD92EB72DAD20333449F8E83CFB4A:0 -AES-128-CFB:2B7E151628AED2A6ABF7158809CF4F3C:3B3FD92EB72DAD20333449F8E83CFB4A:AE2D8A571E03AC9C9EB76FAC45AF8E51:C8A64537A0B3A93FCDE3CDAD9F1CE58B:0 -AES-128-CFB:2B7E151628AED2A6ABF7158809CF4F3C:C8A64537A0B3A93FCDE3CDAD9F1CE58B:30C81C46A35CE411E5FBC1191A0A52EF:26751F67A3CBB140B1808CF187A4F4DF:0 -AES-128-CFB:2B7E151628AED2A6ABF7158809CF4F3C:26751F67A3CBB140B1808CF187A4F4DF:F69F2445DF4F9B17AD2B417BE66C3710:C04B05357C5D1C0EEAC4C66F9FF7F2E6:0 -# CFB128-AES192.Encrypt -AES-192-CFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:CDC80D6FDDF18CAB34C25909C99A4174:1 -AES-192-CFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:CDC80D6FDDF18CAB34C25909C99A4174:AE2D8A571E03AC9C9EB76FAC45AF8E51:67CE7F7F81173621961A2B70171D3D7A:1 -AES-192-CFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:67CE7F7F81173621961A2B70171D3D7A:30C81C46A35CE411E5FBC1191A0A52EF:2E1E8A1DD59B88B1C8E60FED1EFAC4C9:1 -AES-192-CFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:2E1E8A1DD59B88B1C8E60FED1EFAC4C9:F69F2445DF4F9B17AD2B417BE66C3710:C05F9F9CA9834FA042AE8FBA584B09FF:1 -# CFB128-AES192.Decrypt -AES-192-CFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:CDC80D6FDDF18CAB34C25909C99A4174:0 -AES-192-CFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:CDC80D6FDDF18CAB34C25909C99A4174:AE2D8A571E03AC9C9EB76FAC45AF8E51:67CE7F7F81173621961A2B70171D3D7A:0 -AES-192-CFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:67CE7F7F81173621961A2B70171D3D7A:30C81C46A35CE411E5FBC1191A0A52EF:2E1E8A1DD59B88B1C8E60FED1EFAC4C9:0 -AES-192-CFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:2E1E8A1DD59B88B1C8E60FED1EFAC4C9:F69F2445DF4F9B17AD2B417BE66C3710:C05F9F9CA9834FA042AE8FBA584B09FF:0 -# CFB128-AES256.Encrypt -AES-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:DC7E84BFDA79164B7ECD8486985D3860:1 -AES-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:DC7E84BFDA79164B7ECD8486985D3860:AE2D8A571E03AC9C9EB76FAC45AF8E51:39FFED143B28B1C832113C6331E5407B:1 -AES-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:39FFED143B28B1C832113C6331E5407B:30C81C46A35CE411E5FBC1191A0A52EF:DF10132415E54B92A13ED0A8267AE2F9:1 -AES-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:DF10132415E54B92A13ED0A8267AE2F9:F69F2445DF4F9B17AD2B417BE66C3710:75A385741AB9CEF82031623D55B1E471:1 -# CFB128-AES256.Decrypt -AES-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:DC7E84BFDA79164B7ECD8486985D3860:0 -AES-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:DC7E84BFDA79164B7ECD8486985D3860:AE2D8A571E03AC9C9EB76FAC45AF8E51:39FFED143B28B1C832113C6331E5407B:0 -AES-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:39FFED143B28B1C832113C6331E5407B:30C81C46A35CE411E5FBC1191A0A52EF:DF10132415E54B92A13ED0A8267AE2F9:0 -AES-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:DF10132415E54B92A13ED0A8267AE2F9:F69F2445DF4F9B17AD2B417BE66C3710:75A385741AB9CEF82031623D55B1E471:0 -# For all OFB encrypts and decrypts, the transformed sequence is -# AES-bits-CFB:key:IV/output':plaintext:ciphertext:encdec -# OFB-AES128.Encrypt -AES-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:3B3FD92EB72DAD20333449F8E83CFB4A:1 -AES-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:50FE67CC996D32B6DA0937E99BAFEC60:AE2D8A571E03AC9C9EB76FAC45AF8E51:7789508D16918F03F53C52DAC54ED825:1 -AES-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:D9A4DADA0892239F6B8B3D7680E15674:30C81C46A35CE411E5FBC1191A0A52EF:9740051E9C5FECF64344F7A82260EDCC:1 -AES-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:A78819583F0308E7A6BF36B1386ABF23:F69F2445DF4F9B17AD2B417BE66C3710:304C6528F659C77866A510D9C1D6AE5E:1 -# OFB-AES128.Decrypt -AES-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:3B3FD92EB72DAD20333449F8E83CFB4A:0 -AES-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:50FE67CC996D32B6DA0937E99BAFEC60:AE2D8A571E03AC9C9EB76FAC45AF8E51:7789508D16918F03F53C52DAC54ED825:0 -AES-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:D9A4DADA0892239F6B8B3D7680E15674:30C81C46A35CE411E5FBC1191A0A52EF:9740051E9C5FECF64344F7A82260EDCC:0 -AES-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:A78819583F0308E7A6BF36B1386ABF23:F69F2445DF4F9B17AD2B417BE66C3710:304C6528F659C77866A510D9C1D6AE5E:0 -# OFB-AES192.Encrypt -AES-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:CDC80D6FDDF18CAB34C25909C99A4174:1 -AES-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:A609B38DF3B1133DDDFF2718BA09565E:AE2D8A571E03AC9C9EB76FAC45AF8E51:FCC28B8D4C63837C09E81700C1100401:1 -AES-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:52EF01DA52602FE0975F78AC84BF8A50:30C81C46A35CE411E5FBC1191A0A52EF:8D9A9AEAC0F6596F559C6D4DAF59A5F2:1 -AES-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:BD5286AC63AABD7EB067AC54B553F71D:F69F2445DF4F9B17AD2B417BE66C3710:6D9F200857CA6C3E9CAC524BD9ACC92A:1 -# OFB-AES192.Decrypt -AES-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:CDC80D6FDDF18CAB34C25909C99A4174:0 -AES-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:A609B38DF3B1133DDDFF2718BA09565E:AE2D8A571E03AC9C9EB76FAC45AF8E51:FCC28B8D4C63837C09E81700C1100401:0 -AES-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:52EF01DA52602FE0975F78AC84BF8A50:30C81C46A35CE411E5FBC1191A0A52EF:8D9A9AEAC0F6596F559C6D4DAF59A5F2:0 -AES-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:BD5286AC63AABD7EB067AC54B553F71D:F69F2445DF4F9B17AD2B417BE66C3710:6D9F200857CA6C3E9CAC524BD9ACC92A:0 -# OFB-AES256.Encrypt -AES-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:DC7E84BFDA79164B7ECD8486985D3860:1 -AES-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:B7BF3A5DF43989DD97F0FA97EBCE2F4A:AE2D8A571E03AC9C9EB76FAC45AF8E51:4FEBDC6740D20B3AC88F6AD82A4FB08D:1 -AES-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:E1C656305ED1A7A6563805746FE03EDC:30C81C46A35CE411E5FBC1191A0A52EF:71AB47A086E86EEDF39D1C5BBA97C408:1 -AES-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:41635BE625B48AFC1666DD42A09D96E7:F69F2445DF4F9B17AD2B417BE66C3710:0126141D67F37BE8538F5A8BE740E484:1 -# OFB-AES256.Decrypt -AES-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:DC7E84BFDA79164B7ECD8486985D3860:0 -AES-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:B7BF3A5DF43989DD97F0FA97EBCE2F4A:AE2D8A571E03AC9C9EB76FAC45AF8E51:4FEBDC6740D20B3AC88F6AD82A4FB08D:0 -AES-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:E1C656305ED1A7A6563805746FE03EDC:30C81C46A35CE411E5FBC1191A0A52EF:71AB47A086E86EEDF39D1C5BBA97C408:0 -AES-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:41635BE625B48AFC1666DD42A09D96E7:F69F2445DF4F9B17AD2B417BE66C3710:0126141D67F37BE8538F5A8BE740E484:0 - -# AES Counter test vectors from RFC3686 -aes-128-ctr:AE6852F8121067CC4BF7A5765577F39E:00000030000000000000000000000001:53696E676C6520626C6F636B206D7367:E4095D4FB7A7B3792D6175A3261311B8:1 -aes-128-ctr:7E24067817FAE0D743D6CE1F32539163:006CB6DBC0543B59DA48D90B00000001:000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F:5104A106168A72D9790D41EE8EDAD388EB2E1EFC46DA57C8FCE630DF9141BE28:1 -aes-128-ctr:7691BE035E5020A8AC6E618529F9A0DC:00E0017B27777F3F4A1786F000000001:000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20212223:C1CF48A89F2FFDD9CF4652E9EFDB72D74540A42BDE6D7836D59A5CEAAEF3105325B2072F:1 - -aes-192-ctr:16AF5B145FC9F579C175F93E3BFB0EED863D06CCFDB78515:0000004836733C147D6D93CB00000001:53696E676C6520626C6F636B206D7367:4B55384FE259C9C84E7935A003CBE928:1 -aes-192-ctr:7C5CB2401B3DC33C19E7340819E0F69C678C3DB8E6F6A91A:0096B03B020C6EADC2CB500D00000001:000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F:453243FC609B23327EDFAAFA7131CD9F8490701C5AD4A79CFC1FE0FF42F4FB00:1 -aes-192-ctr:02BF391EE8ECB159B959617B0965279BF59B60A786D3E0FE:0007BDFD5CBD60278DCC091200000001:000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20212223:96893FC55E5C722F540B7DD1DDF7E758D288BC95C69165884536C811662F2188ABEE0935:1 - -aes-256-ctr:776BEFF2851DB06F4C8A0542C8696F6C6A81AF1EEC96B4D37FC1D689E6C1C104:00000060DB5672C97AA8F0B200000001:53696E676C6520626C6F636B206D7367:145AD01DBF824EC7560863DC71E3E0C0:1 -aes-256-ctr:F6D66D6BD52D59BB0796365879EFF886C66DD51A5B6A99744B50590C87A23884:00FAAC24C1585EF15A43D87500000001:000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F:F05E231B3894612C49EE000B804EB2A9B8306B508F839D6A5530831D9344AF1C:1 -aes-256-ctr:FF7A617CE69148E4F1726E2F43581DE2AA62D9F805532EDFF1EED687FB54153D:001CC5B751A51D70A1C1114800000001:000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20212223:EB6C52821D0BBBF7CE7594462ACA4FAAB407DF866569FD07F48CC0B583D6071F1EC0E6B8:1 - -# DES ECB tests (from destest) - -DES-ECB:0000000000000000::0000000000000000:8CA64DE9C1B123A7 -DES-ECB:FFFFFFFFFFFFFFFF::FFFFFFFFFFFFFFFF:7359B2163E4EDC58 -DES-ECB:3000000000000000::1000000000000001:958E6E627A05557B -DES-ECB:1111111111111111::1111111111111111:F40379AB9E0EC533 -DES-ECB:0123456789ABCDEF::1111111111111111:17668DFC7292532D -DES-ECB:1111111111111111::0123456789ABCDEF:8A5AE1F81AB8F2DD -DES-ECB:FEDCBA9876543210::0123456789ABCDEF:ED39D950FA74BCC4 - -# DESX-CBC tests (from destest) -DESX-CBC:0123456789abcdeff1e0d3c2b5a49786fedcba9876543210:fedcba9876543210:37363534333231204E6F77206973207468652074696D6520666F722000000000:846B2914851E9A2954732F8AA0A611C115CDC2D7951B1053A63C5E03B21AA3C4 - -# DES EDE3 CBC tests (from destest) -DES-EDE3-CBC:0123456789abcdeff1e0d3c2b5a49786fedcba9876543210:fedcba9876543210:37363534333231204E6F77206973207468652074696D6520666F722000000000:3FE301C962AC01D02213763C1CBD4CDC799657C064ECF5D41C673812CFDE9675 - -# RC4 tests (from rc4test) -RC4:0123456789abcdef0123456789abcdef::0123456789abcdef:75b7878099e0c596 -RC4:0123456789abcdef0123456789abcdef::0000000000000000:7494c2e7104b0879 -RC4:00000000000000000000000000000000::0000000000000000:de188941a3375d3a -RC4:ef012345ef012345ef012345ef012345::0000000000000000000000000000000000000000:d6a141a7ec3c38dfbd615a1162e1c7ba36b67858 -RC4:0123456789abcdef0123456789abcdef::123456789ABCDEF0123456789ABCDEF0123456789ABCDEF012345678:66a0949f8af7d6891f7f832ba833c00c892ebe30143ce28740011ecf -RC4:ef012345ef012345ef012345ef012345::00000000000000000000:d6a141a7ec3c38dfbd61 - - -# Camellia tests from RFC3713 -# For all ECB encrypts and decrypts, the transformed sequence is -# CAMELLIA-bits-ECB:key::plaintext:ciphertext:encdec -CAMELLIA-128-ECB:0123456789abcdeffedcba9876543210::0123456789abcdeffedcba9876543210:67673138549669730857065648eabe43 -CAMELLIA-192-ECB:0123456789abcdeffedcba98765432100011223344556677::0123456789abcdeffedcba9876543210:b4993401b3e996f84ee5cee7d79b09b9 -CAMELLIA-256-ECB:0123456789abcdeffedcba987654321000112233445566778899aabbccddeeff::0123456789abcdeffedcba9876543210:9acc237dff16d76c20ef7c919e3a7509 - -# ECB-CAMELLIA128.Encrypt -CAMELLIA-128-ECB:000102030405060708090A0B0C0D0E0F::00112233445566778899AABBCCDDEEFF:77CF412067AF8270613529149919546F:1 -CAMELLIA-192-ECB:000102030405060708090A0B0C0D0E0F1011121314151617::00112233445566778899AABBCCDDEEFF:B22F3C36B72D31329EEE8ADDC2906C68:1 -CAMELLIA-256-ECB:000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F::00112233445566778899AABBCCDDEEFF:2EDF1F3418D53B88841FC8985FB1ECF2:1 - -# ECB-CAMELLIA128.Encrypt and ECB-CAMELLIA128.Decrypt -CAMELLIA-128-ECB:2B7E151628AED2A6ABF7158809CF4F3C::6BC1BEE22E409F96E93D7E117393172A:432FC5DCD628115B7C388D770B270C96 -CAMELLIA-128-ECB:2B7E151628AED2A6ABF7158809CF4F3C::AE2D8A571E03AC9C9EB76FAC45AF8E51:0BE1F14023782A22E8384C5ABB7FAB2B -CAMELLIA-128-ECB:2B7E151628AED2A6ABF7158809CF4F3C::30C81C46A35CE411E5FBC1191A0A52EF:A0A1ABCD1893AB6FE0FE5B65DF5F8636 -CAMELLIA-128-ECB:2B7E151628AED2A6ABF7158809CF4F3C::F69F2445DF4F9B17AD2B417BE66C3710:E61925E0D5DFAA9BB29F815B3076E51A - -# ECB-CAMELLIA192.Encrypt and ECB-CAMELLIA192.Decrypt -CAMELLIA-192-ECB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B::6BC1BEE22E409F96E93D7E117393172A:CCCC6C4E138B45848514D48D0D3439D3 -CAMELLIA-192-ECB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B::AE2D8A571E03AC9C9EB76FAC45AF8E51:5713C62C14B2EC0F8393B6AFD6F5785A -CAMELLIA-192-ECB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B::30C81C46A35CE411E5FBC1191A0A52EF:B40ED2B60EB54D09D030CF511FEEF366 -CAMELLIA-192-ECB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B::F69F2445DF4F9B17AD2B417BE66C3710:909DBD95799096748CB27357E73E1D26 - -# ECB-CAMELLIA256.Encrypt and ECB-CAMELLIA256.Decrypt -CAMELLIA-256-ECB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4::6BC1BEE22E409F96E93D7E117393172A:BEFD219B112FA00098919CD101C9CCFA -CAMELLIA-256-ECB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4::AE2D8A571E03AC9C9EB76FAC45AF8E51:C91D3A8F1AEA08A9386CF4B66C0169EA -CAMELLIA-256-ECB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4::30C81C46A35CE411E5FBC1191A0A52EF:A623D711DC5F25A51BB8A80D56397D28 -CAMELLIA-256-ECB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4::F69F2445DF4F9B17AD2B417BE66C3710:7960109FB6DC42947FCFE59EA3C5EB6B - -# For all CBC encrypts and decrypts, the transformed sequence is -# CAMELLIA-bits-CBC:key:IV/ciphertext':plaintext:ciphertext:encdec -# CBC-CAMELLIA128.Encrypt and CBC-CAMELLIA128.Decrypt -CAMELLIA-128-CBC:2B7E151628AED2A6ABF7158809CF4F3C:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:1607CF494B36BBF00DAEB0B503C831AB -CAMELLIA-128-CBC:2B7E151628AED2A6ABF7158809CF4F3C:1607CF494B36BBF00DAEB0B503C831AB:AE2D8A571E03AC9C9EB76FAC45AF8E51:A2F2CF671629EF7840C5A5DFB5074887 -CAMELLIA-128-CBC:2B7E151628AED2A6ABF7158809CF4F3C:A2F2CF671629EF7840C5A5DFB5074887:30C81C46A35CE411E5FBC1191A0A52EF:0F06165008CF8B8B5A63586362543E54 -CAMELLIA-128-CBC:2B7E151628AED2A6ABF7158809CF4F3C:36A84CDAFD5F9A85ADA0F0A993D6D577:F69F2445DF4F9B17AD2B417BE66C3710:74C64268CDB8B8FAF5B34E8AF3732980 - -# CBC-CAMELLIA192.Encrypt and CBC-CAMELLIA192.Decrypt -CAMELLIA-192-CBC:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:2A4830AB5AC4A1A2405955FD2195CF93 -CAMELLIA-192-CBC:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:2A4830AB5AC4A1A2405955FD2195CF93:AE2D8A571E03AC9C9EB76FAC45AF8E51:5D5A869BD14CE54264F892A6DD2EC3D5 -CAMELLIA-192-CBC:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:5D5A869BD14CE54264F892A6DD2EC3D5:30C81C46A35CE411E5FBC1191A0A52EF:37D359C3349836D884E310ADDF68C449 -CAMELLIA-192-CBC:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:37D359C3349836D884E310ADDF68C449:F69F2445DF4F9B17AD2B417BE66C3710:01FAAA930B4AB9916E9668E1428C6B08 - -# CBC-CAMELLIA256.Encrypt and CBC-CAMELLIA256.Decrypt -CAMELLIA-256-CBC:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:E6CFA35FC02B134A4D2C0B6737AC3EDA -CAMELLIA-256-CBC:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:E6CFA35FC02B134A4D2C0B6737AC3EDA:AE2D8A571E03AC9C9EB76FAC45AF8E51:36CBEB73BD504B4070B1B7DE2B21EB50 -CAMELLIA-256-CBC:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:36CBEB73BD504B4070B1B7DE2B21EB50:30C81C46A35CE411E5FBC1191A0A52EF:E31A6055297D96CA3330CDF1B1860A83 -CAMELLIA-256-CBC:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:E31A6055297D96CA3330CDF1B1860A83:F69F2445DF4F9B17AD2B417BE66C3710:5D563F6D1CCCF236051C0C5C1C58F28F - -# We don't support CFB{1,8}-CAMELLIAxxx.{En,De}crypt -# For all CFB128 encrypts and decrypts, the transformed sequence is -# CAMELLIA-bits-CFB:key:IV/ciphertext':plaintext:ciphertext:encdec -# CFB128-CAMELLIA128.Encrypt -CAMELLIA-128-CFB:2B7E151628AED2A6ABF7158809CF4F3C:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:14F7646187817EB586599146B82BD719:1 -CAMELLIA-128-CFB:2B7E151628AED2A6ABF7158809CF4F3C:14F7646187817EB586599146B82BD719:AE2D8A571E03AC9C9EB76FAC45AF8E51:A53D28BB82DF741103EA4F921A44880B:1 -CAMELLIA-128-CFB:2B7E151628AED2A6ABF7158809CF4F3C:A53D28BB82DF741103EA4F921A44880B:30C81C46A35CE411E5FBC1191A0A52EF:9C2157A664626D1DEF9EA420FDE69B96:1 -CAMELLIA-128-CFB:2B7E151628AED2A6ABF7158809CF4F3C:9C2157A664626D1DEF9EA420FDE69B96:F69F2445DF4F9B17AD2B417BE66C3710:742A25F0542340C7BAEF24CA8482BB09:1 - -# CFB128-CAMELLIA128.Decrypt -CAMELLIA-128-CFB:2B7E151628AED2A6ABF7158809CF4F3C:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:14F7646187817EB586599146B82BD719:0 -CAMELLIA-128-CFB:2B7E151628AED2A6ABF7158809CF4F3C:14F7646187817EB586599146B82BD719:AE2D8A571E03AC9C9EB76FAC45AF8E51:A53D28BB82DF741103EA4F921A44880B:0 -CAMELLIA-128-CFB:2B7E151628AED2A6ABF7158809CF4F3C:A53D28BB82DF741103EA4F921A44880B:30C81C46A35CE411E5FBC1191A0A52EF:9C2157A664626D1DEF9EA420FDE69B96:0 -CAMELLIA-128-CFB:2B7E151628AED2A6ABF7158809CF4F3C:9C2157A664626D1DEF9EA420FDE69B96:F69F2445DF4F9B17AD2B417BE66C3710:742A25F0542340C7BAEF24CA8482BB09:0 - -# CFB128-CAMELLIA192.Encrypt -CAMELLIA-192-CFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:C832BB9780677DAA82D9B6860DCD565E:1 -CAMELLIA-192-CFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:C832BB9780677DAA82D9B6860DCD565E:AE2D8A571E03AC9C9EB76FAC45AF8E51:86F8491627906D780C7A6D46EA331F98:1 -CAMELLIA-192-CFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:86F8491627906D780C7A6D46EA331F98:30C81C46A35CE411E5FBC1191A0A52EF:69511CCE594CF710CB98BB63D7221F01:1 -CAMELLIA-192-CFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:69511CCE594CF710CB98BB63D7221F01:F69F2445DF4F9B17AD2B417BE66C3710:D5B5378A3ABED55803F25565D8907B84:1 - -# CFB128-CAMELLIA192.Decrypt -CAMELLIA-192-CFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:C832BB9780677DAA82D9B6860DCD565E:0 -CAMELLIA-192-CFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:C832BB9780677DAA82D9B6860DCD565E:AE2D8A571E03AC9C9EB76FAC45AF8E51:86F8491627906D780C7A6D46EA331F98:0 -CAMELLIA-192-CFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:86F8491627906D780C7A6D46EA331F98:30C81C46A35CE411E5FBC1191A0A52EF:69511CCE594CF710CB98BB63D7221F01:0 -CAMELLIA-192-CFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:69511CCE594CF710CB98BB63D7221F01:F69F2445DF4F9B17AD2B417BE66C3710:D5B5378A3ABED55803F25565D8907B84:0 - -# CFB128-CAMELLIA256.Encrypt -CAMELLIA-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:CF6107BB0CEA7D7FB1BD31F5E7B06C93:1 -CAMELLIA-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:CF6107BB0CEA7D7FB1BD31F5E7B06C93:AE2D8A571E03AC9C9EB76FAC45AF8E51:89BEDB4CCDD864EA11BA4CBE849B5E2B:1 -CAMELLIA-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:89BEDB4CCDD864EA11BA4CBE849B5E2B:30C81C46A35CE411E5FBC1191A0A52EF:555FC3F34BDD2D54C62D9E3BF338C1C4:1 -CAMELLIA-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:555FC3F34BDD2D54C62D9E3BF338C1C4:F69F2445DF4F9B17AD2B417BE66C3710:5953ADCE14DB8C7F39F1BD39F359BFFA:1 - -# CFB128-CAMELLIA256.Decrypt -CAMELLIA-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:CF6107BB0CEA7D7FB1BD31F5E7B06C93:0 -CAMELLIA-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:CF6107BB0CEA7D7FB1BD31F5E7B06C93:AE2D8A571E03AC9C9EB76FAC45AF8E51:89BEDB4CCDD864EA11BA4CBE849B5E2B:0 -CAMELLIA-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:89BEDB4CCDD864EA11BA4CBE849B5E2B:30C81C46A35CE411E5FBC1191A0A52EF:555FC3F34BDD2D54C62D9E3BF338C1C4:0 -CAMELLIA-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:555FC3F34BDD2D54C62D9E3BF338C1C4:F69F2445DF4F9B17AD2B417BE66C3710:5953ADCE14DB8C7F39F1BD39F359BFFA:0 - -# For all OFB encrypts and decrypts, the transformed sequence is -# CAMELLIA-bits-OFB:key:IV/output':plaintext:ciphertext:encdec -# OFB-CAMELLIA128.Encrypt -CAMELLIA-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:14F7646187817EB586599146B82BD719:1 -CAMELLIA-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:50FE67CC996D32B6DA0937E99BAFEC60:AE2D8A571E03AC9C9EB76FAC45AF8E51:25623DB569CA51E01482649977E28D84:1 -CAMELLIA-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:D9A4DADA0892239F6B8B3D7680E15674:30C81C46A35CE411E5FBC1191A0A52EF:C776634A60729DC657D12B9FCA801E98:1 -CAMELLIA-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:A78819583F0308E7A6BF36B1386ABF23:F69F2445DF4F9B17AD2B417BE66C3710:D776379BE0E50825E681DA1A4C980E8E:1 - -# OFB-CAMELLIA128.Decrypt -CAMELLIA-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:14F7646187817EB586599146B82BD719:0 -CAMELLIA-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:50FE67CC996D32B6DA0937E99BAFEC60:AE2D8A571E03AC9C9EB76FAC45AF8E51:25623DB569CA51E01482649977E28D84:0 -CAMELLIA-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:D9A4DADA0892239F6B8B3D7680E15674:30C81C46A35CE411E5FBC1191A0A52EF:C776634A60729DC657D12B9FCA801E98:0 -CAMELLIA-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:A78819583F0308E7A6BF36B1386ABF23:F69F2445DF4F9B17AD2B417BE66C3710:D776379BE0E50825E681DA1A4C980E8E:0 - -# OFB-CAMELLIA192.Encrypt -CAMELLIA-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:C832BB9780677DAA82D9B6860DCD565E:1 -CAMELLIA-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:A609B38DF3B1133DDDFF2718BA09565E:AE2D8A571E03AC9C9EB76FAC45AF8E51:8ECEB7D0350D72C7F78562AEBDF99339:1 -CAMELLIA-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:52EF01DA52602FE0975F78AC84BF8A50:30C81C46A35CE411E5FBC1191A0A52EF:BDD62DBBB9700846C53B507F544696F0:1 -CAMELLIA-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:BD5286AC63AABD7EB067AC54B553F71D:F69F2445DF4F9B17AD2B417BE66C3710:E28014E046B802F385C4C2E13EAD4A72:1 - -# OFB-CAMELLIA192.Decrypt -CAMELLIA-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:C832BB9780677DAA82D9B6860DCD565E:0 -CAMELLIA-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:A609B38DF3B1133DDDFF2718BA09565E:AE2D8A571E03AC9C9EB76FAC45AF8E51:8ECEB7D0350D72C7F78562AEBDF99339:0 -CAMELLIA-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:52EF01DA52602FE0975F78AC84BF8A50:30C81C46A35CE411E5FBC1191A0A52EF:BDD62DBBB9700846C53B507F544696F0:0 -CAMELLIA-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:BD5286AC63AABD7EB067AC54B553F71D:F69F2445DF4F9B17AD2B417BE66C3710:E28014E046B802F385C4C2E13EAD4A72:0 - -# OFB-CAMELLIA256.Encrypt -CAMELLIA-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:CF6107BB0CEA7D7FB1BD31F5E7B06C93:1 -CAMELLIA-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:B7BF3A5DF43989DD97F0FA97EBCE2F4A:AE2D8A571E03AC9C9EB76FAC45AF8E51:127AD97E8E3994E4820027D7BA109368:1 -CAMELLIA-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:E1C656305ED1A7A6563805746FE03EDC:30C81C46A35CE411E5FBC1191A0A52EF:6BFF6265A6A6B7A535BC65A80B17214E:1 -CAMELLIA-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:41635BE625B48AFC1666DD42A09D96E7:F69F2445DF4F9B17AD2B417BE66C3710:0A4A0404E26AA78A27CB271E8BF3CF20:1 - -# OFB-CAMELLIA256.Decrypt -CAMELLIA-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:CF6107BB0CEA7D7FB1BD31F5E7B06C93:0 -CAMELLIA-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:B7BF3A5DF43989DD97F0FA97EBCE2F4A:AE2D8A571E03AC9C9EB76FAC45AF8E51:127AD97E8E3994E4820027D7BA109368:0 -CAMELLIA-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:E1C656305ED1A7A6563805746FE03EDC:30C81C46A35CE411E5FBC1191A0A52EF:6BFF6265A6A6B7A535BC65A80B17214E:0 -CAMELLIA-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:41635BE625B48AFC1666DD42A09D96E7:F69F2445DF4F9B17AD2B417BE66C3710:0A4A0404E26AA78A27CB271E8BF3CF20:0 - -# SEED test vectors from RFC4269 -SEED-ECB:00000000000000000000000000000000::000102030405060708090A0B0C0D0E0F:5EBAC6E0054E166819AFF1CC6D346CDB:0 -SEED-ECB:000102030405060708090A0B0C0D0E0F::00000000000000000000000000000000:C11F22F20140505084483597E4370F43:0 -SEED-ECB:4706480851E61BE85D74BFB3FD956185::83A2F8A288641FB9A4E9A5CC2F131C7D:EE54D13EBCAE706D226BC3142CD40D4A:0 -SEED-ECB:28DBC3BC49FFD87DCFA509B11D422BE7::B41E6BE2EBA84A148E2EED84593C5EC7:9B9B7BFCD1813CB95D0B3618F40F5122:0 -SEED-ECB:00000000000000000000000000000000::000102030405060708090A0B0C0D0E0F:5EBAC6E0054E166819AFF1CC6D346CDB:1 -SEED-ECB:000102030405060708090A0B0C0D0E0F::00000000000000000000000000000000:C11F22F20140505084483597E4370F43:1 -SEED-ECB:4706480851E61BE85D74BFB3FD956185::83A2F8A288641FB9A4E9A5CC2F131C7D:EE54D13EBCAE706D226BC3142CD40D4A:1 -SEED-ECB:28DBC3BC49FFD87DCFA509B11D422BE7::B41E6BE2EBA84A148E2EED84593C5EC7:9B9B7BFCD1813CB95D0B3618F40F5122:1
diff --git a/src/third_party/openssl/openssl/test/exptest.c b/src/third_party/openssl/openssl/test/exptest.c deleted file mode 120000 index 50ccf71..0000000 --- a/src/third_party/openssl/openssl/test/exptest.c +++ /dev/null
@@ -1 +0,0 @@ -../crypto/bn/exptest.c \ No newline at end of file
diff --git a/src/third_party/openssl/openssl/test/fips_aesavs.c b/src/third_party/openssl/openssl/test/fips_aesavs.c deleted file mode 120000 index 7d9da0e..0000000 --- a/src/third_party/openssl/openssl/test/fips_aesavs.c +++ /dev/null
@@ -1 +0,0 @@ -../fips/aes/fips_aesavs.c \ No newline at end of file
diff --git a/src/third_party/openssl/openssl/test/fips_desmovs.c b/src/third_party/openssl/openssl/test/fips_desmovs.c deleted file mode 120000 index dd74966..0000000 --- a/src/third_party/openssl/openssl/test/fips_desmovs.c +++ /dev/null
@@ -1 +0,0 @@ -../fips/des/fips_desmovs.c \ No newline at end of file
diff --git a/src/third_party/openssl/openssl/test/fips_dsatest.c b/src/third_party/openssl/openssl/test/fips_dsatest.c deleted file mode 120000 index e43b79b..0000000 --- a/src/third_party/openssl/openssl/test/fips_dsatest.c +++ /dev/null
@@ -1 +0,0 @@ -../fips/dsa/fips_dsatest.c \ No newline at end of file
diff --git a/src/third_party/openssl/openssl/test/fips_dssvs.c b/src/third_party/openssl/openssl/test/fips_dssvs.c deleted file mode 120000 index 93e05e6..0000000 --- a/src/third_party/openssl/openssl/test/fips_dssvs.c +++ /dev/null
@@ -1 +0,0 @@ -../fips/dsa/fips_dssvs.c \ No newline at end of file
diff --git a/src/third_party/openssl/openssl/test/fips_hmactest.c b/src/third_party/openssl/openssl/test/fips_hmactest.c deleted file mode 120000 index b674d16..0000000 --- a/src/third_party/openssl/openssl/test/fips_hmactest.c +++ /dev/null
@@ -1 +0,0 @@ -../fips/hmac/fips_hmactest.c \ No newline at end of file
diff --git a/src/third_party/openssl/openssl/test/fips_randtest.c b/src/third_party/openssl/openssl/test/fips_randtest.c deleted file mode 120000 index 8b8f486..0000000 --- a/src/third_party/openssl/openssl/test/fips_randtest.c +++ /dev/null
@@ -1 +0,0 @@ -../fips/rand/fips_randtest.c \ No newline at end of file
diff --git a/src/third_party/openssl/openssl/test/fips_rngvs.c b/src/third_party/openssl/openssl/test/fips_rngvs.c deleted file mode 120000 index 0d6c9be..0000000 --- a/src/third_party/openssl/openssl/test/fips_rngvs.c +++ /dev/null
@@ -1 +0,0 @@ -../fips/rand/fips_rngvs.c \ No newline at end of file
diff --git a/src/third_party/openssl/openssl/test/fips_rsagtest.c b/src/third_party/openssl/openssl/test/fips_rsagtest.c deleted file mode 120000 index 3ed6b51..0000000 --- a/src/third_party/openssl/openssl/test/fips_rsagtest.c +++ /dev/null
@@ -1 +0,0 @@ -../fips/rsa/fips_rsagtest.c \ No newline at end of file
diff --git a/src/third_party/openssl/openssl/test/fips_rsastest.c b/src/third_party/openssl/openssl/test/fips_rsastest.c deleted file mode 120000 index 2a5f8b0..0000000 --- a/src/third_party/openssl/openssl/test/fips_rsastest.c +++ /dev/null
@@ -1 +0,0 @@ -../fips/rsa/fips_rsastest.c \ No newline at end of file
diff --git a/src/third_party/openssl/openssl/test/fips_rsavtest.c b/src/third_party/openssl/openssl/test/fips_rsavtest.c deleted file mode 120000 index f45aa58..0000000 --- a/src/third_party/openssl/openssl/test/fips_rsavtest.c +++ /dev/null
@@ -1 +0,0 @@ -../fips/rsa/fips_rsavtest.c \ No newline at end of file
diff --git a/src/third_party/openssl/openssl/test/fips_shatest.c b/src/third_party/openssl/openssl/test/fips_shatest.c deleted file mode 120000 index 67c47ca..0000000 --- a/src/third_party/openssl/openssl/test/fips_shatest.c +++ /dev/null
@@ -1 +0,0 @@ -../fips/sha/fips_shatest.c \ No newline at end of file
diff --git a/src/third_party/openssl/openssl/test/fips_test_suite.c b/src/third_party/openssl/openssl/test/fips_test_suite.c deleted file mode 120000 index b538efa..0000000 --- a/src/third_party/openssl/openssl/test/fips_test_suite.c +++ /dev/null
@@ -1 +0,0 @@ -../fips/fips_test_suite.c \ No newline at end of file
diff --git a/src/third_party/openssl/openssl/test/hmactest.c b/src/third_party/openssl/openssl/test/hmactest.c deleted file mode 120000 index 353ee2c..0000000 --- a/src/third_party/openssl/openssl/test/hmactest.c +++ /dev/null
@@ -1 +0,0 @@ -../crypto/hmac/hmactest.c \ No newline at end of file
diff --git a/src/third_party/openssl/openssl/test/ideatest.c b/src/third_party/openssl/openssl/test/ideatest.c deleted file mode 120000 index a9bfb3d..0000000 --- a/src/third_party/openssl/openssl/test/ideatest.c +++ /dev/null
@@ -1 +0,0 @@ -../crypto/idea/ideatest.c \ No newline at end of file
diff --git a/src/third_party/openssl/openssl/test/jpaketest.c b/src/third_party/openssl/openssl/test/jpaketest.c deleted file mode 120000 index 49f44f8..0000000 --- a/src/third_party/openssl/openssl/test/jpaketest.c +++ /dev/null
@@ -1 +0,0 @@ -dummytest.c \ No newline at end of file
diff --git a/src/third_party/openssl/openssl/test/md2test.c b/src/third_party/openssl/openssl/test/md2test.c deleted file mode 120000 index 49f44f8..0000000 --- a/src/third_party/openssl/openssl/test/md2test.c +++ /dev/null
@@ -1 +0,0 @@ -dummytest.c \ No newline at end of file
diff --git a/src/third_party/openssl/openssl/test/md4test.c b/src/third_party/openssl/openssl/test/md4test.c deleted file mode 120000 index 1509be9..0000000 --- a/src/third_party/openssl/openssl/test/md4test.c +++ /dev/null
@@ -1 +0,0 @@ -../crypto/md4/md4test.c \ No newline at end of file
diff --git a/src/third_party/openssl/openssl/test/md5test.c b/src/third_party/openssl/openssl/test/md5test.c deleted file mode 120000 index 20f4aaf..0000000 --- a/src/third_party/openssl/openssl/test/md5test.c +++ /dev/null
@@ -1 +0,0 @@ -../crypto/md5/md5test.c \ No newline at end of file
diff --git a/src/third_party/openssl/openssl/test/mdc2test.c b/src/third_party/openssl/openssl/test/mdc2test.c deleted file mode 120000 index c4ffe48..0000000 --- a/src/third_party/openssl/openssl/test/mdc2test.c +++ /dev/null
@@ -1 +0,0 @@ -../crypto/mdc2/mdc2test.c \ No newline at end of file
diff --git a/src/third_party/openssl/openssl/test/randtest.c b/src/third_party/openssl/openssl/test/randtest.c deleted file mode 120000 index a2b107a..0000000 --- a/src/third_party/openssl/openssl/test/randtest.c +++ /dev/null
@@ -1 +0,0 @@ -../crypto/rand/randtest.c \ No newline at end of file
diff --git a/src/third_party/openssl/openssl/test/rc2test.c b/src/third_party/openssl/openssl/test/rc2test.c deleted file mode 120000 index 5c53ad9..0000000 --- a/src/third_party/openssl/openssl/test/rc2test.c +++ /dev/null
@@ -1 +0,0 @@ -../crypto/rc2/rc2test.c \ No newline at end of file
diff --git a/src/third_party/openssl/openssl/test/rc4test.c b/src/third_party/openssl/openssl/test/rc4test.c deleted file mode 120000 index 061ac37..0000000 --- a/src/third_party/openssl/openssl/test/rc4test.c +++ /dev/null
@@ -1 +0,0 @@ -../crypto/rc4/rc4test.c \ No newline at end of file
diff --git a/src/third_party/openssl/openssl/test/rc5test.c b/src/third_party/openssl/openssl/test/rc5test.c deleted file mode 120000 index 49f44f8..0000000 --- a/src/third_party/openssl/openssl/test/rc5test.c +++ /dev/null
@@ -1 +0,0 @@ -dummytest.c \ No newline at end of file
diff --git a/src/third_party/openssl/openssl/test/rmdtest.c b/src/third_party/openssl/openssl/test/rmdtest.c deleted file mode 120000 index ce66460..0000000 --- a/src/third_party/openssl/openssl/test/rmdtest.c +++ /dev/null
@@ -1 +0,0 @@ -../crypto/ripemd/rmdtest.c \ No newline at end of file
diff --git a/src/third_party/openssl/openssl/test/rsa_test.c b/src/third_party/openssl/openssl/test/rsa_test.c deleted file mode 120000 index aaea20d..0000000 --- a/src/third_party/openssl/openssl/test/rsa_test.c +++ /dev/null
@@ -1 +0,0 @@ -../crypto/rsa/rsa_test.c \ No newline at end of file
diff --git a/src/third_party/openssl/openssl/test/sha1test.c b/src/third_party/openssl/openssl/test/sha1test.c deleted file mode 120000 index 8d66e9e..0000000 --- a/src/third_party/openssl/openssl/test/sha1test.c +++ /dev/null
@@ -1 +0,0 @@ -../crypto/sha/sha1test.c \ No newline at end of file
diff --git a/src/third_party/openssl/openssl/test/sha256t.c b/src/third_party/openssl/openssl/test/sha256t.c deleted file mode 120000 index 952a508..0000000 --- a/src/third_party/openssl/openssl/test/sha256t.c +++ /dev/null
@@ -1 +0,0 @@ -../crypto/sha/sha256t.c \ No newline at end of file
diff --git a/src/third_party/openssl/openssl/test/sha512t.c b/src/third_party/openssl/openssl/test/sha512t.c deleted file mode 120000 index c80d152..0000000 --- a/src/third_party/openssl/openssl/test/sha512t.c +++ /dev/null
@@ -1 +0,0 @@ -../crypto/sha/sha512t.c \ No newline at end of file
diff --git a/src/third_party/openssl/openssl/test/shatest.c b/src/third_party/openssl/openssl/test/shatest.c deleted file mode 120000 index 43cfda7..0000000 --- a/src/third_party/openssl/openssl/test/shatest.c +++ /dev/null
@@ -1 +0,0 @@ -../crypto/sha/shatest.c \ No newline at end of file
diff --git a/src/third_party/openssl/openssl/test/srptest.c b/src/third_party/openssl/openssl/test/srptest.c deleted file mode 120000 index 9534868..0000000 --- a/src/third_party/openssl/openssl/test/srptest.c +++ /dev/null
@@ -1 +0,0 @@ -../crypto/srp/srptest.c \ No newline at end of file
diff --git a/src/third_party/openssl/openssl/test/ssltest.c b/src/third_party/openssl/openssl/test/ssltest.c deleted file mode 120000 index 40191f0..0000000 --- a/src/third_party/openssl/openssl/test/ssltest.c +++ /dev/null
@@ -1 +0,0 @@ -../ssl/ssltest.c \ No newline at end of file
diff --git a/src/third_party/openssl/openssl/test/testcrl.pem b/src/third_party/openssl/openssl/test/testcrl.pem deleted file mode 100644 index 0989788..0000000 --- a/src/third_party/openssl/openssl/test/testcrl.pem +++ /dev/null
@@ -1,16 +0,0 @@ ------BEGIN X509 CRL----- -MIICjTCCAfowDQYJKoZIhvcNAQECBQAwXzELMAkGA1UEBhMCVVMxIDAeBgNVBAoT -F1JTQSBEYXRhIFNlY3VyaXR5LCBJbmMuMS4wLAYDVQQLEyVTZWN1cmUgU2VydmVy -IENlcnRpZmljYXRpb24gQXV0aG9yaXR5Fw05NTA1MDIwMjEyMjZaFw05NTA2MDEw -MDAxNDlaMIIBaDAWAgUCQQAABBcNOTUwMjAxMTcyNDI2WjAWAgUCQQAACRcNOTUw -MjEwMDIxNjM5WjAWAgUCQQAADxcNOTUwMjI0MDAxMjQ5WjAWAgUCQQAADBcNOTUw -MjI1MDA0NjQ0WjAWAgUCQQAAGxcNOTUwMzEzMTg0MDQ5WjAWAgUCQQAAFhcNOTUw -MzE1MTkxNjU0WjAWAgUCQQAAGhcNOTUwMzE1MTk0MDQxWjAWAgUCQQAAHxcNOTUw -MzI0MTk0NDMzWjAWAgUCcgAABRcNOTUwMzI5MjAwNzExWjAWAgUCcgAAERcNOTUw -MzMwMDIzNDI2WjAWAgUCQQAAIBcNOTUwNDA3MDExMzIxWjAWAgUCcgAAHhcNOTUw -NDA4MDAwMjU5WjAWAgUCcgAAQRcNOTUwNDI4MTcxNzI0WjAWAgUCcgAAOBcNOTUw -NDI4MTcyNzIxWjAWAgUCcgAATBcNOTUwNTAyMDIxMjI2WjANBgkqhkiG9w0BAQIF -AAN+AHqOEJXSDejYy0UwxxrH/9+N2z5xu/if0J6qQmK92W0hW158wpJg+ovV3+wQ -wvIEPRL2rocL0tKfAsVq1IawSJzSNgxG0lrcla3MrJBnZ4GaZDu4FutZh72MR3Gt -JaAL3iTJHJD55kK2D/VoyY1djlsPuNh6AEgdVwFAyp0v ------END X509 CRL-----
diff --git a/src/third_party/openssl/openssl/test/testp7.pem b/src/third_party/openssl/openssl/test/testp7.pem deleted file mode 100644 index e5b7866..0000000 --- a/src/third_party/openssl/openssl/test/testp7.pem +++ /dev/null
@@ -1,46 +0,0 @@ ------BEGIN PKCS7----- -MIIIGAYJKoZIhvcNAQcCoIIICTCCCAUCAQExADALBgkqhkiG9w0BBwGgggY8MIIE -cjCCBBygAwIBAgIQeS+OJfWJUZAx6cX0eAiMjzANBgkqhkiG9w0BAQQFADBiMREw -DwYDVQQHEwhJbnRlcm5ldDEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xNDAyBgNV -BAsTK1ZlcmlTaWduIENsYXNzIDEgQ0EgLSBJbmRpdmlkdWFsIFN1YnNjcmliZXIw -HhcNOTYwNzE5MDAwMDAwWhcNOTcwMzMwMjM1OTU5WjCB1TERMA8GA1UEBxMISW50 -ZXJuZXQxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTQwMgYDVQQLEytWZXJpU2ln -biBDbGFzcyAxIENBIC0gSW5kaXZpZHVhbCBTdWJzY3JpYmVyMSgwJgYDVQQLEx9E -aWdpdGFsIElEIENsYXNzIDEgLSBTTUlNRSBUZXN0MUcwRQYDVQQLEz53d3cudmVy -aXNpZ24uY29tL3JlcG9zaXRvcnkvQ1BTLTEuMCBJbmMuIGJ5IFJlZi4sTElBQi5M -VEQoYyk5NjBbMA0GCSqGSIb3DQEBAQUAA0oAMEcCQA7LvHEIAiQ5+4gDYvJGnGAq -UM5GXyG11diEXmIEZTHUZhorooX5sr8IIjSXiPY59YYUFSvAaharFM1xaBN8zNEC -AwEAAaOCAjkwggI1MAkGA1UdEwQCMAAwggImBgNVHQMEggIdMIICGTCCAhUwggIR -BgtghkgBhvhFAQcBATCCAgAWggGrVGhpcyBjZXJ0aWZpY2F0ZSBpbmNvcnBvcmF0 -ZXMgYnkgcmVmZXJlbmNlLCBhbmQgaXRzIHVzZSBpcyBzdHJpY3RseSBzdWJqZWN0 -IHRvLCB0aGUgVmVyaVNpZ24gQ2VydGlmaWNhdGlvbiBQcmFjdGljZSBTdGF0ZW1l -bnQgKENQUyksIGF2YWlsYWJsZSBhdDogaHR0cHM6Ly93d3cudmVyaXNpZ24uY29t -L0NQUy0xLjA7IGJ5IEUtbWFpbCBhdCBDUFMtcmVxdWVzdHNAdmVyaXNpZ24uY29t -OyBvciBieSBtYWlsIGF0IFZlcmlTaWduLCBJbmMuLCAyNTkzIENvYXN0IEF2ZS4s -IE1vdW50YWluIFZpZXcsIENBIDk0MDQzIFVTQSBUZWwuICsxICg0MTUpIDk2MS04 -ODMwIENvcHlyaWdodCAoYykgMTk5NiBWZXJpU2lnbiwgSW5jLiAgQWxsIFJpZ2h0 -cyBSZXNlcnZlZC4gQ0VSVEFJTiBXQVJSQU5USUVTIERJU0NMQUlNRUQgYW5kIExJ -QUJJTElUWSBMSU1JVEVELqAOBgxghkgBhvhFAQcBAQGhDgYMYIZIAYb4RQEHAQEC -MC8wLRYraHR0cHM6Ly93d3cudmVyaXNpZ24uY29tL3JlcG9zaXRvcnkvQ1BTLTEu -AzANBgkqhkiG9w0BAQQFAANBAMCYDuSb/eIlYSxY31nZZTaCZkCSfHjlacMofExr -cF+A2yHoEuT+eCQkqM0pMNHXddUeoQ9RjV+VuMBNmm63DUYwggHCMIIBbKADAgEC -AhB8CYTq1bkRFJBYOd67cp9JMA0GCSqGSIb3DQEBAgUAMD4xCzAJBgNVBAYTAlVT -MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEWMBQGA1UECxMNVEVTVCBSb290IFBD -QTAeFw05NjA3MTcwMDAwMDBaFw05NzA3MTcyMzU5NTlaMGIxETAPBgNVBAcTCElu -dGVybmV0MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE0MDIGA1UECxMrVmVyaVNp -Z24gQ2xhc3MgMSBDQSAtIEluZGl2aWR1YWwgU3Vic2NyaWJlcjBcMA0GCSqGSIb3 -DQEBAQUAA0sAMEgCQQDsVzrNgnDhbAJZrWeLd9g1vMZJA2W67D33TTbga6yMt+ES -TWEywhS6RNP+fzLGg7utinjH4tL60cXa0G27GDsLAgMBAAGjIjAgMAsGA1UdDwQE -AwIBBjARBglghkgBhvhCAQEEBAMCAgQwDQYJKoZIhvcNAQECBQADQQAUp6bRwkaD -2d1MBs/mjUcgTI2fXVmW8tTm/Ud6OzUwpC3vYgybiOOA4f6mOC5dbyUHrLOsrihU -47ZQ0Jo1DUfboYIBrTCBwTBtMA0GCSqGSIb3DQEBAgUAMD4xCzAJBgNVBAYTAlVT -MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEWMBQGA1UECxMNVEVTVCBSb290IFBD -QRcNOTYwNzE3MTc0NDA5WhcNOTgwNzE3MDAwMDAwWjANBgkqhkiG9w0BAQIFAANB -AHitA0/xAukCjHzeh1AMT/l2oC68N+yFb+aJPHBBMxc6gG2MaKjBNwb5hcXUllMl -ExONA3ju10f7owIq3s3wx10wgeYwgZEwDQYJKoZIhvcNAQECBQAwYjERMA8GA1UE -BxMISW50ZXJuZXQxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTQwMgYDVQQLEytW -ZXJpU2lnbiBDbGFzcyAxIENBIC0gSW5kaXZpZHVhbCBTdWJzY3JpYmVyFw05NjA3 -MTcxNzU5MjlaFw05NzA3MTgwMDAwMDBaMA0GCSqGSIb3DQEBAgUAA0EAubVWYTsW -sQmste9f+UgMw8BkjDlM25fwQLrCfmmnLxjewey10kSROypUaJLb+r4oRALc0fG9 -XfZsaiiIgotQHjEA ------END PKCS7-----
diff --git a/src/third_party/openssl/openssl/test/testreq2.pem b/src/third_party/openssl/openssl/test/testreq2.pem deleted file mode 100644 index c3cdcff..0000000 --- a/src/third_party/openssl/openssl/test/testreq2.pem +++ /dev/null
@@ -1,7 +0,0 @@ ------BEGIN CERTIFICATE REQUEST----- -MIHaMIGFAgEAMA4xDDAKBgNVBAMTA2NuNDBcMA0GCSqGSIb3DQEBAQUAA0sAMEgC -QQCQsnkyUGDY2R3mYoeTprFJKgWuJ3f1jUjlIuW5+wfAUoeMt35c4vcFZ2mIBpEG -DtzkNQN1kr2O9ldm9zYnYhyhAgMBAAGgEjAQBgorBgEEAYI3AgEOMQIwADANBgkq -hkiG9w0BAQQFAANBAAb2szZgVIxg3vK6kYLjGSBISyuzcXJ6IvuPW6M+yzi1Qgoi -gQhazHTJp91T8ItZEzUJGZSZl2e5iXlnffWB+/U= ------END CERTIFICATE REQUEST-----
diff --git a/src/third_party/openssl/openssl/test/testrsa.pem b/src/third_party/openssl/openssl/test/testrsa.pem deleted file mode 100644 index aad2106..0000000 --- a/src/third_party/openssl/openssl/test/testrsa.pem +++ /dev/null
@@ -1,9 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIBPAIBAAJBAKrbeqkuRk8VcRmWFmtP+LviMB3+6dizWW3DwaffznyHGAFwUJ/I -Tv0XtbsCyl3QoyKGhrOAy3RvPK5M38iuXT0CAwEAAQJAZ3cnzaHXM/bxGaR5CR1R -rD1qFBAVfoQFiOH9uPJgMaoAuoQEisPHVcZDKcOv4wEg6/TInAIXBnEigtqvRzuy -oQIhAPcgZzUq3yVooAaoov8UbXPxqHlwo6GBMqnv20xzkf6ZAiEAsP4BnIaQTM8S -mvcpHZwQJdmdHHkGKAs37Dfxi67HbkUCIQCeZGliHXFa071Fp06ZeWlR2ADonTZz -rJBhdTe0v5pCeQIhAIZfkiGgGBX4cIuuckzEm43g9WMUjxP/0GlK39vIyihxAiEA -mymehFRT0MvqW5xAKAx7Pgkt8HVKwVhc2LwGKHE0DZM= ------END RSA PRIVATE KEY-----
diff --git a/src/third_party/openssl/openssl/test/testsid.pem b/src/third_party/openssl/openssl/test/testsid.pem deleted file mode 100644 index 7ffd008..0000000 --- a/src/third_party/openssl/openssl/test/testsid.pem +++ /dev/null
@@ -1,12 +0,0 @@ ------BEGIN SSL SESSION PARAMETERS----- -MIIB1gIBAQIBAgQDAQCABBCi11xa5qkOP8xrr02K/NQCBBBkIYQZM0Bt95W0EHNV -bA58oQYCBDIBr7WiBAICASyjggGGMIIBgjCCASwCAQMwDQYJKoZIhvcNAQEEBQAw -ODELMAkGA1UEBhMCQVUxDDAKBgNVBAgTA1FMRDEbMBkGA1UEAxMSU1NMZWF5L3Jz -YSB0ZXN0IENBMB4XDTk1MTAwOTIzMzEzNFoXDTk4MDcwNTIzMzEzNFowYDELMAkG -A1UEBhMCQVUxDDAKBgNVBAgTA1FMRDEZMBcGA1UEChMQTWluY29tIFB0eS4gTHRk -LjELMAkGA1UECxMCQ1MxGzAZBgNVBAMTElNTTGVheSBkZW1vIGNsaWVudDBcMA0G -CSqGSIb3DQEBAQUAA0sAMEgCQQC4pcXEL1lgVA+B5Q3TcuW/O3LZHoA73IYm8oFD -TezgCDhL2RTMn+seKWF36UtJKRIOBU9jZHCVVd0Me5ls6BEjAgMBAAEwDQYJKoZI -hvcNAQEEBQADQQBoIpOcwUY1qlVF7j3ROSGvUsbvByOBFmYWkIBgsCqR+9qo1A7L -CrWF5i8LWt/vLwAHaxWNx2YuBJMFyuK81fTvpA0EC3Rlc3Rjb250ZXh0 ------END SSL SESSION PARAMETERS-----
diff --git a/src/third_party/openssl/openssl/test/testx509.pem b/src/third_party/openssl/openssl/test/testx509.pem deleted file mode 100644 index 8a85d14..0000000 --- a/src/third_party/openssl/openssl/test/testx509.pem +++ /dev/null
@@ -1,10 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIBWzCCAQYCARgwDQYJKoZIhvcNAQEEBQAwODELMAkGA1UEBhMCQVUxDDAKBgNV -BAgTA1FMRDEbMBkGA1UEAxMSU1NMZWF5L3JzYSB0ZXN0IENBMB4XDTk1MDYxOTIz -MzMxMloXDTk1MDcxNzIzMzMxMlowOjELMAkGA1UEBhMCQVUxDDAKBgNVBAgTA1FM -RDEdMBsGA1UEAxMUU1NMZWF5L3JzYSB0ZXN0IGNlcnQwXDANBgkqhkiG9w0BAQEF -AANLADBIAkEAqtt6qS5GTxVxGZYWa0/4u+IwHf7p2LNZbcPBp9/OfIcYAXBQn8hO -/Re1uwLKXdCjIoaGs4DLdG88rkzfyK5dPQIDAQABMAwGCCqGSIb3DQIFBQADQQAE -Wc7EcF8po2/ZO6kNCwK/ICH6DobgLekA5lSLr5EvuioZniZp5lFzAw4+YzPQ7XKJ -zl9HYIMxATFyqSiD9jsx ------END CERTIFICATE-----
diff --git a/src/third_party/openssl/openssl/test/wp_test.c b/src/third_party/openssl/openssl/test/wp_test.c deleted file mode 120000 index 81b2021..0000000 --- a/src/third_party/openssl/openssl/test/wp_test.c +++ /dev/null
@@ -1 +0,0 @@ -../crypto/whrlpool/wp_test.c \ No newline at end of file
diff --git a/src/third_party/openssl/openssl/tools/c_rehash b/src/third_party/openssl/openssl/tools/c_rehash deleted file mode 100644 index 6a20011..0000000 --- a/src/third_party/openssl/openssl/tools/c_rehash +++ /dev/null
@@ -1,180 +0,0 @@ -#!/usr/bin/perl - - -# Perl c_rehash script, scan all files in a directory -# and add symbolic links to their hash values. - -my $openssl; - -my $dir = "/usr/local/ssl"; -my $prefix = "/usr/local/ssl"; - -if(defined $ENV{OPENSSL}) { - $openssl = $ENV{OPENSSL}; -} else { - $openssl = "openssl"; - $ENV{OPENSSL} = $openssl; -} - -my $pwd; -eval "require Cwd"; -if (defined(&Cwd::getcwd)) { - $pwd=Cwd::getcwd(); -} else { - $pwd=`pwd`; chomp($pwd); -} -my $path_delim = ($pwd =~ /^[a-z]\:/i) ? ';' : ':'; # DOS/Win32 or Unix delimiter? - -$ENV{PATH} = "$prefix/bin" . ($ENV{PATH} ? $path_delim . $ENV{PATH} : ""); # prefix our path - -if(! -x $openssl) { - my $found = 0; - foreach (split /$path_delim/, $ENV{PATH}) { - if(-x "$_/$openssl") { - $found = 1; - $openssl = "$_/$openssl"; - last; - } - } - if($found == 0) { - print STDERR "c_rehash: rehashing skipped ('openssl' program not available)\n"; - exit 0; - } -} - -if(@ARGV) { - @dirlist = @ARGV; -} elsif($ENV{SSL_CERT_DIR}) { - @dirlist = split /$path_delim/, $ENV{SSL_CERT_DIR}; -} else { - $dirlist[0] = "$dir/certs"; -} - -if (-d $dirlist[0]) { - chdir $dirlist[0]; - $openssl="$pwd/$openssl" if (!-x $openssl); - chdir $pwd; -} - -foreach (@dirlist) { - if(-d $_ and -w $_) { - hash_dir($_); - } -} - -sub hash_dir { - my %hashlist; - print "Doing $_[0]\n"; - chdir $_[0]; - opendir(DIR, "."); - my @flist = readdir(DIR); - # Delete any existing symbolic links - foreach (grep {/^[\da-f]+\.r{0,1}\d+$/} @flist) { - if(-l $_) { - unlink $_; - } - } - closedir DIR; - FILE: foreach $fname (grep {/\.pem$/} @flist) { - # Check to see if certificates and/or CRLs present. - my ($cert, $crl) = check_file($fname); - if(!$cert && !$crl) { - print STDERR "WARNING: $fname does not contain a certificate or CRL: skipping\n"; - next; - } - link_hash_cert($fname) if($cert); - link_hash_crl($fname) if($crl); - } -} - -sub check_file { - my ($is_cert, $is_crl) = (0,0); - my $fname = $_[0]; - open IN, $fname; - while(<IN>) { - if(/^-----BEGIN (.*)-----/) { - my $hdr = $1; - if($hdr =~ /^(X509 |TRUSTED |)CERTIFICATE$/) { - $is_cert = 1; - last if($is_crl); - } elsif($hdr eq "X509 CRL") { - $is_crl = 1; - last if($is_cert); - } - } - } - close IN; - return ($is_cert, $is_crl); -} - - -# Link a certificate to its subject name hash value, each hash is of -# the form <hash>.<n> where n is an integer. If the hash value already exists -# then we need to up the value of n, unless its a duplicate in which -# case we skip the link. We check for duplicates by comparing the -# certificate fingerprints - -sub link_hash_cert { - my $fname = $_[0]; - $fname =~ s/'/'\\''/g; - my ($hash, $fprint) = `"$openssl" x509 -hash -fingerprint -noout -in "$fname"`; - chomp $hash; - chomp $fprint; - $fprint =~ s/^.*=//; - $fprint =~ tr/://d; - my $suffix = 0; - # Search for an unused hash filename - while(exists $hashlist{"$hash.$suffix"}) { - # Hash matches: if fingerprint matches its a duplicate cert - if($hashlist{"$hash.$suffix"} eq $fprint) { - print STDERR "WARNING: Skipping duplicate certificate $fname\n"; - return; - } - $suffix++; - } - $hash .= ".$suffix"; - print "$fname => $hash\n"; - $symlink_exists=eval {symlink("",""); 1}; - if ($symlink_exists) { - symlink $fname, $hash; - } else { - open IN,"<$fname" or die "can't open $fname for read"; - open OUT,">$hash" or die "can't open $hash for write"; - print OUT <IN>; # does the job for small text files - close OUT; - close IN; - } - $hashlist{$hash} = $fprint; -} - -# Same as above except for a CRL. CRL links are of the form <hash>.r<n> - -sub link_hash_crl { - my $fname = $_[0]; - $fname =~ s/'/'\\''/g; - my ($hash, $fprint) = `"$openssl" crl -hash -fingerprint -noout -in '$fname'`; - chomp $hash; - chomp $fprint; - $fprint =~ s/^.*=//; - $fprint =~ tr/://d; - my $suffix = 0; - # Search for an unused hash filename - while(exists $hashlist{"$hash.r$suffix"}) { - # Hash matches: if fingerprint matches its a duplicate cert - if($hashlist{"$hash.r$suffix"} eq $fprint) { - print STDERR "WARNING: Skipping duplicate CRL $fname\n"; - return; - } - $suffix++; - } - $hash .= ".r$suffix"; - print "$fname => $hash\n"; - $symlink_exists=eval {symlink("",""); 1}; - if ($symlink_exists) { - symlink $fname, $hash; - } else { - system ("cp", $fname, $hash); - } - $hashlist{$hash} = $fprint; -} -