Roll chromium_revision 95336cb92b..191d55580e (557816:557824)
Change log:95336cb92b..191d55580e
Full diff:95336cb92b..191d55580e
Roll chromium third_party 4e16929f46..3a8f2a9e1e Change log:4e16929f46..3a8f2a9e1e
Changed dependencies: * src/tools:c44a3f5eca..f524a53b81
DEPS diff:95336cb92b..191d55580e
/DEPS No update to Clang. TBR=titovartem@google.com, BUG=None CQ_INCLUDE_TRYBOTS=master.internal.tryserver.corp.webrtc:linux_internal Change-Id: Ic9c4a62b050383646e9fcf5cc07a5653c14ac06e Reviewed-on: https://webrtc-review.googlesource.com/76120 Reviewed-by: Patrik Höglund <phoglund@webrtc.org> Reviewed-by: Karl Wiberg <kwiberg@webrtc.org> Reviewed-by: Artem Titov <titovartem@webrtc.org> Commit-Queue: Artem Titov <titovartem@webrtc.org> Cr-Commit-Position: refs/heads/master@{#23205}
This commit is contained in:
6
DEPS
6
DEPS
@ -10,7 +10,7 @@ vars = {
|
||||
'checkout_configuration': 'default',
|
||||
'checkout_instrumented_libraries': 'checkout_linux and checkout_configuration == "default"',
|
||||
'webrtc_git': 'https://webrtc.googlesource.com',
|
||||
'chromium_revision': '95336cb92b1337d4ad5d2a7fcc7409ec25b4a8ee',
|
||||
'chromium_revision': '191d55580e6b2dda1206b51de589e18e7865b863',
|
||||
'boringssl_git': 'https://boringssl.googlesource.com',
|
||||
# Three lines of non-changing comments so that
|
||||
# the commit queue can handle CLs rolling swarming_client
|
||||
@ -43,7 +43,7 @@ vars = {
|
||||
# Three lines of non-changing comments so that
|
||||
# the commit queue can handle CLs rolling Chromium third_party
|
||||
# and whatever else without interference from each other.
|
||||
'chromium_third_party_revision': '4e16929f465a47942875a80da0140bfaa59e99fb',
|
||||
'chromium_third_party_revision': '3a8f2a9e1ee29a040102635292f92d82bab94990',
|
||||
}
|
||||
deps = {
|
||||
# TODO(kjellander): Move this to be Android-only once the libevent dependency
|
||||
@ -175,7 +175,7 @@ deps = {
|
||||
'src/third_party/yasm/source/patched-yasm':
|
||||
Var('chromium_git') + '/chromium/deps/yasm/patched-yasm.git' + '@' + 'b98114e18d8b9b84586b10d24353ab8616d4c5fc',
|
||||
'src/tools':
|
||||
Var('chromium_git') + '/chromium/src/tools' + '@' + 'c44a3f5eca9ea560d23230b73afdb8e31bb16611',
|
||||
Var('chromium_git') + '/chromium/src/tools' + '@' + 'f524a53b8173e5c367d5d6e740d036d8df9347bd',
|
||||
'src/tools/gyp':
|
||||
Var('chromium_git') + '/external/gyp.git' + '@' + 'd61a9397e668fa9843c4aa7da9e79460fe590bfb',
|
||||
'src/tools/swarming_client':
|
||||
|
@ -417,8 +417,8 @@ def _ReportErrorFileAndLineNumber(filename, line_num):
|
||||
|
||||
|
||||
def CheckNoStreamUsageIsAdded(input_api, output_api,
|
||||
error_formatter=_ReportErrorFileAndLineNumber,
|
||||
source_file_filter):
|
||||
source_file_filter,
|
||||
error_formatter=_ReportErrorFileAndLineNumber):
|
||||
"""Make sure that no more dependencies on stringstream are added."""
|
||||
error_msg = ('Usage of <sstream>, <istream> and <ostream> in WebRTC is '
|
||||
'deprecated.\n'
|
||||
@ -813,7 +813,7 @@ def CommonChecks(input_api, output_api):
|
||||
results.extend(CheckNewlineAtTheEndOfProtoFiles(
|
||||
input_api, output_api, source_file_filter=non_third_party_sources))
|
||||
results.extend(CheckNoStreamUsageIsAdded(
|
||||
input_api, output_api, source_file_filter=non_third_party_sources))
|
||||
input_api, output_api, non_third_party_sources))
|
||||
return results
|
||||
|
||||
|
||||
|
@ -86,7 +86,8 @@ class CheckNewlineAtTheEndOfProtoFilesTest(unittest.TestCase):
|
||||
self._GenerateProtoWithoutNewlineAtTheEnd()
|
||||
self.input_api.files = [MockFile(self.proto_file_path)]
|
||||
errors = PRESUBMIT.CheckNewlineAtTheEndOfProtoFiles(self.input_api,
|
||||
self.output_api)
|
||||
self.output_api,
|
||||
lambda x: True)
|
||||
self.assertEqual(1, len(errors))
|
||||
self.assertEqual(
|
||||
'File %s must end with exactly one newline.' % self.proto_file_path,
|
||||
@ -96,7 +97,8 @@ class CheckNewlineAtTheEndOfProtoFilesTest(unittest.TestCase):
|
||||
self._GenerateProtoWithNewlineAtTheEnd()
|
||||
self.input_api.files = [MockFile(self.proto_file_path)]
|
||||
errors = PRESUBMIT.CheckNewlineAtTheEndOfProtoFiles(self.input_api,
|
||||
self.output_api)
|
||||
self.output_api,
|
||||
lambda x: True)
|
||||
self.assertEqual(0, len(errors))
|
||||
|
||||
def _GenerateProtoWithNewlineAtTheEnd(self):
|
||||
|
68
third_party/BUILD.gn
vendored
Normal file
68
third_party/BUILD.gn
vendored
Normal file
@ -0,0 +1,68 @@
|
||||
# Copyright 2014 The Chromium Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
import("//build/config/freetype/freetype.gni")
|
||||
import("//third_party/harfbuzz-ng/harfbuzz.gni")
|
||||
import("//third_party/libjpeg.gni")
|
||||
|
||||
assert(!is_ios, "This is not used on iOS, don't drag it in unintentionally")
|
||||
|
||||
config("system_libjpeg_config") {
|
||||
libs = [ "jpeg" ]
|
||||
defines = [ "USE_SYSTEM_LIBJPEG" ]
|
||||
}
|
||||
|
||||
config("libjpeg_turbo_config") {
|
||||
defines = [ "USE_LIBJPEG_TURBO=1" ]
|
||||
}
|
||||
|
||||
# This is a meta target that forwards to the system's libjpeg,
|
||||
# third_party/libjpeg, or third_party/libjpeg_turbo depending on the build args
|
||||
# declared in this file.
|
||||
group("jpeg") {
|
||||
if (use_system_libjpeg) {
|
||||
public_configs = [ ":system_libjpeg_config" ]
|
||||
} else if (use_libjpeg_turbo) {
|
||||
public_deps = [
|
||||
"//third_party/libjpeg_turbo:libjpeg",
|
||||
]
|
||||
public_configs = [ ":libjpeg_turbo_config" ]
|
||||
} else {
|
||||
public_deps = [
|
||||
"//third_party/libjpeg:libjpeg",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
# This is a meta target that forwards include paths only to the system's
|
||||
# libjpeg, third_party/libjpeg, or third_party/libjpeg_turbo depending on the
|
||||
# build args declared in this file. This is needed, rarely, for targets that
|
||||
# need to reference libjpeg without explicitly building it.
|
||||
group("jpeg_includes") {
|
||||
if (use_system_libjpeg) {
|
||||
public_configs = [ ":system_libjpeg_config" ]
|
||||
} else if (use_libjpeg_turbo) {
|
||||
public_configs = [ "//third_party/libjpeg_turbo:libjpeg_config" ]
|
||||
} else {
|
||||
public_configs = [ "//third_party/libjpeg:libjpeg_config" ]
|
||||
}
|
||||
}
|
||||
|
||||
# FreeType and HarfBuzz libraries are dependent on each other. This component
|
||||
# will depend on the appropriate source sets or export the system packages
|
||||
# for both FreeType and HarfBuzz.
|
||||
component("freetype_harfbuzz") {
|
||||
public_configs = []
|
||||
public_deps = []
|
||||
if (use_system_freetype) {
|
||||
public_configs += [ "//build/linux:freetype_from_pkgconfig" ]
|
||||
} else {
|
||||
public_deps += [ "//third_party/freetype:freetype_source" ]
|
||||
}
|
||||
if (use_system_harfbuzz) {
|
||||
public_configs += [ "//third_party/harfbuzz-ng:harfbuzz_from_pkgconfig" ]
|
||||
} else {
|
||||
public_deps += [ "//third_party/harfbuzz-ng:harfbuzz_source" ]
|
||||
}
|
||||
}
|
11
third_party/DEPS
vendored
Normal file
11
third_party/DEPS
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
# Undo everything in the include_rules section of src/DEPS.
|
||||
include_rules = [
|
||||
'-base',
|
||||
'-build',
|
||||
'-ipc',
|
||||
'-library_loaders',
|
||||
'-testing',
|
||||
'-third_party/icu/source/common/unicode',
|
||||
'-third_party/icu/source/i18n/unicode',
|
||||
'-url',
|
||||
]
|
141
third_party/PRESUBMIT.py
vendored
Normal file
141
third_party/PRESUBMIT.py
vendored
Normal file
@ -0,0 +1,141 @@
|
||||
# Copyright (c) 2011 The Chromium Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
ANDROID_WHITELISTED_LICENSES = [
|
||||
'A(pple )?PSL 2(\.0)?',
|
||||
'Apache( Version)? 2(\.0)?',
|
||||
'(New )?([23]-Clause )?BSD( [23]-Clause)?( with advertising clause)?',
|
||||
'L?GPL ?v?2(\.[01])?( or later)?',
|
||||
'MIT(/X11)?(-like)?',
|
||||
'MPL 1\.1 ?/ ?GPL 2(\.0)? ?/ ?LGPL 2\.1',
|
||||
'MPL 2(\.0)?',
|
||||
'Microsoft Limited Public License',
|
||||
'Microsoft Permissive License',
|
||||
'Public Domain',
|
||||
'Python',
|
||||
'SGI Free Software License B',
|
||||
'University of Illinois\/NCSA Open Source',
|
||||
'X11',
|
||||
]
|
||||
|
||||
def LicenseIsCompatibleWithAndroid(input_api, license):
|
||||
regex = '^(%s)$' % '|'.join(ANDROID_WHITELISTED_LICENSES)
|
||||
tokens = \
|
||||
[x.strip() for x in input_api.re.split(' and |,', license) if len(x) > 0]
|
||||
has_compatible_license = False
|
||||
for token in tokens:
|
||||
if input_api.re.match(regex, token, input_api.re.IGNORECASE):
|
||||
has_compatible_license = True
|
||||
break
|
||||
return has_compatible_license
|
||||
|
||||
def _CheckThirdPartyReadmesUpdated(input_api, output_api):
|
||||
"""
|
||||
Checks to make sure that README.chromium files are properly updated
|
||||
when dependencies in third_party are modified.
|
||||
"""
|
||||
readmes = []
|
||||
files = []
|
||||
errors = []
|
||||
for f in input_api.AffectedFiles():
|
||||
local_path = f.LocalPath()
|
||||
if input_api.os_path.dirname(local_path) == 'third_party':
|
||||
continue
|
||||
if (local_path.startswith('third_party' + input_api.os_path.sep) and
|
||||
not local_path.startswith('third_party' + input_api.os_path.sep +
|
||||
'WebKit' + input_api.os_path.sep) and
|
||||
not local_path.startswith('third_party' + input_api.os_path.sep +
|
||||
'blink' + input_api.os_path.sep) and
|
||||
not local_path.startswith('third_party' + input_api.os_path.sep +
|
||||
'mojo' + input_api.os_path.sep) and
|
||||
not local_path.startswith('third_party' + input_api.os_path.sep +
|
||||
'boringssl' + input_api.os_path.sep)):
|
||||
files.append(f)
|
||||
if local_path.endswith("README.chromium"):
|
||||
readmes.append(f)
|
||||
if files and not readmes:
|
||||
errors.append(output_api.PresubmitPromptWarning(
|
||||
'When updating or adding third party code the appropriate\n'
|
||||
'\'README.chromium\' file should also be updated with the correct\n'
|
||||
'version and package information.', files))
|
||||
if not readmes:
|
||||
return errors
|
||||
|
||||
name_pattern = input_api.re.compile(
|
||||
r'^Name: [a-zA-Z0-9_\-\. \(\)]+\r?$',
|
||||
input_api.re.IGNORECASE | input_api.re.MULTILINE)
|
||||
shortname_pattern = input_api.re.compile(
|
||||
r'^Short Name: [a-zA-Z0-9_\-\.]+\r?$',
|
||||
input_api.re.IGNORECASE | input_api.re.MULTILINE)
|
||||
version_pattern = input_api.re.compile(
|
||||
r'^Version: [a-zA-Z0-9_\-\.:]+\r?$',
|
||||
input_api.re.IGNORECASE | input_api.re.MULTILINE)
|
||||
release_pattern = input_api.re.compile(
|
||||
r'^Security Critical: (yes|no)\r?$',
|
||||
input_api.re.IGNORECASE | input_api.re.MULTILINE)
|
||||
license_pattern = input_api.re.compile(
|
||||
r'^License: (.+)\r?$',
|
||||
input_api.re.IGNORECASE | input_api.re.MULTILINE)
|
||||
license_android_compatible_pattern = input_api.re.compile(
|
||||
r'^License Android Compatible: (yes|no)\r?$',
|
||||
input_api.re.IGNORECASE | input_api.re.MULTILINE)
|
||||
|
||||
for f in readmes:
|
||||
if 'D' in f.Action():
|
||||
_IgnoreIfDeleting(input_api, output_api, f, errors)
|
||||
continue
|
||||
|
||||
contents = input_api.ReadFile(f)
|
||||
if (not shortname_pattern.search(contents)
|
||||
and not name_pattern.search(contents)):
|
||||
errors.append(output_api.PresubmitError(
|
||||
'Third party README files should contain either a \'Short Name\' or\n'
|
||||
'a \'Name\' which is the name under which the package is\n'
|
||||
'distributed. Check README.chromium.template for details.',
|
||||
[f]))
|
||||
if not version_pattern.search(contents):
|
||||
errors.append(output_api.PresubmitError(
|
||||
'Third party README files should contain a \'Version\' field.\n'
|
||||
'If the package is not versioned or the version is not known\n'
|
||||
'list the version as \'unknown\'.\n'
|
||||
'Check README.chromium.template for details.',
|
||||
[f]))
|
||||
if not release_pattern.search(contents):
|
||||
errors.append(output_api.PresubmitError(
|
||||
'Third party README files should contain a \'Security Critical\'\n'
|
||||
'field. This field specifies whether the package is built with\n'
|
||||
'Chromium. Check README.chromium.template for details.',
|
||||
[f]))
|
||||
license_match = license_pattern.search(contents)
|
||||
if not license_match:
|
||||
errors.append(output_api.PresubmitError(
|
||||
'Third party README files should contain a \'License\' field.\n'
|
||||
'This field specifies the license used by the package. Check\n'
|
||||
'README.chromium.template for details.',
|
||||
[f]))
|
||||
elif not LicenseIsCompatibleWithAndroid(input_api, license_match.group(1)) \
|
||||
and not license_android_compatible_pattern.search(contents):
|
||||
errors.append(output_api.PresubmitPromptWarning(
|
||||
'Cannot determine whether specified license is compatible with\n' +
|
||||
'the Android licensing requirements. Please check that the license\n' +
|
||||
'name is spelled according to third_party/PRESUBMIT.py. Please see\n' +
|
||||
'README.chromium.template for details.',
|
||||
[f]))
|
||||
return errors
|
||||
|
||||
|
||||
def _IgnoreIfDeleting(input_api, output_api, affected_file, errors):
|
||||
third_party_dir = input_api.os_path.dirname(affected_file.LocalPath())
|
||||
for f in input_api.AffectedFiles():
|
||||
if f.LocalPath().startswith(third_party_dir):
|
||||
if 'D' not in f.Action():
|
||||
errors.append(output_api.PresubmitError(
|
||||
'Third party README should only be removed when the whole\n'
|
||||
'directory is being removed.\n', [f, affected_file]))
|
||||
|
||||
|
||||
def CheckChangeOnUpload(input_api, output_api):
|
||||
results = []
|
||||
results.extend(_CheckThirdPartyReadmesUpdated(input_api, output_api))
|
||||
return results
|
14
third_party/README.chromium
vendored
Normal file
14
third_party/README.chromium
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
The third_party directory contains sources from other projects.
|
||||
|
||||
Code in third_party must document the license under which the source is being
|
||||
used. If the source itself does not include a license header or file, create
|
||||
an entry in this file that refers to reliable documentation of the project's
|
||||
license terms on the web (and add a note pointing here in the README file in
|
||||
that directory).
|
||||
|
||||
When adding a new directory, or updating a directory to a version which has
|
||||
a different license from before, please add chromium-third-party@google.com
|
||||
as a reviewer on the change.
|
||||
|
||||
<Include table of license information here, once it is available>
|
||||
|
16
third_party/README.chromium.template
vendored
Normal file
16
third_party/README.chromium.template
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
Name: Descriptive name of the package
|
||||
Short Name: Name the package is distributed under (ex. libxml, openssl, etc)
|
||||
URL: The URL where the package lives
|
||||
Version: A searchable version number for the package (if the package does not version or is versioned by date or revision this field should be "0" and the revision, or date should be enumerated in the appropriate field)
|
||||
Date: (OPTIONAL if version is supplied) The date that the package was updated
|
||||
Revision: (OPTIONAL if version is supplied) The current revision of the package
|
||||
License: The license under which the package is distributed. Standard forms are only accepted, eg MIT/X11/BSD/Apache 2.0/GPL/LGPL. See ANDROID_WHITELISTED_LICENSES in PRESUBMIT.py for allowed patterns.
|
||||
License File: (OPTIONAL) File that contains a copy of the package's license. Use the special value NOT_SHIPPED to indicate that the package is not included in the shipped product, so its license does not need to be included in about:credits and no license file is required.
|
||||
Security Critical: Either yes or no depending on whether this package is shipped in releases. For example openssl is critical where cygwin is not.
|
||||
License Android Compatible: (OPTIONAL) Whether the package uses a license compatible with Android. Required only if the package is compatible and the 'License' field uses a non-standard value.
|
||||
|
||||
Description:
|
||||
A short description of what the package is and is used for.
|
||||
|
||||
Local Modifications:
|
||||
Enumerate any changes that have been made locally to the package from the shipping version listed above.
|
10
third_party/accessibility_test_framework/BUILD.gn
vendored
Normal file
10
third_party/accessibility_test_framework/BUILD.gn
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
# Copyright 2016 The Chromium Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
import("//build/config/android/rules.gni")
|
||||
|
||||
java_prebuilt("accessibility_test_framework_java") {
|
||||
testonly = true
|
||||
jar_path = "lib/accessibility-test-framework.jar"
|
||||
}
|
202
third_party/accessibility_test_framework/LICENSE
vendored
Normal file
202
third_party/accessibility_test_framework/LICENSE
vendored
Normal file
@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
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.
|
3
third_party/accessibility_test_framework/OWNERS
vendored
Normal file
3
third_party/accessibility_test_framework/OWNERS
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
jbudorick@chromium.org
|
||||
mikecase@chromium.org
|
||||
yolandyan@chromium.org
|
10
third_party/accessibility_test_framework/README.chromium
vendored
Normal file
10
third_party/accessibility_test_framework/README.chromium
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
Name: Accessibility-Test-Framework-for-Android
|
||||
URL: https://github.com/google/Accessibility-Test-Framework-for-Android
|
||||
Version: 2.1
|
||||
License: Apache 2.0
|
||||
License File: NOT_SHIPPED
|
||||
Security Critical: no
|
||||
Description:
|
||||
Library that contains accessibility-related checks for Android View and
|
||||
AccessibilityNodeInfo objects.
|
||||
Local Modifications: None
|
10
third_party/accessibility_test_framework/cipd.yaml
vendored
Normal file
10
third_party/accessibility_test_framework/cipd.yaml
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
# Copyright 2017 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.
|
||||
|
||||
# To create CIPD package run the following command.
|
||||
# cipd create --pkg-def cipd.yaml -tag version:$(cat version.txt)
|
||||
package: chromium/third_party/accessibility-test-framework
|
||||
description: accessibility-test-framework Java library
|
||||
data:
|
||||
- file: lib/accessibility-test-framework.jar
|
83
third_party/android_platform/BUILD.gn
vendored
Normal file
83
third_party/android_platform/BUILD.gn
vendored
Normal file
@ -0,0 +1,83 @@
|
||||
# Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
import("//testing/test.gni")
|
||||
import("config.gni")
|
||||
|
||||
if (current_toolchain == host_toolchain) {
|
||||
source_set("android_lib_relocation_packer") {
|
||||
deps = [
|
||||
"//third_party/elfutils:libelf",
|
||||
]
|
||||
configs -= [ "//build/config/compiler:chromium_code" ]
|
||||
configs += [ "//build/config/compiler:no_chromium_code" ]
|
||||
sources = [
|
||||
"bionic/tools/relocation_packer/src/debug.cc",
|
||||
"bionic/tools/relocation_packer/src/debug.h",
|
||||
"bionic/tools/relocation_packer/src/delta_encoder.cc",
|
||||
"bionic/tools/relocation_packer/src/delta_encoder.h",
|
||||
"bionic/tools/relocation_packer/src/elf_file.cc",
|
||||
"bionic/tools/relocation_packer/src/elf_file.h",
|
||||
"bionic/tools/relocation_packer/src/elf_traits.h",
|
||||
"bionic/tools/relocation_packer/src/packer.cc",
|
||||
"bionic/tools/relocation_packer/src/packer.h",
|
||||
"bionic/tools/relocation_packer/src/sleb128.cc",
|
||||
"bionic/tools/relocation_packer/src/sleb128.h",
|
||||
]
|
||||
}
|
||||
|
||||
executable("android_relocation_packer") {
|
||||
deps = [
|
||||
":android_lib_relocation_packer",
|
||||
"//build/config:exe_and_shlib_deps",
|
||||
"//third_party/elfutils:libelf",
|
||||
]
|
||||
sources = [
|
||||
"bionic/tools/relocation_packer/src/main.cc",
|
||||
"bionic/tools/relocation_packer/src/nativehelper/ScopedFd.h",
|
||||
]
|
||||
}
|
||||
|
||||
copy("copy_android_relocation_packer_test_data") {
|
||||
sources = [
|
||||
"bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm32.so",
|
||||
"bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm32_packed.so",
|
||||
"bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm64.so",
|
||||
"bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm64_packed.so",
|
||||
"bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_ia32.so",
|
||||
"bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_ia32_packed.so",
|
||||
"bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_mips32.so",
|
||||
"bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_mips32_packed.so",
|
||||
"bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_x64.so",
|
||||
"bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_x64_packed.so",
|
||||
]
|
||||
outputs = [
|
||||
"$root_out_dir/{{source_file_part}}",
|
||||
]
|
||||
}
|
||||
|
||||
test("android_relocation_packer_unittests") {
|
||||
deps = [
|
||||
":android_lib_relocation_packer",
|
||||
":copy_android_relocation_packer_test_data",
|
||||
"//testing/gtest",
|
||||
]
|
||||
sources = [
|
||||
"bionic/tools/relocation_packer/src/debug_unittest.cc",
|
||||
"bionic/tools/relocation_packer/src/delta_encoder_unittest.cc",
|
||||
"bionic/tools/relocation_packer/src/elf_file_unittest.cc",
|
||||
"bionic/tools/relocation_packer/src/packer_unittest.cc",
|
||||
"bionic/tools/relocation_packer/src/run_all_unittests.cc",
|
||||
"bionic/tools/relocation_packer/src/sleb128_unittest.cc",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
if (is_android) {
|
||||
import("//build/config/android/rules.gni")
|
||||
|
||||
wrapper_script("stack_wrapper") {
|
||||
target = "//third_party/android_platform/development/scripts/stack"
|
||||
}
|
||||
}
|
202
third_party/android_platform/LICENSE
vendored
Normal file
202
third_party/android_platform/LICENSE
vendored
Normal file
@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
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.
|
4
third_party/android_platform/OWNERS
vendored
Normal file
4
third_party/android_platform/OWNERS
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
agrieve@chromium.org
|
||||
rmcilroy@chromium.org
|
||||
|
||||
# COMPONENT: Infra>Client>Android
|
64
third_party/android_platform/README.chromium
vendored
Normal file
64
third_party/android_platform/README.chromium
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
Name: Android Platform engineering tools
|
||||
Short Name: android platform development
|
||||
URL: https://android.googlesource.com/platform/development
|
||||
Version: unknown
|
||||
Date: 2014/05/02
|
||||
Revision: 1b10ec4
|
||||
License: Apache 2.0
|
||||
License File: NOT_SHIPPED
|
||||
Security Critical: no
|
||||
|
||||
Description:
|
||||
Android Platform engineering tools, specifically:
|
||||
1. stack symbolization scripts
|
||||
2. A ported copy of the Android relocation packing tool source, along with the
|
||||
files required to build it in the chromium tree.
|
||||
3. IntelliJ formatting settings.
|
||||
Taken from commit: 622d3d4c5b3bee50fd335f3282d9e9d64ae0f5f7
|
||||
|
||||
Local Modifications:
|
||||
Only picked the few components useful to Chromium (as listed above).
|
||||
|
||||
The scripts have been modified to better suit Chromium development. Changes
|
||||
include, but are not limited to, the following:
|
||||
Added memoization of addr2line and objdump.
|
||||
Added option to change the amount of symbolization done.
|
||||
Updated output directories to be set by environment variable or --flags
|
||||
When calling addr2line, check the symbol is a file that looks like it contains
|
||||
symbols.
|
||||
Added support for parsing LOG(FATAL) and DCHECK errors and their
|
||||
stack traces, as emitted by src/base/debug/stack_trace_android.cc
|
||||
Added support for finding symbols when library is loaded directly from the APK.
|
||||
Changed the toolchain to remove references to 4.6 toolchains.
|
||||
Added support for arch=x64 as an alias to arch=x86_64
|
||||
Added debug logging and --verbose parameter.
|
||||
Used fast ELF symbolizer for symbols.py and tombstones
|
||||
Used multiprocessing to pre-process logcat before symbolizing it
|
||||
Added code address adjustment for the debuggerd output from pre-M Android
|
||||
where relocations are packed.
|
||||
Added code to capture java stderr for better handling of native->java crashes.
|
||||
Fixed invalid using decl in logging header debug.h
|
||||
Only attempt to symbolize with ELF libraries.
|
||||
|
||||
Changed the stack script to use llvm symbolizer instead of addr2line,
|
||||
objdump, etc, since llvm symbolizer is more efficient in finding
|
||||
function names, line numbers etc.
|
||||
|
||||
Speedup symbolization by avoiding unnecessary APK manifest extraction loops.
|
||||
|
||||
Android relocation packing tool details:
|
||||
Copy sources from AOSP bionic/tools/relocation_packer
|
||||
Remove scripts that regenerate golden test data (not relevant here)
|
||||
Create a nativehelper/ScopedFd.h to satisfy inclusion from main.cc
|
||||
Create gyp build
|
||||
Create gn build (currently packer only; no unit tests)
|
||||
List of bionic changes currently included:
|
||||
Refresh: https://android-review.googlesource.com/#/c/143878/
|
||||
Refresh: https://android-review.googlesource.com/#/c/147620/
|
||||
https://android-review.googlesource.com/#/c/147745/
|
||||
https://android-review.googlesource.com/#/c/148073/
|
||||
Refresh: https://android-review.googlesource.com/#/c/151901/
|
||||
https://android-review.googlesource.com/#/c/149300/
|
||||
https://android-review.googlesource.com/#/c/148822/
|
||||
https://android-review.googlesource.com/#/c/148492/
|
||||
https://android-review.googlesource.com/#/c/148175/
|
103
third_party/android_platform/bionic/tools/relocation_packer/Android.mk
vendored
Normal file
103
third_party/android_platform/bionic/tools/relocation_packer/Android.mk
vendored
Normal file
@ -0,0 +1,103 @@
|
||||
#
|
||||
# Copyright (C) 2015 The Android Open Source Project
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
common_cppflags := -Wall -Wextra -Wunused -Werror -Wold-style-cast
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_CPP_EXTENSION := .cc
|
||||
|
||||
LOCAL_SRC_FILES := \
|
||||
src/debug.cc \
|
||||
src/delta_encoder.cc \
|
||||
src/elf_file.cc \
|
||||
src/packer.cc \
|
||||
src/sleb128.cc \
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := libelf
|
||||
LOCAL_C_INCLUDES := external/elfutils/src/libelf
|
||||
LOCAL_MODULE := lib_relocation_packer
|
||||
|
||||
LOCAL_CPPFLAGS := $(common_cppflags)
|
||||
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
|
||||
|
||||
include $(BUILD_HOST_STATIC_LIBRARY)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_CPP_EXTENSION := .cc
|
||||
|
||||
LOCAL_SRC_FILES := src/main.cc
|
||||
LOCAL_STATIC_LIBRARIES := lib_relocation_packer libelf
|
||||
|
||||
# Statically linking libc++ to make it work from prebuilts
|
||||
LOCAL_CXX_STL := libc++_static
|
||||
LOCAL_C_INCLUDES := external/elfutils/src/libelf libnativehelper/include
|
||||
|
||||
LOCAL_MODULE := relocation_packer
|
||||
|
||||
LOCAL_CPPFLAGS := $(common_cppflags)
|
||||
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
|
||||
|
||||
include $(BUILD_HOST_EXECUTABLE)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_CPP_EXTENSION := .cc
|
||||
|
||||
LOCAL_SRC_FILES := \
|
||||
src/debug_unittest.cc \
|
||||
src/delta_encoder_unittest.cc \
|
||||
src/elf_file_unittest.cc \
|
||||
src/sleb128_unittest.cc \
|
||||
src/packer_unittest.cc \
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := lib_relocation_packer libelf
|
||||
LOCAL_C_INCLUDES := external/elfutils/src/libelf
|
||||
|
||||
LOCAL_CPPFLAGS := $(common_cppflags)
|
||||
|
||||
LOCAL_MODULE := relocation_packer_unit_tests
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
|
||||
|
||||
include $(BUILD_HOST_NATIVE_TEST)
|
||||
|
||||
# $(1) library name
|
||||
define copy-test-library
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_IS_HOST_MODULE := true
|
||||
LOCAL_MODULE := $(1)
|
||||
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
|
||||
LOCAL_MODULE_PATH := $(HOST_OUT_EXECUTABLES)
|
||||
LOCAL_STRIP_MODULE := false
|
||||
LOCAL_SRC_FILES := test_data/$(1)
|
||||
include $(BUILD_PREBUILT)
|
||||
endef
|
||||
|
||||
$(eval $(call copy-test-library,elf_file_unittest_relocs_arm32.so))
|
||||
$(eval $(call copy-test-library,elf_file_unittest_relocs_arm32_packed.so))
|
||||
$(eval $(call copy-test-library,elf_file_unittest_relocs_arm64.so))
|
||||
$(eval $(call copy-test-library,elf_file_unittest_relocs_arm64_packed.so))
|
||||
$(eval $(call copy-test-library,elf_file_unittest_relocs_ia32.so))
|
||||
$(eval $(call copy-test-library,elf_file_unittest_relocs_ia32_packed.so))
|
||||
$(eval $(call copy-test-library,elf_file_unittest_relocs_x64.so))
|
||||
$(eval $(call copy-test-library,elf_file_unittest_relocs_x64_packed.so))
|
||||
$(eval $(call copy-test-library,elf_file_unittest_relocs_mips32.so))
|
||||
$(eval $(call copy-test-library,elf_file_unittest_relocs_mips32_packed.so))
|
27
third_party/android_platform/bionic/tools/relocation_packer/LICENSE
vendored
Normal file
27
third_party/android_platform/bionic/tools/relocation_packer/LICENSE
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
// Copyright 2014 The Chromium Authors. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
5
third_party/android_platform/bionic/tools/relocation_packer/src/DEPS
vendored
Normal file
5
third_party/android_platform/bionic/tools/relocation_packer/src/DEPS
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
include_rules = [
|
||||
'+gtest',
|
||||
'+nativehelper',
|
||||
'+testing',
|
||||
]
|
55
third_party/android_platform/bionic/tools/relocation_packer/src/debug.cc
vendored
Normal file
55
third_party/android_platform/bionic/tools/relocation_packer/src/debug.cc
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
// Copyright 2014 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
namespace relocation_packer {
|
||||
|
||||
// Construct a new message logger. Prints if level is less than or equal to
|
||||
// the level set with SetVerbose() and predicate is true.
|
||||
Logger::Logger(Severity severity, int level, bool predicate) {
|
||||
severity_ = severity;
|
||||
level_ = level;
|
||||
predicate_ = predicate;
|
||||
}
|
||||
|
||||
// On destruction, flush and print the strings accumulated. Abort if FATAL.
|
||||
Logger::~Logger() {
|
||||
if (predicate_) {
|
||||
if (level_ <= max_level_) {
|
||||
std::ostream* log = severity_ == INFO ? info_stream_ : error_stream_;
|
||||
std::string tag;
|
||||
switch (severity_) {
|
||||
case INFO: tag = "INFO"; break;
|
||||
case WARNING: tag = "WARNING"; break;
|
||||
case ERROR: tag = "ERROR"; break;
|
||||
case FATAL: tag = "FATAL"; break;
|
||||
}
|
||||
stream_.flush();
|
||||
*log << tag << ": " << stream_.str() << std::endl;
|
||||
}
|
||||
if (severity_ == FATAL)
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
// Reset to initial state.
|
||||
void Logger::Reset() {
|
||||
max_level_ = -1;
|
||||
info_stream_ = &std::cout;
|
||||
error_stream_ = &std::cerr;
|
||||
}
|
||||
|
||||
// Verbosity. Not thread-safe.
|
||||
int Logger::max_level_ = -1;
|
||||
|
||||
// Logging streams. Not thread-safe.
|
||||
std::ostream* Logger::info_stream_ = &std::cout;
|
||||
std::ostream* Logger::error_stream_ = &std::cerr;
|
||||
|
||||
} // namespace relocation_packer
|
118
third_party/android_platform/bionic/tools/relocation_packer/src/debug.h
vendored
Normal file
118
third_party/android_platform/bionic/tools/relocation_packer/src/debug.h
vendored
Normal file
@ -0,0 +1,118 @@
|
||||
// Copyright 2014 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Logging and checks. Avoids a dependency on base.
|
||||
//
|
||||
// LOG(tag) prints messages. Tags are INFO, WARNING, ERROR and FATAL.
|
||||
// INFO prints to stdout, the others to stderr. FATAL aborts after printing.
|
||||
//
|
||||
// LOG_IF(tag, predicate) logs if predicate evaluates to true, else silent.
|
||||
//
|
||||
// VLOG(level) logs INFO messages where level is less than or equal to the
|
||||
// verbosity level set with SetVerbose().
|
||||
//
|
||||
// VLOG_IF(level, predicate) logs INFO if predicate evaluates to true,
|
||||
// else silent.
|
||||
//
|
||||
// CHECK(predicate) logs a FATAL error if predicate is false.
|
||||
// NOTREACHED() always aborts.
|
||||
// Log streams can be changed with SetStreams(). Logging is not thread-safe.
|
||||
//
|
||||
|
||||
#ifndef TOOLS_RELOCATION_PACKER_SRC_DEBUG_H_
|
||||
#define TOOLS_RELOCATION_PACKER_SRC_DEBUG_H_
|
||||
|
||||
#include <limits.h>
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
|
||||
namespace relocation_packer {
|
||||
|
||||
class Logger {
|
||||
public:
|
||||
enum Severity {INFO = 0, WARNING, ERROR, FATAL};
|
||||
|
||||
// Construct a new message logger. Prints if level is less than or
|
||||
// equal to the level set with SetVerbose() and predicate is true.
|
||||
// |severity| is an enumerated severity.
|
||||
// |level| is the verbosity level.
|
||||
// |predicate| controls if the logger prints or is silent.
|
||||
Logger(Severity severity, int level, bool predicate);
|
||||
|
||||
// On destruction, flush and print the strings accumulated in stream_.
|
||||
~Logger();
|
||||
|
||||
// Return the stream for this logger.
|
||||
std::ostream& GetStream() { return stream_; }
|
||||
|
||||
// Set verbosity level. Messages with a level less than or equal to
|
||||
// this level are printed, others are discarded. Static, not thread-safe.
|
||||
static void SetVerbose(int level) { max_level_ = level; }
|
||||
|
||||
// Set info and error logging streams. Static, not thread-safe.
|
||||
static void SetStreams(std::ostream* info_stream,
|
||||
std::ostream* error_stream) {
|
||||
info_stream_ = info_stream;
|
||||
error_stream_ = error_stream;
|
||||
}
|
||||
|
||||
// Reset to initial state.
|
||||
static void Reset();
|
||||
|
||||
private:
|
||||
// Message severity, verbosity level, and predicate.
|
||||
Severity severity_;
|
||||
int level_;
|
||||
bool predicate_;
|
||||
|
||||
// String stream, accumulates message text.
|
||||
std::ostringstream stream_;
|
||||
|
||||
// Verbosity for INFO messages. Not thread-safe.
|
||||
static int max_level_;
|
||||
|
||||
// Logging streams. Not thread-safe.
|
||||
static std::ostream* info_stream_;
|
||||
static std::ostream* error_stream_;
|
||||
};
|
||||
|
||||
} // namespace relocation_packer
|
||||
|
||||
// Make logging severities visible globally.
|
||||
typedef relocation_packer::Logger::Severity LogSeverity;
|
||||
|
||||
// LOG(severity) prints a message with the given severity, and aborts if
|
||||
// severity is FATAL. LOG_IF(severity, predicate) does the same but only if
|
||||
// predicate is true. INT_MIN is guaranteed to be less than or equal to
|
||||
// any verbosity level.
|
||||
#define LOG(severity) \
|
||||
(relocation_packer::Logger(relocation_packer::Logger::severity, INT_MIN, \
|
||||
true) \
|
||||
.GetStream())
|
||||
#define LOG_IF(severity, predicate) \
|
||||
(relocation_packer::Logger(relocation_packer::Logger::severity, INT_MIN, \
|
||||
(predicate)) \
|
||||
.GetStream())
|
||||
|
||||
// VLOG(level) prints its message as INFO if level is less than or equal to
|
||||
// the current verbosity level.
|
||||
#define VLOG(level) \
|
||||
(relocation_packer::Logger(relocation_packer::Logger::INFO, (level), true) \
|
||||
.GetStream())
|
||||
#define VLOG_IF(level, predicate) \
|
||||
(relocation_packer::Logger(relocation_packer::Logger::INFO, (level), \
|
||||
(predicate)) \
|
||||
.GetStream())
|
||||
|
||||
// CHECK(predicate) fails with a FATAL log message if predicate is false.
|
||||
#define CHECK(predicate) (LOG_IF(FATAL, !(predicate)) \
|
||||
<< __FILE__ << ":" << __LINE__ << ": " \
|
||||
<< __FUNCTION__ << ": CHECK '" #predicate "' failed")
|
||||
|
||||
// NOTREACHED() always fails with a FATAL log message.
|
||||
#define NOTREACHED(_) (LOG(FATAL) \
|
||||
<< __FILE__ << ":" << __LINE__ << ": " \
|
||||
<< __FUNCTION__ << ": NOTREACHED() hit")
|
||||
|
||||
#endif // TOOLS_RELOCATION_PACKER_SRC_DEBUG_H_
|
122
third_party/android_platform/bionic/tools/relocation_packer/src/debug_unittest.cc
vendored
Normal file
122
third_party/android_platform/bionic/tools/relocation_packer/src/debug_unittest.cc
vendored
Normal file
@ -0,0 +1,122 @@
|
||||
// Copyright 2014 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#include <sstream>
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace relocation_packer {
|
||||
|
||||
TEST(Debug, Log) {
|
||||
Logger::Reset();
|
||||
std::ostringstream info;
|
||||
std::ostringstream error;
|
||||
Logger::SetStreams(&info, &error);
|
||||
|
||||
LOG(INFO) << "INFO log message";
|
||||
LOG(WARNING) << "WARNING log message";
|
||||
LOG(ERROR) << "ERROR log message";
|
||||
|
||||
EXPECT_EQ("INFO: INFO log message\n", info.str());
|
||||
EXPECT_EQ("WARNING: WARNING log message\n"
|
||||
"ERROR: ERROR log message\n", error.str());
|
||||
Logger::Reset();
|
||||
}
|
||||
|
||||
TEST(Debug, LogIf) {
|
||||
Logger::Reset();
|
||||
std::ostringstream info;
|
||||
std::ostringstream error;
|
||||
Logger::SetStreams(&info, &error);
|
||||
|
||||
LOG_IF(INFO, true) << "INFO log message";
|
||||
LOG_IF(INFO, false) << "INFO log message, SHOULD NOT PRINT";
|
||||
LOG_IF(WARNING, true) << "WARNING log message";
|
||||
LOG_IF(WARNING, false) << "WARNING log message, SHOULD NOT PRINT";
|
||||
LOG_IF(ERROR, true) << "ERROR log message";
|
||||
LOG_IF(ERROR, false) << "ERROR log message, SHOULD NOT PRINT";
|
||||
LOG_IF(FATAL, false) << "FATAL log message, SHOULD NOT PRINT";
|
||||
|
||||
EXPECT_EQ("INFO: INFO log message\n", info.str());
|
||||
EXPECT_EQ("WARNING: WARNING log message\n"
|
||||
"ERROR: ERROR log message\n", error.str());
|
||||
Logger::Reset();
|
||||
}
|
||||
|
||||
TEST(Debug, Vlog) {
|
||||
Logger::Reset();
|
||||
std::ostringstream info;
|
||||
std::ostringstream error;
|
||||
Logger::SetStreams(&info, &error);
|
||||
|
||||
VLOG(0) << "VLOG 0 INFO log message, SHOULD NOT PRINT";
|
||||
VLOG(1) << "VLOG 1 INFO log message, SHOULD NOT PRINT";
|
||||
VLOG(2) << "VLOG 2 INFO log message, SHOULD NOT PRINT";
|
||||
|
||||
EXPECT_EQ("", info.str());
|
||||
EXPECT_EQ("", error.str());
|
||||
|
||||
Logger::SetVerbose(1);
|
||||
|
||||
VLOG(0) << "VLOG 0 INFO log message";
|
||||
VLOG(1) << "VLOG 1 INFO log message";
|
||||
VLOG(2) << "VLOG 2 INFO log message, SHOULD NOT PRINT";
|
||||
|
||||
EXPECT_EQ("INFO: VLOG 0 INFO log message\n"
|
||||
"INFO: VLOG 1 INFO log message\n", info.str());
|
||||
EXPECT_EQ("", error.str());
|
||||
Logger::Reset();
|
||||
}
|
||||
|
||||
TEST(Debug, VlogIf) {
|
||||
Logger::Reset();
|
||||
std::ostringstream info;
|
||||
std::ostringstream error;
|
||||
Logger::SetStreams(&info, &error);
|
||||
|
||||
VLOG_IF(0, true) << "VLOG 0 INFO log message, SHOULD NOT PRINT";
|
||||
VLOG_IF(1, true) << "VLOG 1 INFO log message, SHOULD NOT PRINT";
|
||||
VLOG_IF(2, true) << "VLOG 2 INFO log message, SHOULD NOT PRINT";
|
||||
|
||||
EXPECT_EQ("", info.str());
|
||||
EXPECT_EQ("", error.str());
|
||||
|
||||
Logger::SetVerbose(1);
|
||||
|
||||
VLOG_IF(0, true) << "VLOG 0 INFO log message";
|
||||
VLOG_IF(0, false) << "VLOG 0 INFO log message, SHOULD NOT PRINT";
|
||||
VLOG_IF(1, true) << "VLOG 1 INFO log message";
|
||||
VLOG_IF(1, false) << "VLOG 1 INFO log message, SHOULD NOT PRINT";
|
||||
VLOG_IF(2, true) << "VLOG 2 INFO log message, SHOULD NOT PRINT";
|
||||
VLOG_IF(2, false) << "VLOG 2 INFO log message, SHOULD NOT PRINT";
|
||||
|
||||
EXPECT_EQ("INFO: VLOG 0 INFO log message\n"
|
||||
"INFO: VLOG 1 INFO log message\n", info.str());
|
||||
EXPECT_EQ("", error.str());
|
||||
Logger::Reset();
|
||||
}
|
||||
|
||||
TEST(DebugDeathTest, Fatal) {
|
||||
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
||||
Logger::Reset();
|
||||
EXPECT_DEATH(LOG(FATAL) << "FATAL log message", "FATAL: FATAL log message");
|
||||
EXPECT_DEATH(
|
||||
LOG_IF(FATAL, true) << "FATAL log message", "FATAL: FATAL log message");
|
||||
}
|
||||
|
||||
TEST(DebugDeathTest, Check) {
|
||||
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
||||
Logger::Reset();
|
||||
CHECK(0 == 0);
|
||||
EXPECT_DEATH(CHECK(0 == 1), "FATAL: .*:.*: .*: CHECK '0 == 1' failed");
|
||||
}
|
||||
|
||||
TEST(DebugDeathTest, NotReached) {
|
||||
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
||||
Logger::Reset();
|
||||
EXPECT_DEATH(NOTREACHED(), "FATAL: .*:.*: .*: NOTREACHED\\(\\) hit");
|
||||
}
|
||||
|
||||
} // namespace relocation_packer
|
307
third_party/android_platform/bionic/tools/relocation_packer/src/delta_encoder.cc
vendored
Normal file
307
third_party/android_platform/bionic/tools/relocation_packer/src/delta_encoder.cc
vendored
Normal file
@ -0,0 +1,307 @@
|
||||
// Copyright 2014 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "delta_encoder.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
static constexpr uint32_t RELOCATION_GROUPED_BY_INFO_FLAG = 1;
|
||||
static constexpr uint32_t RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG = 2;
|
||||
static constexpr uint32_t RELOCATION_GROUPED_BY_ADDEND_FLAG = 4;
|
||||
static constexpr uint32_t RELOCATION_GROUP_HAS_ADDEND_FLAG = 8;
|
||||
|
||||
static bool is_relocation_grouped_by_info(uint64_t flags) {
|
||||
return (flags & RELOCATION_GROUPED_BY_INFO_FLAG) != 0;
|
||||
}
|
||||
|
||||
static bool is_relocation_grouped_by_offset_delta(uint64_t flags) {
|
||||
return (flags & RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG) != 0;
|
||||
}
|
||||
|
||||
static bool is_relocation_grouped_by_addend(uint64_t flags) {
|
||||
return (flags & RELOCATION_GROUPED_BY_ADDEND_FLAG) != 0;
|
||||
}
|
||||
|
||||
static bool is_relocation_group_has_addend(uint64_t flags) {
|
||||
return (flags & RELOCATION_GROUP_HAS_ADDEND_FLAG) != 0;
|
||||
}
|
||||
|
||||
namespace relocation_packer {
|
||||
|
||||
// Encode relocations into a delta encoded (packed) representation.
|
||||
template <typename ELF>
|
||||
void RelocationDeltaCodec<ELF>::Encode(const std::vector<ElfRela>& relocations,
|
||||
std::vector<ElfAddr>* packed) {
|
||||
if (relocations.size() == 0)
|
||||
return;
|
||||
|
||||
// Start with the relocation count, then append groups
|
||||
// TODO(dimitry): we might want to move it to DT_ANDROID_RELCOUNT section
|
||||
packed->push_back(static_cast<ElfAddr>(relocations.size()));
|
||||
|
||||
// lets write starting offset (offset of the first reloc - first delta)
|
||||
ElfAddr start_offset = relocations.size() > 1 ?
|
||||
relocations[0].r_offset - (relocations[1].r_offset - relocations[0].r_offset) :
|
||||
relocations[0].r_offset;
|
||||
|
||||
packed->push_back(start_offset);
|
||||
|
||||
// this one is used to calculate delta
|
||||
ElfAddr previous_addend = 0;
|
||||
ElfAddr previous_offset = start_offset;
|
||||
|
||||
for (size_t group_start = 0; group_start < relocations.size(); ) {
|
||||
ElfAddr group_flags = 0;
|
||||
ElfAddr group_offset_delta = 0;
|
||||
ElfAddr group_addend = 0;
|
||||
ElfAddr group_info = 0;
|
||||
|
||||
ElfAddr group_size = 0;
|
||||
|
||||
DetectGroup(relocations, group_start, previous_offset, &group_size, &group_flags,
|
||||
&group_offset_delta, &group_info, &group_addend);
|
||||
|
||||
// write the group header
|
||||
packed->push_back(group_size);
|
||||
packed->push_back(group_flags);
|
||||
|
||||
if (is_relocation_grouped_by_offset_delta(group_flags)) {
|
||||
packed->push_back(group_offset_delta);
|
||||
}
|
||||
|
||||
if (is_relocation_grouped_by_info(group_flags)) {
|
||||
packed->push_back(group_info);
|
||||
}
|
||||
|
||||
if (is_relocation_group_has_addend(group_flags) &&
|
||||
is_relocation_grouped_by_addend(group_flags)) {
|
||||
packed->push_back(group_addend - previous_addend);
|
||||
previous_addend = group_addend;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < static_cast<size_t>(group_size); ++i) {
|
||||
CHECK((group_start + i) < relocations.size());
|
||||
const ElfRela* relocation = &relocations[group_start + i];
|
||||
|
||||
if (!is_relocation_grouped_by_offset_delta(group_flags)) {
|
||||
packed->push_back(relocation->r_offset - previous_offset);
|
||||
}
|
||||
previous_offset = relocation->r_offset;
|
||||
|
||||
if (!is_relocation_grouped_by_info(group_flags)) {
|
||||
packed->push_back(relocation->r_info);
|
||||
}
|
||||
|
||||
if (is_relocation_group_has_addend(group_flags) &&
|
||||
!is_relocation_grouped_by_addend(group_flags)) {
|
||||
packed->push_back(relocation->r_addend - previous_addend);
|
||||
previous_addend = relocation->r_addend;
|
||||
}
|
||||
}
|
||||
|
||||
// If the relocation group does not have an addend - reset it to 0
|
||||
// to simplify addend computation for the group following this one.
|
||||
if (!is_relocation_group_has_addend(group_flags)) {
|
||||
previous_addend = 0;
|
||||
}
|
||||
|
||||
group_start += group_size;
|
||||
}
|
||||
}
|
||||
|
||||
// Decode relocations from a delta encoded (packed) representation.
|
||||
template <typename ELF>
|
||||
void RelocationDeltaCodec<ELF>::Decode(const std::vector<ElfAddr>& packed,
|
||||
std::vector<ElfRela>* relocations) {
|
||||
if (packed.size() < 5) {
|
||||
return;
|
||||
}
|
||||
|
||||
size_t ndx = 0;
|
||||
ElfAddr current_count = 0;
|
||||
ElfAddr total_count = packed[ndx++];
|
||||
|
||||
ElfAddr offset = packed[ndx++];
|
||||
ElfAddr info = 0;
|
||||
ElfAddr addend = 0;
|
||||
|
||||
while(current_count < total_count) {
|
||||
// read group
|
||||
ElfAddr group_size = packed[ndx++];
|
||||
ElfAddr group_flags = packed[ndx++];
|
||||
ElfAddr group_offset_delta = 0;
|
||||
|
||||
if (is_relocation_grouped_by_offset_delta(group_flags)) {
|
||||
group_offset_delta = packed[ndx++];
|
||||
}
|
||||
|
||||
if (is_relocation_grouped_by_info(group_flags)) {
|
||||
info = packed[ndx++];
|
||||
}
|
||||
|
||||
if (is_relocation_group_has_addend(group_flags) &&
|
||||
is_relocation_grouped_by_addend(group_flags)) {
|
||||
addend += packed[ndx++];
|
||||
}
|
||||
|
||||
// now read not grouped info
|
||||
for (ElfAddr i = 0; i<group_size; ++i) {
|
||||
if (is_relocation_grouped_by_offset_delta(group_flags)) {
|
||||
offset += group_offset_delta;
|
||||
} else {
|
||||
offset += packed[ndx++];
|
||||
}
|
||||
|
||||
if (!is_relocation_grouped_by_info(group_flags)) {
|
||||
info = packed[ndx++];
|
||||
}
|
||||
|
||||
if (is_relocation_group_has_addend(group_flags) &&
|
||||
!is_relocation_grouped_by_addend(group_flags)) {
|
||||
addend += packed[ndx++];
|
||||
}
|
||||
|
||||
ElfRela reloc;
|
||||
reloc.r_offset = offset;
|
||||
reloc.r_info = info;
|
||||
reloc.r_addend = is_relocation_group_has_addend(group_flags) ? addend : 0;
|
||||
relocations->push_back(reloc);
|
||||
}
|
||||
|
||||
if (!is_relocation_group_has_addend(group_flags)) {
|
||||
addend = 0;
|
||||
}
|
||||
|
||||
current_count += group_size;
|
||||
}
|
||||
}
|
||||
|
||||
// This function detects a way to group reloc_one and reloc_two, sets up group_flags
|
||||
// and initializes values for corresponding group_ fields. For example if relocations
|
||||
// can be grouped by r_info the function will set group_info variable.
|
||||
template <typename ELF>
|
||||
void RelocationDeltaCodec<ELF>::DetectGroupFields(const ElfRela& reloc_one,
|
||||
const ElfRela& reloc_two,
|
||||
ElfAddr current_offset_delta,
|
||||
ElfAddr* group_flags,
|
||||
ElfAddr* group_offset_delta,
|
||||
ElfAddr* group_info,
|
||||
ElfAddr* group_addend) {
|
||||
*group_flags = 0;
|
||||
|
||||
const ElfAddr offset_delta = static_cast<ElfAddr>(reloc_two.r_offset) -
|
||||
static_cast<ElfAddr>(reloc_one.r_offset);
|
||||
|
||||
if (offset_delta == current_offset_delta) {
|
||||
*group_flags |= RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG;
|
||||
if (group_offset_delta != nullptr) {
|
||||
*group_offset_delta = current_offset_delta;
|
||||
}
|
||||
}
|
||||
|
||||
if (reloc_one.r_info == reloc_two.r_info) {
|
||||
*group_flags |= RELOCATION_GROUPED_BY_INFO_FLAG;
|
||||
if (group_info != nullptr) {
|
||||
*group_info = reloc_one.r_info;
|
||||
}
|
||||
}
|
||||
|
||||
if (reloc_one.r_addend != 0 || reloc_two.r_addend != 0) {
|
||||
*group_flags |= RELOCATION_GROUP_HAS_ADDEND_FLAG;
|
||||
if (reloc_one.r_addend == reloc_two.r_addend) {
|
||||
*group_flags |= RELOCATION_GROUPED_BY_ADDEND_FLAG;
|
||||
if (group_addend != nullptr) {
|
||||
*group_addend = reloc_one.r_addend;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This function is used to detect if there is better group available
|
||||
// during RelocationDeltaCodec<ELF>::DetectGroup processing.
|
||||
// Current implementation prefers having groups without addend (== zero addend)
|
||||
// to any other groups field with the ratio 3:1. This is because addend tends
|
||||
// to be more unevenly distributed than other fields.
|
||||
static uint32_t group_weight(uint64_t flags) {
|
||||
uint32_t weight = 0;
|
||||
if (!is_relocation_group_has_addend(flags)) {
|
||||
weight += 3;
|
||||
} else if (is_relocation_grouped_by_addend(flags)) {
|
||||
weight += 1;
|
||||
}
|
||||
|
||||
if (is_relocation_grouped_by_offset_delta(flags)) {
|
||||
weight += 1;
|
||||
}
|
||||
|
||||
if (is_relocation_grouped_by_info(flags)) {
|
||||
weight += 1;
|
||||
}
|
||||
|
||||
return weight;
|
||||
}
|
||||
|
||||
template <typename ELF>
|
||||
void RelocationDeltaCodec<ELF>::DetectGroup(const std::vector<ElfRela>& relocations,
|
||||
size_t group_starts_with, ElfAddr previous_offset,
|
||||
ElfAddr* group_size, ElfAddr* group_flags,
|
||||
ElfAddr* group_offset_delta, ElfAddr* group_info,
|
||||
ElfAddr* group_addend) {
|
||||
CHECK(group_starts_with < relocations.size());
|
||||
CHECK(group_flags != nullptr);
|
||||
|
||||
const ElfRela& reloc_one = relocations[group_starts_with++];
|
||||
if (group_starts_with == relocations.size()) {
|
||||
*group_flags = reloc_one.r_addend == 0 ? 0 : RELOCATION_GROUP_HAS_ADDEND_FLAG;
|
||||
*group_size = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
const ElfAddr offset_delta = reloc_one.r_offset - previous_offset;
|
||||
|
||||
// detect group_flags
|
||||
DetectGroupFields(reloc_one, relocations[group_starts_with], offset_delta, group_flags,
|
||||
group_offset_delta, group_info, group_addend);
|
||||
|
||||
if (group_starts_with + 1 == relocations.size()) {
|
||||
*group_size = 2;
|
||||
return;
|
||||
}
|
||||
|
||||
ElfAddr cnt = 1;
|
||||
for (size_t i = group_starts_with; i < relocations.size() - 1; ++i) {
|
||||
ElfAddr candidate_flags;
|
||||
// check if next group (reloc_current; reloc_next) has better grouped_by flags
|
||||
DetectGroupFields(relocations[i], relocations[i+1], offset_delta, &candidate_flags,
|
||||
nullptr, nullptr, nullptr);
|
||||
|
||||
if (group_weight(*group_flags) < group_weight(candidate_flags)) {
|
||||
break;
|
||||
}
|
||||
cnt++;
|
||||
|
||||
if (candidate_flags != *group_flags) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (i + 1 == relocations.size() - 1) { // last one
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
// if as a result of checking candidates we ended up with cnt == 1
|
||||
// reset flags to the default state
|
||||
if (cnt == 1) {
|
||||
*group_flags = reloc_one.r_addend == 0 ? 0 : RELOCATION_GROUP_HAS_ADDEND_FLAG;
|
||||
}
|
||||
|
||||
*group_size = cnt;
|
||||
}
|
||||
|
||||
template class RelocationDeltaCodec<ELF32_traits>;
|
||||
template class RelocationDeltaCodec<ELF64_traits>;
|
||||
|
||||
} // namespace relocation_packer
|
132
third_party/android_platform/bionic/tools/relocation_packer/src/delta_encoder.h
vendored
Normal file
132
third_party/android_platform/bionic/tools/relocation_packer/src/delta_encoder.h
vendored
Normal file
@ -0,0 +1,132 @@
|
||||
// Copyright 2014 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Delta encode and decode REL/RELA section of elf file.
|
||||
//
|
||||
// The encoded data format is sequence of elements of ElfAddr type (unsigned long):
|
||||
//
|
||||
// [00] relocation_count - the total count of relocations
|
||||
// [01] initial r_offset - this is initial r_offset for the
|
||||
// relocation table.
|
||||
// followed by group structures:
|
||||
// [02] group
|
||||
// ...
|
||||
// [nn] group
|
||||
|
||||
// the generalized format of the group is (! - always present ? - depends on group_flags):
|
||||
// --------------
|
||||
// ! group_size
|
||||
// ! group_flags
|
||||
// ? group_r_offset_delta when RELOCATION_GROUPED_BY_OFFSET_DELTA flag is set
|
||||
// ? group_r_info when RELOCATION_GROUPED_BY_INFO flag is set
|
||||
// ? group_r_addend_group_delta when RELOCATION_GROUP_HAS_ADDEND and RELOCATION_GROUPED_BY_ADDEND
|
||||
// flag is set
|
||||
//
|
||||
// The group description is followed by individual relocations.
|
||||
// please note that there is a case when individual relocation
|
||||
// section could be empty - that is if every field ends up grouped.
|
||||
//
|
||||
// The format for individual relocations section is:
|
||||
// ? r_offset_delta - when RELOCATION_GROUPED_BY_OFFSET_DELTA is not set
|
||||
// ? r_info - when RELOCATION_GROUPED_BY_INFO flag is not set
|
||||
// ? r_addend_delta - RELOCATION_GROUP_HAS_ADDEND is set and RELOCATION_GROUPED_BY_ADDEND is not set
|
||||
//
|
||||
// For example lets pack the following relocations:
|
||||
//
|
||||
// Relocation section '.rela.dyn' at offset 0xbf58 contains 939 entries:
|
||||
// Offset Info Type Symbol's Value Symbol's Name + Addend
|
||||
// 00000000000a2178 0000000000000403 R_AARCH64_RELATIVE 177a8
|
||||
// 00000000000a2180 0000000000000403 R_AARCH64_RELATIVE 177cc
|
||||
// 00000000000a2188 0000000000000403 R_AARCH64_RELATIVE 177e0
|
||||
// 00000000000a2190 0000000000000403 R_AARCH64_RELATIVE 177f4
|
||||
// 00000000000a2198 0000000000000403 R_AARCH64_RELATIVE 17804
|
||||
// 00000000000a21a0 0000000000000403 R_AARCH64_RELATIVE 17818
|
||||
// 00000000000a21a8 0000000000000403 R_AARCH64_RELATIVE 1782c
|
||||
// 00000000000a21b0 0000000000000403 R_AARCH64_RELATIVE 17840
|
||||
// 00000000000a21b8 0000000000000403 R_AARCH64_RELATIVE 17854
|
||||
// 00000000000a21c0 0000000000000403 R_AARCH64_RELATIVE 17868
|
||||
// 00000000000a21c8 0000000000000403 R_AARCH64_RELATIVE 1787c
|
||||
// 00000000000a21d0 0000000000000403 R_AARCH64_RELATIVE 17890
|
||||
// 00000000000a21d8 0000000000000403 R_AARCH64_RELATIVE 178a4
|
||||
// 00000000000a21e8 0000000000000403 R_AARCH64_RELATIVE 178b8
|
||||
//
|
||||
// The header is going to be
|
||||
// [00] 14 <- count
|
||||
// [01] 0x00000000000a2170 <- initial relocation (first relocation - delta,
|
||||
// the delta is 8 in this case)
|
||||
// -- starting the first and only group
|
||||
// [03] 14 <- group size
|
||||
// [03] 0xb <- flags RELOCATION_GROUP_HAS_ADDEND | RELOCATION_GROUPED_BY_OFFSET_DELTA
|
||||
// | RELOCATION_GROUPED_BY_INFO
|
||||
// [04] 8 <- offset delta
|
||||
// [05] 0x403 <- r_info
|
||||
// -- end of group definition, starting list of r_addend deltas
|
||||
// [06] 0x177a8
|
||||
// [07] 0x24 = 177cc - 177a8
|
||||
// [08] 0x14 = 177e0 - 177cc
|
||||
// [09] 0x14 = 177f4 - 177e0
|
||||
// [10] 0x10 = 17804 - 177f4
|
||||
// [11] 0x14 = 17818 - 17804
|
||||
// [12] 0x14 = 1782c - 17818
|
||||
// [13] 0x14 = 17840 - 1782c
|
||||
// [14] 0x14 = 17854 - 17840
|
||||
// [15] 0x14 = 17868 - 17854
|
||||
// [16] 0x14 = 1787c - 17868
|
||||
// [17] 0x14 = 17890 - 1787c
|
||||
// [18] 0x14 = 178a4 - 17890
|
||||
// [19] 0x14 = 178b8 - 178a4
|
||||
// -- the end.
|
||||
|
||||
// TODO (dimitry): consider using r_addend_group_delta in the way we use group offset delta, it can
|
||||
// save us more bytes...
|
||||
|
||||
// The input ends when sum(group_size) == relocation_count
|
||||
|
||||
#ifndef TOOLS_RELOCATION_PACKER_SRC_DELTA_ENCODER_H_
|
||||
#define TOOLS_RELOCATION_PACKER_SRC_DELTA_ENCODER_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "elf.h"
|
||||
#include "elf_traits.h"
|
||||
|
||||
namespace relocation_packer {
|
||||
|
||||
// A RelocationDeltaCodec packs vectors of relative relocations with
|
||||
// addends into more compact forms, and unpacks them to reproduce the
|
||||
// pre-packed data.
|
||||
template <typename ELF>
|
||||
class RelocationDeltaCodec {
|
||||
public:
|
||||
typedef typename ELF::Addr ElfAddr;
|
||||
typedef typename ELF::Rela ElfRela;
|
||||
|
||||
// Encode relocations with addends into a more compact form.
|
||||
// |relocations| is a vector of relative relocation with addend structs.
|
||||
// |packed| is the vector of packed words into which relocations are packed.
|
||||
static void Encode(const std::vector<ElfRela>& relocations,
|
||||
std::vector<ElfAddr>* packed);
|
||||
|
||||
// Decode relative relocations with addends from their more compact form.
|
||||
// |packed| is the vector of packed relocations.
|
||||
// |relocations| is a vector of unpacked relative relocations.
|
||||
static void Decode(const std::vector<ElfAddr>& packed,
|
||||
std::vector<ElfRela>* relocations);
|
||||
|
||||
private:
|
||||
static void DetectGroup(const std::vector<ElfRela>& relocations,
|
||||
size_t group_starts_with, ElfAddr previous_offset,
|
||||
ElfAddr* group_size, ElfAddr* group_flags,
|
||||
ElfAddr* group_offset_delta, ElfAddr* group_info,
|
||||
ElfAddr* group_addend);
|
||||
|
||||
static void DetectGroupFields(const ElfRela& reloc_one, const ElfRela& reloc_two,
|
||||
ElfAddr current_offset_delta, ElfAddr* group_flags,
|
||||
ElfAddr* group_offset_delta, ElfAddr* group_info,
|
||||
ElfAddr* group_addend);
|
||||
};
|
||||
|
||||
} // namespace relocation_packer
|
||||
|
||||
#endif // TOOLS_RELOCATION_PACKER_SRC_DELTA_ENCODER_H_
|
223
third_party/android_platform/bionic/tools/relocation_packer/src/delta_encoder_unittest.cc
vendored
Normal file
223
third_party/android_platform/bionic/tools/relocation_packer/src/delta_encoder_unittest.cc
vendored
Normal file
@ -0,0 +1,223 @@
|
||||
// Copyright 2014 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "delta_encoder.h"
|
||||
|
||||
#include <vector>
|
||||
#include "elf.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace {
|
||||
|
||||
template <typename T>
|
||||
void AddRelocation(uint32_t addr,
|
||||
uint32_t info,
|
||||
int32_t addend,
|
||||
std::vector<T>* relocations) {
|
||||
T relocation;
|
||||
relocation.r_offset = addr;
|
||||
relocation.r_info = info;
|
||||
relocation.r_addend = addend;
|
||||
relocations->push_back(relocation);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool CheckRelocation(uint32_t addr,
|
||||
uint32_t info,
|
||||
int32_t addend,
|
||||
const T& relocation) {
|
||||
return relocation.r_offset == addr &&
|
||||
relocation.r_info == info &&
|
||||
relocation.r_addend == addend;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace relocation_packer {
|
||||
|
||||
template <typename ELF>
|
||||
static void encode() {
|
||||
std::vector<typename ELF::Rela> relocations;
|
||||
std::vector<typename ELF::Addr> packed;
|
||||
|
||||
RelocationDeltaCodec<ELF> codec;
|
||||
|
||||
codec.Encode(relocations, &packed);
|
||||
|
||||
ASSERT_EQ(0U, packed.size());
|
||||
|
||||
// Initial relocation.
|
||||
AddRelocation(0xf00d0000, 11U, 10000, &relocations);
|
||||
|
||||
codec.Encode(relocations, &packed);
|
||||
|
||||
// size of reloc table, size of group, flags, 3 fields, zero
|
||||
EXPECT_EQ(7U, packed.size());
|
||||
// One pair present.
|
||||
size_t ndx = 0;
|
||||
EXPECT_EQ(1U, packed[ndx++]);
|
||||
EXPECT_EQ(0xf00d0000, packed[ndx++]);
|
||||
EXPECT_EQ(1U, packed[ndx++]); // group_size
|
||||
EXPECT_EQ(8U, packed[ndx++]); // flags
|
||||
// Delta from the neutral element is zero
|
||||
EXPECT_EQ(0U, packed[ndx++]); // offset_delta
|
||||
EXPECT_EQ(11U, packed[ndx++]); // info
|
||||
EXPECT_EQ(10000U, packed[ndx++]); // addend_delta
|
||||
|
||||
// Add a second relocation, 4 byte offset delta, 12 byte addend delta.
|
||||
// same info
|
||||
AddRelocation(0xf00d0004, 11U, 10012, &relocations);
|
||||
|
||||
packed.clear();
|
||||
codec.Encode(relocations, &packed);
|
||||
|
||||
ndx = 0;
|
||||
EXPECT_EQ(8U, packed.size());
|
||||
|
||||
EXPECT_EQ(2U, packed[ndx++]); // relocs count
|
||||
EXPECT_EQ(0xf00cfffc, packed[ndx++]); // initial offset
|
||||
EXPECT_EQ(2U, packed[ndx++]); // group count
|
||||
EXPECT_EQ(11U, packed[ndx++]); // flags
|
||||
EXPECT_EQ(4U, packed[ndx++]); // group offset delta
|
||||
EXPECT_EQ(11U, packed[ndx++]); // info
|
||||
|
||||
EXPECT_EQ(10000U, packed[ndx++]); // addend delta
|
||||
EXPECT_EQ(12U, packed[ndx++]); // addend delta
|
||||
|
||||
// Add a third relocation, 4 byte offset delta, 12 byte addend delta.
|
||||
// different info
|
||||
AddRelocation(0xf00d0008, 41U, 10024, &relocations);
|
||||
|
||||
// Add three more relocations, 8 byte offset deltas, -24 byte addend deltas.
|
||||
AddRelocation(0xf00d0010, 42U, 10000, &relocations);
|
||||
AddRelocation(0xf00d0018, 42U, 9976, &relocations);
|
||||
AddRelocation(0xf00d0020, 42U, 9952, &relocations);
|
||||
|
||||
AddRelocation(0xf00d2028, 1042U, 0, &relocations);
|
||||
AddRelocation(0xf00d2030, 3442U, 0, &relocations);
|
||||
|
||||
packed.clear();
|
||||
codec.Encode(relocations, &packed);
|
||||
|
||||
ndx = 0;
|
||||
EXPECT_EQ(26U, packed.size());
|
||||
// Total number of relocs
|
||||
EXPECT_EQ(8U, packed[ndx++]);
|
||||
EXPECT_EQ(0xf00cfffc, packed[ndx++]);
|
||||
// 2 in first group
|
||||
EXPECT_EQ(2U, packed[ndx++]);
|
||||
EXPECT_EQ(11U, packed[ndx++]); //flags
|
||||
EXPECT_EQ(4U, packed[ndx++]); // group offset delta
|
||||
EXPECT_EQ(11U, packed[ndx++]); // info
|
||||
|
||||
// Initial relocation.
|
||||
EXPECT_EQ(10000U, packed[ndx++]); // addend delta
|
||||
// Two relocations, 4 byte offset deltas, 12 byte addend deltas.
|
||||
EXPECT_EQ(12U, packed[ndx++]); // addend delta
|
||||
|
||||
// second group has only one reloc
|
||||
EXPECT_EQ(1U, packed[ndx++]); // count
|
||||
EXPECT_EQ(8U, packed[ndx++]); // flags
|
||||
|
||||
EXPECT_EQ(4U, packed[ndx++]); // offset delta
|
||||
EXPECT_EQ(41U, packed[ndx++]); // info
|
||||
EXPECT_EQ(12U, packed[ndx++]); // addend delta
|
||||
|
||||
// next - 3 relocs grouped by info
|
||||
EXPECT_EQ(3U, packed[ndx++]); // count
|
||||
EXPECT_EQ(11U, packed[ndx++]); // flags
|
||||
EXPECT_EQ(8U, packed[ndx++]); // group offset delta
|
||||
EXPECT_EQ(42U, packed[ndx++]); // info
|
||||
// Three relocations, 8 byte offset deltas, -24 byte addend deltas.
|
||||
EXPECT_EQ(static_cast<typename ELF::Addr>(-24), packed[ndx++]);
|
||||
EXPECT_EQ(static_cast<typename ELF::Addr>(-24), packed[ndx++]);
|
||||
EXPECT_EQ(static_cast<typename ELF::Addr>(-24), packed[ndx++]);
|
||||
|
||||
// and last - 2 relocations without addend
|
||||
EXPECT_EQ(2U, packed[ndx++]);
|
||||
EXPECT_EQ(0U, packed[ndx++]); // flags
|
||||
// offset_deltas and r_infos for next 2 relocations
|
||||
EXPECT_EQ(0x2008U, packed[ndx++]); // offset delta
|
||||
EXPECT_EQ(1042U, packed[ndx++]); // r_info
|
||||
EXPECT_EQ(0x8U, packed[ndx++]); // offset delta
|
||||
EXPECT_EQ(3442U, packed[ndx++]); // r_info
|
||||
|
||||
EXPECT_EQ(packed.size(), ndx);
|
||||
}
|
||||
|
||||
TEST(Delta, Encode32) {
|
||||
encode<ELF32_traits>();
|
||||
}
|
||||
|
||||
TEST(Delta, Encode64) {
|
||||
encode<ELF64_traits>();
|
||||
}
|
||||
|
||||
template <typename ELF>
|
||||
static void decode() {
|
||||
std::vector<typename ELF::Addr> packed;
|
||||
std::vector<typename ELF::Rela> relocations;
|
||||
|
||||
RelocationDeltaCodec<ELF> codec;
|
||||
codec.Decode(packed, &relocations);
|
||||
|
||||
EXPECT_EQ(0U, relocations.size());
|
||||
|
||||
// Six pairs.
|
||||
packed.push_back(6U); // count
|
||||
packed.push_back(0xc0ddfffc); // base offset
|
||||
packed.push_back(3U); // group count
|
||||
packed.push_back(11U); // flags
|
||||
packed.push_back(4U); // offset delta
|
||||
packed.push_back(11U); // info
|
||||
// Initial relocation.
|
||||
packed.push_back(10000U);
|
||||
// Two relocations, 4 byte offset deltas, 12 byte addend deltas.
|
||||
packed.push_back(12U); // addend
|
||||
packed.push_back(12U); // addend
|
||||
|
||||
// Three relocations, 8 byte offset deltas, -24 byte addend deltas.
|
||||
packed.push_back(1U); // group count
|
||||
packed.push_back(9U); // flags
|
||||
packed.push_back(11U); // info
|
||||
|
||||
packed.push_back(8U);
|
||||
packed.push_back(static_cast<typename ELF::Addr>(-24));
|
||||
// next group with 2 relocs
|
||||
packed.push_back(2U); // group count
|
||||
packed.push_back(11U); // flags
|
||||
packed.push_back(8U); // offset
|
||||
packed.push_back(42U); // info
|
||||
|
||||
packed.push_back(static_cast<typename ELF::Addr>(-24)); // addend
|
||||
packed.push_back(static_cast<typename ELF::Addr>(-24)); // addend
|
||||
|
||||
relocations.clear();
|
||||
codec.Decode(packed, &relocations);
|
||||
|
||||
EXPECT_EQ(6U, relocations.size());
|
||||
// Initial relocation.
|
||||
EXPECT_TRUE(CheckRelocation(0xc0de0000, 11U, 10000, relocations[0]));
|
||||
// Two relocations, 4 byte offset deltas, 12 byte addend deltas.
|
||||
EXPECT_TRUE(CheckRelocation(0xc0de0004, 11U, 10012, relocations[1]));
|
||||
EXPECT_TRUE(CheckRelocation(0xc0de0008, 11U, 10024, relocations[2]));
|
||||
// Three relocations, 8 byte offset deltas, -24 byte addend deltas.
|
||||
EXPECT_TRUE(CheckRelocation(0xc0de0010, 11U, 10000, relocations[3]));
|
||||
EXPECT_TRUE(CheckRelocation(0xc0de0018, 42U, 9976, relocations[4]));
|
||||
EXPECT_TRUE(CheckRelocation(0xc0de0020, 42U, 9952, relocations[5]));
|
||||
}
|
||||
|
||||
TEST(Delta, Decode32) {
|
||||
decode<ELF32_traits>();
|
||||
}
|
||||
|
||||
TEST(Delta, Decode64) {
|
||||
decode<ELF64_traits>();
|
||||
}
|
||||
|
||||
// TODO (dimitry): add more tests (fix by 19 January 2038 03:14:07 UTC)
|
||||
// TODO (dimtiry): 1. Incorrect packed array for decode
|
||||
// TODO (dimtiry): 2. Try to catch situation where it is likely to get series of groups with size 1
|
||||
|
||||
} // namespace relocation_packer
|
993
third_party/android_platform/bionic/tools/relocation_packer/src/elf_file.cc
vendored
Normal file
993
third_party/android_platform/bionic/tools/relocation_packer/src/elf_file.cc
vendored
Normal file
@ -0,0 +1,993 @@
|
||||
// Copyright 2014 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Implementation notes:
|
||||
//
|
||||
// We need to remove a piece from the ELF shared library. However, we also
|
||||
// want to avoid fixing DWARF cfi data and relative relocation addresses.
|
||||
// So after packing we shift offets and starting address of the RX segment
|
||||
// while preserving code/data vaddrs location.
|
||||
// This requires some fixups for symtab/hash/gnu_hash dynamic section addresses.
|
||||
|
||||
#include "elf_file.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "debug.h"
|
||||
#include "elf_traits.h"
|
||||
#include "libelf.h"
|
||||
#include "packer.h"
|
||||
|
||||
namespace relocation_packer {
|
||||
|
||||
// Out-of-band dynamic tags used to indicate the offset and size of the
|
||||
// android packed relocations section.
|
||||
static constexpr int32_t DT_ANDROID_REL = DT_LOOS + 2;
|
||||
static constexpr int32_t DT_ANDROID_RELSZ = DT_LOOS + 3;
|
||||
|
||||
static constexpr int32_t DT_ANDROID_RELA = DT_LOOS + 4;
|
||||
static constexpr int32_t DT_ANDROID_RELASZ = DT_LOOS + 5;
|
||||
|
||||
static constexpr uint32_t SHT_ANDROID_REL = SHT_LOOS + 1;
|
||||
static constexpr uint32_t SHT_ANDROID_RELA = SHT_LOOS + 2;
|
||||
|
||||
static const size_t kPageSize = 4096;
|
||||
|
||||
// Alignment to preserve, in bytes. This must be at least as large as the
|
||||
// largest d_align and sh_addralign values found in the loaded file.
|
||||
// Out of caution for RELRO page alignment, we preserve to a complete target
|
||||
// page. See http://www.airs.com/blog/archives/189.
|
||||
static const size_t kPreserveAlignment = kPageSize;
|
||||
|
||||
// Get section data. Checks that the section has exactly one data entry,
|
||||
// so that the section size and the data size are the same. True in
|
||||
// practice for all sections we resize when packing or unpacking. Done
|
||||
// by ensuring that a call to elf_getdata(section, data) returns NULL as
|
||||
// the next data entry.
|
||||
static Elf_Data* GetSectionData(Elf_Scn* section) {
|
||||
Elf_Data* data = elf_getdata(section, NULL);
|
||||
CHECK(data && elf_getdata(section, data) == NULL);
|
||||
return data;
|
||||
}
|
||||
|
||||
// Rewrite section data. Allocates new data and makes it the data element's
|
||||
// buffer. Relies on program exit to free allocated data.
|
||||
static void RewriteSectionData(Elf_Scn* section,
|
||||
const void* section_data,
|
||||
size_t size) {
|
||||
Elf_Data* data = GetSectionData(section);
|
||||
CHECK(size == data->d_size);
|
||||
uint8_t* area = new uint8_t[size];
|
||||
memcpy(area, section_data, size);
|
||||
data->d_buf = area;
|
||||
}
|
||||
|
||||
// Verbose ELF header logging.
|
||||
template <typename Ehdr>
|
||||
static void VerboseLogElfHeader(const Ehdr* elf_header) {
|
||||
VLOG(1) << "e_phoff = " << elf_header->e_phoff;
|
||||
VLOG(1) << "e_shoff = " << elf_header->e_shoff;
|
||||
VLOG(1) << "e_ehsize = " << elf_header->e_ehsize;
|
||||
VLOG(1) << "e_phentsize = " << elf_header->e_phentsize;
|
||||
VLOG(1) << "e_phnum = " << elf_header->e_phnum;
|
||||
VLOG(1) << "e_shnum = " << elf_header->e_shnum;
|
||||
VLOG(1) << "e_shstrndx = " << elf_header->e_shstrndx;
|
||||
}
|
||||
|
||||
// Verbose ELF program header logging.
|
||||
template <typename Phdr>
|
||||
static void VerboseLogProgramHeader(size_t program_header_index,
|
||||
const Phdr* program_header) {
|
||||
std::string type;
|
||||
switch (program_header->p_type) {
|
||||
case PT_NULL: type = "NULL"; break;
|
||||
case PT_LOAD: type = "LOAD"; break;
|
||||
case PT_DYNAMIC: type = "DYNAMIC"; break;
|
||||
case PT_INTERP: type = "INTERP"; break;
|
||||
case PT_PHDR: type = "PHDR"; break;
|
||||
case PT_GNU_RELRO: type = "GNU_RELRO"; break;
|
||||
case PT_GNU_STACK: type = "GNU_STACK"; break;
|
||||
case PT_ARM_EXIDX: type = "EXIDX"; break;
|
||||
default: type = "(OTHER)"; break;
|
||||
}
|
||||
VLOG(1) << "phdr[" << program_header_index << "] : " << type;
|
||||
VLOG(1) << " p_offset = " << program_header->p_offset;
|
||||
VLOG(1) << " p_vaddr = " << program_header->p_vaddr;
|
||||
VLOG(1) << " p_paddr = " << program_header->p_paddr;
|
||||
VLOG(1) << " p_filesz = " << program_header->p_filesz;
|
||||
VLOG(1) << " p_memsz = " << program_header->p_memsz;
|
||||
VLOG(1) << " p_flags = " << program_header->p_flags;
|
||||
VLOG(1) << " p_align = " << program_header->p_align;
|
||||
}
|
||||
|
||||
// Verbose ELF section header logging.
|
||||
template <typename Shdr>
|
||||
static void VerboseLogSectionHeader(const std::string& section_name,
|
||||
const Shdr* section_header) {
|
||||
VLOG(1) << "section " << section_name;
|
||||
VLOG(1) << " sh_addr = " << section_header->sh_addr;
|
||||
VLOG(1) << " sh_offset = " << section_header->sh_offset;
|
||||
VLOG(1) << " sh_size = " << section_header->sh_size;
|
||||
VLOG(1) << " sh_entsize = " << section_header->sh_entsize;
|
||||
VLOG(1) << " sh_addralign = " << section_header->sh_addralign;
|
||||
}
|
||||
|
||||
// Verbose ELF section data logging.
|
||||
static void VerboseLogSectionData(const Elf_Data* data) {
|
||||
VLOG(1) << " data";
|
||||
VLOG(1) << " d_buf = " << data->d_buf;
|
||||
VLOG(1) << " d_off = " << data->d_off;
|
||||
VLOG(1) << " d_size = " << data->d_size;
|
||||
VLOG(1) << " d_align = " << data->d_align;
|
||||
}
|
||||
|
||||
// Load the complete ELF file into a memory image in libelf, and identify
|
||||
// the .rel.dyn or .rela.dyn, .dynamic, and .android.rel.dyn or
|
||||
// .android.rela.dyn sections. No-op if the ELF file has already been loaded.
|
||||
template <typename ELF>
|
||||
bool ElfFile<ELF>::Load() {
|
||||
if (elf_)
|
||||
return true;
|
||||
|
||||
Elf* elf = elf_begin(fd_, ELF_C_RDWR, NULL);
|
||||
CHECK(elf);
|
||||
|
||||
if (elf_kind(elf) != ELF_K_ELF) {
|
||||
LOG(ERROR) << "File not in ELF format";
|
||||
return false;
|
||||
}
|
||||
|
||||
auto elf_header = ELF::getehdr(elf);
|
||||
if (!elf_header) {
|
||||
LOG(ERROR) << "Failed to load ELF header: " << elf_errmsg(elf_errno());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (elf_header->e_type != ET_DYN) {
|
||||
LOG(ERROR) << "ELF file is not a shared object";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Require that our endianness matches that of the target, and that both
|
||||
// are little-endian. Safe for all current build/target combinations.
|
||||
const int endian = elf_header->e_ident[EI_DATA];
|
||||
CHECK(endian == ELFDATA2LSB);
|
||||
CHECK(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__);
|
||||
|
||||
const int file_class = elf_header->e_ident[EI_CLASS];
|
||||
VLOG(1) << "endian = " << endian << ", file class = " << file_class;
|
||||
VerboseLogElfHeader(elf_header);
|
||||
|
||||
auto elf_program_header = ELF::getphdr(elf);
|
||||
CHECK(elf_program_header != nullptr);
|
||||
|
||||
const typename ELF::Phdr* dynamic_program_header = NULL;
|
||||
for (size_t i = 0; i < elf_header->e_phnum; ++i) {
|
||||
auto program_header = &elf_program_header[i];
|
||||
VerboseLogProgramHeader(i, program_header);
|
||||
|
||||
if (program_header->p_type == PT_DYNAMIC) {
|
||||
CHECK(dynamic_program_header == NULL);
|
||||
dynamic_program_header = program_header;
|
||||
}
|
||||
}
|
||||
CHECK(dynamic_program_header != nullptr);
|
||||
|
||||
size_t string_index;
|
||||
elf_getshdrstrndx(elf, &string_index);
|
||||
|
||||
// Notes of the dynamic relocations, packed relocations, and .dynamic
|
||||
// sections. Found while iterating sections, and later stored in class
|
||||
// attributes.
|
||||
Elf_Scn* found_relocations_section = nullptr;
|
||||
Elf_Scn* found_dynamic_section = nullptr;
|
||||
|
||||
// Notes of relocation section types seen. We require one or the other of
|
||||
// these; both is unsupported.
|
||||
bool has_rel_relocations = false;
|
||||
bool has_rela_relocations = false;
|
||||
bool has_android_relocations = false;
|
||||
|
||||
Elf_Scn* section = NULL;
|
||||
while ((section = elf_nextscn(elf, section)) != nullptr) {
|
||||
auto section_header = ELF::getshdr(section);
|
||||
std::string name = elf_strptr(elf, string_index, section_header->sh_name);
|
||||
VerboseLogSectionHeader(name, section_header);
|
||||
|
||||
// Note relocation section types.
|
||||
if (section_header->sh_type == SHT_REL || section_header->sh_type == SHT_ANDROID_REL) {
|
||||
has_rel_relocations = true;
|
||||
}
|
||||
if (section_header->sh_type == SHT_RELA || section_header->sh_type == SHT_ANDROID_RELA) {
|
||||
has_rela_relocations = true;
|
||||
}
|
||||
|
||||
// Note special sections as we encounter them.
|
||||
if ((name == ".rel.dyn" || name == ".rela.dyn") &&
|
||||
section_header->sh_size > 0) {
|
||||
found_relocations_section = section;
|
||||
|
||||
// Note if relocation section is already packed
|
||||
has_android_relocations =
|
||||
section_header->sh_type == SHT_ANDROID_REL ||
|
||||
section_header->sh_type == SHT_ANDROID_RELA;
|
||||
}
|
||||
|
||||
if (section_header->sh_offset == dynamic_program_header->p_offset) {
|
||||
found_dynamic_section = section;
|
||||
}
|
||||
|
||||
// Ensure we preserve alignment, repeated later for the data block(s).
|
||||
CHECK(section_header->sh_addralign <= kPreserveAlignment);
|
||||
|
||||
Elf_Data* data = NULL;
|
||||
while ((data = elf_getdata(section, data)) != NULL) {
|
||||
CHECK(data->d_align <= kPreserveAlignment);
|
||||
VerboseLogSectionData(data);
|
||||
}
|
||||
}
|
||||
|
||||
// Loading failed if we did not find the required special sections.
|
||||
if (!found_relocations_section) {
|
||||
LOG(ERROR) << "Missing or empty .rel.dyn or .rela.dyn section";
|
||||
return false;
|
||||
}
|
||||
if (!found_dynamic_section) {
|
||||
LOG(ERROR) << "Missing .dynamic section";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Loading failed if we could not identify the relocations type.
|
||||
if (!has_rel_relocations && !has_rela_relocations) {
|
||||
LOG(ERROR) << "No relocations sections found";
|
||||
return false;
|
||||
}
|
||||
if (has_rel_relocations && has_rela_relocations) {
|
||||
LOG(ERROR) << "Multiple relocations sections with different types found, "
|
||||
<< "not currently supported";
|
||||
return false;
|
||||
}
|
||||
|
||||
elf_ = elf;
|
||||
relocations_section_ = found_relocations_section;
|
||||
dynamic_section_ = found_dynamic_section;
|
||||
relocations_type_ = has_rel_relocations ? REL : RELA;
|
||||
has_android_relocations_ = has_android_relocations;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Helper for ResizeSection(). Adjust the main ELF header for the hole.
|
||||
template <typename ELF>
|
||||
static void AdjustElfHeaderForHole(typename ELF::Ehdr* elf_header,
|
||||
typename ELF::Off hole_start,
|
||||
ssize_t hole_size) {
|
||||
if (elf_header->e_phoff > hole_start) {
|
||||
elf_header->e_phoff += hole_size;
|
||||
VLOG(1) << "e_phoff adjusted to " << elf_header->e_phoff;
|
||||
}
|
||||
if (elf_header->e_shoff > hole_start) {
|
||||
elf_header->e_shoff += hole_size;
|
||||
VLOG(1) << "e_shoff adjusted to " << elf_header->e_shoff;
|
||||
}
|
||||
}
|
||||
|
||||
// Helper for ResizeSection(). Adjust all section headers for the hole.
|
||||
template <typename ELF>
|
||||
static void AdjustSectionHeadersForHole(Elf* elf,
|
||||
typename ELF::Off hole_start,
|
||||
ssize_t hole_size) {
|
||||
size_t string_index;
|
||||
elf_getshdrstrndx(elf, &string_index);
|
||||
|
||||
Elf_Scn* section = NULL;
|
||||
while ((section = elf_nextscn(elf, section)) != NULL) {
|
||||
auto section_header = ELF::getshdr(section);
|
||||
std::string name = elf_strptr(elf, string_index, section_header->sh_name);
|
||||
|
||||
if (section_header->sh_offset > hole_start) {
|
||||
section_header->sh_offset += hole_size;
|
||||
VLOG(1) << "section " << name
|
||||
<< " sh_offset adjusted to " << section_header->sh_offset;
|
||||
} else {
|
||||
section_header->sh_addr -= hole_size;
|
||||
VLOG(1) << "section " << name
|
||||
<< " sh_addr adjusted to " << section_header->sh_addr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Helpers for ResizeSection(). On packing, reduce p_align for LOAD segments
|
||||
// to 4kb if larger. On unpacking, restore p_align for LOAD segments if
|
||||
// packing reduced it to 4kb. Return true if p_align was changed.
|
||||
template <typename ELF>
|
||||
static bool ClampLoadSegmentAlignment(typename ELF::Phdr* program_header) {
|
||||
CHECK(program_header->p_type == PT_LOAD);
|
||||
|
||||
// If large, reduce p_align for a LOAD segment to page size on packing.
|
||||
if (program_header->p_align > kPageSize) {
|
||||
program_header->p_align = kPageSize;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename ELF>
|
||||
static bool RestoreLoadSegmentAlignment(typename ELF::Phdr* program_headers,
|
||||
size_t count,
|
||||
typename ELF::Phdr* program_header) {
|
||||
CHECK(program_header->p_type == PT_LOAD);
|
||||
|
||||
// If p_align was reduced on packing, restore it to its previous value
|
||||
// on unpacking. We do this by searching for a different LOAD segment
|
||||
// and setting p_align to that of the other LOAD segment found.
|
||||
//
|
||||
// Relies on the following observations:
|
||||
// - a packable ELF executable has more than one LOAD segment;
|
||||
// - before packing all LOAD segments have the same p_align;
|
||||
// - on packing we reduce only one LOAD segment's p_align.
|
||||
if (program_header->p_align == kPageSize) {
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
typename ELF::Phdr* other_header = &program_headers[i];
|
||||
if (other_header->p_type == PT_LOAD && other_header != program_header) {
|
||||
program_header->p_align = other_header->p_align;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
LOG(WARNING) << "Cannot find a LOAD segment from which to restore p_align";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename ELF>
|
||||
static bool AdjustLoadSegmentAlignment(typename ELF::Phdr* program_headers,
|
||||
size_t count,
|
||||
typename ELF::Phdr* program_header,
|
||||
ssize_t hole_size) {
|
||||
CHECK(program_header->p_type == PT_LOAD);
|
||||
|
||||
bool status = false;
|
||||
if (hole_size < 0) {
|
||||
status = ClampLoadSegmentAlignment<ELF>(program_header);
|
||||
} else if (hole_size > 0) {
|
||||
status = RestoreLoadSegmentAlignment<ELF>(program_headers,
|
||||
count,
|
||||
program_header);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
// Helper for ResizeSection(). Adjust the offsets of any program headers
|
||||
// that have offsets currently beyond the hole start, and adjust the
|
||||
// virtual and physical addrs (and perhaps alignment) of the others.
|
||||
template <typename ELF>
|
||||
static void AdjustProgramHeaderFields(typename ELF::Phdr* program_headers,
|
||||
size_t count,
|
||||
typename ELF::Off hole_start,
|
||||
ssize_t hole_size) {
|
||||
int alignment_changes = 0;
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
typename ELF::Phdr* program_header = &program_headers[i];
|
||||
|
||||
// Do not adjust PT_GNU_STACK - it confuses gdb and results
|
||||
// in incorrect unwinding if the executable is stripped after
|
||||
// packing.
|
||||
if (program_header->p_type == PT_GNU_STACK) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (program_header->p_offset > hole_start) {
|
||||
// The hole start is past this segment, so adjust offset.
|
||||
program_header->p_offset += hole_size;
|
||||
VLOG(1) << "phdr[" << i
|
||||
<< "] p_offset adjusted to "<< program_header->p_offset;
|
||||
} else {
|
||||
program_header->p_vaddr -= hole_size;
|
||||
program_header->p_paddr -= hole_size;
|
||||
|
||||
// If packing, clamp LOAD segment alignment to 4kb to prevent strip
|
||||
// from adjusting it unnecessarily if run on a packed file. If
|
||||
// unpacking, attempt to restore a reduced alignment to its previous
|
||||
// value. Ensure that we do this on at most one LOAD segment.
|
||||
if (program_header->p_type == PT_LOAD) {
|
||||
alignment_changes += AdjustLoadSegmentAlignment<ELF>(program_headers,
|
||||
count,
|
||||
program_header,
|
||||
hole_size);
|
||||
LOG_IF(FATAL, alignment_changes > 1)
|
||||
<< "Changed p_align on more than one LOAD segment";
|
||||
}
|
||||
|
||||
VLOG(1) << "phdr[" << i
|
||||
<< "] p_vaddr adjusted to "<< program_header->p_vaddr
|
||||
<< "; p_paddr adjusted to "<< program_header->p_paddr
|
||||
<< "; p_align adjusted to "<< program_header->p_align;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Helper for ResizeSection(). Find the first loadable segment in the
|
||||
// file. We expect it to map from file offset zero.
|
||||
template <typename ELF>
|
||||
static typename ELF::Phdr* FindLoadSegmentForHole(typename ELF::Phdr* program_headers,
|
||||
size_t count,
|
||||
typename ELF::Off hole_start) {
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
typename ELF::Phdr* program_header = &program_headers[i];
|
||||
|
||||
if (program_header->p_type == PT_LOAD &&
|
||||
program_header->p_offset <= hole_start &&
|
||||
(program_header->p_offset + program_header->p_filesz) >= hole_start ) {
|
||||
return program_header;
|
||||
}
|
||||
}
|
||||
LOG(FATAL) << "Cannot locate a LOAD segment with hole_start=0x" << std::hex << hole_start;
|
||||
NOTREACHED();
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Helper for ResizeSection(). Rewrite program headers.
|
||||
template <typename ELF>
|
||||
static void RewriteProgramHeadersForHole(Elf* elf,
|
||||
typename ELF::Off hole_start,
|
||||
ssize_t hole_size) {
|
||||
const typename ELF::Ehdr* elf_header = ELF::getehdr(elf);
|
||||
CHECK(elf_header);
|
||||
|
||||
typename ELF::Phdr* elf_program_header = ELF::getphdr(elf);
|
||||
CHECK(elf_program_header);
|
||||
|
||||
const size_t program_header_count = elf_header->e_phnum;
|
||||
|
||||
// Locate the segment that we can overwrite to form the new LOAD entry,
|
||||
// and the segment that we are going to split into two parts.
|
||||
typename ELF::Phdr* target_load_header =
|
||||
FindLoadSegmentForHole<ELF>(elf_program_header, program_header_count, hole_start);
|
||||
|
||||
VLOG(1) << "phdr[" << target_load_header - elf_program_header << "] adjust";
|
||||
// Adjust PT_LOAD program header memsz and filesz
|
||||
target_load_header->p_filesz += hole_size;
|
||||
target_load_header->p_memsz += hole_size;
|
||||
|
||||
// Adjust the offsets and p_vaddrs
|
||||
AdjustProgramHeaderFields<ELF>(elf_program_header,
|
||||
program_header_count,
|
||||
hole_start,
|
||||
hole_size);
|
||||
}
|
||||
|
||||
// Helper for ResizeSection(). Locate and return the dynamic section.
|
||||
template <typename ELF>
|
||||
static Elf_Scn* GetDynamicSection(Elf* elf) {
|
||||
const typename ELF::Ehdr* elf_header = ELF::getehdr(elf);
|
||||
CHECK(elf_header);
|
||||
|
||||
const typename ELF::Phdr* elf_program_header = ELF::getphdr(elf);
|
||||
CHECK(elf_program_header);
|
||||
|
||||
// Find the program header that describes the dynamic section.
|
||||
const typename ELF::Phdr* dynamic_program_header = NULL;
|
||||
for (size_t i = 0; i < elf_header->e_phnum; ++i) {
|
||||
const typename ELF::Phdr* program_header = &elf_program_header[i];
|
||||
|
||||
if (program_header->p_type == PT_DYNAMIC) {
|
||||
dynamic_program_header = program_header;
|
||||
}
|
||||
}
|
||||
CHECK(dynamic_program_header);
|
||||
|
||||
// Now find the section with the same offset as this program header.
|
||||
Elf_Scn* dynamic_section = NULL;
|
||||
Elf_Scn* section = NULL;
|
||||
while ((section = elf_nextscn(elf, section)) != NULL) {
|
||||
typename ELF::Shdr* section_header = ELF::getshdr(section);
|
||||
|
||||
if (section_header->sh_offset == dynamic_program_header->p_offset) {
|
||||
dynamic_section = section;
|
||||
}
|
||||
}
|
||||
CHECK(dynamic_section != NULL);
|
||||
|
||||
return dynamic_section;
|
||||
}
|
||||
|
||||
// Helper for ResizeSection(). Adjust the .dynamic section for the hole.
|
||||
template <typename ELF>
|
||||
void ElfFile<ELF>::AdjustDynamicSectionForHole(Elf_Scn* dynamic_section,
|
||||
typename ELF::Off hole_start,
|
||||
ssize_t hole_size,
|
||||
relocations_type_t relocations_type) {
|
||||
CHECK(relocations_type != NONE);
|
||||
Elf_Data* data = GetSectionData(dynamic_section);
|
||||
|
||||
auto dynamic_base = reinterpret_cast<typename ELF::Dyn*>(data->d_buf);
|
||||
std::vector<typename ELF::Dyn> dynamics(
|
||||
dynamic_base,
|
||||
dynamic_base + data->d_size / sizeof(dynamics[0]));
|
||||
|
||||
if (hole_size > 0) { // expanding
|
||||
hole_start += hole_size;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < dynamics.size(); ++i) {
|
||||
typename ELF::Dyn* dynamic = &dynamics[i];
|
||||
const typename ELF::Sword tag = dynamic->d_tag;
|
||||
|
||||
// Any tags that hold offsets are adjustment candidates.
|
||||
const bool is_adjustable = (tag == DT_PLTGOT ||
|
||||
tag == DT_HASH ||
|
||||
tag == DT_GNU_HASH ||
|
||||
tag == DT_STRTAB ||
|
||||
tag == DT_SYMTAB ||
|
||||
tag == DT_RELA ||
|
||||
tag == DT_INIT ||
|
||||
tag == DT_FINI ||
|
||||
tag == DT_REL ||
|
||||
tag == DT_JMPREL ||
|
||||
tag == DT_INIT_ARRAY ||
|
||||
tag == DT_FINI_ARRAY ||
|
||||
tag == DT_VERSYM ||
|
||||
tag == DT_VERNEED ||
|
||||
tag == DT_VERDEF ||
|
||||
tag == DT_ANDROID_REL||
|
||||
tag == DT_ANDROID_RELA);
|
||||
|
||||
if (is_adjustable && dynamic->d_un.d_ptr <= hole_start) {
|
||||
dynamic->d_un.d_ptr -= hole_size;
|
||||
VLOG(1) << "dynamic[" << i << "] " << dynamic->d_tag
|
||||
<< " d_ptr adjusted to " << dynamic->d_un.d_ptr;
|
||||
}
|
||||
|
||||
// DT_RELSZ or DT_RELASZ indicate the overall size of relocations.
|
||||
// Only one will be present. Adjust by hole size.
|
||||
if (tag == DT_RELSZ || tag == DT_RELASZ || tag == DT_ANDROID_RELSZ || tag == DT_ANDROID_RELASZ) {
|
||||
dynamic->d_un.d_val += hole_size;
|
||||
VLOG(1) << "dynamic[" << i << "] " << dynamic->d_tag
|
||||
<< " d_val adjusted to " << dynamic->d_un.d_val;
|
||||
}
|
||||
|
||||
// Special case: DT_MIPS_RLD_MAP2 stores the difference between dynamic
|
||||
// entry address and the address of the _r_debug (used by GDB)
|
||||
// since the dynamic section and target address are on the
|
||||
// different sides of the hole it needs to be adjusted accordingly
|
||||
if (tag == DT_MIPS_RLD_MAP2) {
|
||||
dynamic->d_un.d_val += hole_size;
|
||||
VLOG(1) << "dynamic[" << i << "] " << dynamic->d_tag
|
||||
<< " d_val adjusted to " << dynamic->d_un.d_val;
|
||||
}
|
||||
|
||||
// Ignore DT_RELCOUNT and DT_RELACOUNT: (1) nobody uses them and
|
||||
// technically (2) the relative relocation count is not changed.
|
||||
|
||||
// DT_RELENT and DT_RELAENT don't change, ignore them as well.
|
||||
}
|
||||
|
||||
void* section_data = &dynamics[0];
|
||||
size_t bytes = dynamics.size() * sizeof(dynamics[0]);
|
||||
RewriteSectionData(dynamic_section, section_data, bytes);
|
||||
}
|
||||
|
||||
// Resize a section. If the new size is larger than the current size, open
|
||||
// up a hole by increasing file offsets that come after the hole. If smaller
|
||||
// than the current size, remove the hole by decreasing those offsets.
|
||||
template <typename ELF>
|
||||
void ElfFile<ELF>::ResizeSection(Elf* elf, Elf_Scn* section, size_t new_size,
|
||||
typename ELF::Word new_sh_type,
|
||||
relocations_type_t relocations_type) {
|
||||
|
||||
size_t string_index;
|
||||
elf_getshdrstrndx(elf, &string_index);
|
||||
auto section_header = ELF::getshdr(section);
|
||||
std::string name = elf_strptr(elf, string_index, section_header->sh_name);
|
||||
|
||||
if (section_header->sh_size == new_size) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Require that the section size and the data size are the same. True
|
||||
// in practice for all sections we resize when packing or unpacking.
|
||||
Elf_Data* data = GetSectionData(section);
|
||||
CHECK(data->d_off == 0 && data->d_size == section_header->sh_size);
|
||||
|
||||
// Require that the section is not zero-length (that is, has allocated
|
||||
// data that we can validly expand).
|
||||
CHECK(data->d_size && data->d_buf);
|
||||
|
||||
const auto hole_start = section_header->sh_offset;
|
||||
const ssize_t hole_size = new_size - data->d_size;
|
||||
|
||||
VLOG_IF(1, (hole_size > 0)) << "expand section (" << name << ") size: " <<
|
||||
data->d_size << " -> " << (data->d_size + hole_size);
|
||||
VLOG_IF(1, (hole_size < 0)) << "shrink section (" << name << ") size: " <<
|
||||
data->d_size << " -> " << (data->d_size + hole_size);
|
||||
|
||||
// libelf overrides sh_entsize for known sh_types, so it does not matter what we set
|
||||
// for SHT_REL/SHT_RELA.
|
||||
typename ELF::Xword new_entsize =
|
||||
(new_sh_type == SHT_ANDROID_REL || new_sh_type == SHT_ANDROID_RELA) ? 1 : 0;
|
||||
|
||||
VLOG(1) << "Update section (" << name << ") entry size: " <<
|
||||
section_header->sh_entsize << " -> " << new_entsize;
|
||||
|
||||
// Resize the data and the section header.
|
||||
data->d_size += hole_size;
|
||||
section_header->sh_size += hole_size;
|
||||
section_header->sh_entsize = new_entsize;
|
||||
section_header->sh_type = new_sh_type;
|
||||
|
||||
// Add the hole size to all offsets in the ELF file that are after the
|
||||
// start of the hole. If the hole size is positive we are expanding the
|
||||
// section to create a new hole; if negative, we are closing up a hole.
|
||||
|
||||
// Start with the main ELF header.
|
||||
typename ELF::Ehdr* elf_header = ELF::getehdr(elf);
|
||||
AdjustElfHeaderForHole<ELF>(elf_header, hole_start, hole_size);
|
||||
|
||||
// Adjust all section headers.
|
||||
AdjustSectionHeadersForHole<ELF>(elf, hole_start, hole_size);
|
||||
|
||||
// Rewrite the program headers to either split or coalesce segments,
|
||||
// and adjust dynamic entries to match.
|
||||
RewriteProgramHeadersForHole<ELF>(elf, hole_start, hole_size);
|
||||
|
||||
Elf_Scn* dynamic_section = GetDynamicSection<ELF>(elf);
|
||||
AdjustDynamicSectionForHole(dynamic_section, hole_start, hole_size, relocations_type);
|
||||
}
|
||||
|
||||
// Find the first slot in a dynamics array with the given tag. The array
|
||||
// always ends with a free (unused) element, and which we exclude from the
|
||||
// search. Returns dynamics->size() if not found.
|
||||
template <typename ELF>
|
||||
static size_t FindDynamicEntry(typename ELF::Sword tag,
|
||||
std::vector<typename ELF::Dyn>* dynamics) {
|
||||
// Loop until the penultimate entry. We exclude the end sentinel.
|
||||
for (size_t i = 0; i < dynamics->size() - 1; ++i) {
|
||||
if (dynamics->at(i).d_tag == tag) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
// The tag was not found.
|
||||
return dynamics->size();
|
||||
}
|
||||
|
||||
// Replace dynamic entry.
|
||||
template <typename ELF>
|
||||
static void ReplaceDynamicEntry(typename ELF::Sword tag,
|
||||
const typename ELF::Dyn& dyn,
|
||||
std::vector<typename ELF::Dyn>* dynamics) {
|
||||
const size_t slot = FindDynamicEntry<ELF>(tag, dynamics);
|
||||
if (slot == dynamics->size()) {
|
||||
LOG(FATAL) << "Dynamic slot is not found for tag=" << tag;
|
||||
}
|
||||
|
||||
// Replace this entry with the one supplied.
|
||||
dynamics->at(slot) = dyn;
|
||||
VLOG(1) << "dynamic[" << slot << "] overwritten with " << dyn.d_tag;
|
||||
}
|
||||
|
||||
// Remove relative entries from dynamic relocations and write as packed
|
||||
// data into android packed relocations.
|
||||
template <typename ELF>
|
||||
bool ElfFile<ELF>::PackRelocations() {
|
||||
// Load the ELF file into libelf.
|
||||
if (!Load()) {
|
||||
LOG(ERROR) << "Failed to load as ELF";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Retrieve the current dynamic relocations section data.
|
||||
Elf_Data* data = GetSectionData(relocations_section_);
|
||||
// we always pack rela, because packed format is pretty much the same
|
||||
std::vector<typename ELF::Rela> relocations;
|
||||
|
||||
if (relocations_type_ == REL) {
|
||||
// Convert data to a vector of relocations.
|
||||
const typename ELF::Rel* relocations_base = reinterpret_cast<typename ELF::Rel*>(data->d_buf);
|
||||
ConvertRelArrayToRelaVector(relocations_base,
|
||||
data->d_size / sizeof(typename ELF::Rel), &relocations);
|
||||
VLOG(1) << "Relocations : REL";
|
||||
} else if (relocations_type_ == RELA) {
|
||||
// Convert data to a vector of relocations with addends.
|
||||
const typename ELF::Rela* relocations_base = reinterpret_cast<typename ELF::Rela*>(data->d_buf);
|
||||
relocations = std::vector<typename ELF::Rela>(
|
||||
relocations_base,
|
||||
relocations_base + data->d_size / sizeof(relocations[0]));
|
||||
|
||||
VLOG(1) << "Relocations : RELA";
|
||||
} else {
|
||||
NOTREACHED();
|
||||
}
|
||||
|
||||
return PackTypedRelocations(&relocations);
|
||||
}
|
||||
|
||||
// Helper for PackRelocations(). Rel type is one of ELF::Rel or ELF::Rela.
|
||||
template <typename ELF>
|
||||
bool ElfFile<ELF>::PackTypedRelocations(std::vector<typename ELF::Rela>* relocations) {
|
||||
typedef typename ELF::Rela Rela;
|
||||
|
||||
if (has_android_relocations_) {
|
||||
LOG(INFO) << "Relocation table is already packed";
|
||||
return true;
|
||||
}
|
||||
|
||||
// If no relocations then we have nothing packable. Perhaps
|
||||
// the shared object has already been packed?
|
||||
if (relocations->empty()) {
|
||||
LOG(ERROR) << "No relocations found";
|
||||
return false;
|
||||
}
|
||||
|
||||
const size_t rel_size =
|
||||
relocations_type_ == RELA ? sizeof(typename ELF::Rela) : sizeof(typename ELF::Rel);
|
||||
const size_t initial_bytes = relocations->size() * rel_size;
|
||||
|
||||
VLOG(1) << "Unpacked : " << initial_bytes << " bytes";
|
||||
std::vector<uint8_t> packed;
|
||||
RelocationPacker<ELF> packer;
|
||||
|
||||
// Pack relocations: dry run to estimate memory savings.
|
||||
packer.PackRelocations(*relocations, &packed);
|
||||
const size_t packed_bytes_estimate = packed.size() * sizeof(packed[0]);
|
||||
VLOG(1) << "Packed (no padding): " << packed_bytes_estimate << " bytes";
|
||||
|
||||
if (packed.empty()) {
|
||||
LOG(INFO) << "Too few relocations to pack";
|
||||
return true;
|
||||
}
|
||||
|
||||
// Pre-calculate the size of the hole we will close up when we rewrite
|
||||
// dynamic relocations. We have to adjust relocation addresses to
|
||||
// account for this.
|
||||
typename ELF::Shdr* section_header = ELF::getshdr(relocations_section_);
|
||||
ssize_t hole_size = initial_bytes - packed_bytes_estimate;
|
||||
|
||||
// hole_size needs to be page_aligned.
|
||||
hole_size -= hole_size % kPreserveAlignment;
|
||||
|
||||
LOG(INFO) << "Compaction : " << hole_size << " bytes";
|
||||
|
||||
// Adjusting for alignment may have removed any packing benefit.
|
||||
if (hole_size == 0) {
|
||||
LOG(INFO) << "Too few relocations to pack after alignment";
|
||||
return true;
|
||||
}
|
||||
|
||||
if (hole_size <= 0) {
|
||||
LOG(INFO) << "Packing relocations saves no space";
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t data_padding_bytes = is_padding_relocations_ ?
|
||||
initial_bytes - packed_bytes_estimate :
|
||||
initial_bytes - hole_size - packed_bytes_estimate;
|
||||
|
||||
// pad data
|
||||
std::vector<uint8_t> padding(data_padding_bytes, 0);
|
||||
packed.insert(packed.end(), padding.begin(), padding.end());
|
||||
|
||||
const void* packed_data = &packed[0];
|
||||
|
||||
// Run a loopback self-test as a check that packing is lossless.
|
||||
std::vector<Rela> unpacked;
|
||||
packer.UnpackRelocations(packed, &unpacked);
|
||||
CHECK(unpacked.size() == relocations->size());
|
||||
CHECK(!memcmp(&unpacked[0],
|
||||
&relocations->at(0),
|
||||
unpacked.size() * sizeof(unpacked[0])));
|
||||
|
||||
// Rewrite the current dynamic relocations section with packed one then shrink it to size.
|
||||
const size_t bytes = packed.size() * sizeof(packed[0]);
|
||||
ResizeSection(elf_, relocations_section_, bytes,
|
||||
relocations_type_ == REL ? SHT_ANDROID_REL : SHT_ANDROID_RELA, relocations_type_);
|
||||
RewriteSectionData(relocations_section_, packed_data, bytes);
|
||||
|
||||
// TODO (dimitry): fix string table and replace .rel.dyn/plt with .android.rel.dyn/plt
|
||||
|
||||
// Rewrite .dynamic and rename relocation tags describing the packed android
|
||||
// relocations.
|
||||
Elf_Data* data = GetSectionData(dynamic_section_);
|
||||
const typename ELF::Dyn* dynamic_base = reinterpret_cast<typename ELF::Dyn*>(data->d_buf);
|
||||
std::vector<typename ELF::Dyn> dynamics(
|
||||
dynamic_base,
|
||||
dynamic_base + data->d_size / sizeof(dynamics[0]));
|
||||
section_header = ELF::getshdr(relocations_section_);
|
||||
{
|
||||
typename ELF::Dyn dyn;
|
||||
dyn.d_tag = relocations_type_ == REL ? DT_ANDROID_REL : DT_ANDROID_RELA;
|
||||
dyn.d_un.d_ptr = section_header->sh_addr;
|
||||
ReplaceDynamicEntry<ELF>(relocations_type_ == REL ? DT_REL : DT_RELA, dyn, &dynamics);
|
||||
}
|
||||
{
|
||||
typename ELF::Dyn dyn;
|
||||
dyn.d_tag = relocations_type_ == REL ? DT_ANDROID_RELSZ : DT_ANDROID_RELASZ;
|
||||
dyn.d_un.d_val = section_header->sh_size;
|
||||
ReplaceDynamicEntry<ELF>(relocations_type_ == REL ? DT_RELSZ : DT_RELASZ, dyn, &dynamics);
|
||||
}
|
||||
|
||||
const void* dynamics_data = &dynamics[0];
|
||||
const size_t dynamics_bytes = dynamics.size() * sizeof(dynamics[0]);
|
||||
RewriteSectionData(dynamic_section_, dynamics_data, dynamics_bytes);
|
||||
|
||||
Flush();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Find packed relative relocations in the packed android relocations
|
||||
// section, unpack them, and rewrite the dynamic relocations section to
|
||||
// contain unpacked data.
|
||||
template <typename ELF>
|
||||
bool ElfFile<ELF>::UnpackRelocations() {
|
||||
// Load the ELF file into libelf.
|
||||
if (!Load()) {
|
||||
LOG(ERROR) << "Failed to load as ELF";
|
||||
return false;
|
||||
}
|
||||
|
||||
typename ELF::Shdr* section_header = ELF::getshdr(relocations_section_);
|
||||
// Retrieve the current packed android relocations section data.
|
||||
Elf_Data* data = GetSectionData(relocations_section_);
|
||||
|
||||
// Convert data to a vector of bytes.
|
||||
const uint8_t* packed_base = reinterpret_cast<uint8_t*>(data->d_buf);
|
||||
std::vector<uint8_t> packed(
|
||||
packed_base,
|
||||
packed_base + data->d_size / sizeof(packed[0]));
|
||||
|
||||
if ((section_header->sh_type == SHT_ANDROID_RELA || section_header->sh_type == SHT_ANDROID_REL) &&
|
||||
packed.size() > 3 &&
|
||||
packed[0] == 'A' &&
|
||||
packed[1] == 'P' &&
|
||||
packed[2] == 'S' &&
|
||||
packed[3] == '2') {
|
||||
LOG(INFO) << "Relocations : " << (relocations_type_ == REL ? "REL" : "RELA");
|
||||
} else {
|
||||
LOG(ERROR) << "Packed relocations not found (not packed?)";
|
||||
return false;
|
||||
}
|
||||
|
||||
return UnpackTypedRelocations(packed);
|
||||
}
|
||||
|
||||
// Helper for UnpackRelocations(). Rel type is one of ELF::Rel or ELF::Rela.
|
||||
template <typename ELF>
|
||||
bool ElfFile<ELF>::UnpackTypedRelocations(const std::vector<uint8_t>& packed) {
|
||||
// Unpack the data to re-materialize the relative relocations.
|
||||
const size_t packed_bytes = packed.size() * sizeof(packed[0]);
|
||||
LOG(INFO) << "Packed : " << packed_bytes << " bytes";
|
||||
std::vector<typename ELF::Rela> unpacked_relocations;
|
||||
RelocationPacker<ELF> packer;
|
||||
packer.UnpackRelocations(packed, &unpacked_relocations);
|
||||
|
||||
const size_t relocation_entry_size =
|
||||
relocations_type_ == REL ? sizeof(typename ELF::Rel) : sizeof(typename ELF::Rela);
|
||||
const size_t unpacked_bytes = unpacked_relocations.size() * relocation_entry_size;
|
||||
LOG(INFO) << "Unpacked : " << unpacked_bytes << " bytes";
|
||||
|
||||
// Retrieve the current dynamic relocations section data.
|
||||
Elf_Data* data = GetSectionData(relocations_section_);
|
||||
|
||||
LOG(INFO) << "Relocations : " << unpacked_relocations.size() << " entries";
|
||||
|
||||
// If we found the same number of null relocation entries in the dynamic
|
||||
// relocations section as we hold as unpacked relative relocations, then
|
||||
// this is a padded file.
|
||||
|
||||
const bool is_padded = packed_bytes == unpacked_bytes;
|
||||
|
||||
// Unless padded, pre-apply relative relocations to account for the
|
||||
// hole, and pre-adjust all relocation offsets accordingly.
|
||||
typename ELF::Shdr* section_header = ELF::getshdr(relocations_section_);
|
||||
|
||||
if (!is_padded) {
|
||||
LOG(INFO) << "Expansion : " << unpacked_bytes - packed_bytes << " bytes";
|
||||
}
|
||||
|
||||
// Rewrite the current dynamic relocations section with unpacked version of
|
||||
// relocations.
|
||||
const void* section_data = nullptr;
|
||||
std::vector<typename ELF::Rel> unpacked_rel_relocations;
|
||||
if (relocations_type_ == RELA) {
|
||||
section_data = &unpacked_relocations[0];
|
||||
} else if (relocations_type_ == REL) {
|
||||
ConvertRelaVectorToRelVector(unpacked_relocations, &unpacked_rel_relocations);
|
||||
section_data = &unpacked_rel_relocations[0];
|
||||
} else {
|
||||
NOTREACHED();
|
||||
}
|
||||
|
||||
ResizeSection(elf_, relocations_section_, unpacked_bytes,
|
||||
relocations_type_ == REL ? SHT_REL : SHT_RELA, relocations_type_);
|
||||
RewriteSectionData(relocations_section_, section_data, unpacked_bytes);
|
||||
|
||||
// Rewrite .dynamic to remove two tags describing packed android relocations.
|
||||
data = GetSectionData(dynamic_section_);
|
||||
const typename ELF::Dyn* dynamic_base = reinterpret_cast<typename ELF::Dyn*>(data->d_buf);
|
||||
std::vector<typename ELF::Dyn> dynamics(
|
||||
dynamic_base,
|
||||
dynamic_base + data->d_size / sizeof(dynamics[0]));
|
||||
{
|
||||
typename ELF::Dyn dyn;
|
||||
dyn.d_tag = relocations_type_ == REL ? DT_REL : DT_RELA;
|
||||
dyn.d_un.d_ptr = section_header->sh_addr;
|
||||
ReplaceDynamicEntry<ELF>(relocations_type_ == REL ? DT_ANDROID_REL : DT_ANDROID_RELA,
|
||||
dyn, &dynamics);
|
||||
}
|
||||
|
||||
{
|
||||
typename ELF::Dyn dyn;
|
||||
dyn.d_tag = relocations_type_ == REL ? DT_RELSZ : DT_RELASZ;
|
||||
dyn.d_un.d_val = section_header->sh_size;
|
||||
ReplaceDynamicEntry<ELF>(relocations_type_ == REL ? DT_ANDROID_RELSZ : DT_ANDROID_RELASZ,
|
||||
dyn, &dynamics);
|
||||
}
|
||||
|
||||
const void* dynamics_data = &dynamics[0];
|
||||
const size_t dynamics_bytes = dynamics.size() * sizeof(dynamics[0]);
|
||||
RewriteSectionData(dynamic_section_, dynamics_data, dynamics_bytes);
|
||||
|
||||
Flush();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Flush rewritten shared object file data.
|
||||
template <typename ELF>
|
||||
void ElfFile<ELF>::Flush() {
|
||||
// Flag all ELF data held in memory as needing to be written back to the
|
||||
// file, and tell libelf that we have controlled the file layout.
|
||||
elf_flagelf(elf_, ELF_C_SET, ELF_F_DIRTY);
|
||||
elf_flagelf(elf_, ELF_C_SET, ELF_F_LAYOUT);
|
||||
|
||||
// Write ELF data back to disk.
|
||||
const off_t file_bytes = elf_update(elf_, ELF_C_WRITE);
|
||||
if (file_bytes == -1) {
|
||||
LOG(ERROR) << "elf_update failed: " << elf_errmsg(elf_errno());
|
||||
}
|
||||
|
||||
CHECK(file_bytes > 0);
|
||||
VLOG(1) << "elf_update returned: " << file_bytes;
|
||||
|
||||
// Clean up libelf, and truncate the output file to the number of bytes
|
||||
// written by elf_update().
|
||||
elf_end(elf_);
|
||||
elf_ = NULL;
|
||||
const int truncate = ftruncate(fd_, file_bytes);
|
||||
CHECK(truncate == 0);
|
||||
}
|
||||
|
||||
template <typename ELF>
|
||||
void ElfFile<ELF>::ConvertRelArrayToRelaVector(const typename ELF::Rel* rel_array,
|
||||
size_t rel_array_size,
|
||||
std::vector<typename ELF::Rela>* rela_vector) {
|
||||
for (size_t i = 0; i<rel_array_size; ++i) {
|
||||
typename ELF::Rela rela;
|
||||
rela.r_offset = rel_array[i].r_offset;
|
||||
rela.r_info = rel_array[i].r_info;
|
||||
rela.r_addend = 0;
|
||||
rela_vector->push_back(rela);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename ELF>
|
||||
void ElfFile<ELF>::ConvertRelaVectorToRelVector(const std::vector<typename ELF::Rela>& rela_vector,
|
||||
std::vector<typename ELF::Rel>* rel_vector) {
|
||||
for (auto rela : rela_vector) {
|
||||
typename ELF::Rel rel;
|
||||
rel.r_offset = rela.r_offset;
|
||||
rel.r_info = rela.r_info;
|
||||
CHECK(rela.r_addend == 0);
|
||||
rel_vector->push_back(rel);
|
||||
}
|
||||
}
|
||||
|
||||
template class ElfFile<ELF32_traits>;
|
||||
template class ElfFile<ELF64_traits>;
|
||||
|
||||
} // namespace relocation_packer
|
121
third_party/android_platform/bionic/tools/relocation_packer/src/elf_file.h
vendored
Normal file
121
third_party/android_platform/bionic/tools/relocation_packer/src/elf_file.h
vendored
Normal file
@ -0,0 +1,121 @@
|
||||
// Copyright 2014 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// ELF shared object file updates handler.
|
||||
//
|
||||
// Provides functions to pack relocations in the .rel.dyn or .rela.dyn
|
||||
// sections, and unpack to return the file to its pre-packed state.
|
||||
//
|
||||
// SetPadding() causes PackRelocations() to pad .rel.dyn or .rela.dyn with
|
||||
// NONE-type entries rather than cutting a hole out of the shared object
|
||||
// file. This keeps all load addresses and offsets constant, and enables
|
||||
// easier debugging and testing.
|
||||
//
|
||||
// A packed shared object file is shorter than its non-packed original.
|
||||
// Unpacking a packed file restores the file to its non-packed state.
|
||||
|
||||
#ifndef TOOLS_RELOCATION_PACKER_SRC_ELF_FILE_H_
|
||||
#define TOOLS_RELOCATION_PACKER_SRC_ELF_FILE_H_
|
||||
|
||||
#include <string.h>
|
||||
#include <vector>
|
||||
|
||||
#include "elf.h"
|
||||
#include "libelf.h"
|
||||
#include "packer.h"
|
||||
|
||||
namespace relocation_packer {
|
||||
|
||||
// An ElfFile reads shared objects, and shuttles relative relocations
|
||||
// between .rel.dyn or .rela.dyn and .android.rel.dyn or .android.rela.dyn
|
||||
// sections.
|
||||
template <typename ELF>
|
||||
class ElfFile {
|
||||
public:
|
||||
explicit ElfFile(int fd)
|
||||
: fd_(fd), is_padding_relocations_(false), elf_(NULL),
|
||||
relocations_section_(NULL), dynamic_section_(NULL),
|
||||
relocations_type_(NONE), has_android_relocations_(false) {}
|
||||
~ElfFile() {}
|
||||
|
||||
// Set padding mode. When padding, PackRelocations() will not shrink
|
||||
// the .rel.dyn or .rela.dyn section, but instead replace relative with
|
||||
// NONE-type entries.
|
||||
// |flag| is true to pad .rel.dyn or .rela.dyn, false to shrink it.
|
||||
inline void SetPadding(bool flag) { is_padding_relocations_ = flag; }
|
||||
|
||||
// Transfer relative relocations from .rel.dyn or .rela.dyn to a packed
|
||||
// representation in .android.rel.dyn or .android.rela.dyn. Returns true
|
||||
// on success.
|
||||
bool PackRelocations();
|
||||
|
||||
// Transfer relative relocations from a packed representation in
|
||||
// .android.rel.dyn or .android.rela.dyn to .rel.dyn or .rela.dyn. Returns
|
||||
// true on success.
|
||||
bool UnpackRelocations();
|
||||
|
||||
private:
|
||||
enum relocations_type_t {
|
||||
NONE = 0, REL, RELA
|
||||
};
|
||||
|
||||
// Load a new ElfFile from a filedescriptor. If flushing, the file must
|
||||
// be open for read/write. Returns true on successful ELF file load.
|
||||
// |fd| is an open file descriptor for the shared object.
|
||||
bool Load();
|
||||
|
||||
// Templated packer, helper for PackRelocations(). Rel type is one of
|
||||
// ELF::Rel or ELF::Rela.
|
||||
bool PackTypedRelocations(std::vector<typename ELF::Rela>* relocations);
|
||||
|
||||
// Templated unpacker, helper for UnpackRelocations(). Rel type is one of
|
||||
// ELF::Rel or ELF::Rela.
|
||||
bool UnpackTypedRelocations(const std::vector<uint8_t>& packed);
|
||||
|
||||
// Write ELF file changes.
|
||||
void Flush();
|
||||
|
||||
void AdjustRelativeRelocationTargets(typename ELF::Off hole_start,
|
||||
ssize_t hole_size,
|
||||
std::vector<typename ELF::Rela>* relocations);
|
||||
|
||||
static void ResizeSection(Elf* elf, Elf_Scn* section, size_t new_size,
|
||||
typename ELF::Word new_sh_type, relocations_type_t relocations_type);
|
||||
|
||||
static void AdjustDynamicSectionForHole(Elf_Scn* dynamic_section,
|
||||
typename ELF::Off hole_start,
|
||||
ssize_t hole_size,
|
||||
relocations_type_t relocations_type);
|
||||
|
||||
static void ConvertRelArrayToRelaVector(const typename ELF::Rel* rel_array, size_t rel_array_size,
|
||||
std::vector<typename ELF::Rela>* rela_vector);
|
||||
|
||||
static void ConvertRelaVectorToRelVector(const std::vector<typename ELF::Rela>& rela_vector,
|
||||
std::vector<typename ELF::Rel>* rel_vector);
|
||||
|
||||
|
||||
// File descriptor opened on the shared object.
|
||||
int fd_;
|
||||
|
||||
// If set, pad rather than shrink .rel.dyn or .rela.dyn. Primarily for
|
||||
// debugging, allows packing to be checked without affecting load addresses.
|
||||
bool is_padding_relocations_;
|
||||
|
||||
// Libelf handle, assigned by Load().
|
||||
Elf* elf_;
|
||||
|
||||
// Sections that we manipulate, assigned by Load().
|
||||
Elf_Scn* relocations_section_;
|
||||
Elf_Scn* dynamic_section_;
|
||||
|
||||
// Relocation type found, assigned by Load().
|
||||
relocations_type_t relocations_type_;
|
||||
|
||||
// Elf-file has android relocations section
|
||||
bool has_android_relocations_;
|
||||
};
|
||||
|
||||
} // namespace relocation_packer
|
||||
|
||||
#endif // TOOLS_RELOCATION_PACKER_SRC_ELF_FILE_H_
|
218
third_party/android_platform/bionic/tools/relocation_packer/src/elf_file_unittest.cc
vendored
Normal file
218
third_party/android_platform/bionic/tools/relocation_packer/src/elf_file_unittest.cc
vendored
Normal file
@ -0,0 +1,218 @@
|
||||
// Copyright 2014 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "elf_file.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "debug.h"
|
||||
#include "elf_traits.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace {
|
||||
|
||||
void GetDataFilePath(const char* name, std::string* path) {
|
||||
std::string data_dir;
|
||||
|
||||
const char* bindir = getenv("bindir");
|
||||
if (bindir) {
|
||||
data_dir = std::string(bindir);
|
||||
} else {
|
||||
char path[PATH_MAX];
|
||||
memset(path, 0, sizeof(path));
|
||||
ASSERT_NE(-1, readlink("/proc/self/exe", path, sizeof(path) - 1));
|
||||
|
||||
data_dir = std::string(path);
|
||||
size_t pos = data_dir.rfind('/');
|
||||
ASSERT_NE(std::string::npos, pos);
|
||||
|
||||
data_dir.erase(pos);
|
||||
}
|
||||
|
||||
*path = data_dir + "/" + name;
|
||||
}
|
||||
|
||||
void OpenRelocsTestFile(const char* name, FILE** stream) {
|
||||
std::string path;
|
||||
GetDataFilePath(name, &path);
|
||||
|
||||
FILE* testfile = fopen(path.c_str(), "rb");
|
||||
ASSERT_FALSE(testfile == NULL) << "Error opening '" << path << "'";
|
||||
|
||||
FILE* temporary = tmpfile();
|
||||
ASSERT_FALSE(temporary == NULL);
|
||||
|
||||
static const size_t buffer_size = 4096;
|
||||
unsigned char buffer[buffer_size];
|
||||
|
||||
size_t bytes;
|
||||
do {
|
||||
bytes = fread(buffer, 1, sizeof(buffer), testfile);
|
||||
ASSERT_EQ(bytes, fwrite(buffer, 1, bytes, temporary));
|
||||
} while (bytes > 0);
|
||||
|
||||
ASSERT_EQ(0, fclose(testfile));
|
||||
ASSERT_EQ(0, fseek(temporary, 0, SEEK_SET));
|
||||
ASSERT_EQ(0, lseek(fileno(temporary), 0, SEEK_SET));
|
||||
|
||||
*stream = temporary;
|
||||
}
|
||||
|
||||
void OpenRelocsTestFiles(const std::string& arch, FILE** relocs_so, FILE** packed_relocs_so) {
|
||||
const std::string base = std::string("elf_file_unittest_relocs_") + arch;
|
||||
const std::string relocs = base + ".so";
|
||||
const std::string packed_relocs = base + "_packed.so";
|
||||
|
||||
OpenRelocsTestFile(relocs.c_str(), relocs_so);
|
||||
OpenRelocsTestFile(packed_relocs.c_str(), packed_relocs_so);
|
||||
}
|
||||
|
||||
void CloseRelocsTestFile(FILE* temporary) {
|
||||
fclose(temporary);
|
||||
}
|
||||
|
||||
void CloseRelocsTestFiles(FILE* relocs_so, FILE* packed_relocs_so) {
|
||||
CloseRelocsTestFile(relocs_so);
|
||||
CloseRelocsTestFile(packed_relocs_so);
|
||||
}
|
||||
|
||||
void CheckFileContentsEqual(FILE* first, FILE* second) {
|
||||
ASSERT_EQ(0, fseek(first, 0, SEEK_SET));
|
||||
ASSERT_EQ(0, fseek(second, 0, SEEK_SET));
|
||||
|
||||
static const size_t buffer_size = 4096;
|
||||
unsigned char first_buffer[buffer_size];
|
||||
unsigned char second_buffer[buffer_size];
|
||||
|
||||
do {
|
||||
size_t first_read = fread(first_buffer, 1, sizeof(first_buffer), first);
|
||||
size_t second_read = fread(second_buffer, 1, sizeof(second_buffer), second);
|
||||
|
||||
EXPECT_EQ(first_read, second_read);
|
||||
EXPECT_EQ(0, memcmp(first_buffer, second_buffer, first_read));
|
||||
} while (!feof(first) && !feof(second));
|
||||
|
||||
EXPECT_TRUE(feof(first) && feof(second));
|
||||
}
|
||||
|
||||
template <typename ELF>
|
||||
static void ProcessUnpack(FILE* relocs_so, FILE* packed_relocs_so) {
|
||||
relocation_packer::ElfFile<ELF> elf_file(fileno(packed_relocs_so));
|
||||
|
||||
// Ensure packing already packed elf-file does not fail the build.
|
||||
EXPECT_TRUE(elf_file.PackRelocations());
|
||||
|
||||
// Unpack golden relocations, and check files are now identical.
|
||||
EXPECT_TRUE(elf_file.UnpackRelocations());
|
||||
CheckFileContentsEqual(packed_relocs_so, relocs_so);
|
||||
|
||||
CloseRelocsTestFiles(relocs_so, packed_relocs_so);
|
||||
}
|
||||
|
||||
static void RunUnpackRelocationsTestFor(const std::string& arch) {
|
||||
ASSERT_NE(static_cast<uint32_t>(EV_NONE), elf_version(EV_CURRENT));
|
||||
|
||||
FILE* relocs_so = NULL;
|
||||
FILE* packed_relocs_so = NULL;
|
||||
OpenRelocsTestFiles(arch, &relocs_so, &packed_relocs_so);
|
||||
|
||||
if (relocs_so != NULL && packed_relocs_so != NULL) {
|
||||
// lets detect elf class
|
||||
ASSERT_EQ(0, fseek(relocs_so, EI_CLASS, SEEK_SET))
|
||||
<< "Invalid file length: " << strerror(errno);
|
||||
uint8_t elf_class = 0;
|
||||
ASSERT_EQ(1U, fread(&elf_class, 1, 1, relocs_so));
|
||||
ASSERT_EQ(0, fseek(relocs_so, 0, SEEK_SET));
|
||||
if (elf_class == ELFCLASS32) {
|
||||
ProcessUnpack<ELF32_traits>(relocs_so, packed_relocs_so);
|
||||
} else {
|
||||
ProcessUnpack<ELF64_traits>(relocs_so, packed_relocs_so);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename ELF>
|
||||
static void ProcessPack(FILE* relocs_so, FILE* packed_relocs_so) {
|
||||
relocation_packer::ElfFile<ELF> elf_file(fileno(relocs_so));
|
||||
|
||||
// Ensure unpacking fails (not packed).
|
||||
EXPECT_FALSE(elf_file.UnpackRelocations());
|
||||
|
||||
// Pack relocations, and check files are now identical.
|
||||
EXPECT_TRUE(elf_file.PackRelocations());
|
||||
CheckFileContentsEqual(relocs_so, packed_relocs_so);
|
||||
|
||||
CloseRelocsTestFiles(relocs_so, packed_relocs_so);
|
||||
}
|
||||
|
||||
static void RunPackRelocationsTestFor(const std::string& arch) {
|
||||
ASSERT_NE(static_cast<uint32_t>(EV_NONE), elf_version(EV_CURRENT));
|
||||
|
||||
FILE* relocs_so = NULL;
|
||||
FILE* packed_relocs_so = NULL;
|
||||
OpenRelocsTestFiles(arch, &relocs_so, &packed_relocs_so);
|
||||
|
||||
if (relocs_so != NULL && packed_relocs_so != NULL) {
|
||||
// lets detect elf class
|
||||
ASSERT_EQ(0, fseek(packed_relocs_so, EI_CLASS, SEEK_SET))
|
||||
<< "Invalid file length: " << strerror(errno);
|
||||
uint8_t elf_class = 0;
|
||||
ASSERT_EQ(1U, fread(&elf_class, 1, 1, packed_relocs_so));
|
||||
fseek(packed_relocs_so, 0, SEEK_SET);
|
||||
if (elf_class == ELFCLASS32) {
|
||||
ProcessPack<ELF32_traits>(relocs_so, packed_relocs_so);
|
||||
} else {
|
||||
ProcessPack<ELF64_traits>(relocs_so, packed_relocs_so);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace relocation_packer {
|
||||
|
||||
TEST(ElfFile, PackRelocationsArm32) {
|
||||
RunPackRelocationsTestFor("arm32");
|
||||
}
|
||||
|
||||
TEST(ElfFile, PackRelocationsArm64) {
|
||||
RunPackRelocationsTestFor("arm64");
|
||||
}
|
||||
|
||||
TEST(ElfFile, PackRelocationsMips32) {
|
||||
RunPackRelocationsTestFor("mips32");
|
||||
}
|
||||
|
||||
TEST(ElfFile, PackRelocationsIa32) {
|
||||
RunPackRelocationsTestFor("ia32");
|
||||
}
|
||||
|
||||
TEST(ElfFile, PackRelocationsX64) {
|
||||
RunPackRelocationsTestFor("x64");
|
||||
}
|
||||
|
||||
TEST(ElfFile, UnpackRelocationsArm32) {
|
||||
RunUnpackRelocationsTestFor("arm32");
|
||||
}
|
||||
|
||||
TEST(ElfFile, UnpackRelocationsArm64) {
|
||||
RunUnpackRelocationsTestFor("arm64");
|
||||
}
|
||||
|
||||
TEST(ElfFile, UnpackRelocationsMips32) {
|
||||
RunUnpackRelocationsTestFor("mips32");
|
||||
}
|
||||
|
||||
TEST(ElfFile, UnpackRelocationsIa32) {
|
||||
RunUnpackRelocationsTestFor("ia32");
|
||||
}
|
||||
|
||||
TEST(ElfFile, UnpackRelocationsX64) {
|
||||
RunUnpackRelocationsTestFor("x64");
|
||||
}
|
||||
|
||||
} // namespace relocation_packer
|
68
third_party/android_platform/bionic/tools/relocation_packer/src/elf_traits.h
vendored
Normal file
68
third_party/android_platform/bionic/tools/relocation_packer/src/elf_traits.h
vendored
Normal file
@ -0,0 +1,68 @@
|
||||
// Copyright 2014 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Target-specific ELF type traits.
|
||||
|
||||
#ifndef TOOLS_RELOCATION_PACKER_SRC_ELF_TRAITS_H_
|
||||
#define TOOLS_RELOCATION_PACKER_SRC_ELF_TRAITS_H_
|
||||
|
||||
#include "elf.h"
|
||||
#include "libelf.h"
|
||||
|
||||
#if !defined(DT_MIPS_RLD_MAP2)
|
||||
#define DT_MIPS_RLD_MAP2 0x70000035
|
||||
#endif
|
||||
|
||||
// ELF is a traits structure used to provide convenient aliases for
|
||||
// 32/64 bit Elf types and functions, depending on the target file.
|
||||
|
||||
struct ELF32_traits {
|
||||
typedef Elf32_Addr Addr;
|
||||
typedef Elf32_Dyn Dyn;
|
||||
typedef Elf32_Ehdr Ehdr;
|
||||
typedef Elf32_Off Off;
|
||||
typedef Elf32_Phdr Phdr;
|
||||
typedef Elf32_Rel Rel;
|
||||
typedef Elf32_Rela Rela;
|
||||
typedef Elf32_Shdr Shdr;
|
||||
typedef Elf32_Sword Sword;
|
||||
typedef Elf32_Sxword Sxword;
|
||||
typedef Elf32_Sym Sym;
|
||||
typedef Elf32_Word Word;
|
||||
typedef Elf32_Xword Xword;
|
||||
typedef Elf32_Half Half;
|
||||
|
||||
static inline Ehdr* getehdr(Elf* elf) { return elf32_getehdr(elf); }
|
||||
static inline Phdr* getphdr(Elf* elf) { return elf32_getphdr(elf); }
|
||||
static inline Shdr* getshdr(Elf_Scn* scn) { return elf32_getshdr(scn); }
|
||||
static inline Word elf_r_type(Word info) { return ELF32_R_TYPE(info); }
|
||||
static inline int elf_st_type(uint8_t info) { return ELF32_ST_TYPE(info); }
|
||||
static inline Word elf_r_sym(Word info) { return ELF32_R_SYM(info); }
|
||||
};
|
||||
|
||||
struct ELF64_traits {
|
||||
typedef Elf64_Addr Addr;
|
||||
typedef Elf64_Dyn Dyn;
|
||||
typedef Elf64_Ehdr Ehdr;
|
||||
typedef Elf64_Off Off;
|
||||
typedef Elf64_Phdr Phdr;
|
||||
typedef Elf64_Rel Rel;
|
||||
typedef Elf64_Rela Rela;
|
||||
typedef Elf64_Shdr Shdr;
|
||||
typedef Elf64_Sword Sword;
|
||||
typedef Elf64_Sxword Sxword;
|
||||
typedef Elf64_Sym Sym;
|
||||
typedef Elf64_Word Word;
|
||||
typedef Elf64_Xword Xword;
|
||||
typedef Elf64_Half Half;
|
||||
|
||||
static inline Ehdr* getehdr(Elf* elf) { return elf64_getehdr(elf); }
|
||||
static inline Phdr* getphdr(Elf* elf) { return elf64_getphdr(elf); }
|
||||
static inline Shdr* getshdr(Elf_Scn* scn) { return elf64_getshdr(scn); }
|
||||
static inline Xword elf_r_type(Xword info) { return ELF64_R_TYPE(info); }
|
||||
static inline int elf_st_type(uint8_t info) { return ELF64_ST_TYPE(info); }
|
||||
static inline Word elf_r_sym(Xword info) { return ELF64_R_SYM(info); }
|
||||
};
|
||||
|
||||
#endif // TOOLS_RELOCATION_PACKER_SRC_ELF_TRAITS_H_
|
150
third_party/android_platform/bionic/tools/relocation_packer/src/main.cc
vendored
Normal file
150
third_party/android_platform/bionic/tools/relocation_packer/src/main.cc
vendored
Normal file
@ -0,0 +1,150 @@
|
||||
// Copyright 2014 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Tool to pack and unpack relative relocations in a shared library.
|
||||
//
|
||||
// Invoke with -v to trace actions taken when packing or unpacking.
|
||||
// Invoke with -p to pad removed relocations with R_*_NONE. Suppresses
|
||||
// shrinking of .rel.dyn.
|
||||
// See PrintUsage() below for full usage details.
|
||||
//
|
||||
// NOTE: Breaks with libelf 0.152, which is buggy. libelf 0.158 works.
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <string>
|
||||
|
||||
#include "debug.h"
|
||||
#include "elf_file.h"
|
||||
#include "elf_traits.h"
|
||||
#include "libelf.h"
|
||||
|
||||
#include "nativehelper/ScopedFd.h"
|
||||
|
||||
static void PrintUsage(const char* argv0) {
|
||||
std::string temporary = argv0;
|
||||
const size_t last_slash = temporary.find_last_of("/");
|
||||
if (last_slash != temporary.npos) {
|
||||
temporary.erase(0, last_slash + 1);
|
||||
}
|
||||
const char* basename = temporary.c_str();
|
||||
|
||||
printf(
|
||||
"Usage: %s [-u] [-v] [-p] file\n\n"
|
||||
"Pack or unpack relative relocations in a shared library.\n\n"
|
||||
" -u, --unpack unpack previously packed relative relocations\n"
|
||||
" -v, --verbose trace object file modifications (for debugging)\n"
|
||||
" -p, --pad do not shrink relocations, but pad (for debugging)\n\n",
|
||||
basename);
|
||||
|
||||
printf(
|
||||
"Debug sections are not handled, so packing should not be used on\n"
|
||||
"shared libraries compiled for debugging or otherwise unstripped.\n");
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
bool is_unpacking = false;
|
||||
bool is_verbose = false;
|
||||
bool is_padding = false;
|
||||
|
||||
static const option options[] = {
|
||||
{"unpack", 0, 0, 'u'}, {"verbose", 0, 0, 'v'}, {"pad", 0, 0, 'p'},
|
||||
{"help", 0, 0, 'h'}, {NULL, 0, 0, 0}
|
||||
};
|
||||
bool has_options = true;
|
||||
while (has_options) {
|
||||
int c = getopt_long(argc, argv, "uvph", options, NULL);
|
||||
switch (c) {
|
||||
case 'u':
|
||||
is_unpacking = true;
|
||||
break;
|
||||
case 'v':
|
||||
is_verbose = true;
|
||||
break;
|
||||
case 'p':
|
||||
is_padding = true;
|
||||
break;
|
||||
case 'h':
|
||||
PrintUsage(argv[0]);
|
||||
return 0;
|
||||
case '?':
|
||||
LOG(INFO) << "Try '" << argv[0] << " --help' for more information.";
|
||||
return 1;
|
||||
case -1:
|
||||
has_options = false;
|
||||
break;
|
||||
default:
|
||||
NOTREACHED();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (optind != argc - 1) {
|
||||
LOG(INFO) << "Try '" << argv[0] << " --help' for more information.";
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (elf_version(EV_CURRENT) == EV_NONE) {
|
||||
LOG(WARNING) << "Elf Library is out of date!";
|
||||
}
|
||||
|
||||
const char* file = argv[argc - 1];
|
||||
ScopedFd fd(open(file, O_RDWR));
|
||||
if (fd.get() == -1) {
|
||||
LOG(ERROR) << file << ": " << strerror(errno);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (is_verbose)
|
||||
relocation_packer::Logger::SetVerbose(1);
|
||||
|
||||
// We need to detect elf class in order to create
|
||||
// correct implementation
|
||||
uint8_t e_ident[EI_NIDENT];
|
||||
if (TEMP_FAILURE_RETRY(read(fd.get(), e_ident, EI_NIDENT) != EI_NIDENT)) {
|
||||
LOG(ERROR) << file << ": failed to read elf header:" << strerror(errno);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (TEMP_FAILURE_RETRY(lseek(fd.get(), 0, SEEK_SET)) != 0) {
|
||||
LOG(ERROR) << file << ": lseek to 0 failed:" << strerror(errno);
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool status = false;
|
||||
|
||||
if (e_ident[EI_CLASS] == ELFCLASS32) {
|
||||
relocation_packer::ElfFile<ELF32_traits> elf_file(fd.get());
|
||||
elf_file.SetPadding(is_padding);
|
||||
|
||||
if (is_unpacking) {
|
||||
status = elf_file.UnpackRelocations();
|
||||
} else {
|
||||
status = elf_file.PackRelocations();
|
||||
}
|
||||
} else if (e_ident[EI_CLASS] == ELFCLASS64) {
|
||||
relocation_packer::ElfFile<ELF64_traits> elf_file(fd.get());
|
||||
elf_file.SetPadding(is_padding);
|
||||
|
||||
if (is_unpacking) {
|
||||
status = elf_file.UnpackRelocations();
|
||||
} else {
|
||||
status = elf_file.PackRelocations();
|
||||
}
|
||||
} else {
|
||||
LOG(ERROR) << file << ": unknown ELFCLASS: " << e_ident[EI_CLASS];
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!status) {
|
||||
LOG(ERROR) << file << ": failed to pack/unpack file";
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
62
third_party/android_platform/bionic/tools/relocation_packer/src/nativehelper/ScopedFd.h
vendored
Normal file
62
third_party/android_platform/bionic/tools/relocation_packer/src/nativehelper/ScopedFd.h
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (C) 2009 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef SCOPED_FD_H_included
|
||||
#define SCOPED_FD_H_included
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
// Local definition of DISALLOW_COPY_AND_ASSIGN, avoids depending on base.
|
||||
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
|
||||
TypeName(const TypeName&); \
|
||||
void operator=(const TypeName&)
|
||||
|
||||
// A smart pointer that closes the given fd on going out of scope.
|
||||
// Use this when the fd is incidental to the purpose of your function,
|
||||
// but needs to be cleaned up on exit.
|
||||
class ScopedFd {
|
||||
public:
|
||||
explicit ScopedFd(int fd) : fd_(fd) {
|
||||
}
|
||||
|
||||
~ScopedFd() {
|
||||
reset();
|
||||
}
|
||||
|
||||
int get() const {
|
||||
return fd_;
|
||||
}
|
||||
|
||||
int release() __attribute__((warn_unused_result)) {
|
||||
int localFd = fd_;
|
||||
fd_ = -1;
|
||||
return localFd;
|
||||
}
|
||||
|
||||
void reset(int new_fd = -1) {
|
||||
if (fd_ != -1) {
|
||||
TEMP_FAILURE_RETRY(close(fd_));
|
||||
}
|
||||
fd_ = new_fd;
|
||||
}
|
||||
|
||||
private:
|
||||
int fd_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ScopedFd);
|
||||
};
|
||||
|
||||
#endif // SCOPED_FD_H_included
|
67
third_party/android_platform/bionic/tools/relocation_packer/src/packer.cc
vendored
Normal file
67
third_party/android_platform/bionic/tools/relocation_packer/src/packer.cc
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
// Copyright 2014 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "packer.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "debug.h"
|
||||
#include "delta_encoder.h"
|
||||
#include "elf_traits.h"
|
||||
#include "sleb128.h"
|
||||
|
||||
namespace relocation_packer {
|
||||
|
||||
// Pack relocations into a group encoded packed representation.
|
||||
template <typename ELF>
|
||||
void RelocationPacker<ELF>::PackRelocations(const std::vector<typename ELF::Rela>& relocations,
|
||||
std::vector<uint8_t>* packed) {
|
||||
// Run-length encode.
|
||||
std::vector<typename ELF::Addr> packed_words;
|
||||
RelocationDeltaCodec<ELF> codec;
|
||||
codec.Encode(relocations, &packed_words);
|
||||
|
||||
// If insufficient data do nothing.
|
||||
if (packed_words.empty())
|
||||
return;
|
||||
|
||||
Sleb128Encoder<typename ELF::Addr> sleb128_encoder;
|
||||
|
||||
std::vector<uint8_t> sleb128_packed;
|
||||
|
||||
sleb128_encoder.EnqueueAll(packed_words);
|
||||
sleb128_encoder.GetEncoding(&sleb128_packed);
|
||||
|
||||
packed->push_back('A');
|
||||
packed->push_back('P');
|
||||
packed->push_back('S');
|
||||
packed->push_back('2');
|
||||
packed->insert(packed->end(), sleb128_packed.begin(), sleb128_packed.end());
|
||||
}
|
||||
|
||||
// Unpack relative relocations from a run-length encoded packed
|
||||
// representation.
|
||||
template <typename ELF>
|
||||
void RelocationPacker<ELF>::UnpackRelocations(
|
||||
const std::vector<uint8_t>& packed,
|
||||
std::vector<typename ELF::Rela>* relocations) {
|
||||
|
||||
std::vector<typename ELF::Addr> packed_words;
|
||||
CHECK(packed.size() > 4 &&
|
||||
packed[0] == 'A' &&
|
||||
packed[1] == 'P' &&
|
||||
packed[2] == 'S' &&
|
||||
packed[3] == '2');
|
||||
|
||||
Sleb128Decoder<typename ELF::Addr> decoder(packed, 4);
|
||||
decoder.DequeueAll(&packed_words);
|
||||
|
||||
RelocationDeltaCodec<ELF> codec;
|
||||
codec.Decode(packed_words, relocations);
|
||||
}
|
||||
|
||||
template class RelocationPacker<ELF32_traits>;
|
||||
template class RelocationPacker<ELF64_traits>;
|
||||
|
||||
} // namespace relocation_packer
|
37
third_party/android_platform/bionic/tools/relocation_packer/src/packer.h
vendored
Normal file
37
third_party/android_platform/bionic/tools/relocation_packer/src/packer.h
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
// Copyright 2014 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Pack relative relocations into a more compact form.
|
||||
|
||||
#ifndef TOOLS_RELOCATION_PACKER_SRC_PACKER_H_
|
||||
#define TOOLS_RELOCATION_PACKER_SRC_PACKER_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
#include "elf.h"
|
||||
|
||||
namespace relocation_packer {
|
||||
|
||||
// A RelocationPacker packs vectors of relocations into more
|
||||
// compact forms, and unpacks them to reproduce the pre-packed data.
|
||||
template <typename ELF>
|
||||
class RelocationPacker {
|
||||
public:
|
||||
// Pack relocations into a more compact form.
|
||||
// |relocations| is a vector of relocation structs.
|
||||
// |packed| is the vector of packed bytes into which relocations are packed.
|
||||
static void PackRelocations(const std::vector<typename ELF::Rela>& relocations,
|
||||
std::vector<uint8_t>* packed);
|
||||
|
||||
// Unpack relocations from their more compact form.
|
||||
// |packed| is the vector of packed relocations.
|
||||
// |relocations| is a vector of unpacked relocation structs.
|
||||
static void UnpackRelocations(const std::vector<uint8_t>& packed,
|
||||
std::vector<typename ELF::Rela>* relocations);
|
||||
};
|
||||
|
||||
} // namespace relocation_packer
|
||||
|
||||
#endif // TOOLS_RELOCATION_PACKER_SRC_PACKER_H_
|
300
third_party/android_platform/bionic/tools/relocation_packer/src/packer_unittest.cc
vendored
Normal file
300
third_party/android_platform/bionic/tools/relocation_packer/src/packer_unittest.cc
vendored
Normal file
@ -0,0 +1,300 @@
|
||||
// Copyright 2014 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "packer.h"
|
||||
|
||||
#include <vector>
|
||||
#include "elf.h"
|
||||
#include "elf_traits.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
|
||||
template <typename ELF>
|
||||
static void AddRelocation(typename ELF::Addr addr,
|
||||
typename ELF::Xword info,
|
||||
typename ELF::Sxword addend,
|
||||
std::vector<typename ELF::Rela>* relocations) {
|
||||
typename ELF::Rela relocation;
|
||||
relocation.r_offset = addr;
|
||||
relocation.r_info = info;
|
||||
relocation.r_addend = addend;
|
||||
|
||||
relocations->push_back(relocation);
|
||||
}
|
||||
|
||||
template <typename ELF>
|
||||
static bool CheckRelocation(typename ELF::Addr addr,
|
||||
typename ELF::Xword info,
|
||||
typename ELF::Sxword addend,
|
||||
const typename ELF::Rela& relocation) {
|
||||
return relocation.r_offset == addr &&
|
||||
relocation.r_info == info &&
|
||||
relocation.r_addend == addend;
|
||||
}
|
||||
|
||||
namespace relocation_packer {
|
||||
|
||||
template <typename ELF>
|
||||
static void DoPackNoAddend() {
|
||||
std::vector<typename ELF::Rela> relocations;
|
||||
std::vector<uint8_t> packed;
|
||||
bool is_32 = sizeof(typename ELF::Addr) == 4;
|
||||
// Initial relocation.
|
||||
AddRelocation<ELF>(0xd1ce0000, 0x11, 0, &relocations);
|
||||
// Two more relocations, 4 byte deltas.
|
||||
AddRelocation<ELF>(0xd1ce0004, 0x11, 0, &relocations);
|
||||
AddRelocation<ELF>(0xd1ce0008, 0x11, 0, &relocations);
|
||||
// Three more relocations, 8 byte deltas.
|
||||
AddRelocation<ELF>(0xd1ce0010, 0x11, 0, &relocations);
|
||||
AddRelocation<ELF>(0xd1ce0018, 0x11, 0, &relocations);
|
||||
AddRelocation<ELF>(0xd1ce0020, 0x11, 0, &relocations);
|
||||
|
||||
RelocationPacker<ELF> packer;
|
||||
|
||||
packed.clear();
|
||||
packer.PackRelocations(relocations, &packed);
|
||||
|
||||
ASSERT_EQ(18U, packed.size());
|
||||
// Identifier.
|
||||
size_t ndx = 0;
|
||||
EXPECT_EQ('A', packed[ndx++]);
|
||||
EXPECT_EQ('P', packed[ndx++]);
|
||||
EXPECT_EQ('S', packed[ndx++]);
|
||||
EXPECT_EQ('2', packed[ndx++]);
|
||||
// relocation count
|
||||
EXPECT_EQ(6, packed[ndx++]);
|
||||
// base relocation = 0xd1cdfffc -> fc, ff, b7, 8e, 7d/0d (32/64bit)
|
||||
EXPECT_EQ(0xfc, packed[ndx++]);
|
||||
EXPECT_EQ(0xff, packed[ndx++]);
|
||||
EXPECT_EQ(0xb7, packed[ndx++]);
|
||||
EXPECT_EQ(0x8e, packed[ndx++]);
|
||||
EXPECT_EQ(is_32 ? 0x7d : 0x0d, packed[ndx++]);
|
||||
// first group
|
||||
EXPECT_EQ(3, packed[ndx++]); // size
|
||||
EXPECT_EQ(3, packed[ndx++]); // flags
|
||||
EXPECT_EQ(4, packed[ndx++]); // r_offset_delta
|
||||
EXPECT_EQ(0x11, packed[ndx++]); // r_info
|
||||
// second group
|
||||
EXPECT_EQ(3, packed[ndx++]); // size
|
||||
EXPECT_EQ(3, packed[ndx++]); // flags
|
||||
EXPECT_EQ(8, packed[ndx++]); // r_offset_delta
|
||||
EXPECT_EQ(0x11, packed[ndx++]); // r_info
|
||||
|
||||
EXPECT_EQ(ndx, packed.size());
|
||||
}
|
||||
|
||||
TEST(Packer, PackNoAddend32) {
|
||||
DoPackNoAddend<ELF32_traits>();
|
||||
}
|
||||
|
||||
TEST(Packer, PackNoAddend64) {
|
||||
DoPackNoAddend<ELF64_traits>();
|
||||
}
|
||||
|
||||
template <typename ELF>
|
||||
static void DoUnpackNoAddend() {
|
||||
std::vector<typename ELF::Rela> relocations;
|
||||
std::vector<uint8_t> packed;
|
||||
bool is_32 = sizeof(typename ELF::Addr) == 4;
|
||||
packed.push_back('A');
|
||||
packed.push_back('P');
|
||||
packed.push_back('S');
|
||||
packed.push_back('2');
|
||||
// relocation count
|
||||
packed.push_back(6);
|
||||
// base relocation = 0xd1cdfffc -> fc, ff, b7, 8e, 7d/0d (32/64bit)
|
||||
packed.push_back(0xfc);
|
||||
packed.push_back(0xff);
|
||||
packed.push_back(0xb7);
|
||||
packed.push_back(0x8e);
|
||||
packed.push_back(is_32 ? 0x7d : 0x0d);
|
||||
// first group
|
||||
packed.push_back(3); // size
|
||||
packed.push_back(3); // flags
|
||||
packed.push_back(4); // r_offset_delta
|
||||
packed.push_back(0x11); // r_info
|
||||
// second group
|
||||
packed.push_back(3); // size
|
||||
packed.push_back(3); // flags
|
||||
packed.push_back(8); // r_offset_delta
|
||||
packed.push_back(0x11); // r_info
|
||||
|
||||
RelocationPacker<ELF> packer;
|
||||
packer.UnpackRelocations(packed, &relocations);
|
||||
|
||||
size_t ndx = 0;
|
||||
EXPECT_EQ(6U, relocations.size());
|
||||
EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0000, 0x11, 0, relocations[ndx++]));
|
||||
EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0004, 0x11, 0, relocations[ndx++]));
|
||||
EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0008, 0x11, 0, relocations[ndx++]));
|
||||
|
||||
EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0010, 0x11, 0, relocations[ndx++]));
|
||||
EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0018, 0x11, 0, relocations[ndx++]));
|
||||
EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0020, 0x11, 0, relocations[ndx++]));
|
||||
|
||||
EXPECT_EQ(ndx, relocations.size());
|
||||
}
|
||||
|
||||
TEST(Packer, UnpackNoAddend32) {
|
||||
DoUnpackNoAddend<ELF32_traits>();
|
||||
}
|
||||
|
||||
TEST(Packer, UnpackNoAddend64) {
|
||||
DoUnpackNoAddend<ELF64_traits>();
|
||||
}
|
||||
|
||||
template <typename ELF>
|
||||
static void DoPackWithAddend() {
|
||||
std::vector<typename ELF::Rela> relocations;
|
||||
|
||||
// Initial relocation.
|
||||
AddRelocation<ELF>(0xd1ce0000, 0x01, 10024, &relocations);
|
||||
// Two more relocations, 4 byte offset deltas, 12 byte addend deltas.
|
||||
AddRelocation<ELF>(0xd1ce0004, 0x01, 10012, &relocations);
|
||||
AddRelocation<ELF>(0xd1ce0008, 0x01, 10024, &relocations);
|
||||
// Three more relocations, 8 byte deltas, -24 byte addend deltas.
|
||||
AddRelocation<ELF>(0xd1ce0010, 0x01, 10000, &relocations);
|
||||
AddRelocation<ELF>(0xd1ce0018, 0x01, 9976, &relocations);
|
||||
AddRelocation<ELF>(0xd1ce0020, 0x01, 9952, &relocations);
|
||||
|
||||
std::vector<uint8_t> packed;
|
||||
|
||||
RelocationPacker<ELF> packer;
|
||||
|
||||
packed.clear();
|
||||
packer.PackRelocations(relocations, &packed);
|
||||
|
||||
EXPECT_EQ(26U, packed.size());
|
||||
size_t ndx = 0;
|
||||
// Identifier.
|
||||
EXPECT_EQ('A', packed[ndx++]);
|
||||
EXPECT_EQ('P', packed[ndx++]);
|
||||
EXPECT_EQ('S', packed[ndx++]);
|
||||
EXPECT_EQ('2', packed[ndx++]);
|
||||
// Relocation count
|
||||
EXPECT_EQ(6U, packed[ndx++]);
|
||||
// base relocation = 0xd1cdfffc -> fc, ff, b7, 8e, 0d/7d (depending on ELF::Addr)
|
||||
EXPECT_EQ(0xfc, packed[ndx++]);
|
||||
EXPECT_EQ(0xff, packed[ndx++]);
|
||||
EXPECT_EQ(0xb7, packed[ndx++]);
|
||||
EXPECT_EQ(0x8e, packed[ndx++]);
|
||||
if (sizeof(typename ELF::Addr) == 8) {
|
||||
// positive for uint64_t
|
||||
EXPECT_EQ(0x0d, packed[ndx++]);
|
||||
} else {
|
||||
// negative for uint32_t
|
||||
EXPECT_EQ(0x7d, packed[ndx++]);
|
||||
}
|
||||
// group 1
|
||||
EXPECT_EQ(0x03, packed[ndx++]); // size
|
||||
EXPECT_EQ(0x0b, packed[ndx++]); // flags
|
||||
EXPECT_EQ(0x04, packed[ndx++]); // r_offset_delta
|
||||
EXPECT_EQ(0x01, packed[ndx++]); // r_info
|
||||
// group 1 - addend 1: 10024 = 0xa8, 0xce, 0x80
|
||||
EXPECT_EQ(0xa8, packed[ndx++]);
|
||||
EXPECT_EQ(0xce, packed[ndx++]);
|
||||
EXPECT_EQ(0x00, packed[ndx++]);
|
||||
// group 1 - addend 2: -12 = 0x74
|
||||
EXPECT_EQ(0x74, packed[ndx++]);
|
||||
// group 1 - addend 3: +12 = 0x0c
|
||||
EXPECT_EQ(0x0c, packed[ndx++]);
|
||||
|
||||
// group 2
|
||||
EXPECT_EQ(0x03, packed[ndx++]); // size
|
||||
EXPECT_EQ(0x0b, packed[ndx++]); // flags
|
||||
EXPECT_EQ(0x08, packed[ndx++]); // r_offset_delta
|
||||
EXPECT_EQ(0x01, packed[ndx++]); // r_info
|
||||
|
||||
// group 2 - addend 1: -24 = 0x68
|
||||
EXPECT_EQ(0x68, packed[ndx++]);
|
||||
// group 2 - addend 2: -24 = 0x68
|
||||
EXPECT_EQ(0x68, packed[ndx++]);
|
||||
// group 2 - addend 3: -24 = 0x68
|
||||
EXPECT_EQ(0x68, packed[ndx++]);
|
||||
|
||||
EXPECT_EQ(ndx, packed.size());
|
||||
}
|
||||
|
||||
TEST(Packer, PackWithAddend) {
|
||||
DoPackWithAddend<ELF32_traits>();
|
||||
DoPackWithAddend<ELF64_traits>();
|
||||
}
|
||||
|
||||
template <typename ELF>
|
||||
static void DoUnpackWithAddend() {
|
||||
std::vector<uint8_t> packed;
|
||||
// Identifier.
|
||||
packed.push_back('A');
|
||||
packed.push_back('P');
|
||||
packed.push_back('S');
|
||||
packed.push_back('2');
|
||||
// Relocation count
|
||||
packed.push_back(6U);
|
||||
// base relocation = 0xd1cdfffc -> fc, ff, b7, 8e, 0d
|
||||
packed.push_back(0xfc);
|
||||
packed.push_back(0xff);
|
||||
packed.push_back(0xb7);
|
||||
packed.push_back(0x8e);
|
||||
if (sizeof(typename ELF::Addr) == 8) {
|
||||
// positive for uint64_t
|
||||
packed.push_back(0x0d);
|
||||
} else {
|
||||
// negative for uint32_t
|
||||
packed.push_back(0x7d);
|
||||
}
|
||||
// group 1
|
||||
packed.push_back(0x03); // size
|
||||
packed.push_back(0x0b); // flags
|
||||
packed.push_back(0x04); // r_offset_delta
|
||||
packed.push_back(0x01); // r_info
|
||||
// group 1 - addend 1: 10024 = 0xa8, 0xce, 0x80
|
||||
packed.push_back(0xa8);
|
||||
packed.push_back(0xce);
|
||||
packed.push_back(0x00);
|
||||
// group 1 - addend 2: -12 = 0x74
|
||||
packed.push_back(0x74);
|
||||
// group 1 - addend 3: +12 = 0x0c
|
||||
packed.push_back(0x0c);
|
||||
|
||||
// group 2
|
||||
packed.push_back(0x03); // size
|
||||
packed.push_back(0x0b); // flags
|
||||
packed.push_back(0x08); // r_offset_delta
|
||||
packed.push_back(0x01); // r_info
|
||||
|
||||
// group 2 - addend 1: -24 = 0x68
|
||||
packed.push_back(0x68);
|
||||
// group 2 - addend 2: -24 = 0x68
|
||||
packed.push_back(0x68);
|
||||
// group 2 - addend 3: -24 = 0x68
|
||||
packed.push_back(0x68);
|
||||
|
||||
std::vector<typename ELF::Rela> relocations;
|
||||
|
||||
RelocationPacker<ELF> packer;
|
||||
|
||||
relocations.clear();
|
||||
packer.UnpackRelocations(packed, &relocations);
|
||||
|
||||
EXPECT_EQ(6U, relocations.size());
|
||||
size_t ndx = 0;
|
||||
// Initial relocation.
|
||||
EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0000, 0x01, 10024, relocations[ndx++]));
|
||||
// Two more relocations, 4 byte offset deltas, 12 byte addend deltas.
|
||||
EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0004, 0x01, 10012, relocations[ndx++]));
|
||||
EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0008, 0x01, 10024, relocations[ndx++]));
|
||||
// Three more relocations, 8 byte offset deltas, -24 byte addend deltas.
|
||||
EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0010, 0x01, 10000, relocations[ndx++]));
|
||||
EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0018, 0x01, 9976, relocations[ndx++]));
|
||||
EXPECT_TRUE(CheckRelocation<ELF>(0xd1ce0020, 0x01, 9952, relocations[ndx++]));
|
||||
|
||||
EXPECT_EQ(ndx, relocations.size());
|
||||
}
|
||||
|
||||
TEST(Packer, UnpackWithAddend) {
|
||||
DoUnpackWithAddend<ELF32_traits>();
|
||||
DoUnpackWithAddend<ELF64_traits>();
|
||||
}
|
||||
|
||||
} // namespace relocation_packer
|
10
third_party/android_platform/bionic/tools/relocation_packer/src/run_all_unittests.cc
vendored
Normal file
10
third_party/android_platform/bionic/tools/relocation_packer/src/run_all_unittests.cc
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
// Copyright 2014 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
131
third_party/android_platform/bionic/tools/relocation_packer/src/sleb128.cc
vendored
Normal file
131
third_party/android_platform/bionic/tools/relocation_packer/src/sleb128.cc
vendored
Normal file
@ -0,0 +1,131 @@
|
||||
// Copyright 2014 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "sleb128.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
#include "elf_traits.h"
|
||||
|
||||
namespace {
|
||||
|
||||
template <typename T>
|
||||
class uint_traits {};
|
||||
|
||||
template <>
|
||||
class uint_traits<uint64_t> {
|
||||
public:
|
||||
typedef int64_t int_t;
|
||||
};
|
||||
|
||||
template <>
|
||||
class uint_traits<uint32_t> {
|
||||
public:
|
||||
typedef int32_t int_t;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace relocation_packer {
|
||||
|
||||
// Empty constructor and destructor to silence chromium-style.
|
||||
template <typename uint_t>
|
||||
Sleb128Encoder<uint_t>::Sleb128Encoder() { }
|
||||
|
||||
template <typename uint_t>
|
||||
Sleb128Encoder<uint_t>::~Sleb128Encoder() { }
|
||||
|
||||
// Add a single value to the encoding. Values are encoded with variable
|
||||
// length. The least significant 7 bits of each byte hold 7 bits of data,
|
||||
// and the most significant bit is set on each byte except the last. The
|
||||
// value is sign extended up to a multiple of 7 bits (ensuring that the
|
||||
// most significant bit is zero for a positive number and one for a
|
||||
// negative number).
|
||||
template <typename uint_t>
|
||||
void Sleb128Encoder<uint_t>::Enqueue(uint_t value) {
|
||||
typedef typename uint_traits<uint_t>::int_t int_t;
|
||||
static const size_t size = CHAR_BIT * sizeof(value);
|
||||
|
||||
bool more = true;
|
||||
const bool negative = static_cast<int_t>(value) < 0;
|
||||
|
||||
while (more) {
|
||||
uint8_t byte = value & 127;
|
||||
value >>= 7;
|
||||
|
||||
// Sign extend if encoding a -ve value.
|
||||
if (negative)
|
||||
value |= -(static_cast<uint_t>(1) << (size - 7));
|
||||
|
||||
// The sign bit of byte is second high order bit.
|
||||
const bool sign_bit = byte & 64;
|
||||
if ((value == 0 && !sign_bit) || (value == static_cast<uint_t>(-1) && sign_bit))
|
||||
more = false;
|
||||
else
|
||||
byte |= 128;
|
||||
encoding_.push_back(byte);
|
||||
}
|
||||
}
|
||||
|
||||
// Add a vector of values to the encoding.
|
||||
template <typename uint_t>
|
||||
void Sleb128Encoder<uint_t>::EnqueueAll(const std::vector<uint_t>& values) {
|
||||
for (size_t i = 0; i < values.size(); ++i) {
|
||||
Enqueue(values[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Create a new decoder for the given encoded stream.
|
||||
template <typename uint_t>
|
||||
Sleb128Decoder<uint_t>::Sleb128Decoder(const std::vector<uint8_t>& encoding, size_t start_with) {
|
||||
encoding_ = encoding;
|
||||
cursor_ = start_with;
|
||||
}
|
||||
|
||||
// Empty destructor to silence chromium-style.
|
||||
template <typename uint_t>
|
||||
Sleb128Decoder<uint_t>::~Sleb128Decoder() { }
|
||||
|
||||
// Decode and retrieve a single value from the encoding. Consume bytes
|
||||
// until one without its most significant bit is found, and re-form the
|
||||
// value from the 7 bit fields of the bytes consumed.
|
||||
template <typename uint_t>
|
||||
uint_t Sleb128Decoder<uint_t>::Dequeue() {
|
||||
uint_t value = 0;
|
||||
static const size_t size = CHAR_BIT * sizeof(value);
|
||||
|
||||
size_t shift = 0;
|
||||
uint8_t byte;
|
||||
|
||||
// Loop until we reach a byte with its high order bit clear.
|
||||
do {
|
||||
byte = encoding_[cursor_++];
|
||||
value |= (static_cast<uint_t>(byte & 127) << shift);
|
||||
shift += 7;
|
||||
} while (byte & 128);
|
||||
|
||||
// The sign bit is second high order bit of the final byte decoded.
|
||||
// Sign extend if value is -ve and we did not shift all of it.
|
||||
if (shift < size && (byte & 64))
|
||||
value |= -(static_cast<uint_t>(1) << shift);
|
||||
|
||||
return static_cast<uint_t>(value);
|
||||
}
|
||||
|
||||
// Decode and retrieve all remaining values from the encoding.
|
||||
template <typename uint_t>
|
||||
void Sleb128Decoder<uint_t>::DequeueAll(std::vector<uint_t>* values) {
|
||||
while (cursor_ < encoding_.size()) {
|
||||
values->push_back(Dequeue());
|
||||
}
|
||||
}
|
||||
|
||||
template class Sleb128Encoder<uint32_t>;
|
||||
template class Sleb128Encoder<uint64_t>;
|
||||
template class Sleb128Decoder<uint32_t>;
|
||||
template class Sleb128Decoder<uint64_t>;
|
||||
|
||||
} // namespace relocation_packer
|
76
third_party/android_platform/bionic/tools/relocation_packer/src/sleb128.h
vendored
Normal file
76
third_party/android_platform/bionic/tools/relocation_packer/src/sleb128.h
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
// Copyright 2014 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// SLEB128 encoder and decoder for packed relative relocations.
|
||||
//
|
||||
// Packed relocations consist of a large number of relatively small
|
||||
// integer values. Encoding these as LEB128 saves space.
|
||||
//
|
||||
// For more on LEB128 see http://en.wikipedia.org/wiki/LEB128.
|
||||
|
||||
#ifndef TOOLS_RELOCATION_PACKER_SRC_SLEB128_H_
|
||||
#define TOOLS_RELOCATION_PACKER_SRC_SLEB128_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <vector>
|
||||
|
||||
#include "elf_traits.h"
|
||||
|
||||
namespace relocation_packer {
|
||||
|
||||
// Encode packed words as a signed LEB128 byte stream.
|
||||
template<typename int_t>
|
||||
class Sleb128Encoder {
|
||||
public:
|
||||
// Explicit (but empty) constructor and destructor, for chromium-style.
|
||||
Sleb128Encoder();
|
||||
~Sleb128Encoder();
|
||||
|
||||
// Add a value to the encoding stream.
|
||||
// |value| is the signed int to add.
|
||||
void Enqueue(int_t value);
|
||||
|
||||
// Add a vector of values to the encoding stream.
|
||||
// |values| is the vector of signed ints to add.
|
||||
void EnqueueAll(const std::vector<int_t>& values);
|
||||
|
||||
// Retrieve the encoded representation of the values.
|
||||
// |encoding| is the returned vector of encoded data.
|
||||
void GetEncoding(std::vector<uint8_t>* encoding) { *encoding = encoding_; }
|
||||
|
||||
private:
|
||||
// Growable vector holding the encoded LEB128 stream.
|
||||
std::vector<uint8_t> encoding_;
|
||||
};
|
||||
|
||||
// Decode a LEB128 byte stream to produce packed words.
|
||||
template <typename int_t>
|
||||
class Sleb128Decoder {
|
||||
public:
|
||||
// Create a new decoder for the given encoded stream.
|
||||
// |encoding| is the vector of encoded data.
|
||||
explicit Sleb128Decoder(const std::vector<uint8_t>& encoding, size_t start_with);
|
||||
|
||||
// Explicit (but empty) destructor, for chromium-style.
|
||||
~Sleb128Decoder();
|
||||
|
||||
// Retrieve the next value from the encoded stream.
|
||||
int_t Dequeue();
|
||||
|
||||
// Retrieve all remaining values from the encoded stream.
|
||||
// |values| is the vector of decoded data.
|
||||
void DequeueAll(std::vector<int_t>* values);
|
||||
|
||||
private:
|
||||
// Encoded LEB128 stream.
|
||||
std::vector<uint8_t> encoding_;
|
||||
|
||||
// Cursor indicating the current stream retrieval point.
|
||||
size_t cursor_;
|
||||
};
|
||||
|
||||
} // namespace relocation_packer
|
||||
|
||||
#endif // TOOLS_RELOCATION_PACKER_SRC_SLEB128_H_
|
166
third_party/android_platform/bionic/tools/relocation_packer/src/sleb128_unittest.cc
vendored
Normal file
166
third_party/android_platform/bionic/tools/relocation_packer/src/sleb128_unittest.cc
vendored
Normal file
@ -0,0 +1,166 @@
|
||||
// Copyright 2014 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "sleb128.h"
|
||||
|
||||
#include <vector>
|
||||
#include "elf_traits.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace relocation_packer {
|
||||
|
||||
TEST(Sleb128, Encoder64) {
|
||||
std::vector<uint64_t> values;
|
||||
values.push_back(624485U);
|
||||
values.push_back(0U);
|
||||
values.push_back(1U);
|
||||
values.push_back(63U);
|
||||
values.push_back(64U);
|
||||
values.push_back(static_cast<uint64_t>(-1));
|
||||
values.push_back(static_cast<uint64_t>(-624485));
|
||||
|
||||
Sleb128Encoder<uint64_t> encoder;
|
||||
encoder.EnqueueAll(values);
|
||||
|
||||
encoder.Enqueue(2147483647U);
|
||||
encoder.Enqueue(static_cast<uint64_t>(-2147483648));
|
||||
encoder.Enqueue(9223372036854775807ULL);
|
||||
encoder.Enqueue(static_cast<uint64_t>(-9223372036854775807LL - 1));
|
||||
|
||||
std::vector<uint8_t> encoding;
|
||||
encoder.GetEncoding(&encoding);
|
||||
|
||||
EXPECT_EQ(42u, encoding.size());
|
||||
// 624485
|
||||
EXPECT_EQ(0xe5, encoding[0]);
|
||||
EXPECT_EQ(0x8e, encoding[1]);
|
||||
EXPECT_EQ(0x26, encoding[2]);
|
||||
// 0
|
||||
EXPECT_EQ(0x00, encoding[3]);
|
||||
// 1
|
||||
EXPECT_EQ(0x01, encoding[4]);
|
||||
// 63
|
||||
EXPECT_EQ(0x3f, encoding[5]);
|
||||
// 64
|
||||
EXPECT_EQ(0xc0, encoding[6]);
|
||||
EXPECT_EQ(0x00, encoding[7]);
|
||||
// -1
|
||||
EXPECT_EQ(0x7f, encoding[8]);
|
||||
// -624485
|
||||
EXPECT_EQ(0x9b, encoding[9]);
|
||||
EXPECT_EQ(0xf1, encoding[10]);
|
||||
EXPECT_EQ(0x59, encoding[11]);
|
||||
// 2147483647
|
||||
EXPECT_EQ(0xff, encoding[12]);
|
||||
EXPECT_EQ(0xff, encoding[13]);
|
||||
EXPECT_EQ(0xff, encoding[14]);
|
||||
EXPECT_EQ(0xff, encoding[15]);
|
||||
EXPECT_EQ(0x07, encoding[16]);
|
||||
// -2147483648
|
||||
EXPECT_EQ(0x80, encoding[17]);
|
||||
EXPECT_EQ(0x80, encoding[18]);
|
||||
EXPECT_EQ(0x80, encoding[19]);
|
||||
EXPECT_EQ(0x80, encoding[20]);
|
||||
EXPECT_EQ(0x78, encoding[21]);
|
||||
// 9223372036854775807
|
||||
EXPECT_EQ(0xff, encoding[22]);
|
||||
EXPECT_EQ(0xff, encoding[23]);
|
||||
EXPECT_EQ(0xff, encoding[24]);
|
||||
EXPECT_EQ(0xff, encoding[25]);
|
||||
EXPECT_EQ(0xff, encoding[26]);
|
||||
EXPECT_EQ(0xff, encoding[27]);
|
||||
EXPECT_EQ(0xff, encoding[28]);
|
||||
EXPECT_EQ(0xff, encoding[29]);
|
||||
EXPECT_EQ(0xff, encoding[30]);
|
||||
EXPECT_EQ(0x00, encoding[31]);
|
||||
// -9223372036854775808
|
||||
EXPECT_EQ(0x80, encoding[32]);
|
||||
EXPECT_EQ(0x80, encoding[33]);
|
||||
EXPECT_EQ(0x80, encoding[34]);
|
||||
EXPECT_EQ(0x80, encoding[35]);
|
||||
EXPECT_EQ(0x80, encoding[36]);
|
||||
EXPECT_EQ(0x80, encoding[37]);
|
||||
EXPECT_EQ(0x80, encoding[38]);
|
||||
EXPECT_EQ(0x80, encoding[39]);
|
||||
EXPECT_EQ(0x80, encoding[40]);
|
||||
EXPECT_EQ(0x7f, encoding[41]);
|
||||
}
|
||||
|
||||
TEST(Sleb128, Decoder) {
|
||||
std::vector<uint8_t> encoding;
|
||||
// 624485
|
||||
encoding.push_back(0xe5);
|
||||
encoding.push_back(0x8e);
|
||||
encoding.push_back(0x26);
|
||||
// 0
|
||||
encoding.push_back(0x00);
|
||||
// 1
|
||||
encoding.push_back(0x01);
|
||||
// 63
|
||||
encoding.push_back(0x3f);
|
||||
// 64
|
||||
encoding.push_back(0xc0);
|
||||
encoding.push_back(0x00);
|
||||
// -1
|
||||
encoding.push_back(0x7f);
|
||||
// -624485
|
||||
encoding.push_back(0x9b);
|
||||
encoding.push_back(0xf1);
|
||||
encoding.push_back(0x59);
|
||||
// 2147483647
|
||||
encoding.push_back(0xff);
|
||||
encoding.push_back(0xff);
|
||||
encoding.push_back(0xff);
|
||||
encoding.push_back(0xff);
|
||||
encoding.push_back(0x07);
|
||||
// -2147483648
|
||||
encoding.push_back(0x80);
|
||||
encoding.push_back(0x80);
|
||||
encoding.push_back(0x80);
|
||||
encoding.push_back(0x80);
|
||||
encoding.push_back(0x78);
|
||||
// 9223372036854775807
|
||||
encoding.push_back(0xff);
|
||||
encoding.push_back(0xff);
|
||||
encoding.push_back(0xff);
|
||||
encoding.push_back(0xff);
|
||||
encoding.push_back(0xff);
|
||||
encoding.push_back(0xff);
|
||||
encoding.push_back(0xff);
|
||||
encoding.push_back(0xff);
|
||||
encoding.push_back(0xff);
|
||||
encoding.push_back(0x00);
|
||||
// -9223372036854775808
|
||||
encoding.push_back(0x80);
|
||||
encoding.push_back(0x80);
|
||||
encoding.push_back(0x80);
|
||||
encoding.push_back(0x80);
|
||||
encoding.push_back(0x80);
|
||||
encoding.push_back(0x80);
|
||||
encoding.push_back(0x80);
|
||||
encoding.push_back(0x80);
|
||||
encoding.push_back(0x80);
|
||||
encoding.push_back(0x7f);
|
||||
|
||||
Sleb128Decoder<uint64_t> decoder(encoding, 0);
|
||||
|
||||
EXPECT_EQ(624485U, decoder.Dequeue());
|
||||
|
||||
std::vector<uint64_t> dequeued;
|
||||
decoder.DequeueAll(&dequeued);
|
||||
|
||||
EXPECT_EQ(10U, dequeued.size());
|
||||
EXPECT_EQ(0U, dequeued[0]);
|
||||
EXPECT_EQ(1U, dequeued[1]);
|
||||
EXPECT_EQ(63U, dequeued[2]);
|
||||
EXPECT_EQ(64U, dequeued[3]);
|
||||
EXPECT_EQ(static_cast<uint64_t>(-1), dequeued[4]);
|
||||
EXPECT_EQ(static_cast<uint64_t>(-624485), dequeued[5]);
|
||||
EXPECT_EQ(2147483647U, dequeued[6]);
|
||||
EXPECT_EQ(static_cast<uint64_t>(-2147483648), dequeued[7]);
|
||||
EXPECT_EQ(9223372036854775807ULL, dequeued[8]);
|
||||
EXPECT_EQ(static_cast<uint64_t>(-9223372036854775807LL - 1), dequeued[9]);
|
||||
}
|
||||
|
||||
} // namespace relocation_packer
|
1014
third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs.cc
vendored
Normal file
1014
third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs.cc
vendored
Normal file
File diff suppressed because it is too large
Load Diff
BIN
third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm32.so
vendored
Executable file
BIN
third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm32.so
vendored
Executable file
Binary file not shown.
BIN
third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm32_packed.so
vendored
Executable file
BIN
third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm32_packed.so
vendored
Executable file
Binary file not shown.
BIN
third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm64.so
vendored
Executable file
BIN
third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm64.so
vendored
Executable file
Binary file not shown.
BIN
third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm64_packed.so
vendored
Executable file
BIN
third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm64_packed.so
vendored
Executable file
Binary file not shown.
BIN
third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_ia32.so
vendored
Executable file
BIN
third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_ia32.so
vendored
Executable file
Binary file not shown.
BIN
third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_ia32_packed.so
vendored
Executable file
BIN
third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_ia32_packed.so
vendored
Executable file
Binary file not shown.
BIN
third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_mips32.so
vendored
Executable file
BIN
third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_mips32.so
vendored
Executable file
Binary file not shown.
BIN
third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_mips32_packed.so
vendored
Executable file
BIN
third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_mips32_packed.so
vendored
Executable file
Binary file not shown.
BIN
third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_x64.so
vendored
Executable file
BIN
third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_x64.so
vendored
Executable file
Binary file not shown.
BIN
third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_x64_packed.so
vendored
Executable file
BIN
third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_x64_packed.so
vendored
Executable file
Binary file not shown.
9
third_party/android_platform/config.gni
vendored
Normal file
9
third_party/android_platform/config.gni
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
# Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
relocation_packer_target =
|
||||
"//third_party/android_platform:android_relocation_packer($host_toolchain)"
|
||||
relocation_packer_dir =
|
||||
get_label_info("$relocation_packer_target", "root_out_dir")
|
||||
relocation_packer_exe = "${relocation_packer_dir}/android_relocation_packer"
|
320
third_party/android_platform/development/ide/intellij/codestyles/AndroidStyle.xml
vendored
Normal file
320
third_party/android_platform/development/ide/intellij/codestyles/AndroidStyle.xml
vendored
Normal file
@ -0,0 +1,320 @@
|
||||
<code_scheme name="AndroidStyle">
|
||||
<option name="JAVA_INDENT_OPTIONS">
|
||||
<value>
|
||||
<option name="INDENT_SIZE" value="4" />
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="8" />
|
||||
<option name="TAB_SIZE" value="8" />
|
||||
<option name="USE_TAB_CHARACTER" value="false" />
|
||||
<option name="SMART_TABS" value="false" />
|
||||
<option name="LABEL_INDENT_SIZE" value="0" />
|
||||
<option name="LABEL_INDENT_ABSOLUTE" value="false" />
|
||||
<option name="USE_RELATIVE_INDENTS" value="false" />
|
||||
</value>
|
||||
</option>
|
||||
<option name="FIELD_NAME_PREFIX" value="m" />
|
||||
<option name="STATIC_FIELD_NAME_PREFIX" value="s" />
|
||||
<option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="9999" />
|
||||
<option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="9999" />
|
||||
<option name="IMPORT_LAYOUT_TABLE">
|
||||
<value>
|
||||
<package name="android" withSubpackages="true" static="true" />
|
||||
<emptyLine />
|
||||
<package name="com.android" withSubpackages="true" static="true" />
|
||||
<emptyLine />
|
||||
<package name="dalvik" withSubpackages="true" static="true" />
|
||||
<emptyLine />
|
||||
<package name="libcore" withSubpackages="true" static="true" />
|
||||
<emptyLine />
|
||||
<package name="com" withSubpackages="true" static="true" />
|
||||
<emptyLine />
|
||||
<package name="gov" withSubpackages="true" static="true" />
|
||||
<emptyLine />
|
||||
<package name="junit" withSubpackages="true" static="true" />
|
||||
<emptyLine />
|
||||
<package name="net" withSubpackages="true" static="true" />
|
||||
<emptyLine />
|
||||
<package name="org" withSubpackages="true" static="true" />
|
||||
<emptyLine />
|
||||
<package name="java" withSubpackages="true" static="true" />
|
||||
<emptyLine />
|
||||
<package name="javax" withSubpackages="true" static="true" />
|
||||
<emptyLine />
|
||||
<package name="" withSubpackages="true" static="true" />
|
||||
<emptyLine />
|
||||
<package name="android" withSubpackages="true" static="false" />
|
||||
<emptyLine />
|
||||
<package name="com.android" withSubpackages="true" static="false" />
|
||||
<emptyLine />
|
||||
<package name="dalvik" withSubpackages="true" static="false" />
|
||||
<emptyLine />
|
||||
<package name="libcore" withSubpackages="true" static="false" />
|
||||
<emptyLine />
|
||||
<package name="com" withSubpackages="true" static="false" />
|
||||
<emptyLine />
|
||||
<package name="gov" withSubpackages="true" static="false" />
|
||||
<emptyLine />
|
||||
<package name="junit" withSubpackages="true" static="false" />
|
||||
<emptyLine />
|
||||
<package name="net" withSubpackages="true" static="false" />
|
||||
<emptyLine />
|
||||
<package name="org" withSubpackages="true" static="false" />
|
||||
<emptyLine />
|
||||
<package name="java" withSubpackages="true" static="false" />
|
||||
<emptyLine />
|
||||
<package name="javax" withSubpackages="true" static="false" />
|
||||
<emptyLine />
|
||||
<package name="" withSubpackages="true" static="false" />
|
||||
</value>
|
||||
</option>
|
||||
<option name="RIGHT_MARGIN" value="100" />
|
||||
<option name="JD_P_AT_EMPTY_LINES" value="false" />
|
||||
<option name="JD_DO_NOT_WRAP_ONE_LINE_COMMENTS" value="true" />
|
||||
<option name="JD_KEEP_EMPTY_PARAMETER" value="false" />
|
||||
<option name="JD_KEEP_EMPTY_EXCEPTION" value="false" />
|
||||
<option name="JD_KEEP_EMPTY_RETURN" value="false" />
|
||||
<option name="JD_PRESERVE_LINE_FEEDS" value="true" />
|
||||
<option name="KEEP_CONTROL_STATEMENT_IN_ONE_LINE" value="false" />
|
||||
<option name="KEEP_BLANK_LINES_IN_CODE" value="1" />
|
||||
<option name="BLANK_LINES_AROUND_FIELD" value="1" />
|
||||
<option name="BLANK_LINES_AFTER_CLASS_HEADER" value="1" />
|
||||
<option name="ALIGN_MULTILINE_PARAMETERS" value="false" />
|
||||
<option name="ALIGN_MULTILINE_FOR" value="false" />
|
||||
<option name="CALL_PARAMETERS_WRAP" value="1" />
|
||||
<option name="METHOD_PARAMETERS_WRAP" value="1" />
|
||||
<option name="EXTENDS_LIST_WRAP" value="1" />
|
||||
<option name="THROWS_LIST_WRAP" value="1" />
|
||||
<option name="EXTENDS_KEYWORD_WRAP" value="1" />
|
||||
<option name="THROWS_KEYWORD_WRAP" value="1" />
|
||||
<option name="METHOD_CALL_CHAIN_WRAP" value="1" />
|
||||
<option name="BINARY_OPERATION_WRAP" value="1" />
|
||||
<option name="BINARY_OPERATION_SIGN_ON_NEXT_LINE" value="true" />
|
||||
<option name="TERNARY_OPERATION_WRAP" value="1" />
|
||||
<option name="TERNARY_OPERATION_SIGNS_ON_NEXT_LINE" value="true" />
|
||||
<option name="FOR_STATEMENT_WRAP" value="1" />
|
||||
<option name="ARRAY_INITIALIZER_WRAP" value="1" />
|
||||
<option name="ASSIGNMENT_WRAP" value="1" />
|
||||
<option name="PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE" value="true" />
|
||||
<option name="WRAP_COMMENTS" value="true" />
|
||||
<option name="IF_BRACE_FORCE" value="3" />
|
||||
<option name="DOWHILE_BRACE_FORCE" value="3" />
|
||||
<option name="WHILE_BRACE_FORCE" value="3" />
|
||||
<option name="FOR_BRACE_FORCE" value="3" />
|
||||
<XML>
|
||||
<option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" />
|
||||
</XML>
|
||||
<ADDITIONAL_INDENT_OPTIONS fileType="java">
|
||||
<option name="TAB_SIZE" value="8" />
|
||||
</ADDITIONAL_INDENT_OPTIONS>
|
||||
<ADDITIONAL_INDENT_OPTIONS fileType="js">
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
||||
</ADDITIONAL_INDENT_OPTIONS>
|
||||
<codeStyleSettings language="JAVA">
|
||||
<option name="ALIGN_MULTILINE_PARAMETERS" value="false" />
|
||||
<option name="ALIGN_MULTILINE_FOR" value="false" />
|
||||
<option name="CALL_PARAMETERS_WRAP" value="1" />
|
||||
<option name="PREFER_PARAMETERS_WRAP" value="true" />
|
||||
<option name="METHOD_PARAMETERS_WRAP" value="1" />
|
||||
<option name="RESOURCE_LIST_WRAP" value="1" />
|
||||
<option name="EXTENDS_LIST_WRAP" value="1" />
|
||||
<option name="THROWS_LIST_WRAP" value="1" />
|
||||
<option name="THROWS_KEYWORD_WRAP" value="1" />
|
||||
<option name="BINARY_OPERATION_WRAP" value="1" />
|
||||
<option name="BINARY_OPERATION_SIGN_ON_NEXT_LINE" value="true" />
|
||||
<option name="TERNARY_OPERATION_WRAP" value="1" />
|
||||
<option name="TERNARY_OPERATION_SIGNS_ON_NEXT_LINE" value="true" />
|
||||
<option name="FOR_STATEMENT_WRAP" value="1" />
|
||||
<option name="ARRAY_INITIALIZER_WRAP" value="1" />
|
||||
<option name="ASSIGNMENT_WRAP" value="1" />
|
||||
<option name="IF_BRACE_FORCE" value="1" />
|
||||
<option name="DOWHILE_BRACE_FORCE" value="1" />
|
||||
<option name="WHILE_BRACE_FORCE" value="1" />
|
||||
<option name="FOR_BRACE_FORCE" value="1" />
|
||||
<option name="WRAP_LONG_LINES" value="true" />
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="JavaScript">
|
||||
<option name="KEEP_CONTROL_STATEMENT_IN_ONE_LINE" value="false" />
|
||||
<option name="KEEP_BLANK_LINES_IN_CODE" value="1" />
|
||||
<option name="BLANK_LINES_AROUND_FIELD" value="1" />
|
||||
<option name="BLANK_LINES_AFTER_CLASS_HEADER" value="1" />
|
||||
<option name="ALIGN_MULTILINE_PARAMETERS" value="false" />
|
||||
<option name="ALIGN_MULTILINE_FOR" value="false" />
|
||||
<option name="CALL_PARAMETERS_WRAP" value="1" />
|
||||
<option name="METHOD_PARAMETERS_WRAP" value="1" />
|
||||
<option name="EXTENDS_LIST_WRAP" value="1" />
|
||||
<option name="THROWS_LIST_WRAP" value="1" />
|
||||
<option name="EXTENDS_KEYWORD_WRAP" value="1" />
|
||||
<option name="THROWS_KEYWORD_WRAP" value="1" />
|
||||
<option name="METHOD_CALL_CHAIN_WRAP" value="1" />
|
||||
<option name="BINARY_OPERATION_WRAP" value="1" />
|
||||
<option name="BINARY_OPERATION_SIGN_ON_NEXT_LINE" value="true" />
|
||||
<option name="TERNARY_OPERATION_WRAP" value="1" />
|
||||
<option name="TERNARY_OPERATION_SIGNS_ON_NEXT_LINE" value="true" />
|
||||
<option name="FOR_STATEMENT_WRAP" value="1" />
|
||||
<option name="ARRAY_INITIALIZER_WRAP" value="1" />
|
||||
<option name="ASSIGNMENT_WRAP" value="1" />
|
||||
<option name="PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE" value="true" />
|
||||
<option name="WRAP_COMMENTS" value="true" />
|
||||
<option name="IF_BRACE_FORCE" value="3" />
|
||||
<option name="DOWHILE_BRACE_FORCE" value="3" />
|
||||
<option name="WHILE_BRACE_FORCE" value="3" />
|
||||
<option name="FOR_BRACE_FORCE" value="3" />
|
||||
<option name="PARENT_SETTINGS_INSTALLED" value="true" />
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="XML">
|
||||
<option name="FORCE_REARRANGE_MODE" value="1" />
|
||||
<indentOptions>
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
||||
</indentOptions>
|
||||
<arrangement>
|
||||
<rules>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>xmlns:android</NAME>
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>xmlns:.*</NAME>
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*:id</NAME>
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*:name</NAME>
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>name</NAME>
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>style</NAME>
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*</NAME>
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*:layout_width</NAME>
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*:layout_height</NAME>
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*:layout_.*</NAME>
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*:width</NAME>
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*:height</NAME>
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*</NAME>
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*</NAME>
|
||||
<XML_NAMESPACE>.*</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
</rules>
|
||||
</arrangement>
|
||||
</codeStyleSettings>
|
||||
</code_scheme>
|
8
third_party/android_platform/development/scripts/stack
vendored
Executable file
8
third_party/android_platform/development/scripts/stack
vendored
Executable file
@ -0,0 +1,8 @@
|
||||
#! /bin/bash
|
||||
# Copyright 2017 The Chromium Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
base_dir=$(dirname "$0")
|
||||
|
||||
exec python "$base_dir/stack.py" "$@"
|
250
third_party/android_platform/development/scripts/stack.py
vendored
Executable file
250
third_party/android_platform/development/scripts/stack.py
vendored
Executable file
@ -0,0 +1,250 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2013 The Android Open Source Project
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""stack symbolizes native crash dumps."""
|
||||
|
||||
import getopt
|
||||
import glob
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
|
||||
import stack_core
|
||||
import stack_libs
|
||||
import subprocess
|
||||
import symbol
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__),
|
||||
os.pardir, os.pardir, os.pardir, os.pardir,
|
||||
'build', 'android'))
|
||||
|
||||
from pylib import constants
|
||||
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__),
|
||||
os.pardir, os.pardir, os.pardir, os.pardir,
|
||||
'tools', 'python'))
|
||||
import llvm_symbolizer
|
||||
|
||||
DEFAULT_SYMROOT='/tmp/symbols'
|
||||
# From: https://source.android.com/source/build-numbers.html
|
||||
_ANDROID_M_MAJOR_VERSION=6
|
||||
|
||||
def PrintUsage():
|
||||
"""Print usage and exit with error."""
|
||||
# pylint: disable-msg=C6310
|
||||
print
|
||||
print " usage: " + sys.argv[0] + " [options] [FILE]"
|
||||
print
|
||||
print " --symbols-dir=path"
|
||||
print " the path to a symbols dir, such as =/tmp/out/target/product/dream/symbols"
|
||||
print
|
||||
print " --chrome-symbols-dir=path"
|
||||
print " the path to a Chrome symbols dir (can be absolute or relative"
|
||||
print " to src), such as =out/Debug/lib.unstripped"
|
||||
print
|
||||
print " --output-directory=path"
|
||||
print " the path to the build output directory, such as out/Debug."
|
||||
print " Ignored if --chrome-symbols-dir is passed."
|
||||
print
|
||||
print " --packed-relocation-adjustments"
|
||||
print " --no-packed-relocation-adjustments"
|
||||
print " turn packed relocation adjustment on and off (default is off)"
|
||||
print " If running on pre-M Android and the stack trace appears to"
|
||||
print " make no sense, try turning this feature on."
|
||||
print
|
||||
print " --symbols-zip=path"
|
||||
print " the path to a symbols zip file, such as =dream-symbols-12345.zip"
|
||||
print
|
||||
print " --more-info"
|
||||
print " --less-info"
|
||||
print " Change the level of detail in the output."
|
||||
print " --more-info is slower and more verbose, but more functions will"
|
||||
print " be fully qualified with namespace/classname and have full"
|
||||
print " argument information. Also, the 'stack data' section will be"
|
||||
print " printed."
|
||||
print
|
||||
print " --arch=arm|arm64|x64|x86|mips"
|
||||
print " the target architecture"
|
||||
print
|
||||
print " --fallback-monochrome"
|
||||
print " fallback to monochrome instead of chrome if fail to detect"
|
||||
print " shared lib which is loaded from APK, this doesn't work for"
|
||||
print " component build."
|
||||
print
|
||||
print " --verbose"
|
||||
print " enable extra logging, particularly for debugging failed symbolization"
|
||||
print
|
||||
print " FILE should contain a stack trace in it somewhere"
|
||||
print " the tool will find that and re-print it with"
|
||||
print " source files and line numbers. If you don't"
|
||||
print " pass FILE, or if file is -, it reads from"
|
||||
print " stdin."
|
||||
print
|
||||
# pylint: enable-msg=C6310
|
||||
sys.exit(1)
|
||||
|
||||
def UnzipSymbols(symbolfile, symdir=None):
|
||||
"""Unzips a file to DEFAULT_SYMROOT and returns the unzipped location.
|
||||
|
||||
Args:
|
||||
symbolfile: The .zip file to unzip
|
||||
symdir: Optional temporary directory to use for extraction
|
||||
|
||||
Returns:
|
||||
A tuple containing (the directory into which the zip file was unzipped,
|
||||
the path to the "symbols" directory in the unzipped file). To clean
|
||||
up, the caller can delete the first element of the tuple.
|
||||
|
||||
Raises:
|
||||
SymbolDownloadException: When the unzip fails.
|
||||
"""
|
||||
if not symdir:
|
||||
symdir = "%s/%s" % (DEFAULT_SYMROOT, hash(symbolfile))
|
||||
if not os.path.exists(symdir):
|
||||
os.makedirs(symdir)
|
||||
|
||||
print "extracting %s..." % symbolfile
|
||||
saveddir = os.getcwd()
|
||||
os.chdir(symdir)
|
||||
try:
|
||||
unzipcode = subprocess.call(["unzip", "-qq", "-o", symbolfile])
|
||||
if unzipcode > 0:
|
||||
os.remove(symbolfile)
|
||||
raise SymbolDownloadException("failed to extract symbol files (%s)."
|
||||
% symbolfile)
|
||||
finally:
|
||||
os.chdir(saveddir)
|
||||
|
||||
android_symbols = glob.glob("%s/out/target/product/*/symbols" % symdir)
|
||||
if android_symbols:
|
||||
return (symdir, android_symbols[0])
|
||||
else:
|
||||
# This is a zip of Chrome symbols, so symbol.CHROME_SYMBOLS_DIR needs to be
|
||||
# updated to point here.
|
||||
symbol.CHROME_SYMBOLS_DIR = symdir
|
||||
return (symdir, symdir)
|
||||
|
||||
|
||||
def main(argv):
|
||||
try:
|
||||
options, arguments = getopt.getopt(argv, "",
|
||||
["packed-relocation-adjustments",
|
||||
"no-packed-relocation-adjustments",
|
||||
"more-info",
|
||||
"less-info",
|
||||
"chrome-symbols-dir=",
|
||||
"output-directory=",
|
||||
"symbols-dir=",
|
||||
"symbols-zip=",
|
||||
"packed-lib=",
|
||||
"arch=",
|
||||
"fallback-monochrome",
|
||||
"verbose",
|
||||
"help"])
|
||||
except getopt.GetoptError, unused_error:
|
||||
PrintUsage()
|
||||
|
||||
zip_arg = None
|
||||
more_info = False
|
||||
fallback_monochrome = False
|
||||
arch_defined = False
|
||||
packed_libs = []
|
||||
for option, value in options:
|
||||
if option == "--help":
|
||||
PrintUsage()
|
||||
elif option == "--symbols-dir":
|
||||
symbol.SYMBOLS_DIR = os.path.expanduser(value)
|
||||
elif option == "--symbols-zip":
|
||||
zip_arg = os.path.expanduser(value)
|
||||
elif option == "--arch":
|
||||
symbol.ARCH = value
|
||||
arch_defined = True
|
||||
elif option == "--chrome-symbols-dir":
|
||||
symbol.CHROME_SYMBOLS_DIR = os.path.join(constants.DIR_SOURCE_ROOT,
|
||||
value)
|
||||
elif option == "--output-directory":
|
||||
constants.SetOutputDirectory(value)
|
||||
elif option == "--packed-lib":
|
||||
packed_libs.append(os.path.expanduser(value))
|
||||
elif option == "--more-info":
|
||||
more_info = True
|
||||
elif option == "--less-info":
|
||||
more_info = False
|
||||
elif option == "--fallback-monochrome":
|
||||
fallback_monochrome = True
|
||||
elif option == "--verbose":
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
elif option in (
|
||||
'--packed-relocation-adjustments',
|
||||
'--no-packed-relocation-adjustments'):
|
||||
print ('--[no-]packed-relocation-adjustments options are deprecated. '
|
||||
'Specify packed libs directory instead.')
|
||||
|
||||
if len(arguments) > 1:
|
||||
PrintUsage()
|
||||
|
||||
# Do an up-front test that the output directory is known.
|
||||
if not symbol.CHROME_SYMBOLS_DIR:
|
||||
constants.CheckOutputDirectory()
|
||||
|
||||
if not arguments or arguments[0] == "-":
|
||||
print "Reading native crash info from stdin"
|
||||
f = sys.stdin
|
||||
else:
|
||||
print "Searching for native crashes in: " + os.path.realpath(arguments[0])
|
||||
f = open(arguments[0], "r")
|
||||
|
||||
lines = f.readlines()
|
||||
f.close()
|
||||
|
||||
rootdir = None
|
||||
if zip_arg:
|
||||
rootdir, symbol.SYMBOLS_DIR = UnzipSymbols(zip_arg)
|
||||
|
||||
version = stack_libs.GetTargetAndroidVersionNumber(lines)
|
||||
if version is None:
|
||||
print ("Unknown Android release, "
|
||||
"consider passing --packed-lib.")
|
||||
elif version < _ANDROID_M_MAJOR_VERSION and not packed_libs:
|
||||
print ("Pre-M Android release detected, "
|
||||
"but --packed-lib not specified. Stack symbolization may fail.")
|
||||
|
||||
if (version is None or version < _ANDROID_M_MAJOR_VERSION) and packed_libs:
|
||||
load_vaddrs = stack_libs.GetLoadVaddrs(stripped_libs=packed_libs)
|
||||
else:
|
||||
load_vaddrs = {}
|
||||
|
||||
print ("Reading Android symbols from: "
|
||||
+ os.path.normpath(symbol.SYMBOLS_DIR))
|
||||
chrome_search_path = symbol.GetLibrarySearchPaths()
|
||||
|
||||
with llvm_symbolizer.LLVMSymbolizer() as symbolizer:
|
||||
print ("Searching for Chrome symbols from within: "
|
||||
+ ':'.join((os.path.normpath(d) for d in chrome_search_path)))
|
||||
stack_core.ConvertTrace(lines, load_vaddrs, more_info, fallback_monochrome,
|
||||
arch_defined, symbolizer)
|
||||
|
||||
if rootdir:
|
||||
# be a good citizen and clean up...os.rmdir and os.removedirs() don't work
|
||||
cmd = "rm -rf \"%s\"" % rootdir
|
||||
print "\ncleaning up (%s)" % cmd
|
||||
os.system(cmd)
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main(sys.argv[1:]))
|
||||
|
||||
# vi: ts=2 sw=2
|
548
third_party/android_platform/development/scripts/stack_core.py
vendored
Executable file
548
third_party/android_platform/development/scripts/stack_core.py
vendored
Executable file
@ -0,0 +1,548 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2013 The Android Open Source Project
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""stack symbolizes native crash dumps."""
|
||||
|
||||
import itertools
|
||||
import logging
|
||||
import multiprocessing
|
||||
import os
|
||||
import re
|
||||
import struct
|
||||
import subprocess
|
||||
import time
|
||||
import zipfile
|
||||
|
||||
import symbol
|
||||
|
||||
|
||||
from pylib import constants
|
||||
|
||||
UNKNOWN = '<unknown>'
|
||||
HEAP = '[heap]'
|
||||
STACK = '[stack]'
|
||||
_DEFAULT_JOBS=8
|
||||
_CHUNK_SIZE = 1000
|
||||
|
||||
_BASE_APK = 'base.apk'
|
||||
_FALLBACK_SO = 'libchrome.so'
|
||||
|
||||
_ABI_LINE = re.compile('ABI: \'(?P<abi>[a-z0-9A-Z]+)\'')
|
||||
_PROCESS_INFO_LINE = re.compile('(pid: [0-9]+, tid: [0-9]+.*)')
|
||||
# Same as above, but used to extract the pid.
|
||||
_PROCESS_INFO_PID = re.compile('pid: ([0-9]+)')
|
||||
_SIGNAL_LINE = re.compile('(signal [0-9]+ \(.*\).*)')
|
||||
_REGISTER_LINE = re.compile('(([ ]*[0-9a-z]{2} [0-9a-f]{8}){4})')
|
||||
_THREAD_LINE = re.compile('(.*)(\-\-\- ){15}\-\-\-')
|
||||
_DALVIK_JNI_THREAD_LINE = re.compile("(\".*\" prio=[0-9]+ tid=[0-9]+ NATIVE.*)")
|
||||
_DALVIK_NATIVE_THREAD_LINE = re.compile("(\".*\" sysTid=[0-9]+ nice=[0-9]+.*)")
|
||||
_JAVA_STDERR_LINE = re.compile("([0-9]+)\s+[0-9]+\s+.\s+System.err:\s*(.+)")
|
||||
|
||||
_WIDTH = '{8}'
|
||||
|
||||
# Matches LOG(FATAL) lines, like the following example:
|
||||
# [FATAL:source_file.cc(33)] Check failed: !instances_.empty()
|
||||
_LOG_FATAL_LINE = re.compile('(\[FATAL\:.*\].*)$')
|
||||
|
||||
# Note that both trace and value line matching allow for variable amounts of
|
||||
# whitespace (e.g. \t). This is because the we want to allow for the stack
|
||||
# tool to operate on AndroidFeedback provided system logs. AndroidFeedback
|
||||
# strips out double spaces that are found in tombsone files and logcat output.
|
||||
#
|
||||
# Examples of matched trace lines include lines from tombstone files like:
|
||||
# #00 pc 001cf42e /data/data/com.my.project/lib/libmyproject.so
|
||||
# #00 pc 001cf42e /data/data/com.my.project/lib/libmyproject.so (symbol)
|
||||
# Or lines from AndroidFeedback crash report system logs like:
|
||||
# 03-25 00:51:05.520 I/DEBUG ( 65): #00 pc 001cf42e /data/data/com.my.project/lib/libmyproject.so
|
||||
# Please note the spacing differences.
|
||||
_TRACE_LINE = re.compile('(.*)\#(?P<frame>[0-9]+)[ \t]+(..)[ \t]+(0x)?(?P<address>[0-9a-f]{0,16})[ \t]+(?P<lib>[^\r\n \t]*)(?P<symbol_present> \((?P<symbol_name>.*)\))?') # pylint: disable-msg=C6310
|
||||
|
||||
def InitWidthRelatedLineMatchers():
|
||||
global _WIDTH
|
||||
global _DEBUG_TRACE_LINE, _VALUE_LINE, _CODE_LINE
|
||||
if symbol.ARCH == 'arm64' or symbol.ARCH == 'x86_64' or symbol.ARCH == 'x64':
|
||||
_WIDTH = '{16}'
|
||||
# Matches lines emitted by src/base/debug/stack_trace_android.cc, like:
|
||||
# #00 0x7324d92d /data/app-lib/org.chromium.native_test-1/libbase.cr.so+0x0006992d
|
||||
# This pattern includes the unused named capture groups <symbol_present> and
|
||||
# <symbol_name> so that it can interoperate with the |_TRACE_LINE| regex.
|
||||
_DEBUG_TRACE_LINE = re.compile(
|
||||
'(.*)(?P<frame>\#[0-9]+ 0x[0-9a-f]' + _WIDTH + ') '
|
||||
'(?P<lib>[^+]+)\+0x(?P<address>[0-9a-f]' + _WIDTH + ')'
|
||||
'(?P<symbol_present>)(?P<symbol_name>)')
|
||||
|
||||
# Examples of matched value lines include:
|
||||
# bea4170c 8018e4e9 /data/data/com.my.project/lib/libmyproject.so
|
||||
# bea4170c 8018e4e9 /data/data/com.my.project/lib/libmyproject.so (symbol)
|
||||
# 03-25 00:51:05.530 I/DEBUG ( 65): bea4170c 8018e4e9 /data/data/com.my.project/lib/libmyproject.so
|
||||
# Again, note the spacing differences.
|
||||
_VALUE_LINE = re.compile('(.*)([0-9a-f]' + _WIDTH + ')[ \t]+([0-9a-f]' + _WIDTH + ')[ \t]+([^\r\n \t]*)( \((.*)\))?')
|
||||
# Lines from 'code around' sections of the output will be matched before
|
||||
# value lines because otheriwse the 'code around' sections will be confused as
|
||||
# value lines.
|
||||
#
|
||||
# Examples include:
|
||||
# 801cf40c ffffc4cc 00b2f2c5 00b2f1c7 00c1e1a8
|
||||
# 03-25 00:51:05.530 I/DEBUG ( 65): 801cf40c ffffc4cc 00b2f2c5 00b2f1c7 00c1e1a8
|
||||
_CODE_LINE = re.compile('(.*)[ \t]*[a-f0-9]' + _WIDTH + '[ \t]*[a-f0-9]' + _WIDTH +
|
||||
'[ \t]*[a-f0-9]' + _WIDTH + '[ \t]*[a-f0-9]' + _WIDTH +
|
||||
'[ \t]*[a-f0-9]' + _WIDTH + '[ \t]*[ \r\n]') # pylint: disable-msg=C6310
|
||||
|
||||
# This pattern is used to find shared library offset in APK.
|
||||
# Example:
|
||||
# (offset 0x568000)
|
||||
_SHARED_LIB_OFFSET_IN_APK = re.compile(' \(offset 0x(?P<offset>[0-9a-f]{0,16})\)$')
|
||||
|
||||
def PrintTraceLines(trace_lines):
|
||||
"""Print back trace."""
|
||||
maxlen = max(map(lambda tl: len(tl[1]), trace_lines))
|
||||
print
|
||||
print 'Stack Trace:'
|
||||
print ' RELADDR ' + 'FUNCTION'.ljust(maxlen) + ' FILE:LINE'
|
||||
for tl in trace_lines:
|
||||
(addr, symbol_with_offset, location) = tl
|
||||
normalized = os.path.normpath(location)
|
||||
print ' %8s %s %s' % (addr, symbol_with_offset.ljust(maxlen), normalized)
|
||||
return
|
||||
|
||||
|
||||
def PrintValueLines(value_lines):
|
||||
"""Print stack data values."""
|
||||
maxlen = max(map(lambda tl: len(tl[2]), value_lines))
|
||||
print
|
||||
print 'Stack Data:'
|
||||
print ' ADDR VALUE ' + 'FUNCTION'.ljust(maxlen) + ' FILE:LINE'
|
||||
for vl in value_lines:
|
||||
(addr, value, symbol_with_offset, location) = vl
|
||||
print ' %8s %8s %s %s' % (addr, value, symbol_with_offset.ljust(maxlen), location)
|
||||
return
|
||||
|
||||
|
||||
def PrintJavaLines(java_lines):
|
||||
"""Print java stderr lines."""
|
||||
print
|
||||
print 'Java stderr from crashing pid (may identify underlying Java exception):'
|
||||
for l in java_lines:
|
||||
if l.startswith('at'):
|
||||
print ' ',
|
||||
print l
|
||||
|
||||
def PrintOutput(trace_lines, value_lines, java_lines, more_info):
|
||||
if trace_lines:
|
||||
PrintTraceLines(trace_lines)
|
||||
if value_lines:
|
||||
# TODO(cjhopman): it seems that symbol.SymbolInformation always fails to
|
||||
# find information for addresses in value_lines in chrome libraries, and so
|
||||
# value_lines have little value to us and merely clutter the output.
|
||||
# Since information is sometimes contained in these lines (from system
|
||||
# libraries), don't completely disable them.
|
||||
if more_info:
|
||||
PrintValueLines(value_lines)
|
||||
if java_lines:
|
||||
PrintJavaLines(java_lines)
|
||||
|
||||
def PrintDivider():
|
||||
print
|
||||
print '-----------------------------------------------------\n'
|
||||
|
||||
def ConvertTrace(lines, load_vaddrs, more_info, fallback_monochrome, arch_defined, llvm_symbolizer):
|
||||
"""Convert strings containing native crash to a stack."""
|
||||
InitWidthRelatedLineMatchers()
|
||||
|
||||
if fallback_monochrome:
|
||||
global _FALLBACK_SO
|
||||
_FALLBACK_SO = 'libmonochrome.so'
|
||||
start = time.time()
|
||||
|
||||
chunks = [lines[i: i+_CHUNK_SIZE] for i in xrange(0, len(lines), _CHUNK_SIZE)]
|
||||
pool = multiprocessing.Pool(processes=_DEFAULT_JOBS)
|
||||
results = pool.map(PreProcessLog(load_vaddrs), chunks)
|
||||
useful_log = []
|
||||
so_dirs = []
|
||||
for result in results:
|
||||
useful_log += result[0]
|
||||
so_dirs += result[1]
|
||||
pool.close()
|
||||
pool.join()
|
||||
end = time.time()
|
||||
logging.debug('Finished processing. Elapsed time: %.4fs', (end - start))
|
||||
if so_dirs:
|
||||
UpdateLibrarySearchPath(so_dirs)
|
||||
|
||||
# if arch isn't defined in command line, find it from log
|
||||
if not arch_defined:
|
||||
arch = _FindAbi(useful_log)
|
||||
if arch:
|
||||
print ('Find ABI:' + arch)
|
||||
symbol.ARCH = arch
|
||||
|
||||
ResolveCrashSymbol(list(useful_log), more_info, llvm_symbolizer)
|
||||
end = time.time()
|
||||
logging.debug('Finished resolving symbols. Elapsed time: %.4fs',
|
||||
(end - start))
|
||||
|
||||
class PreProcessLog:
|
||||
"""Closure wrapper, for multiprocessing.Pool.map."""
|
||||
def __init__(self, load_vaddrs):
|
||||
"""Bind load_vaddrs to the PreProcessLog closure.
|
||||
Args:
|
||||
load_vaddrs: LOAD segment min_vaddrs keyed on mapped executable
|
||||
"""
|
||||
self._load_vaddrs = load_vaddrs;
|
||||
# This is mapping from apk's offset to shared libraries.
|
||||
self._shared_libraries_mapping = dict()
|
||||
# The list of directires in which instead of default output dir,
|
||||
# the shared libraries is found.
|
||||
self._so_dirs = []
|
||||
|
||||
def _DetectSharedLibrary(self, lib, symbol_present):
|
||||
"""Detect the possible shared library from the mapping offset of APK
|
||||
Return:
|
||||
the shared library in APK if only one is found.
|
||||
"""
|
||||
offset_match = _SHARED_LIB_OFFSET_IN_APK.match(symbol_present)
|
||||
if not offset_match:
|
||||
return
|
||||
offset = offset_match.group('offset')
|
||||
key = '%s:%s' % (lib, offset)
|
||||
if self._shared_libraries_mapping.has_key(key):
|
||||
soname = self._shared_libraries_mapping[key]
|
||||
else:
|
||||
soname, host_so = _FindSharedLibraryFromAPKs(constants.GetOutDirectory(),
|
||||
int(offset, 16))
|
||||
if soname:
|
||||
self._shared_libraries_mapping[key] = soname
|
||||
so_dir = os.path.dirname(host_so)
|
||||
# Store the directory if it is not the default output dir, so
|
||||
# we can update library search path in main process.
|
||||
if not os.path.samefile(constants.GetOutDirectory(), so_dir):
|
||||
self._so_dirs.append(so_dir)
|
||||
print ("Detected: %s is %s which is loaded directly from APK."
|
||||
% (host_so, soname))
|
||||
return soname
|
||||
|
||||
def _AdjustAddress(self, address, lib):
|
||||
"""Add the vaddr of the library's first LOAD segment to address.
|
||||
Args:
|
||||
address: symbol address as a hexadecimal string
|
||||
lib: path to loaded library
|
||||
|
||||
Returns:
|
||||
address+load_vaddrs[key] if lib ends with /key, otherwise address
|
||||
"""
|
||||
for key, offset in self._load_vaddrs.iteritems():
|
||||
if lib.endswith('/' + key):
|
||||
# Add offset to address, and return the result as a hexadecimal string
|
||||
# with the same number of digits as the original. This allows the
|
||||
# caller to make a direct textual substitution.
|
||||
return ('%%0%dx' % len(address)) % (int(address, 16) + offset)
|
||||
return address
|
||||
|
||||
def __call__(self, lines):
|
||||
"""Preprocess the strings, only keep the useful ones.
|
||||
Args:
|
||||
lines: a list of byte strings read from logcat
|
||||
|
||||
Returns:
|
||||
A list of unicode strings related to native crash
|
||||
"""
|
||||
useful_log = []
|
||||
for ln in lines:
|
||||
line = unicode(ln, errors='ignore')
|
||||
if (_PROCESS_INFO_LINE.search(line)
|
||||
or _SIGNAL_LINE.search(line)
|
||||
or _REGISTER_LINE.search(line)
|
||||
or _THREAD_LINE.search(line)
|
||||
or _DALVIK_JNI_THREAD_LINE.search(line)
|
||||
or _DALVIK_NATIVE_THREAD_LINE.search(line)
|
||||
or _LOG_FATAL_LINE.search(line)
|
||||
or _DEBUG_TRACE_LINE.search(line)
|
||||
or _ABI_LINE.search(line)
|
||||
or _JAVA_STDERR_LINE.search(line)):
|
||||
useful_log.append(line)
|
||||
continue
|
||||
|
||||
match = _TRACE_LINE.match(line)
|
||||
if match:
|
||||
lib, symbol_present = match.group('lib', 'symbol_present')
|
||||
if os.path.splitext(lib)[1] == '.apk' and symbol_present:
|
||||
soname = self._DetectSharedLibrary(lib, symbol_present)
|
||||
if soname:
|
||||
line = line.replace('/' + os.path.basename(lib), '/' + soname)
|
||||
else:
|
||||
# If the trace line suggests a direct load from APK, replace the
|
||||
# APK name with _FALLBACK_SO.
|
||||
line = line.replace('/' + _BASE_APK, '/' + _FALLBACK_SO)
|
||||
logging.debug("Can't detect shared library in APK, fallback to" +
|
||||
" library " + _FALLBACK_SO)
|
||||
# For trace lines specifically, the address may need to be adjusted
|
||||
# to account for relocation packing. This is because debuggerd on
|
||||
# pre-M platforms does not understand non-zero vaddr LOAD segments.
|
||||
address, lib = match.group('address', 'lib')
|
||||
adjusted_address = self._AdjustAddress(address, lib)
|
||||
useful_log.append(line.replace(address, adjusted_address, 1))
|
||||
continue
|
||||
|
||||
if _CODE_LINE.match(line):
|
||||
# Code lines should be ignored. If this were excluded the 'code around'
|
||||
# sections would trigger value_line matches.
|
||||
continue
|
||||
if _VALUE_LINE.match(line):
|
||||
useful_log.append(line)
|
||||
return useful_log, self._so_dirs
|
||||
|
||||
def ResolveCrashSymbol(lines, more_info, llvm_symbolizer):
|
||||
"""Convert unicode strings which contains native crash to a stack
|
||||
"""
|
||||
|
||||
trace_lines = []
|
||||
value_lines = []
|
||||
last_frame = -1
|
||||
pid = -1
|
||||
|
||||
# Collects all java exception lines, keyed by pid for later output during
|
||||
# native crash handling.
|
||||
java_stderr_by_pid = {}
|
||||
for line in lines:
|
||||
java_stderr_match = _JAVA_STDERR_LINE.search(line)
|
||||
if java_stderr_match:
|
||||
pid, msg = java_stderr_match.groups()
|
||||
java_stderr_by_pid.setdefault(pid, []).append(msg)
|
||||
|
||||
for line in lines:
|
||||
# AndroidFeedback adds zero width spaces into its crash reports. These
|
||||
# should be removed or the regular expresssions will fail to match.
|
||||
process_header = _PROCESS_INFO_LINE.search(line)
|
||||
signal_header = _SIGNAL_LINE.search(line)
|
||||
register_header = _REGISTER_LINE.search(line)
|
||||
thread_header = _THREAD_LINE.search(line)
|
||||
dalvik_jni_thread_header = _DALVIK_JNI_THREAD_LINE.search(line)
|
||||
dalvik_native_thread_header = _DALVIK_NATIVE_THREAD_LINE.search(line)
|
||||
log_fatal_header = _LOG_FATAL_LINE.search(line)
|
||||
if (process_header or signal_header or register_header or thread_header or
|
||||
dalvik_jni_thread_header or dalvik_native_thread_header or
|
||||
log_fatal_header) :
|
||||
if trace_lines or value_lines:
|
||||
java_lines = []
|
||||
if pid != -1 and pid in java_stderr_by_pid:
|
||||
java_lines = java_stderr_by_pid[pid]
|
||||
PrintOutput(trace_lines, value_lines, java_lines, more_info)
|
||||
PrintDivider()
|
||||
trace_lines = []
|
||||
value_lines = []
|
||||
last_frame = -1
|
||||
pid = -1
|
||||
if process_header:
|
||||
# Track the last reported pid to find java exceptions.
|
||||
pid = _PROCESS_INFO_PID.search(process_header.group(1)).group(1)
|
||||
print process_header.group(1)
|
||||
if signal_header:
|
||||
print signal_header.group(1)
|
||||
if register_header:
|
||||
print register_header.group(1)
|
||||
if thread_header:
|
||||
print thread_header.group(1)
|
||||
if dalvik_jni_thread_header:
|
||||
print dalvik_jni_thread_header.group(1)
|
||||
if dalvik_native_thread_header:
|
||||
print dalvik_native_thread_header.group(1)
|
||||
if log_fatal_header:
|
||||
print log_fatal_header.group(1)
|
||||
continue
|
||||
|
||||
match = _TRACE_LINE.match(line) or _DEBUG_TRACE_LINE.match(line)
|
||||
if match:
|
||||
frame, code_addr, area, symbol_present, symbol_name = match.group(
|
||||
'frame', 'address', 'lib', 'symbol_present', 'symbol_name')
|
||||
logging.debug('Found trace line: %s' % line.strip())
|
||||
|
||||
if frame <= last_frame and (trace_lines or value_lines):
|
||||
java_lines = []
|
||||
if pid != -1 and pid in java_stderr_by_pid:
|
||||
java_lines = java_stderr_by_pid[pid]
|
||||
PrintOutput(trace_lines, value_lines, java_lines, more_info)
|
||||
PrintDivider()
|
||||
trace_lines = []
|
||||
value_lines = []
|
||||
pid = -1
|
||||
last_frame = frame
|
||||
|
||||
if area == UNKNOWN or area == HEAP or area == STACK:
|
||||
trace_lines.append((code_addr, '', area))
|
||||
else:
|
||||
logging.debug('Identified lib: %s' % area)
|
||||
# If a calls b which further calls c and c is inlined to b, we want to
|
||||
# display "a -> b -> c" in the stack trace instead of just "a -> c"
|
||||
# To use llvm symbolizer, the hexadecimal address has to start with 0x.
|
||||
info = llvm_symbolizer.GetSymbolInformation(
|
||||
os.path.join(symbol.SYMBOLS_DIR, symbol.TranslateLibPath(area)),
|
||||
'0x' + code_addr)
|
||||
logging.debug('symbol information: %s' % info)
|
||||
nest_count = len(info) - 1
|
||||
for source_symbol, source_location in info:
|
||||
if nest_count > 0:
|
||||
nest_count = nest_count - 1
|
||||
trace_lines.append(('v------>', source_symbol, source_location))
|
||||
else:
|
||||
trace_lines.append((code_addr,
|
||||
source_symbol,
|
||||
source_location))
|
||||
match = _VALUE_LINE.match(line)
|
||||
if match:
|
||||
(unused_, addr, value, area, symbol_present, symbol_name) = match.groups()
|
||||
if area == UNKNOWN or area == HEAP or area == STACK or not area:
|
||||
value_lines.append((addr, value, '', area))
|
||||
else:
|
||||
info = llvm_symbolizer.GetSymbolInformation(
|
||||
os.path.join(symbol.SYMBOLS_DIR, symbol.TranslateLibPath(area)),
|
||||
'0x' + value)
|
||||
source_symbol, source_location = info.pop()
|
||||
|
||||
value_lines.append((addr,
|
||||
value,
|
||||
source_symbol,
|
||||
source_location))
|
||||
|
||||
java_lines = []
|
||||
if pid != -1 and pid in java_stderr_by_pid:
|
||||
java_lines = java_stderr_by_pid[pid]
|
||||
PrintOutput(trace_lines, value_lines, java_lines, more_info)
|
||||
|
||||
|
||||
def UpdateLibrarySearchPath(so_dirs):
|
||||
# All dirs in so_dirs must be same, since a dir represents the cpu arch.
|
||||
so_dir = set(so_dirs)
|
||||
so_dir_len = len(so_dir)
|
||||
if so_dir_len > 0:
|
||||
if so_dir_len > 1:
|
||||
raise Exception("Found different so dirs, they are %s", repr(so_dir))
|
||||
else:
|
||||
search_path = so_dir.pop()
|
||||
print "Search libraries in " + search_path
|
||||
symbol.SetSecondaryAbiOutputPath(search_path)
|
||||
|
||||
|
||||
def GetUncompressedSharedLibraryFromAPK(apkname, offset):
|
||||
"""Check if there is uncompressed shared library at specifc offset of APK."""
|
||||
FILE_NAME_LEN_OFFSET = 26
|
||||
FILE_NAME_OFFSET = 30
|
||||
soname = ""
|
||||
sosize = 0
|
||||
with zipfile.ZipFile(apkname, 'r') as apk:
|
||||
for infoList in apk.infolist():
|
||||
filename, file_extension = os.path.splitext(infoList.filename)
|
||||
if (file_extension == '.so' and
|
||||
infoList.file_size == infoList.compress_size):
|
||||
with open(apkname, 'rb') as f:
|
||||
f.seek(infoList.header_offset + FILE_NAME_LEN_OFFSET)
|
||||
file_name_len = struct.unpack('H', f.read(2))[0]
|
||||
extra_field_len = struct.unpack('H', f.read(2))[0]
|
||||
file_offset = (infoList.header_offset + FILE_NAME_OFFSET +
|
||||
file_name_len + extra_field_len)
|
||||
f.seek(file_offset)
|
||||
if offset == file_offset and f.read(4) == "\x7fELF":
|
||||
soname = infoList.filename
|
||||
sosize = infoList.file_size
|
||||
break
|
||||
return soname, sosize
|
||||
|
||||
|
||||
def _GetSharedLibraryInHost(soname, dirs):
|
||||
"""Find a shared library by name in a list of directories.
|
||||
|
||||
Args:
|
||||
soname: library name (e.g. libfoo.so)
|
||||
dirs: list of directories to look for the corresponding file.
|
||||
Returns:
|
||||
host library path if found, or None
|
||||
"""
|
||||
for dir in dirs:
|
||||
host_so_file = os.path.join(dir, os.path.basename(soname))
|
||||
if not os.path.isfile(host_so_file):
|
||||
continue
|
||||
logging.debug("%s match to the one in APK" % host_so_file)
|
||||
return host_so_file
|
||||
|
||||
|
||||
def _FindSharedLibraryFromAPKs(out_dir, offset):
|
||||
"""Find the shared library at the specifc offset of an APK file.
|
||||
|
||||
WARNING: This function will look at *all* the apks under $out_dir/apks/
|
||||
looking for native libraries they may contain at |offset|.
|
||||
|
||||
This is error-prone, since a typical full Chrome build has more than a
|
||||
hundred APKs these days, meaning that several APKs might actually match
|
||||
the offset.
|
||||
|
||||
The function tries to detect this by looking at the names of the
|
||||
extracted libraries. If they are all the same, it will consider that
|
||||
as a success, and return its name, even if the APKs embed the same
|
||||
library at different offsets!!
|
||||
|
||||
If there are more than one library at offset from the pool of all APKs,
|
||||
the function prints an error message and fails.
|
||||
|
||||
TODO(digit): Either find a way to pass a list of valid APKs here, or
|
||||
rewrite this script entirely to avoid so many other problematic things
|
||||
in it.
|
||||
|
||||
Args:
|
||||
out_dir: Chromium output directory.
|
||||
offset: APK file offset, as extracted from the stack trace.
|
||||
Returns:
|
||||
A (library_name, host_library_path) tuple on success, or (None, None)
|
||||
in case of failure.
|
||||
"""
|
||||
apk_dir = os.path.join(out_dir, "apks")
|
||||
if not os.path.isdir(apk_dir):
|
||||
return (None, None)
|
||||
|
||||
apks = [os.path.join(apk_dir, f) for f in os.listdir(apk_dir)
|
||||
if (os.path.isfile(os.path.join(apk_dir, f)) and
|
||||
os.path.splitext(f)[1] == '.apk')]
|
||||
shared_libraries = []
|
||||
for apk in apks:
|
||||
soname, sosize = GetUncompressedSharedLibraryFromAPK(apk, offset)
|
||||
if soname == "":
|
||||
continue
|
||||
# The relocation section of libraries in APK is packed, we can't
|
||||
# detect library by its size, and have to rely on the order of lib
|
||||
# directories; for a specific ARCH, the libraries are in either
|
||||
# out_dir or out_dir/android_ARCH, and android_ARCH directory could
|
||||
# exists or not, so having android_ARCH directory be in first, we
|
||||
# will find the correct lib.
|
||||
dirs = [
|
||||
os.path.join(out_dir, "android_%s" % symbol.ARCH),
|
||||
out_dir,
|
||||
]
|
||||
host_so_file = _GetSharedLibraryInHost(soname, dirs)
|
||||
if host_so_file:
|
||||
shared_libraries += [(soname, host_so_file)]
|
||||
# If there are more than one libraries found, it means detecting
|
||||
# library failed.
|
||||
number_of_library = len(shared_libraries)
|
||||
if number_of_library == 1:
|
||||
return shared_libraries[0]
|
||||
elif number_of_library > 1:
|
||||
print "More than one libraries could be loaded from APK."
|
||||
return (None, None)
|
||||
|
||||
|
||||
def _FindAbi(lines):
|
||||
for line in lines:
|
||||
match = _ABI_LINE.search(line)
|
||||
if match:
|
||||
return match.group('abi')
|
133
third_party/android_platform/development/scripts/stack_libs.py
vendored
Executable file
133
third_party/android_platform/development/scripts/stack_libs.py
vendored
Executable file
@ -0,0 +1,133 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (c) 2015 The Chromium Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
|
||||
"""Identifies address adjustments required for native crash dumps."""
|
||||
|
||||
import glob
|
||||
import os.path
|
||||
import re
|
||||
import subprocess
|
||||
|
||||
|
||||
_BASE_APK = 'base.apk'
|
||||
_LIBCHROME_SO = 'libchrome.so'
|
||||
|
||||
_BUILD_FINGERPRINT_RE = re.compile('.*Build fingerprint: (.*)$')
|
||||
|
||||
|
||||
def GetTargetAndroidVersionNumber(lines):
|
||||
"""Return the Android major version number from the build fingerprint.
|
||||
|
||||
Args:
|
||||
lines: Lines read from the tombstone file, before preprocessing.
|
||||
Returns:
|
||||
5, 6, etc, or None if not determinable (developer build?)
|
||||
"""
|
||||
# For example, "Build fingerprint: 'Android/aosp_flo/flo:5.1.1/...'" is 5.
|
||||
for line in lines:
|
||||
m = _BUILD_FINGERPRINT_RE.match(line)
|
||||
if not m:
|
||||
continue
|
||||
fingerprint = m.group(1)
|
||||
try:
|
||||
version = fingerprint.split('/')[2].split(':')[1].split('.')[0]
|
||||
return int(version)
|
||||
except Exception:
|
||||
pass
|
||||
return None
|
||||
|
||||
|
||||
def _HasElfHeader(path):
|
||||
"""Return True if the file at the given path has an ELF magic header.
|
||||
|
||||
Minimal check only, for 'ELF' in bytes 1 to 3 of the file. Filters out
|
||||
the zero-byte false-positives such as libchromeview.so returned by glob.
|
||||
|
||||
Args:
|
||||
path: Path to file to check.
|
||||
Returns:
|
||||
True or False
|
||||
"""
|
||||
with open(path) as stream:
|
||||
elf_header = stream.read(4)
|
||||
return len(elf_header) == 4 and elf_header[1:4] == 'ELF'
|
||||
|
||||
|
||||
def _ReadElfProgramHeaders(lib):
|
||||
"""Return an iterable of program headers, from 'readelf -l ...'.
|
||||
|
||||
Uses the platform readelf in all cases. This is somewhat lazy, but suffices
|
||||
in practice because program headers in ELF files are architecture-agnostic.
|
||||
|
||||
Args:
|
||||
lib: Library file to read.
|
||||
Returns:
|
||||
[readelf -l output line, ...]
|
||||
"""
|
||||
string = subprocess.check_output(['readelf', '-l', lib])
|
||||
return string.split('\n')
|
||||
|
||||
|
||||
def _FindMinLoadVaddr(lib):
|
||||
"""Return the minimum VirtAddr field of all library LOAD segments.
|
||||
|
||||
Args:
|
||||
lib: Library file to read.
|
||||
Returns:
|
||||
Min VirtAddr field for all LOAD segments, or 0 if none found.
|
||||
"""
|
||||
vaddrs = []
|
||||
# Locate LOAD lines and find the smallest VirtAddr field, eg:
|
||||
# Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
|
||||
# LOAD 0x000000 0x001d6000 0x001d6000 0x20f63fc 0x20f63fc R E 0x1000
|
||||
# LOAD 0x20f6970 0x022cd970 0x022cd970 0x182df8 0x1b4490 RW 0x1000
|
||||
# would return 0x1d6000. Ignores all non-LOAD lines.
|
||||
for line in _ReadElfProgramHeaders(lib):
|
||||
elements = line.split()
|
||||
if elements and elements[0] == 'LOAD':
|
||||
vaddrs.append(int(elements[2], 16))
|
||||
if vaddrs:
|
||||
return min(vaddrs)
|
||||
return 0
|
||||
|
||||
|
||||
def GetLoadVaddrs(stripped_libs=None, stripped_libs_dir=None):
|
||||
"""Return a dict of minimum VirtAddr for libraries in the given directory.
|
||||
|
||||
The dictionary returned may be passed to stack_core.ConvertTrace(). In
|
||||
pre-M Android releases the addresses printed by debuggerd into tombstones
|
||||
do not take account of non-zero vaddrs. Here we collect this information,
|
||||
so that we can use it later to correct such debuggerd tombstones.
|
||||
|
||||
Args:
|
||||
stripped_libs_dir: Path to directory containing apk's stripped libraries.
|
||||
Returns:
|
||||
{'libchrome.so': 12345, ...}
|
||||
"""
|
||||
if not stripped_libs:
|
||||
stripped_libs = []
|
||||
if stripped_libs_dir:
|
||||
stripped_libs.extend(glob.glob(os.path.join(stripped_libs_dir, '*.so')))
|
||||
libs = [l for l in stripped_libs if _HasElfHeader(l)]
|
||||
|
||||
load_vaddrs = {}
|
||||
for lib in libs:
|
||||
min_vaddr = _FindMinLoadVaddr(lib)
|
||||
if min_vaddr:
|
||||
# Store with the library basename as the key. This is because once on
|
||||
# the device its path may not fully match its place in the APK staging
|
||||
# directory
|
||||
load_vaddrs[os.path.basename(lib)] = min_vaddr
|
||||
|
||||
# Direct load from APK causes debuggerd to tag trace lines as if from the
|
||||
# file .../base.apk. So if we encounter a libchrome.so with packed
|
||||
# relocations, replicate this as base.apk so that later adjustment code
|
||||
# finds the appropriate adjustment.
|
||||
if _LIBCHROME_SO in load_vaddrs:
|
||||
load_vaddrs[_BASE_APK] = load_vaddrs[_LIBCHROME_SO]
|
||||
|
||||
return load_vaddrs
|
498
third_party/android_platform/development/scripts/symbol.py
vendored
Executable file
498
third_party/android_platform/development/scripts/symbol.py
vendored
Executable file
@ -0,0 +1,498 @@
|
||||
#!/usr/bin/python
|
||||
#
|
||||
# Copyright (C) 2013 The Android Open Source Project
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""Module for looking up symbolic debugging information.
|
||||
|
||||
The information can include symbol names, offsets, and source locations.
|
||||
"""
|
||||
|
||||
import glob
|
||||
import itertools
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import struct
|
||||
import subprocess
|
||||
import sys
|
||||
import zipfile
|
||||
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__),
|
||||
os.pardir, os.pardir, os.pardir, os.pardir,
|
||||
'build', 'android'))
|
||||
from pylib import constants
|
||||
from pylib.constants import host_paths
|
||||
from pylib.symbols import elf_symbolizer
|
||||
|
||||
|
||||
# WARNING: These global variables can be modified by other scripts!
|
||||
SYMBOLS_DIR = constants.DIR_SOURCE_ROOT
|
||||
CHROME_SYMBOLS_DIR = None
|
||||
ARCH = "arm"
|
||||
|
||||
_SECONDARY_ABI_OUTPUT_PATH = None
|
||||
|
||||
# See:
|
||||
# http://bugs.python.org/issue14315
|
||||
# https://hg.python.org/cpython/rev/6dd5e9556a60#l2.8
|
||||
def _PatchZipFile():
|
||||
oldDecodeExtra = zipfile.ZipInfo._decodeExtra
|
||||
def decodeExtra(self):
|
||||
try:
|
||||
oldDecodeExtra(self)
|
||||
except struct.error:
|
||||
pass
|
||||
zipfile.ZipInfo._decodeExtra = decodeExtra
|
||||
_PatchZipFile()
|
||||
|
||||
|
||||
# Used by _GetApkPackageName() to extract package name from aapt dump output.
|
||||
_PACKAGE_NAME_RE = re.compile(r'package: .*name=\'(\S*)\'')
|
||||
|
||||
# Used to speed up _GetApkPackageName() because the latter is called far too
|
||||
# often at the moment. Maps APK file paths to the corresponding package name.
|
||||
_package_name_cache = {}
|
||||
|
||||
def _GetApkPackageName(apk_path):
|
||||
"""Return the package name of a given apk."""
|
||||
package_name = _package_name_cache.get(apk_path, None)
|
||||
if package_name:
|
||||
return package_name
|
||||
|
||||
aapt_path = host_paths.GetAaptPath()
|
||||
aapt_output = subprocess.check_output(
|
||||
[aapt_path, 'dump', 'badging', apk_path]).split('\n')
|
||||
for line in aapt_output:
|
||||
match = _PACKAGE_NAME_RE.match(line)
|
||||
if match:
|
||||
package_name = match.group(1)
|
||||
_package_name_cache[apk_path] = package_name
|
||||
logging.debug('Package name %s for %s', package_name, apk_path)
|
||||
return package_name
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def _PathListJoin(prefix_list, suffix_list):
|
||||
"""Returns each prefix in prefix_list joined with each suffix in suffix list.
|
||||
|
||||
Args:
|
||||
prefix_list: list of path prefixes.
|
||||
suffix_list: list of path suffixes.
|
||||
|
||||
Returns:
|
||||
List of paths each of which joins a prefix with a suffix.
|
||||
"""
|
||||
return [
|
||||
os.path.join(prefix, suffix)
|
||||
for suffix in suffix_list for prefix in prefix_list ]
|
||||
|
||||
|
||||
def GetCandidates(dirs, filepart, candidate_fun):
|
||||
"""Returns a list of candidate filenames, sorted by modification time.
|
||||
|
||||
Args:
|
||||
dirs: a list of the directory part of the pathname.
|
||||
filepart: the file part of the pathname.
|
||||
candidate_fun: a function to apply to each candidate, returns a list.
|
||||
|
||||
Returns:
|
||||
A list of candidate files ordered by modification time, newest first.
|
||||
"""
|
||||
candidates = _PathListJoin(dirs, [filepart])
|
||||
logging.debug('GetCandidates: prefiltered candidates = %s' % candidates)
|
||||
candidates = list(
|
||||
itertools.chain.from_iterable(map(candidate_fun, candidates)))
|
||||
candidates.sort(key=os.path.getmtime, reverse=True)
|
||||
return candidates
|
||||
|
||||
|
||||
# Used by _GetCandidateApks() to speed up its result.
|
||||
_cached_candidate_apks = None
|
||||
|
||||
def _GetCandidateApks():
|
||||
"""Returns a list of APKs which could contain the library.
|
||||
|
||||
Args:
|
||||
None
|
||||
|
||||
Returns:
|
||||
list of APK file paths which could contain the library.
|
||||
"""
|
||||
global _cached_candidate_apks
|
||||
if _cached_candidate_apks is not None:
|
||||
return _cached_candidate_apks
|
||||
|
||||
apk_dir = os.path.join(constants.GetOutDirectory(), 'apks')
|
||||
candidates = GetCandidates([apk_dir], '*.apk', glob.glob)
|
||||
_cached_candidate_apks = candidates
|
||||
return candidates
|
||||
|
||||
|
||||
def GetCrazyLib(apk_filename):
|
||||
"""Returns the name of the first crazy library from this APK.
|
||||
|
||||
Args:
|
||||
apk_filename: name of an APK file.
|
||||
|
||||
Returns:
|
||||
Name of the first library which would be crazy loaded from this APK.
|
||||
"""
|
||||
zip_file = zipfile.ZipFile(apk_filename, 'r')
|
||||
for filename in zip_file.namelist():
|
||||
match = re.match('lib/[^/]*/crazy.(lib.*[.]so)', filename)
|
||||
if match:
|
||||
return match.group(1)
|
||||
|
||||
def GetApkFromLibrary(device_library_path):
|
||||
match = re.match(r'.*/([^/]*)-[0-9]+(\/[^/]*)?\.apk$', device_library_path)
|
||||
if not match:
|
||||
return None
|
||||
return match.group(1)
|
||||
|
||||
|
||||
def GetMatchingApks(package_name):
|
||||
"""Find any APKs which match the package indicated by the device_apk_name.
|
||||
|
||||
Args:
|
||||
package_name: package name of the APK on the device.
|
||||
|
||||
Returns:
|
||||
A list of APK filenames which could contain the desired library.
|
||||
"""
|
||||
return [apk_path for apk_path in _GetCandidateApks() if (
|
||||
_GetApkPackageName(apk_path) == package_name)]
|
||||
|
||||
|
||||
def MapDeviceApkToLibrary(device_apk_name):
|
||||
"""Provide a library name which corresponds with device_apk_name.
|
||||
|
||||
Args:
|
||||
device_apk_name: name of the APK on the device.
|
||||
|
||||
Returns:
|
||||
Name of the library which corresponds to that APK.
|
||||
"""
|
||||
matching_apks = GetMatchingApks(device_apk_name)
|
||||
logging.debug('MapDeviceApkToLibrary: matching_apks=%s' % matching_apks)
|
||||
for matching_apk in matching_apks:
|
||||
crazy_lib = GetCrazyLib(matching_apk)
|
||||
if crazy_lib:
|
||||
return crazy_lib
|
||||
|
||||
|
||||
def GetLibrarySearchPaths():
|
||||
"""Return a list of directories where to find native shared libraries."""
|
||||
if _SECONDARY_ABI_OUTPUT_PATH:
|
||||
return _PathListJoin([_SECONDARY_ABI_OUTPUT_PATH], ['lib.unstripped', '.'])
|
||||
if CHROME_SYMBOLS_DIR:
|
||||
return [CHROME_SYMBOLS_DIR]
|
||||
output_dir = constants.GetOutDirectory()
|
||||
# GN places stripped libraries under $CHROMIUM_OUTPUT_DIR and unstripped ones
|
||||
# under $CHROMIUM_OUTPUT_OUT/lib.unstripped. Place the unstripped path before
|
||||
# to get symbols from them when they exist.
|
||||
return _PathListJoin([output_dir], ['lib.unstripped', '.'])
|
||||
|
||||
|
||||
def GetCandidateLibraries(library_name):
|
||||
"""Returns a list of candidate library filenames.
|
||||
|
||||
Args:
|
||||
library_name: basename of the library to match.
|
||||
|
||||
Returns:
|
||||
A list of matching library filenames for library_name.
|
||||
"""
|
||||
def extant_library(filename):
|
||||
if (os.path.exists(filename)
|
||||
and elf_symbolizer.ContainsElfMagic(filename)):
|
||||
return [filename]
|
||||
return []
|
||||
|
||||
candidates = GetCandidates(
|
||||
GetLibrarySearchPaths(), library_name,
|
||||
extant_library)
|
||||
# For GN, candidates includes both stripped an unstripped libraries. Stripped
|
||||
# libraries are always newer. Explicitly look for .unstripped and sort them
|
||||
# ahead.
|
||||
candidates.sort(key=lambda c: int('unstripped' not in c))
|
||||
return candidates
|
||||
|
||||
|
||||
def TranslateLibPath(lib):
|
||||
# The filename in the stack trace maybe an APK name rather than a library
|
||||
# name. This happens when the library was loaded directly from inside the
|
||||
# APK. If this is the case we try to figure out the library name by looking
|
||||
# for a matching APK file and finding the name of the library in contains.
|
||||
# The name of the APK file on the device is of the form
|
||||
# <package_name>-<number>.apk. The APK file on the host may have any name
|
||||
# so we look at the APK badging to see if the package name matches.
|
||||
apk = GetApkFromLibrary(lib)
|
||||
if apk is not None:
|
||||
logging.debug('TranslateLibPath: apk=%s' % apk)
|
||||
mapping = MapDeviceApkToLibrary(apk)
|
||||
if mapping:
|
||||
lib = mapping
|
||||
|
||||
# SymbolInformation(lib, addr) receives lib as the path from symbols
|
||||
# root to the symbols file. This needs to be translated to point to the
|
||||
# correct .so path. If the user doesn't explicitly specify which directory to
|
||||
# use, then use the most recently updated one in one of the known directories.
|
||||
# If the .so is not found somewhere in CHROME_SYMBOLS_DIR, leave it
|
||||
# untranslated in case it is an Android symbol in SYMBOLS_DIR.
|
||||
library_name = os.path.basename(lib)
|
||||
|
||||
logging.debug('TranslateLibPath: lib=%s library_name=%s' % (lib, library_name))
|
||||
|
||||
candidate_libraries = GetCandidateLibraries(library_name)
|
||||
logging.debug('TranslateLibPath: candidate_libraries=%s' % candidate_libraries)
|
||||
if not candidate_libraries:
|
||||
return lib
|
||||
|
||||
library_path = os.path.relpath(candidate_libraries[0], SYMBOLS_DIR)
|
||||
logging.debug('TranslateLibPath: library_path=%s' % library_path)
|
||||
return library_path
|
||||
|
||||
|
||||
def _FormatSymbolWithOffset(symbol, offset):
|
||||
if offset == 0:
|
||||
return symbol
|
||||
return "%s+%d" % (symbol, offset)
|
||||
|
||||
|
||||
def SetSecondaryAbiOutputPath(path):
|
||||
global _SECONDARY_ABI_OUTPUT_PATH
|
||||
if _SECONDARY_ABI_OUTPUT_PATH and _SECONDARY_ABI_OUTPUT_PATH != path:
|
||||
raise Exception ('SetSecondaryAbiOutputPath() was already called with a ' +
|
||||
'different value, previous: %s new: %s' % (
|
||||
_SECONDARY_ABI_OUTPUT_PATH, path))
|
||||
else:
|
||||
_SECONDARY_ABI_OUTPUT_PATH = path
|
||||
|
||||
|
||||
def SymbolInformationForSet(lib, unique_addrs, get_detailed_info,
|
||||
cpu_arch=ARCH):
|
||||
"""Look up symbol information for a set of addresses from the given library.
|
||||
|
||||
Args:
|
||||
lib: library (or executable) pathname containing symbols
|
||||
unique_addrs: set of hexidecimal addresses
|
||||
get_detailed_info: If True, add additional info from objdump.
|
||||
cpu_arch: Target CPU architecture.
|
||||
|
||||
Returns:
|
||||
A dictionary of the form {addr: [(source_symbol, source_location,
|
||||
object_symbol_with_offset)]} where each address has a list of
|
||||
associated symbols and locations. The list is always non-empty.
|
||||
|
||||
If the function has been inlined then the list may contain
|
||||
more than one element with the symbols for the most deeply
|
||||
nested inlined location appearing first. The list is
|
||||
always non-empty, even if no information is available.
|
||||
|
||||
Usually you want to display the source_location and
|
||||
object_symbol_with_offset from the last element in the list.
|
||||
"""
|
||||
if not lib:
|
||||
return None
|
||||
|
||||
addr_to_line = _CallAddr2LineForSet(lib, unique_addrs, cpu_arch)
|
||||
if not addr_to_line:
|
||||
return None
|
||||
|
||||
if get_detailed_info:
|
||||
addr_to_objdump = _CallObjdumpForSet(lib, unique_addrs, cpu_arch)
|
||||
if not addr_to_objdump:
|
||||
return None
|
||||
else:
|
||||
addr_to_objdump = dict((addr, ("", 0)) for addr in unique_addrs)
|
||||
|
||||
result = {}
|
||||
for addr in unique_addrs:
|
||||
source_info = addr_to_line.get(addr)
|
||||
if not source_info:
|
||||
source_info = [(None, None)]
|
||||
if addr in addr_to_objdump:
|
||||
(object_symbol, object_offset) = addr_to_objdump.get(addr)
|
||||
object_symbol_with_offset = _FormatSymbolWithOffset(object_symbol,
|
||||
object_offset)
|
||||
else:
|
||||
object_symbol_with_offset = None
|
||||
result[addr] = [(source_symbol, source_location, object_symbol_with_offset)
|
||||
for (source_symbol, source_location) in source_info]
|
||||
|
||||
return result
|
||||
|
||||
|
||||
class _MemoizedForSet(object):
|
||||
"""Decorator class used to memoize CallXXXForSet() results."""
|
||||
def __init__(self, fn):
|
||||
self.fn = fn
|
||||
self.cache = {}
|
||||
self.cpu_arch = None
|
||||
|
||||
def __call__(self, lib, unique_addrs, cpu_arch):
|
||||
if self.cpu_arch is None:
|
||||
self.cpu_arch = cpu_arch
|
||||
else:
|
||||
# Sanity check, this doesn't expect cpu_arch to change.
|
||||
assert self.cpu_arch == cpu_arch
|
||||
|
||||
lib_cache = self.cache.setdefault(lib, {})
|
||||
|
||||
uncached_addrs = [k for k in unique_addrs if k not in lib_cache]
|
||||
if uncached_addrs:
|
||||
lib_cache.update((k, None) for k in uncached_addrs)
|
||||
result = self.fn(lib, uncached_addrs, cpu_arch)
|
||||
if result:
|
||||
lib_cache.update(result)
|
||||
|
||||
return dict((k, lib_cache[k]) for k in unique_addrs if lib_cache[k])
|
||||
|
||||
|
||||
@_MemoizedForSet
|
||||
def _CallAddr2LineForSet(lib, unique_addrs, cpu_arch):
|
||||
"""Look up line and symbol information for a set of addresses.
|
||||
|
||||
Args:
|
||||
lib: library (or executable) pathname containing symbols
|
||||
unique_addrs: set of string hexidecimal addresses look up.
|
||||
cpu_arch: Target CPU architecture.
|
||||
|
||||
Returns:
|
||||
A dictionary of the form {addr: [(symbol, file:line)]} where
|
||||
each address has a list of associated symbols and locations
|
||||
or an empty list if no symbol information was found.
|
||||
|
||||
If the function has been inlined then the list may contain
|
||||
more than one element with the symbols for the most deeply
|
||||
nested inlined location appearing first.
|
||||
"""
|
||||
if not lib:
|
||||
return None
|
||||
|
||||
symbols = SYMBOLS_DIR + lib
|
||||
if not os.path.splitext(symbols)[1] in ['', '.so', '.apk']:
|
||||
return None
|
||||
|
||||
if not os.path.isfile(symbols):
|
||||
return None
|
||||
|
||||
addrs = sorted(unique_addrs)
|
||||
result = {}
|
||||
|
||||
def _Callback(sym, addr):
|
||||
records = []
|
||||
while sym: # Traverse all the inlines following the |inlined_by| chain.
|
||||
if sym.source_path and sym.source_line:
|
||||
location = '%s:%d' % (sym.source_path, sym.source_line)
|
||||
else:
|
||||
location = None
|
||||
records += [(sym.name, location)]
|
||||
sym = sym.inlined_by
|
||||
result[addr] = records
|
||||
|
||||
symbolizer = elf_symbolizer.ELFSymbolizer(
|
||||
elf_file_path=symbols,
|
||||
addr2line_path=host_paths.ToolPath("addr2line", cpu_arch),
|
||||
callback=_Callback,
|
||||
inlines=True)
|
||||
|
||||
for addr in addrs:
|
||||
symbolizer.SymbolizeAsync(int(addr, 16), addr)
|
||||
symbolizer.Join()
|
||||
return result
|
||||
|
||||
|
||||
@_MemoizedForSet
|
||||
def _CallObjdumpForSet(lib, unique_addrs, cpu_arch):
|
||||
"""Use objdump to find out the names of the containing functions.
|
||||
|
||||
Args:
|
||||
lib: library (or executable) pathname containing symbols
|
||||
unique_addrs: set of string hexidecimal addresses to find the functions for.
|
||||
cpu_arch: Target CPU architecture.
|
||||
|
||||
Returns:
|
||||
A dictionary of the form {addr: (string symbol, offset)}.
|
||||
"""
|
||||
if not lib:
|
||||
return None
|
||||
|
||||
symbols = SYMBOLS_DIR + lib
|
||||
if not os.path.exists(symbols):
|
||||
return None
|
||||
|
||||
symbols = SYMBOLS_DIR + lib
|
||||
if not os.path.exists(symbols):
|
||||
return None
|
||||
|
||||
result = {}
|
||||
|
||||
# Function lines look like:
|
||||
# 000177b0 <android::IBinder::~IBinder()+0x2c>:
|
||||
# We pull out the address and function first. Then we check for an optional
|
||||
# offset. This is tricky due to functions that look like "operator+(..)+0x2c"
|
||||
func_regexp = re.compile("(^[a-f0-9]*) \<(.*)\>:$")
|
||||
offset_regexp = re.compile("(.*)\+0x([a-f0-9]*)")
|
||||
|
||||
# A disassembly line looks like:
|
||||
# 177b2: b510 push {r4, lr}
|
||||
asm_regexp = re.compile("(^[ a-f0-9]*):[ a-f0-0]*.*$")
|
||||
|
||||
for target_addr in unique_addrs:
|
||||
start_addr_dec = str(StripPC(int(target_addr, 16)))
|
||||
stop_addr_dec = str(StripPC(int(target_addr, 16)) + 8)
|
||||
cmd = [host_paths.ToolPath("objdump", cpu_arch),
|
||||
"--section=.text",
|
||||
"--demangle",
|
||||
"--disassemble",
|
||||
"--start-address=" + start_addr_dec,
|
||||
"--stop-address=" + stop_addr_dec,
|
||||
symbols]
|
||||
|
||||
current_symbol = None # The current function symbol in the disassembly.
|
||||
current_symbol_addr = 0 # The address of the current function.
|
||||
|
||||
stream = subprocess.Popen(cmd, stdout=subprocess.PIPE).stdout
|
||||
for line in stream:
|
||||
# Is it a function line like:
|
||||
# 000177b0 <android::IBinder::~IBinder()>:
|
||||
components = func_regexp.match(line)
|
||||
if components:
|
||||
# This is a new function, so record the current function and its address.
|
||||
current_symbol_addr = int(components.group(1), 16)
|
||||
current_symbol = components.group(2)
|
||||
|
||||
# Does it have an optional offset like: "foo(..)+0x2c"?
|
||||
components = offset_regexp.match(current_symbol)
|
||||
if components:
|
||||
current_symbol = components.group(1)
|
||||
offset = components.group(2)
|
||||
if offset:
|
||||
current_symbol_addr -= int(offset, 16)
|
||||
|
||||
# Is it an disassembly line like:
|
||||
# 177b2: b510 push {r4, lr}
|
||||
components = asm_regexp.match(line)
|
||||
if components:
|
||||
addr = components.group(1)
|
||||
i_addr = int(addr, 16)
|
||||
i_target = StripPC(int(target_addr, 16))
|
||||
if i_addr == i_target:
|
||||
result[target_addr] = (current_symbol, i_target - current_symbol_addr)
|
||||
stream.close()
|
||||
|
||||
return result
|
24
third_party/android_support_test_runner/BUILD.gn
vendored
Normal file
24
third_party/android_support_test_runner/BUILD.gn
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
# Copyright 2016 The Chromium Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
import("//build/config/android/rules.gni")
|
||||
|
||||
android_java_prebuilt("runner_java") {
|
||||
testonly = true
|
||||
jar_path = "lib/runner-release-no-dep.jar"
|
||||
deps = [
|
||||
":exposed_instrumentation_api_publish_java",
|
||||
"//third_party/guava:guava_android_java",
|
||||
"//third_party/junit",
|
||||
]
|
||||
}
|
||||
|
||||
android_java_prebuilt("exposed_instrumentation_api_publish_java") {
|
||||
jar_path = "lib/exposed-instrumentation-api-publish-no-dep.jar"
|
||||
}
|
||||
|
||||
android_aar_prebuilt("rules_java") {
|
||||
testonly = true
|
||||
aar_path = "lib/rules.aar"
|
||||
}
|
202
third_party/android_support_test_runner/LICENSE
vendored
Normal file
202
third_party/android_support_test_runner/LICENSE
vendored
Normal file
@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
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.
|
3
third_party/android_support_test_runner/OWNERS
vendored
Normal file
3
third_party/android_support_test_runner/OWNERS
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
jbudorick@chromium.org
|
||||
mikecase@chromium.org
|
||||
yolandyan@chromium.org
|
14
third_party/android_support_test_runner/README.chromium
vendored
Normal file
14
third_party/android_support_test_runner/README.chromium
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
Name: Android Testing Support Library Test Runner
|
||||
Short Name: runner
|
||||
URL: https://github.com/googlesamples/android-testing/tree/master/ui/espresso/BasicSampleBundled
|
||||
Version: 0.5
|
||||
License: Apache 2.0
|
||||
License File: NOT_SHIPPED
|
||||
Security Critical: no
|
||||
|
||||
Description:
|
||||
These static jars are part of Android Testing Support Library. They are needed
|
||||
for Android JUnit runner. IMPORTANT: There should only be one version of
|
||||
espresso library (crbug.com/622057)
|
||||
|
||||
Local Modifications: None
|
12
third_party/android_support_test_runner/cipd.yaml
vendored
Normal file
12
third_party/android_support_test_runner/cipd.yaml
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
# Copyright 2017 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.
|
||||
|
||||
# To create CIPD package run the following command.
|
||||
# cipd create --pkg-def cipd.yaml -tag version:$(cat version.txt)
|
||||
package: chromium/third_party/android_support_test_runner
|
||||
description: android_support_test_runner Java libraries
|
||||
data:
|
||||
- file: lib/exposed-instrumentation-api-publish-no-dep.jar
|
||||
- file: lib/rules.aar
|
||||
- file: lib/runner-release-no-dep.jar
|
13
third_party/android_support_test_runner/rules_java.info
vendored
Normal file
13
third_party/android_support_test_runner/rules_java.info
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
# Generated by //build/android/gyp/aar.py
|
||||
# To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
|
||||
|
||||
aidl = [ ]
|
||||
assets = [ ]
|
||||
has_classes_jar = true
|
||||
has_native_libraries = false
|
||||
has_proguard_flags = false
|
||||
has_r_text_file = true
|
||||
is_manifest_empty = true
|
||||
resources = [ "res/values/values.xml" ]
|
||||
subjar_tuples = [ ]
|
||||
subjars = [ ]
|
350
third_party/android_system_sdk/LICENSE
vendored
Normal file
350
third_party/android_system_sdk/LICENSE
vendored
Normal file
@ -0,0 +1,350 @@
|
||||
GNU General Public License, version 2,
|
||||
with the Classpath Exception
|
||||
|
||||
The GNU General Public License (GPL)
|
||||
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies of this license
|
||||
document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your freedom to share
|
||||
and change it. By contrast, the GNU General Public License is intended to
|
||||
guarantee your freedom to share and change free software--to make sure the
|
||||
software is free for all its users. This General Public License applies to
|
||||
most of the Free Software Foundation's software and to any other program whose
|
||||
authors commit to using it. (Some other Free Software Foundation software is
|
||||
covered by the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not price. Our
|
||||
General Public Licenses are designed to make sure that you have the freedom to
|
||||
distribute copies of free software (and charge for this service if you wish),
|
||||
that you receive source code or can get it if you want it, that you can change
|
||||
the software or use pieces of it in new free programs; and that you know you
|
||||
can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid anyone to deny
|
||||
you these rights or to ask you to surrender the rights. These restrictions
|
||||
translate to certain responsibilities for you if you distribute copies of the
|
||||
software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether gratis or for
|
||||
a fee, you must give the recipients all the rights that you have. You must
|
||||
make sure that they, too, receive or can get the source code. And you must
|
||||
show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and (2)
|
||||
offer you this license which gives you legal permission to copy, distribute
|
||||
and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain that
|
||||
everyone understands that there is no warranty for this free software. If the
|
||||
software is modified by someone else and passed on, we want its recipients to
|
||||
know that what they have is not the original, so that any problems introduced
|
||||
by others will not reflect on the original authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software patents. We
|
||||
wish to avoid the danger that redistributors of a free program will
|
||||
individually obtain patent licenses, in effect making the program proprietary.
|
||||
To prevent this, we have made it clear that any patent must be licensed for
|
||||
everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and modification
|
||||
follow.
|
||||
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains a notice
|
||||
placed by the copyright holder saying it may be distributed under the terms of
|
||||
this General Public License. The "Program", below, refers to any such program
|
||||
or work, and a "work based on the Program" means either the Program or any
|
||||
derivative work under copyright law: that is to say, a work containing the
|
||||
Program or a portion of it, either verbatim or with modifications and/or
|
||||
translated into another language. (Hereinafter, translation is included
|
||||
without limitation in the term "modification".) Each licensee is addressed as
|
||||
"you".
|
||||
|
||||
Activities other than copying, distribution and modification are not covered by
|
||||
this License; they are outside its scope. The act of running the Program is
|
||||
not restricted, and the output from the Program is covered only if its contents
|
||||
constitute a work based on the Program (independent of having been made by
|
||||
running the Program). Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's source code as
|
||||
you receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice and
|
||||
disclaimer of warranty; keep intact all the notices that refer to this License
|
||||
and to the absence of any warranty; and give any other recipients of the
|
||||
Program a copy of this License along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and you may
|
||||
at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion of it, thus
|
||||
forming a work based on the Program, and copy and distribute such modifications
|
||||
or work under the terms of Section 1 above, provided that you also meet all of
|
||||
these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices stating
|
||||
that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in whole or
|
||||
in part contains or is derived from the Program or any part thereof, to be
|
||||
licensed as a whole at no charge to all third parties under the terms of
|
||||
this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively when run,
|
||||
you must cause it, when started running for such interactive use in the
|
||||
most ordinary way, to print or display an announcement including an
|
||||
appropriate copyright notice and a notice that there is no warranty (or
|
||||
else, saying that you provide a warranty) and that users may redistribute
|
||||
the program under these conditions, and telling the user how to view a copy
|
||||
of this License. (Exception: if the Program itself is interactive but does
|
||||
not normally print such an announcement, your work based on the Program is
|
||||
not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If identifiable
|
||||
sections of that work are not derived from the Program, and can be reasonably
|
||||
considered independent and separate works in themselves, then this License, and
|
||||
its terms, do not apply to those sections when you distribute them as separate
|
||||
works. But when you distribute the same sections as part of a whole which is a
|
||||
work based on the Program, the distribution of the whole must be on the terms
|
||||
of this License, whose permissions for other licensees extend to the entire
|
||||
whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest your
|
||||
rights to work written entirely by you; rather, the intent is to exercise the
|
||||
right to control the distribution of derivative or collective works based on
|
||||
the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program with the
|
||||
Program (or with a work based on the Program) on a volume of a storage or
|
||||
distribution medium does not bring the other work under the scope of this
|
||||
License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it, under
|
||||
Section 2) in object code or executable form under the terms of Sections 1 and
|
||||
2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable source
|
||||
code, which must be distributed under the terms of Sections 1 and 2 above
|
||||
on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three years, to
|
||||
give any third party, for a charge no more than your cost of physically
|
||||
performing source distribution, a complete machine-readable copy of the
|
||||
corresponding source code, to be distributed under the terms of Sections 1
|
||||
and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer to
|
||||
distribute corresponding source code. (This alternative is allowed only
|
||||
for noncommercial distribution and only if you received the program in
|
||||
object code or executable form with such an offer, in accord with
|
||||
Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for making
|
||||
modifications to it. For an executable work, complete source code means all
|
||||
the source code for all modules it contains, plus any associated interface
|
||||
definition files, plus the scripts used to control compilation and installation
|
||||
of the executable. However, as a special exception, the source code
|
||||
distributed need not include anything that is normally distributed (in either
|
||||
source or binary form) with the major components (compiler, kernel, and so on)
|
||||
of the operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the source
|
||||
code from the same place counts as distribution of the source code, even though
|
||||
third parties are not compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program except as
|
||||
expressly provided under this License. Any attempt otherwise to copy, modify,
|
||||
sublicense or distribute the Program is void, and will automatically terminate
|
||||
your rights under this License. However, parties who have received copies, or
|
||||
rights, from you under this License will not have their licenses terminated so
|
||||
long as such parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not signed it.
|
||||
However, nothing else grants you permission to modify or distribute the Program
|
||||
or its derivative works. These actions are prohibited by law if you do not
|
||||
accept this License. Therefore, by modifying or distributing the Program (or
|
||||
any work based on the Program), you indicate your acceptance of this License to
|
||||
do so, and all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the Program),
|
||||
the recipient automatically receives a license from the original licensor to
|
||||
copy, distribute or modify the Program subject to these terms and conditions.
|
||||
You may not impose any further restrictions on the recipients' exercise of the
|
||||
rights granted herein. You are not responsible for enforcing compliance by
|
||||
third parties to this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues), conditions
|
||||
are imposed on you (whether by court order, agreement or otherwise) that
|
||||
contradict the conditions of this License, they do not excuse you from the
|
||||
conditions of this License. If you cannot distribute so as to satisfy
|
||||
simultaneously your obligations under this License and any other pertinent
|
||||
obligations, then as a consequence you may not distribute the Program at all.
|
||||
For example, if a patent license would not permit royalty-free redistribution
|
||||
of the Program by all those who receive copies directly or indirectly through
|
||||
you, then the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply and
|
||||
the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any patents or
|
||||
other property right claims or to contest validity of any such claims; this
|
||||
section has the sole purpose of protecting the integrity of the free software
|
||||
distribution system, which is implemented by public license practices. Many
|
||||
people have made generous contributions to the wide range of software
|
||||
distributed through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing to
|
||||
distribute software through any other system and a licensee cannot impose that
|
||||
choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to be a
|
||||
consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in certain
|
||||
countries either by patents or by copyrighted interfaces, the original
|
||||
copyright holder who places the Program under this License may add an explicit
|
||||
geographical distribution limitation excluding those countries, so that
|
||||
distribution is permitted only in or among countries not thus excluded. In
|
||||
such case, this License incorporates the limitation as if written in the body
|
||||
of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions of the
|
||||
General Public License from time to time. Such new versions will be similar in
|
||||
spirit to the present version, but may differ in detail to address new problems
|
||||
or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any later
|
||||
version", you have the option of following the terms and conditions either of
|
||||
that version or of any later version published by the Free Software Foundation.
|
||||
If the Program does not specify a version number of this License, you may
|
||||
choose any version ever published by the Free Software Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free programs
|
||||
whose distribution conditions are different, write to the author to ask for
|
||||
permission. For software which is copyrighted by the Free Software Foundation,
|
||||
write to the Free Software Foundation; we sometimes make exceptions for this.
|
||||
Our decision will be guided by the two goals of preserving the free status of
|
||||
all derivatives of our free software and of promoting the sharing and reuse of
|
||||
software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
|
||||
THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE
|
||||
STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE
|
||||
PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND
|
||||
PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE,
|
||||
YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL
|
||||
ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE
|
||||
PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
|
||||
INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
|
||||
BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER
|
||||
OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest possible
|
||||
use to the public, the best way to achieve this is to make it free software
|
||||
which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest to attach
|
||||
them to the start of each source file to most effectively convey the exclusion
|
||||
of warranty; and each file should have at least the "copyright" line and a
|
||||
pointer to where the full notice is found.
|
||||
|
||||
One line to give the program's name and a brief idea of what it does.
|
||||
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 2 of the License, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc., 59
|
||||
Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this when it
|
||||
starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author Gnomovision comes
|
||||
with ABSOLUTELY NO WARRANTY; for details type 'show w'. This is free
|
||||
software, and you are welcome to redistribute it under certain conditions;
|
||||
type 'show c' for details.
|
||||
|
||||
The hypothetical commands 'show w' and 'show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may be
|
||||
called something other than 'show w' and 'show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary. Here
|
||||
is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
'Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
signature of Ty Coon, 1 April 1989
|
||||
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General Public
|
||||
License instead of this License.
|
||||
|
||||
|
||||
"CLASSPATH" EXCEPTION TO THE GPL
|
||||
|
||||
Certain source files distributed by Oracle America and/or its affiliates are
|
||||
subject to the following clarification and special exception to the GPL, but
|
||||
only where Oracle has expressly included in the particular source file's header
|
||||
the words "Oracle designates this particular file as subject to the "Classpath"
|
||||
exception as provided by Oracle in the LICENSE file that accompanied this code."
|
||||
|
||||
Linking this library statically or dynamically with other modules is making
|
||||
a combined work based on this library. Thus, the terms and conditions of
|
||||
the GNU General Public License cover the whole combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent modules,
|
||||
and to copy and distribute the resulting executable under terms of your
|
||||
choice, provided that you also meet, for each linked independent module,
|
||||
the terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library. If
|
||||
you modify this library, you may extend this exception to your version of
|
||||
the library, but you are not obligated to do so. If you do not wish to do
|
||||
so, delete this exception statement from your version.
|
5
third_party/android_system_sdk/OWNERS
vendored
Normal file
5
third_party/android_system_sdk/OWNERS
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
torne@chromium.org
|
||||
tobiasjs@chromium.org
|
||||
|
||||
# TEAM: android-webview-dev@chromium.org
|
||||
# COMPONENT: Mobile>WebView
|
14
third_party/android_system_sdk/README.chromium
vendored
Normal file
14
third_party/android_system_sdk/README.chromium
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
Name: Android System SDK
|
||||
Short Name: Android System SDK
|
||||
Version: 0
|
||||
Revision: OPM1.171018.001
|
||||
License: GPL v2
|
||||
License File: LICENSE
|
||||
Security Critical: No
|
||||
|
||||
Description:
|
||||
System SDK stubs for compiling Android Webview and Monochrome targets.
|
||||
Revision is the BUILD ID of the Android release build.
|
||||
|
||||
Local Modifications:
|
||||
None
|
11
third_party/android_system_sdk/cipd.yaml
vendored
Normal file
11
third_party/android_system_sdk/cipd.yaml
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
# Copyright 2017 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.
|
||||
|
||||
# To create CIPD package run the following command.
|
||||
# cipd create --pkg-def cipd.yaml -tag version:$(cat version.txt)
|
||||
package: chromium/third_party/android_system_sdk
|
||||
description: System SDK stubs for compile WebView and Monochrome targets
|
||||
data:
|
||||
- file: android-stubs-src.jar
|
||||
- file: android_system.jar
|
202
third_party/apk-patch-size-estimator/LICENSE
vendored
Normal file
202
third_party/apk-patch-size-estimator/LICENSE
vendored
Normal file
@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
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.
|
4
third_party/apk-patch-size-estimator/OWNERS
vendored
Normal file
4
third_party/apk-patch-size-estimator/OWNERS
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
agrieve@chromium.org
|
||||
estevenson@chromium.org
|
||||
|
||||
# COMPONENT: Build
|
16
third_party/apk-patch-size-estimator/README.chromium
vendored
Normal file
16
third_party/apk-patch-size-estimator/README.chromium
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
Name: APK patch size estimator
|
||||
URL: https://github.com/googlesamples/apk-patch-size-estimator
|
||||
Version: 0.2
|
||||
Date: Dec 16, 2016
|
||||
Revision: 823a9504f237e4bb236cadf8b804ed27498e54fd
|
||||
License: Apache 2.0
|
||||
License File: NOT_SHIPPED
|
||||
Security Critical: No
|
||||
|
||||
Description:
|
||||
Estimates the size of Google Play patches and the new gzipped APK. See README.md
|
||||
for more details.
|
||||
|
||||
Local Modifications:
|
||||
- Removed the following files: CONTRIBUTING.md, tests/, images/.
|
||||
- Changed file-by-file-tools.jar path to be absolute instead of relative.
|
77
third_party/apk-patch-size-estimator/README.md
vendored
Normal file
77
third_party/apk-patch-size-estimator/README.md
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
# APK patch size estimator
|
||||
Estimates the size of Google Play patches and the new gzipped APK.
|
||||
|
||||
From two APKs it estimates the size of the new patches as well as the size of the gzipped version of the new APK, which would be used in
|
||||
cases where the patches are unexpectedly large, unavailable, or unsuitable.
|
||||
Google Play uses multiple techniques to generate patches and generally picks the best match for the device. The best match is usually, but not always, the smallest patch file produced. The numbers that this script produces are **ESTIMATES** that can be used to characterize the impact of arbitrary changes to APKs. There is **NO GUARANTEE** that this tool produces the same patches or patch sizes that Google Play generates, stores or transmits, and the actual implementation within Google Play may change at any time, without notice.
|
||||
|
||||
***This is not an official Google product***
|
||||
|
||||
## Usage
|
||||
|
||||
The script uses *Python 2.7.X*, *bsdiff* and *Java* (you may need to install them in your system)
|
||||
|
||||
For the file-by-file estimation we use a jar (at /lib/file-by-file-tools.jar) generated from: https://github.com/andrewhayden/archive-patcher
|
||||
|
||||
#### To estimate the patches sizes of two APKs run:
|
||||
```bash
|
||||
$ python apk_patch_size_estimator.py --old-file old.apk --new-file new.apk
|
||||
```
|
||||
|
||||
#### Output:
|
||||
```bash
|
||||
New APK size on disk: 18,271,850 bytes [17.4MB]
|
||||
|
||||
Estimated download size for new installs:
|
||||
Full new APK (gzipped) size: 16,339,603 bytes [15.6MB]
|
||||
|
||||
Estimated download size for updates from the old APK, using Bsdiff:
|
||||
Bsdiff patch (gzipped) size: 2,989,691 bytes [2.85MB]
|
||||
|
||||
Estimated download size for updates from the old APK,
|
||||
using File-by-File:
|
||||
File-by-File patch (gzipped) size: 1,912,751 bytes [1.82MB]
|
||||
```
|
||||
|
||||
## Patches estimation process
|
||||
|
||||
### Bsdiff estimation
|
||||

|
||||
|
||||
### File-by-file estimation
|
||||
Please visit https://github.com/andrewhayden/archive-patcher for further details.
|
||||
|
||||
## Installing external dependencies
|
||||
The script uses *bsdiff*, *gzip*, *head*, *tail*, *bunzip2* and *java* binaries, [**bsdiff**](https://www.freebsd.org/cgi/man.cgi?query=bsdiff) is the only one not installed by defult in a unix based OS.
|
||||
|
||||
#### Linux debian-based
|
||||
Install bsdiff:
|
||||
```bash
|
||||
sudo apt-get install bsdiff
|
||||
```
|
||||
|
||||
#### OS X
|
||||
Install bsdiff using [Homebrew](http://brew.sh/):
|
||||
```bash
|
||||
brew install bsdiff
|
||||
```
|
||||
|
||||
#### Windows
|
||||
|
||||
The easiest way to run the script in Windows is by using [Cygwin](https://www.cygwin.com/), make sure you install *python* and *bsdiff* using Cygwin's installer/setup.
|
||||
|
||||
## Runing the unittests
|
||||
|
||||
#### Install unittest.mock
|
||||
```bash
|
||||
pip install mock
|
||||
```
|
||||
|
||||
#### Run the test
|
||||
```bash
|
||||
python -m unittest discover tests/
|
||||
```
|
||||
|
||||
## Authors
|
||||
Julian Toledo
|
||||
Andrew Hayden
|
353
third_party/apk-patch-size-estimator/apk_patch_size_estimator.py
vendored
Executable file
353
third_party/apk-patch-size-estimator/apk_patch_size_estimator.py
vendored
Executable file
@ -0,0 +1,353 @@
|
||||
#!/usr/bin/python
|
||||
#
|
||||
# Copyright 2016 Google Inc. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""Estimates the size of Google Play patches and the new gzipped APK.
|
||||
|
||||
From two APKs it estimates the size of new patches as well as
|
||||
the size of a gzipped version of the APK, which would be used in
|
||||
cases where patches are unexpectedly large, unavailable, or unsuitable.
|
||||
Google Play uses multiple techniques to generate patches and generally picks
|
||||
the best match for the device. The best match is usually, but not always, the
|
||||
smallest patch file produced. The numbers that this script produces are
|
||||
ESTIMATES that can be used to characterize the impact of arbitrary changes to
|
||||
APKs. There is NO GUARANTEE that this tool produces the same patches or patch
|
||||
sizes that Google Play generates, stores or transmits, and the actual
|
||||
implementation within Google Play may change at any time, without notice.
|
||||
|
||||
"""
|
||||
|
||||
import sys
|
||||
import argparse
|
||||
import locale
|
||||
import math
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
_FILEBYFILE_JAR_PATH = os.path.abspath(
|
||||
os.path.join(os.path.dirname(__file__), 'lib', 'file-by-file-tools.jar'))
|
||||
|
||||
bsdiff_path = None
|
||||
gzip_path = None
|
||||
head_path = None
|
||||
tail_path = None
|
||||
bunzip2_path = None
|
||||
java_path = None
|
||||
|
||||
|
||||
def find_bins_or_die():
|
||||
"""Checks that all the binaries needed are available.
|
||||
|
||||
The script needs bsdiff, gzip, head, tail and bunzip2
|
||||
binaries availables in the system.
|
||||
"""
|
||||
|
||||
global bsdiff_path
|
||||
if not bsdiff_path:
|
||||
bsdiff_path = find_binary('bsdiff')
|
||||
global gzip_path
|
||||
if not gzip_path:
|
||||
gzip_path = find_binary('gzip')
|
||||
global head_path
|
||||
if not head_path:
|
||||
head_path = find_binary('head')
|
||||
global tail_path
|
||||
if not tail_path:
|
||||
tail_path = find_binary('tail')
|
||||
global bunzip2_path
|
||||
if not bunzip2_path:
|
||||
bunzip2_path = find_binary('bunzip2')
|
||||
global java_path
|
||||
if not java_path:
|
||||
java_path = find_binary('java')
|
||||
|
||||
|
||||
def find_binary(binary_name):
|
||||
"""Finds the path of a binary."""
|
||||
|
||||
try:
|
||||
return subprocess.check_output(['which', binary_name]).strip()
|
||||
except subprocess.CalledProcessError:
|
||||
raise Exception(
|
||||
'No "' + binary_name + '" on PATH, please install or fix PATH.')
|
||||
|
||||
|
||||
def human_file_size(size):
|
||||
"""Converts a byte size number into a human readable value."""
|
||||
|
||||
size = abs(size)
|
||||
if size == 0:
|
||||
return '0B'
|
||||
units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
|
||||
p = math.floor(math.log(size, 2) / 10)
|
||||
return '%.3g%s' % (size/math.pow(1024, p), units[int(p)])
|
||||
|
||||
|
||||
def calculate_bsdiff(old_file, new_file, save_patch_path, temp_path):
|
||||
"""Estimates the size the Bsdiff patch gzipped.
|
||||
|
||||
Args:
|
||||
old_file: the old APK file
|
||||
new_file: the new APK file
|
||||
save_patch_path: the path including filename to save the generated patch.
|
||||
temp_path: the directory to use for the process
|
||||
|
||||
Returns:
|
||||
a dictionary with:
|
||||
'gzipped_new_file_size': the estimated size of the new gzipped APK
|
||||
'bsdiff_patch_size': the estimated size of the patch from the two APKs
|
||||
|
||||
Raises:
|
||||
Exception: if there is a problem calling the binaries needed in the process
|
||||
"""
|
||||
|
||||
# Oddities:
|
||||
# Bsdiff forces bzip2 compression, which starts after byte 32. Bzip2 isn't
|
||||
# necessarily the best choice in all cases, and isn't necessarily what Google
|
||||
# Play uses, so it has to be uncompressed and rewritten with gzip.
|
||||
|
||||
# Checks that the OS binaries needed are available
|
||||
find_bins_or_die()
|
||||
# Clean temp files
|
||||
if os.path.exists(temp_path): os.remove(temp_path)
|
||||
|
||||
# Create the bsdiff of the two APKs
|
||||
subprocess.check_output(
|
||||
[bsdiff_path, old_file, new_file, temp_path])
|
||||
|
||||
# bsdiff paths
|
||||
raw_bsdiff_path = temp_path + '.raw_bsdiff'
|
||||
bzipped_bsdiff_path = raw_bsdiff_path + '.bz2'
|
||||
gzipped_bsdiff_path = raw_bsdiff_path + '.gz'
|
||||
bsdiff_header_path = temp_path + '.raw_bsdiff_header'
|
||||
if os.path.exists(raw_bsdiff_path): os.remove(raw_bsdiff_path)
|
||||
if os.path.exists(bzipped_bsdiff_path): os.remove(bzipped_bsdiff_path)
|
||||
if os.path.exists(gzipped_bsdiff_path): os.remove(gzipped_bsdiff_path)
|
||||
if os.path.exists(bsdiff_header_path): os.remove(bsdiff_header_path)
|
||||
|
||||
# Strip the first 32 bytes the bsdiff file, which is a bsdiff-specific header.
|
||||
bsdiff_header = open(bsdiff_header_path, 'w')
|
||||
p = subprocess.Popen(
|
||||
[head_path, '-c', '32', bsdiff_header_path],
|
||||
shell=False, stdout=bsdiff_header)
|
||||
ret_code = p.wait()
|
||||
if ret_code != 0:
|
||||
raise Exception('Problem at the bsdiff step, returned code: %s' % ret_code)
|
||||
bsdiff_header.flush()
|
||||
bsdiff_header.close()
|
||||
|
||||
# Take the remainder of the file to gain an uncompressed copy.
|
||||
bzipped_bsdiff_patch = open(bzipped_bsdiff_path, 'w')
|
||||
p = subprocess.Popen(
|
||||
[tail_path, '-c', '+33', temp_path],
|
||||
shell=False, stdout=bzipped_bsdiff_patch)
|
||||
ret_code = p.wait()
|
||||
if ret_code != 0:
|
||||
raise Exception('Problem at the tail step, returned code: %s' % ret_code)
|
||||
bzipped_bsdiff_patch.flush()
|
||||
bzipped_bsdiff_patch.close()
|
||||
subprocess.check_output([bunzip2_path, '-d', '-q', bzipped_bsdiff_path])
|
||||
|
||||
# Prepend the 32 bytes of bsdiff header back onto the uncompressed file.
|
||||
if save_patch_path:
|
||||
rebuilt_bsdiff_path = save_patch_path + '-bsdiff-patch'
|
||||
else:
|
||||
rebuilt_bsdiff_path = raw_bsdiff_path + '.rebuilt'
|
||||
gzipped_rebuilt_bsdiff_path = rebuilt_bsdiff_path + '.gz'
|
||||
if os.path.exists(rebuilt_bsdiff_path): os.remove(rebuilt_bsdiff_path)
|
||||
if os.path.exists(gzipped_rebuilt_bsdiff_path):
|
||||
os.remove(gzipped_rebuilt_bsdiff_path)
|
||||
rebuilt_bsdiff = open(rebuilt_bsdiff_path, 'w')
|
||||
p = subprocess.Popen(
|
||||
['cat', bsdiff_header_path, raw_bsdiff_path],
|
||||
shell=False, stdout=rebuilt_bsdiff)
|
||||
ret_code = p.wait()
|
||||
if ret_code != 0:
|
||||
raise Exception('Problem at the cat step, returned code: %s' % ret_code)
|
||||
rebuilt_bsdiff.flush()
|
||||
rebuilt_bsdiff.close()
|
||||
|
||||
# gzip the patch and get its size.
|
||||
subprocess.check_output([gzip_path, '-9', rebuilt_bsdiff_path])
|
||||
bsdiff_patch_size = os.stat(gzipped_rebuilt_bsdiff_path).st_size
|
||||
|
||||
# Clean up.
|
||||
if os.path.exists(temp_path): os.remove(temp_path)
|
||||
if os.path.exists(raw_bsdiff_path): os.remove(raw_bsdiff_path)
|
||||
if os.path.exists(bsdiff_header_path): os.remove(bsdiff_header_path)
|
||||
if os.path.exists(gzipped_bsdiff_path): os.remove(gzipped_bsdiff_path)
|
||||
if not save_patch_path and os.path.exists(gzipped_rebuilt_bsdiff_path):
|
||||
os.remove(gzipped_rebuilt_bsdiff_path)
|
||||
|
||||
return bsdiff_patch_size
|
||||
|
||||
|
||||
def calculate_new_apk(new_file, temp_path):
|
||||
"""Estimates the size the new APK gzipped.
|
||||
|
||||
Args:
|
||||
new_file: the new APK file
|
||||
temp_path: the directory to use for the process
|
||||
|
||||
Returns:
|
||||
the size of the new APK gzipped
|
||||
|
||||
Raises:
|
||||
Exception: if there is a problem calling the binaries needed in the process
|
||||
"""
|
||||
|
||||
# Checks that the OS binaries needed are available
|
||||
find_bins_or_die()
|
||||
# Clean temp files
|
||||
if os.path.exists(temp_path + '.gz'): os.remove(temp_path + '.gz')
|
||||
|
||||
# gzip new APK and get its size
|
||||
gzipped_new_file = open(temp_path, 'w')
|
||||
p = subprocess.Popen(
|
||||
[gzip_path, '--keep', '-c', '-9', new_file],
|
||||
shell=False, stdout=gzipped_new_file)
|
||||
ret_code = p.wait()
|
||||
if ret_code != 0: raise Exception(
|
||||
'Problem gzipping the new APK, returned code: %s' % ret_code)
|
||||
gzipped_new_file.flush()
|
||||
gzipped_new_file.close()
|
||||
gzipped_size = os.stat(temp_path).st_size
|
||||
# Clean up
|
||||
if os.path.exists(temp_path + '.gz'): os.remove(temp_path + '.gz')
|
||||
return gzipped_size
|
||||
|
||||
|
||||
def calculate_filebyfile(old_file, new_file, save_patch_path, temp_path):
|
||||
"""Estimates the size the File-by-File patch gzipped.
|
||||
|
||||
Args:
|
||||
old_file: the old APK file
|
||||
new_file: the new APK file
|
||||
save_patch_path: the path including filename to save the generated patch.
|
||||
temp_path: the directory to use for the process
|
||||
|
||||
Returns:
|
||||
the size the File-by-File patch gzipped
|
||||
|
||||
Raises:
|
||||
Exception: if there is a problem calling the binaries needed in the process
|
||||
"""
|
||||
|
||||
# Checks that the OS binaries needed are available
|
||||
find_bins_or_die()
|
||||
# Clean temp files
|
||||
if os.path.exists(temp_path): os.remove(temp_path)
|
||||
|
||||
if save_patch_path:
|
||||
filebyfile_patch_path = save_patch_path + '-file-by-file-patch'
|
||||
else:
|
||||
filebyfile_patch_path = temp_path + '.filebyfile'
|
||||
gzipped_filebyfile_patch_path = filebyfile_patch_path + '.gz'
|
||||
if os.path.exists(gzipped_filebyfile_patch_path):
|
||||
os.remove(gzipped_filebyfile_patch_path)
|
||||
|
||||
# file by file patch
|
||||
# We use a jar from https://github.com/andrewhayden/archive-patcher
|
||||
if os.path.exists(filebyfile_patch_path): os.remove(filebyfile_patch_path)
|
||||
p = subprocess.Popen(
|
||||
[java_path, '-jar', _FILEBYFILE_JAR_PATH, '--generate', '--old', old_file,
|
||||
'--new', new_file, '--patch', filebyfile_patch_path],
|
||||
shell=False)
|
||||
ret_code = p.wait()
|
||||
if ret_code != 0: raise Exception(
|
||||
'Problem creating file by file patch, returned code: %s' % ret_code)
|
||||
|
||||
# gzip file by file patch and get its size
|
||||
subprocess.check_output([gzip_path, '-9', filebyfile_patch_path])
|
||||
gzipped_filebyfile_patch_size = os.stat(gzipped_filebyfile_patch_path).st_size
|
||||
# Clean temp files
|
||||
if os.path.exists(temp_path): os.remove(temp_path)
|
||||
if not save_patch_path and os.path.exists(gzipped_filebyfile_patch_path):
|
||||
os.remove(gzipped_filebyfile_patch_path)
|
||||
return gzipped_filebyfile_patch_size
|
||||
|
||||
|
||||
def main():
|
||||
locale.setlocale(locale.LC_ALL, '')
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Estimate the sizes of APK patches for Google Play')
|
||||
parser.add_argument(
|
||||
'--old-file', default=None, required=True,
|
||||
help='the path to the "old" file to generate patches from.')
|
||||
parser.add_argument(
|
||||
'--new-file', default=None, required=True,
|
||||
help='the path to the "new" file to generate patches from.')
|
||||
parser.add_argument(
|
||||
'--save-patch', default=None,
|
||||
help='the path prefix to save the generated patches.')
|
||||
parser.add_argument(
|
||||
'--temp-dir', default='/tmp',
|
||||
help='the temp directory to use for patch generation; defaults to /tmp')
|
||||
if not sys.argv[1:]:
|
||||
parser.print_help()
|
||||
parser.exit()
|
||||
args = parser.parse_args()
|
||||
|
||||
if not os.path.isfile(args.old_file):
|
||||
raise Exception('File does not exist: %s' % args.old_file)
|
||||
if not os.path.isfile(args.new_file):
|
||||
raise Exception('File does not exist: %s' % args.new_file)
|
||||
if args.save_patch and not os.access(
|
||||
os.path.dirname(os.path.abspath(args.save_patch)), os.W_OK):
|
||||
raise Exception('The save patch path is not writable: %s' % args.save_patch)
|
||||
if args.save_patch and os.path.isdir(args.save_patch):
|
||||
raise Exception('Please include the filename in the path: %s'
|
||||
% args.save_patch)
|
||||
save_patch_path = args.save_patch
|
||||
if not os.path.isdir(args.temp_dir):
|
||||
raise Exception('Temp directory does not exist: %s' % args.temp_dir)
|
||||
temp_path = args.temp_dir + '/patch.tmp'
|
||||
|
||||
new_file_size = os.stat(args.new_file).st_size
|
||||
|
||||
bsdiff_size = calculate_bsdiff(
|
||||
args.old_file, args.new_file, save_patch_path, temp_path)
|
||||
|
||||
gzipped_size = calculate_new_apk(args.new_file, temp_path)
|
||||
|
||||
# Calculate the size of the File-by-File patch gzipped
|
||||
gzipped_filebyfile_patch_size = calculate_filebyfile(
|
||||
args.old_file, args.new_file, save_patch_path, temp_path)
|
||||
|
||||
print ('\nNew APK size on disk: %s bytes [%s]'
|
||||
% (locale.format('%d', new_file_size, grouping=True),
|
||||
human_file_size(new_file_size)))
|
||||
|
||||
print '\nEstimated download size for new installs:'
|
||||
print (' Full new APK (gzipped) size:'
|
||||
' %s bytes [%s]'
|
||||
% (locale.format('%d', gzipped_size, grouping=True),
|
||||
human_file_size(gzipped_size)))
|
||||
|
||||
print '\nEstimated download size for updates from the old APK, using Bsdiff:'
|
||||
print (' Bsdiff patch (gzipped) size: %s bytes [%s]'
|
||||
% (locale.format('%d', bsdiff_size, grouping=True),
|
||||
human_file_size(bsdiff_size)))
|
||||
|
||||
print '\nEstimated download size for updates from the old APK,'
|
||||
print ' using File-by-File:'
|
||||
print (' File-by-File patch (gzipped) size: %s bytes [%s]\n'
|
||||
% (locale.format('%d', gzipped_filebyfile_patch_size, grouping=True),
|
||||
human_file_size(gzipped_filebyfile_patch_size)))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
10
third_party/apk-patch-size-estimator/cipd.yaml
vendored
Normal file
10
third_party/apk-patch-size-estimator/cipd.yaml
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
# Copyright 2017 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.
|
||||
|
||||
# To create CIPD package run the following command.
|
||||
# cipd create --pkg-def cipd.yaml -tag version:$(cat version.txt)
|
||||
package: chromium/third_party/apk-patch-size-estimator
|
||||
description: apk-patch-size-estimator Java library
|
||||
data:
|
||||
- file: lib/file-by-file-tools.jar
|
12
third_party/ashmem/BUILD.gn
vendored
Normal file
12
third_party/ashmem/BUILD.gn
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
# Copyright 2014 The Chromium Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
assert(is_android)
|
||||
|
||||
source_set("ashmem") {
|
||||
sources = [
|
||||
"ashmem-dev.c",
|
||||
"ashmem.h",
|
||||
]
|
||||
}
|
202
third_party/ashmem/LICENSE
vendored
Normal file
202
third_party/ashmem/LICENSE
vendored
Normal file
@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
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.
|
1
third_party/ashmem/OWNERS
vendored
Normal file
1
third_party/ashmem/OWNERS
vendored
Normal file
@ -0,0 +1 @@
|
||||
digit@chromium.org
|
10
third_party/ashmem/README.chromium
vendored
Normal file
10
third_party/ashmem/README.chromium
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
Name: Android
|
||||
URL: http://source.android.com
|
||||
Description: Android shared memory implementation. Only applies to OS_ANDROID.
|
||||
Version: 7203eb2a8a29a7b721a48cd291700f38f3da1456
|
||||
Security Critical: yes
|
||||
License: Apache 2.0
|
||||
Patches:
|
||||
0001-Add-ashmem-get-prot-region.path:
|
||||
Add ashmem_get_prot_region() declaration and implementation to return
|
||||
the current protection mask of a given Ashmem region.
|
105
third_party/ashmem/ashmem-dev.c
vendored
Normal file
105
third_party/ashmem/ashmem-dev.c
vendored
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Implementation of the user-space ashmem API for devices, which have our
|
||||
* ashmem-enabled kernel. See ashmem-sim.c for the "fake" tmp-based version,
|
||||
* used by the simulator.
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <linux/ashmem.h>
|
||||
#include "ashmem.h"
|
||||
|
||||
#define ASHMEM_DEVICE "/dev/ashmem"
|
||||
|
||||
/*
|
||||
* ashmem_create_region - creates a new ashmem region and returns the file
|
||||
* descriptor, or <0 on error
|
||||
*
|
||||
* `name' is an optional label to give the region (visible in /proc/pid/maps)
|
||||
* `size' is the size of the region, in page-aligned bytes
|
||||
*/
|
||||
int ashmem_create_region(const char *name, size_t size)
|
||||
{
|
||||
int fd, ret;
|
||||
|
||||
fd = open(ASHMEM_DEVICE, O_RDWR);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
if (name) {
|
||||
char buf[ASHMEM_NAME_LEN];
|
||||
|
||||
strlcpy(buf, name, sizeof(buf));
|
||||
ret = ioctl(fd, ASHMEM_SET_NAME, buf);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = ioctl(fd, ASHMEM_SET_SIZE, size);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
return fd;
|
||||
|
||||
error:
|
||||
close(fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ashmem_set_prot_region(int fd, int prot)
|
||||
{
|
||||
return ioctl(fd, ASHMEM_SET_PROT_MASK, prot);
|
||||
}
|
||||
|
||||
int ashmem_get_prot_region(int fd)
|
||||
{
|
||||
return ioctl(fd, ASHMEM_GET_PROT_MASK);
|
||||
}
|
||||
|
||||
int ashmem_pin_region(int fd, size_t offset, size_t len)
|
||||
{
|
||||
struct ashmem_pin pin = { offset, len };
|
||||
return ioctl(fd, ASHMEM_PIN, &pin);
|
||||
}
|
||||
|
||||
int ashmem_unpin_region(int fd, size_t offset, size_t len)
|
||||
{
|
||||
struct ashmem_pin pin = { offset, len };
|
||||
return ioctl(fd, ASHMEM_UNPIN, &pin);
|
||||
}
|
||||
|
||||
int ashmem_get_size_region(int fd)
|
||||
{
|
||||
return ioctl(fd, ASHMEM_GET_SIZE, NULL);
|
||||
}
|
||||
|
||||
int ashmem_purge_all(void)
|
||||
{
|
||||
const int fd = open(ASHMEM_DEVICE, O_RDWR);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
const int ret = ioctl(fd, ASHMEM_PURGE_ALL_CACHES, 0);
|
||||
close(fd);
|
||||
return ret;
|
||||
}
|
47
third_party/ashmem/ashmem.h
vendored
Normal file
47
third_party/ashmem/ashmem.h
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
/* third_party/ashmem/ashmem.h
|
||||
**
|
||||
** Copyright 2008 The Android Open Source Project
|
||||
**
|
||||
** This file is dual licensed. It may be redistributed and/or modified
|
||||
** under the terms of the Apache 2.0 License OR version 2 of the GNU
|
||||
** General Public License.
|
||||
*/
|
||||
|
||||
#ifndef _THIRD_PARTY_ASHMEM_H
|
||||
#define _THIRD_PARTY_ASHMEM_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int ashmem_create_region(const char *name, size_t size);
|
||||
int ashmem_set_prot_region(int fd, int prot);
|
||||
int ashmem_get_prot_region(int fd);
|
||||
int ashmem_pin_region(int fd, size_t offset, size_t len);
|
||||
int ashmem_unpin_region(int fd, size_t offset, size_t len);
|
||||
int ashmem_get_size_region(int fd);
|
||||
int ashmem_purge_all(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef __ASHMEMIOC /* in case someone included <linux/ashmem.h> too */
|
||||
|
||||
#define ASHMEM_NAME_LEN 256
|
||||
|
||||
#define ASHMEM_NAME_DEF "dev/ashmem"
|
||||
|
||||
/* Return values from ASHMEM_PIN: Was the mapping purged while unpinned? */
|
||||
#define ASHMEM_NOT_PURGED 0
|
||||
#define ASHMEM_WAS_PURGED 1
|
||||
|
||||
/* Return values from ASHMEM_UNPIN: Is the mapping now pinned or unpinned? */
|
||||
#define ASHMEM_IS_UNPINNED 0
|
||||
#define ASHMEM_IS_PINNED 1
|
||||
|
||||
#endif /* ! __ASHMEMIOC */
|
||||
|
||||
#endif /* _THIRD_PARTY_ASHMEM_H */
|
28
third_party/ashmem/patches/0001-Add-ashmem-get-prot-region.patch
vendored
Normal file
28
third_party/ashmem/patches/0001-Add-ashmem-get-prot-region.patch
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
diff --git a/third_party/ashmem/ashmem-dev.c b/third_party/ashmem/ashmem-dev.c
|
||||
index 2303369d8167..52b3f47eeae0 100644
|
||||
--- a/third_party/ashmem/ashmem-dev.c
|
||||
+++ b/third_party/ashmem/ashmem-dev.c
|
||||
@@ -72,6 +72,11 @@ int ashmem_set_prot_region(int fd, int prot)
|
||||
return ioctl(fd, ASHMEM_SET_PROT_MASK, prot);
|
||||
}
|
||||
|
||||
+int ashmem_get_prot_region(int fd)
|
||||
+{
|
||||
+ return ioctl(fd, ASHMEM_GET_PROT_MASK);
|
||||
+}
|
||||
+
|
||||
int ashmem_pin_region(int fd, size_t offset, size_t len)
|
||||
{
|
||||
struct ashmem_pin pin = { offset, len };
|
||||
diff --git a/third_party/ashmem/ashmem.h b/third_party/ashmem/ashmem.h
|
||||
index 7d411cc064ba..d8afccbd2a6e 100644
|
||||
--- a/third_party/ashmem/ashmem.h
|
||||
+++ b/third_party/ashmem/ashmem.h
|
||||
@@ -18,6 +18,7 @@ extern "C" {
|
||||
|
||||
int ashmem_create_region(const char *name, size_t size);
|
||||
int ashmem_set_prot_region(int fd, int prot);
|
||||
+int ashmem_get_prot_region(int fd);
|
||||
int ashmem_pin_region(int fd, size_t offset, size_t len);
|
||||
int ashmem_unpin_region(int fd, size_t offset, size_t len);
|
||||
int ashmem_get_size_region(int fd);
|
46
third_party/auto/BUILD.gn
vendored
Normal file
46
third_party/auto/BUILD.gn
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
# Copyright 2017 The Chromium Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
import("//build/config/android/rules.gni")
|
||||
|
||||
java_library("auto_common_java") {
|
||||
java_files = [
|
||||
"src/common/src/main/java/com/google/auto/common/AnnotationMirrors.java",
|
||||
"src/common/src/main/java/com/google/auto/common/BasicAnnotationProcessor.java",
|
||||
"src/common/src/main/java/com/google/auto/common/MoreTypes.java",
|
||||
"src/common/src/main/java/com/google/auto/common/SuperficialValidation.java",
|
||||
"src/common/src/main/java/com/google/auto/common/AnnotationValues.java",
|
||||
"src/common/src/main/java/com/google/auto/common/MoreElements.java",
|
||||
"src/common/src/main/java/com/google/auto/common/Overrides.java",
|
||||
"src/common/src/main/java/com/google/auto/common/Visibility.java",
|
||||
]
|
||||
|
||||
deps = [
|
||||
"//third_party/guava:guava_java",
|
||||
]
|
||||
}
|
||||
|
||||
java_library("auto_service_java") {
|
||||
java_files =
|
||||
[ "src/service/src/main/java/com/google/auto/service/AutoService.java" ]
|
||||
deps = [
|
||||
":auto_common_java",
|
||||
"//third_party/guava:guava_java",
|
||||
]
|
||||
}
|
||||
|
||||
java_annotation_processor("auto_service_processor") {
|
||||
java_files = [
|
||||
"src/service/src/main/java/com/google/auto/service/processor/AutoServiceProcessor.java",
|
||||
"src/service/src/main/java/com/google/auto/service/processor/package-info.java",
|
||||
"src/service/src/main/java/com/google/auto/service/processor/ServicesFiles.java",
|
||||
]
|
||||
main_class = "com.google.auto.service.processor.AutoServiceProcessor"
|
||||
|
||||
deps = [
|
||||
":auto_common_java",
|
||||
":auto_service_java",
|
||||
"//third_party/guava:guava_java",
|
||||
]
|
||||
}
|
3
third_party/auto/OWNERS
vendored
Normal file
3
third_party/auto/OWNERS
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
agrieve@chromium.org
|
||||
nyquist@chromium.org
|
||||
wnwen@chromium.org
|
15
third_party/auto/README.chromium
vendored
Normal file
15
third_party/auto/README.chromium
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
Name: Auto
|
||||
Short Name: auto
|
||||
URL: https://github.com/google/auto
|
||||
Version: 8a81a858ae7b78a1aef71ac3905fade0bbd64e82
|
||||
Date: January 15, 2018
|
||||
License: Apache 2.0
|
||||
License File: NOT_SHIPPED
|
||||
Security Critical: no
|
||||
|
||||
Description:
|
||||
* A collection of source code generators for Java.
|
||||
* AutoService used for custom plugins in //tools/android/errorprone_plugin.
|
||||
|
||||
Local Modifications:
|
||||
* Add BUILD.gn.
|
202
third_party/bazel/LICENSE
vendored
Normal file
202
third_party/bazel/LICENSE
vendored
Normal file
@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
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.
|
4
third_party/bazel/OWNERS
vendored
Normal file
4
third_party/bazel/OWNERS
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
agrieve@chromium.org
|
||||
jbudorick@chromium.org
|
||||
|
||||
# COMPONENT: Build
|
13
third_party/bazel/README.chromium
vendored
Normal file
13
third_party/bazel/README.chromium
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
Name: (Components of) Bazel
|
||||
Short Name: (Components of) Bazel
|
||||
URL: https://github.com/bazelbuild/bazel
|
||||
License: Apache 2.0
|
||||
License File: NOT_SHIPPED
|
||||
Version: Unknown
|
||||
Security Critical: no
|
||||
|
||||
Description:
|
||||
This directory contains Bazel components used for building Android binaries.
|
||||
Chromium does not use Bazel itself as the build platform. Please refer to each
|
||||
sub-directory for information on each Bazel component.
|
||||
|
7
third_party/bazel/cipd.yaml
vendored
Normal file
7
third_party/bazel/cipd.yaml
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
# Copyright 2017 The Chromium Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
package: chromium/third_party/bazel
|
||||
data:
|
||||
- file: desugar/Desugar.jar
|
12
third_party/bazel/desugar/BUILD.gn
vendored
Normal file
12
third_party/bazel/desugar/BUILD.gn
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
# Copyright 2017 The Chromium Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
import("//build/config/android/rules.gni")
|
||||
|
||||
# Provides runtime support for desugar transformations.
|
||||
java_prebuilt("desugar_runtime_java") {
|
||||
supports_android = true
|
||||
jar_path = "Desugar-runtime.jar"
|
||||
no_build_hooks = true
|
||||
}
|
BIN
third_party/bazel/desugar/Desugar-runtime.jar
vendored
Normal file
BIN
third_party/bazel/desugar/Desugar-runtime.jar
vendored
Normal file
Binary file not shown.
43
third_party/bazel/desugar/README.chromium
vendored
Normal file
43
third_party/bazel/desugar/README.chromium
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
Name: Desugar, transforming Java 8 bytecode to be Java 7 compatible
|
||||
Short Name: desugar
|
||||
URL: It's part of Bazel build system (https://github.com/bazelbuild/bazel).
|
||||
Also, go/desugar for @google.com account owners
|
||||
Version: 0.10.0
|
||||
Date: Feb 1, 2018
|
||||
License: Apache 2.0
|
||||
Security Critical: no
|
||||
|
||||
Description:
|
||||
Desugar is a Google-developed open-source Java library used by the build process
|
||||
to transform Java 8 bytecode to Java 7. It is used to enable Java 8 features
|
||||
such as lambda experssions for Chrome on Android.
|
||||
|
||||
Local Modifications:
|
||||
* Desugar.jar is the "Desugar_deploy.jar" target defined in
|
||||
[bazel]src/tools/android/java/com/google/devtools/build/android/desugar/BUILD
|
||||
* Desugar-runtime.jar is derived from Desugar.jar (refer to update
|
||||
instructions).
|
||||
|
||||
Update instructions (requires @google.com account for uploading):
|
||||
* Check out Bazel from https://github.com/bazelbuild/bazel
|
||||
* Compile or install Bazel by following instructions on
|
||||
https://docs.bazel.build/versions/master/install.html
|
||||
* Build Desugar_deploy.jar by running
|
||||
bazel build //src/tools/android/java/com/google/devtools/build/android/desugar:Desugar_deploy.jar
|
||||
* Move Desugar_deploy.jar to location within Chromium:
|
||||
rm $CHROMIUM_SRC/third_party/bazel/desugar/Desugar.jar
|
||||
mv bazel-bin/src/tools/android/java/com/google/devtools/build/android/desugar/Desugar_deploy.jar $CHROMIUM_SRC/third_party/bazel/desugar/Desugar.jar
|
||||
* Update Desugar-runtime.jar:
|
||||
unzip Desugar.jar "com/google/devtools/build/android/desugar/runtime*"
|
||||
zip -rD0 Desugar-runtime.jar com
|
||||
rm -r com
|
||||
* Perform a sanity check of chrome_public_apk:
|
||||
ninja chrome_public_apk
|
||||
bin/chrome_public_apk run
|
||||
* Update this README.chromium (Version & Date)
|
||||
* Upload new jar to CIPD:
|
||||
cd third_party/bazel
|
||||
VERSION=$(grep Version -m1 desugar/README.chromium | cut -d' ' -f2)
|
||||
cipd create --pkg-def cipd.yaml -tag version:$VERSION
|
||||
* Update revision in //build/cipd/android/android.ensure (soon to be right in
|
||||
//DEPS)
|
340
third_party/binutils/LICENSE
vendored
Normal file
340
third_party/binutils/LICENSE
vendored
Normal file
@ -0,0 +1,340 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
1
third_party/binutils/Linux_ia32/binutils.tar.bz2.sha1
vendored
Normal file
1
third_party/binutils/Linux_ia32/binutils.tar.bz2.sha1
vendored
Normal file
@ -0,0 +1 @@
|
||||
ee534836babdf330503ad62934a1975fc9b6fba9
|
1
third_party/binutils/Linux_x64/binutils.tar.bz2.sha1
vendored
Normal file
1
third_party/binutils/Linux_x64/binutils.tar.bz2.sha1
vendored
Normal file
@ -0,0 +1 @@
|
||||
5230f6066998df2f4d61d5fa586152ab20cca300
|
3
third_party/binutils/OWNERS
vendored
Normal file
3
third_party/binutils/OWNERS
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
thakis@chromium.org
|
||||
thestig@chromium.org
|
||||
thomasanderson@chromium.org
|
39
third_party/binutils/README.chromium
vendored
Normal file
39
third_party/binutils/README.chromium
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
Name: binutils
|
||||
URL: http://www.gnu.org/software/binutils/
|
||||
Version: 2.29.1
|
||||
License: GPL v2
|
||||
License File: NOT_SHIPPED
|
||||
Security Critical: no
|
||||
|
||||
Description:
|
||||
This directory contains i386 and amd64 binaries of the binutils tools
|
||||
(including gold linker).
|
||||
|
||||
They were built from binutils-2.29.1 using the "build-all.sh" script on Debian
|
||||
Testing.
|
||||
|
||||
The script creates chroots for 32bit and 64bit Ubuntu Xenial and then builds
|
||||
binutils inside the roots.
|
||||
|
||||
Local patches:
|
||||
|
||||
* (build-all.sh|build-one.sh|upload.sh) scripts for building the binutils
|
||||
binaries and uploading them to Google storage.
|
||||
|
||||
Upgrading:
|
||||
|
||||
To upgrade binutils, use the following steps:
|
||||
|
||||
* Update build-all.sh with the new binutil version.
|
||||
* Remove any patches which have been merged upstream from build-all.sh
|
||||
* Update this README.chromium file
|
||||
* Run build-all.sh
|
||||
* Run upload.sh. Note: you will need write access to
|
||||
gs://chromium-binutils bucket on Google Cloud Storage. To get the
|
||||
access, subscribe to the internal chrome-team mailing list.
|
||||
* Wait for goma to have new binutils deployed (see http://go/ma).
|
||||
Please notify {ukai,yyanagisawa,shinyak}@chromium.org and await
|
||||
confirmation.
|
||||
* Commit the change
|
||||
|
||||
See https://codereview.chromium.org/1368233002/ for an example upgrade.
|
113
third_party/binutils/build-all.sh
vendored
Executable file
113
third_party/binutils/build-all.sh
vendored
Executable file
@ -0,0 +1,113 @@
|
||||
#!/bin/sh
|
||||
# Copyright 2014 The Chromium Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
# Script to build binutils for both i386 and AMD64 Linux architectures.
|
||||
# Must be run on an AMD64 supporting machine which has debootstrap and sudo
|
||||
# installed.
|
||||
# Uses Ubuntu Xenial chroots as build environment.
|
||||
|
||||
set -e
|
||||
set -u
|
||||
|
||||
if [ x"$(whoami)" = x"root" ]; then
|
||||
echo "Script must not be run as root."
|
||||
exit 1
|
||||
fi
|
||||
sudo -v
|
||||
|
||||
OUTPUTDIR="${1:-$PWD/output-$(date +%Y%m%d-%H%M%S)}"
|
||||
if [ ! -d "$OUTPUTDIR" ]; then
|
||||
mkdir -p "$OUTPUTDIR"
|
||||
fi
|
||||
|
||||
# Download the source
|
||||
VERSION=2.29.1
|
||||
wget -c http://ftp.gnu.org/gnu/binutils/binutils-$VERSION.tar.bz2
|
||||
|
||||
# Verify the signature
|
||||
wget -c -q http://ftp.gnu.org/gnu/binutils/binutils-$VERSION.tar.bz2.sig
|
||||
if ! gpg --verify binutils-$VERSION.tar.bz2.sig; then
|
||||
echo "GPG Signature failed to verify."
|
||||
echo ""
|
||||
echo "You may need to import the vendor GPG key with:"
|
||||
echo "# gpg --keyserver hkp://pgp.mit.edu:80 --recv-key 4AE55E93 DD9E3C4F"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Extract the source
|
||||
rm -rf binutils-$VERSION
|
||||
tar jxf binutils-$VERSION.tar.bz2
|
||||
|
||||
for ARCH in i386 amd64; do
|
||||
CHROOT_DIR="xenial-chroot-$ARCH"
|
||||
if [ ! -d ${CHROOT_DIR} ]; then
|
||||
# Refresh sudo credentials
|
||||
sudo -v
|
||||
|
||||
CHROOT_TEMPDIR=$(mktemp -d ${CHROOT_DIR}.XXXXXX)
|
||||
|
||||
# Create the chroot
|
||||
echo ""
|
||||
echo "Building chroot for $ARCH"
|
||||
echo "============================="
|
||||
sudo debootstrap \
|
||||
--arch=$ARCH \
|
||||
--include=build-essential,flex,bison \
|
||||
xenial ${CHROOT_TEMPDIR}
|
||||
echo "============================="
|
||||
mv ${CHROOT_TEMPDIR} ${CHROOT_DIR}
|
||||
fi
|
||||
|
||||
BUILDDIR=${CHROOT_DIR}/build
|
||||
|
||||
# Clean up any previous failed build attempts inside chroot
|
||||
if [ -d "$BUILDDIR" ]; then
|
||||
sudo rm -rf "$BUILDDIR"
|
||||
fi
|
||||
|
||||
# Copy data into the chroot
|
||||
sudo mkdir -p "$BUILDDIR"
|
||||
sudo cp -a binutils-$VERSION "$BUILDDIR"
|
||||
sudo cp -a build-one.sh "$BUILDDIR"
|
||||
|
||||
# Do the build
|
||||
PREFIX=
|
||||
case $ARCH in
|
||||
i386)
|
||||
PREFIX="setarch linux32"
|
||||
ARCHNAME=i686-pc-linux-gnu
|
||||
;;
|
||||
amd64)
|
||||
PREFIX="setarch linux64"
|
||||
ARCHNAME=x86_64-pc-linux-gnu
|
||||
;;
|
||||
esac
|
||||
echo ""
|
||||
echo "Building binutils for $ARCH"
|
||||
LOGFILE="$OUTPUTDIR/build-$ARCH.log"
|
||||
if ! sudo $PREFIX chroot ${CHROOT_DIR} /build/build-one.sh \
|
||||
/build/binutils-$VERSION > $LOGFILE 2>&1; then
|
||||
echo "Build failed! See $LOGFILE for details."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Copy data out of the chroot
|
||||
sudo chown -R $(whoami) "$BUILDDIR/output/"
|
||||
|
||||
# Strip the output binaries
|
||||
strip "$BUILDDIR/output/$ARCHNAME/bin/"*
|
||||
|
||||
# Copy them out of the chroot
|
||||
cp -a "$BUILDDIR/output/$ARCHNAME" "$OUTPUTDIR"
|
||||
|
||||
# Clean up chroot
|
||||
sudo rm -rf "$BUILDDIR"
|
||||
done
|
||||
|
||||
echo "Check you are happy with the binaries in"
|
||||
echo " $OUTPUTDIR"
|
||||
echo "Then"
|
||||
echo " * upload to Google Storage using the upload.sh script"
|
||||
echo " * roll dependencies"
|
32
third_party/binutils/build-one.sh
vendored
Executable file
32
third_party/binutils/build-one.sh
vendored
Executable file
@ -0,0 +1,32 @@
|
||||
#!/bin/sh
|
||||
# Copyright 2014 The Chromium Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
# Script to build binutils found in /build/binutils-XXXX when inside a chroot.
|
||||
# Don't call this script yourself, instead use the build-all.sh script.
|
||||
|
||||
set -e
|
||||
set -x
|
||||
|
||||
if [ -z "$1" ]; then
|
||||
echo "Directory of binutils not given."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd "$1"
|
||||
./configure \
|
||||
--enable-deterministic-archives \
|
||||
--enable-gold=default \
|
||||
--enable-plugins \
|
||||
--enable-threads \
|
||||
--prefix=/build/output
|
||||
|
||||
|
||||
make -j8 all
|
||||
echo
|
||||
echo "= binutils/config.h ================================================"
|
||||
cat binutils/config.h
|
||||
echo "===================================================================="
|
||||
echo
|
||||
make install
|
130
third_party/binutils/download.py
vendored
Executable file
130
third_party/binutils/download.py
vendored
Executable file
@ -0,0 +1,130 @@
|
||||
#!/usr/bin/env python
|
||||
# Copyright 2014 The Chromium Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
# vim: set ts=2 sw=2 et sts=2 ai:
|
||||
|
||||
"""Minimal tool to download binutils from Google storage.
|
||||
|
||||
TODO(mithro): Replace with generic download_and_extract tool.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import platform
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
|
||||
BINUTILS_DIR = os.path.abspath(os.path.dirname(__file__))
|
||||
BINUTILS_FILE = 'binutils.tar.bz2'
|
||||
BINUTILS_TOOLS = ['bin/ld.gold', 'bin/objcopy', 'bin/objdump']
|
||||
BINUTILS_OUT = 'Release'
|
||||
|
||||
DETECT_HOST_ARCH = os.path.abspath(os.path.join(
|
||||
BINUTILS_DIR, '../../build/detect_host_arch.py'))
|
||||
|
||||
|
||||
def ReadFile(filename):
|
||||
with file(filename, 'r') as f:
|
||||
return f.read().strip()
|
||||
|
||||
|
||||
def WriteFile(filename, content):
|
||||
assert not os.path.exists(filename)
|
||||
with file(filename, 'w') as f:
|
||||
f.write(content)
|
||||
f.write('\n')
|
||||
|
||||
|
||||
def GetArch():
|
||||
gyp_host_arch = re.search(
|
||||
'host_arch=(\S*)', os.environ.get('GYP_DEFINES', ''))
|
||||
if gyp_host_arch:
|
||||
arch = gyp_host_arch.group(1)
|
||||
# This matches detect_host_arch.py.
|
||||
if arch == 'x86_64':
|
||||
return 'x64'
|
||||
return arch
|
||||
|
||||
return subprocess.check_output(['python', DETECT_HOST_ARCH]).strip()
|
||||
|
||||
|
||||
def FetchAndExtract(arch):
|
||||
archdir = os.path.join(BINUTILS_DIR, 'Linux_' + arch)
|
||||
tarball = os.path.join(archdir, BINUTILS_FILE)
|
||||
outdir = os.path.join(archdir, BINUTILS_OUT)
|
||||
|
||||
sha1file = tarball + '.sha1'
|
||||
if not os.path.exists(sha1file):
|
||||
print "WARNING: No binutils found for your architecture (%s)!" % arch
|
||||
return 0
|
||||
|
||||
checksum = ReadFile(sha1file)
|
||||
|
||||
stampfile = tarball + '.stamp'
|
||||
if os.path.exists(stampfile):
|
||||
if (os.path.exists(tarball) and
|
||||
os.path.exists(outdir) and
|
||||
checksum == ReadFile(stampfile)):
|
||||
return 0
|
||||
else:
|
||||
os.unlink(stampfile)
|
||||
|
||||
print "Downloading", tarball
|
||||
subprocess.check_call([
|
||||
'download_from_google_storage',
|
||||
'--no_resume',
|
||||
'--no_auth',
|
||||
'--bucket', 'chromium-binutils',
|
||||
'-s', sha1file])
|
||||
assert os.path.exists(tarball)
|
||||
|
||||
if os.path.exists(outdir):
|
||||
shutil.rmtree(outdir)
|
||||
assert not os.path.exists(outdir)
|
||||
os.makedirs(outdir)
|
||||
assert os.path.exists(outdir)
|
||||
|
||||
print "Extracting", tarball
|
||||
subprocess.check_call(['tar', 'axf', tarball], cwd=outdir)
|
||||
|
||||
for tool in BINUTILS_TOOLS:
|
||||
assert os.path.exists(os.path.join(outdir, tool))
|
||||
|
||||
WriteFile(stampfile, checksum)
|
||||
return 0
|
||||
|
||||
|
||||
def main(args):
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--ignore-if-arch', metavar='ARCH',
|
||||
action='append', default=[],
|
||||
help='Do nothing on host architecture ARCH')
|
||||
|
||||
options = parser.parse_args(args)
|
||||
|
||||
if not sys.platform.startswith('linux'):
|
||||
return 0
|
||||
|
||||
arch = GetArch()
|
||||
if arch in options.ignore_if_arch:
|
||||
return 0
|
||||
|
||||
if arch == 'x64':
|
||||
return FetchAndExtract(arch)
|
||||
if arch == 'ia32':
|
||||
ret = FetchAndExtract(arch)
|
||||
if ret != 0:
|
||||
return ret
|
||||
# Fetch the x64 toolchain as well for official bots with 64-bit kernels.
|
||||
return FetchAndExtract('x64')
|
||||
|
||||
print "Host architecture %s is not supported." % arch
|
||||
return 1
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main(sys.argv[1:]))
|
68
third_party/binutils/upload.sh
vendored
Executable file
68
third_party/binutils/upload.sh
vendored
Executable file
@ -0,0 +1,68 @@
|
||||
#!/bin/sh
|
||||
# Copyright 2014 The Chromium Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
# Upload the generated output to Google storage.
|
||||
|
||||
set -e
|
||||
|
||||
if [ ! -d "$1" ]; then
|
||||
echo "update.sh <output directory from build-all.sh>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if echo "$PWD" | grep -qE "/src/third_party/binutils$"; then
|
||||
echo -n
|
||||
else
|
||||
echo "update.sh should be run in src/third_party/binutils"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f ~/.boto ]; then
|
||||
echo "You need to run 'gsutil config' to set up authentication before running this script."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for DIR in $1/*; do
|
||||
# Skip if not directory
|
||||
if [ ! -d "$DIR" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
case "$DIR" in
|
||||
*/i686-pc-linux-gnu)
|
||||
export ARCH="Linux_ia32"
|
||||
;;
|
||||
|
||||
*/x86_64-pc-linux-gnu)
|
||||
export ARCH="Linux_x64"
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Unknown architecture directory $DIR"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ ! -d "$ARCH" ]; then
|
||||
mkdir -p "$ARCH"
|
||||
fi
|
||||
|
||||
BINUTILS_TAR_BZ2="$ARCH/binutils.tar.bz2"
|
||||
FULL_BINUTILS_TAR_BZ2="$PWD/$BINUTILS_TAR_BZ2"
|
||||
if [ -f "${BINUTILS_TAR_BZ2}.sha1" ]; then
|
||||
rm "${BINUTILS_TAR_BZ2}.sha1"
|
||||
fi
|
||||
(cd "$DIR"; tar jcf "$FULL_BINUTILS_TAR_BZ2" .)
|
||||
|
||||
upload_to_google_storage.py --bucket chromium-binutils "$BINUTILS_TAR_BZ2"
|
||||
git add -f "${BINUTILS_TAR_BZ2}.sha1"
|
||||
done
|
||||
|
||||
echo "Please commit the new .sha1 to the Chromium repository"
|
||||
echo "# git commit"
|
||||
echo ""
|
||||
echo "Make sure goma is updated with the new binutils *before* landing."
|
||||
echo " Notify {ukai,yyanagisawa,shinyak}@chromium.org with the .sha1 files"
|
||||
echo " and await confirmation."
|
1
third_party/boringssl/.clang-format
vendored
Normal file
1
third_party/boringssl/.clang-format
vendored
Normal file
@ -0,0 +1 @@
|
||||
DisableFormat: true
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user