Commit 764226bd authored by Siddhartha's avatar Siddhartha Committed by Commit Bot

Add a script to extract and add unwind table to apk

The unwind tables are stripped from release builds. This CL adds a
script to extract the unwind table sections from unstripped binary and
adds it as an asset file in the apk.
This script is first used in the test apk, when add_unwind_tables_in_apk
is specified. Will be used later added to chrome apk.

BUG=819888

Change-Id: I68d2ea843ed0c7a7a3ee60c48f683e01809ff217
Reviewed-on: https://chromium-review.googlesource.com/954421Reviewed-by: default avatarDirk Pranke <dpranke@chromium.org>
Reviewed-by: default avataragrieve <agrieve@chromium.org>
Commit-Queue: Siddhartha S <ssid@chromium.org>
Cr-Commit-Position: refs/heads/master@{#542699}
parent 5d5fef12
#!/usr/bin/env python
# Copyright 2018 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.
"""Extracts the unwind tables in ARM EHABI format.
The ARM EHABI format requires 2 sections for unwinding, ARM.exidx and ARM.extab.
This script copies these sections from unstripped binary into an output file.
Usage:
extract_unwind_tables.py --input_path [root path to unstripped chrome.so]
--output_path [output path]
"""
import argparse
import struct
import subprocess
import sys
def _GetArmSectionsFromObjdump(input_path):
"""Parses the objdump of the binary and returns the relevant sections."""
objdump = subprocess.check_output(['objdump', '-h', input_path]).splitlines()
sections = {}
for line in objdump:
if '.ARM' not in line:
continue
parts = line.split()
section = {}
section['size'] = int(parts[2], 16)
section['offset'] = int(parts[5], 16)
sections[parts[1]] = section
return sections
def _Write4Bytes(output_file, val):
"""Writes a 32 bit unsigned integer to the given output file."""
output_file.write(struct.pack('<L', val));
def _AddSectionToOutput(input_path, output_file, section):
"""Copies the specified section from input file to output."""
_Write4Bytes(output_file, section['size'])
_Write4Bytes(output_file, section['offset'])
with open(input_path, 'rb') as f:
f.seek(section['offset'])
data = f.read(section['size'])
output_file.write(data)
def main():
parser = argparse.ArgumentParser()
parser.add_argument(
'--input_path', required=True,
help='The input path of the unstripped binary')
parser.add_argument(
'--output_path', required=True,
help='The path of the output file')
args = parser.parse_args()
sections = _GetArmSectionsFromObjdump(args.input_path)
exidx = sections.get('.ARM.exidx')
extab = sections.get('.ARM.extab')
if not exidx or not extab:
raise Exception('No arm32 exception section found.')
with open(args.output_path, 'wb') as outputFile:
_AddSectionToOutput(args.input_path, outputFile, exidx)
_AddSectionToOutput(args.input_path, outputFile, extab)
return 0
if __name__ == '__main__':
sys.exit(main())
# Copyright 2018 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")
template("unwind_table_asset") {
_unwind_action = "${target_name}__extract"
_asset_path = "${target_gen_dir}/${target_name}/unwind_cfi"
action(_unwind_action) {
if (defined(invoker.testonly)) {
testonly = invoker.testonly
}
script = "//build/android/gyp/extract_unwind_tables.py"
outputs = [
_asset_path,
]
args = [
"--input_path",
rebase_path(
"$root_out_dir/lib.unstripped/$shlib_prefix${invoker.library_target}$shlib_extension",
root_build_dir),
"--output_path",
rebase_path(_asset_path, root_build_dir),
]
deps = [
":${invoker.library_target}",
]
}
android_assets(target_name) {
testonly = invoker.testonly
sources = [
_asset_path,
]
disable_compression = true
deps = [
":$_unwind_action",
]
}
}
...@@ -2830,7 +2830,6 @@ if (enable_java_templates) { ...@@ -2830,7 +2830,6 @@ if (enable_java_templates) {
android_apk(target_name) { android_apk(target_name) {
data_deps = [] data_deps = []
deps = []
forward_variables_from(invoker, "*") forward_variables_from(invoker, "*")
testonly = true testonly = true
create_apk_script = false create_apk_script = false
......
...@@ -10,6 +10,7 @@ if (is_android) { ...@@ -10,6 +10,7 @@ if (is_android) {
import("//build/config/android/config.gni") import("//build/config/android/config.gni")
import("//build/config/android/rules.gni") import("//build/config/android/rules.gni")
import("//build/config/sanitizers/sanitizers.gni") import("//build/config/sanitizers/sanitizers.gni")
import("//build/config/android/extract_unwind_tables.gni")
} }
if (is_fuchsia) { if (is_fuchsia) {
...@@ -100,6 +101,18 @@ template("test") { ...@@ -100,6 +101,18 @@ template("test") {
"write_asset_list", "write_asset_list",
"use_native_activity", "use_native_activity",
] ]
# Adds the unwind tables from unstripped binary as an asset file in the
# apk, if |add_unwind_tables_in_apk| is specified by the test.
if (defined(invoker.add_unwind_tables_in_apk) &&
invoker.add_unwind_tables_in_apk) {
_unwind_table_asset_name = "${target_name}_unwind_assets"
unwind_table_asset(_unwind_table_asset_name) {
testonly = true
library_target = _library_target
}
}
shared_library(_library_target) { shared_library(_library_target) {
# Configs will always be defined since we set_defaults in BUILDCONFIG.gn. # Configs will always be defined since we set_defaults in BUILDCONFIG.gn.
configs = [] # Prevent list overwriting warning. configs = [] # Prevent list overwriting warning.
...@@ -129,6 +142,10 @@ template("test") { ...@@ -129,6 +142,10 @@ template("test") {
# Add the Java classes so that each target does not have to do it. # Add the Java classes so that each target does not have to do it.
deps += [ "//base/test:test_support_java" ] deps += [ "//base/test:test_support_java" ]
if (defined(_unwind_table_asset_name)) {
deps += [ ":${_unwind_table_asset_name}" ]
}
# TODO(agrieve): Remove this data_dep once bots don't build the _apk # TODO(agrieve): Remove this data_dep once bots don't build the _apk
# target (post-GYP). # target (post-GYP).
# It's a bit backwards for the apk to depend on the runner script, since # It's a bit backwards for the apk to depend on the runner script, since
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment