mac: Introduce libaperitif.dylib
Chrome currently has several .app executables packaged within its bundle and the the Framework. Each one of these executables statically links libc++, and in the helpers, a //sandbox target. Apéritif moves the C++ components of early app initialization into a shared library, reducing the size of each of the executables. The executable main file transitions back to being a plain C file rather than C++ to avoid linking in libc++. In order to support linking the library to multiple images at different bundle depths, the linker_driver.py gains the ability to run install_name_tool as part of the link step. Disk size changes for an x86_64, official, branded, stripped build: 17168 out/official/aperitif/Google Chrome.app/Contents/MacOS/Google Chrome 214512 out/official/pristine/Google Chrome.app/Contents/MacOS/Google Chrome 17240 out/official/aperitif/Google Chrome.app/Contents/Frameworks/Google Chrome Framework.framework/Helpers/Google Chrome Helper (Alerts).app/Contents/MacOS/Google Chrome Helper (Alerts) 17240 out/official/aperitif/Google Chrome.app/Contents/Frameworks/Google Chrome Framework.framework/Helpers/Google Chrome Helper (GPU).app/Contents/MacOS/Google Chrome Helper (GPU) 17240 out/official/aperitif/Google Chrome.app/Contents/Frameworks/Google Chrome Framework.framework/Helpers/Google Chrome Helper (Plugin).app/Contents/MacOS/Google Chrome Helper (Plugin) 17240 out/official/aperitif/Google Chrome.app/Contents/Frameworks/Google Chrome Framework.framework/Helpers/Google Chrome Helper (Renderer).app/Contents/MacOS/Google Chrome Helper (Renderer) 17240 out/official/aperitif/Google Chrome.app/Contents/Frameworks/Google Chrome Framework.framework/Helpers/Google Chrome Helper.app/Contents/MacOS/Google Chrome Helper 264736 out/official/pristine/Google Chrome.app/Contents/Frameworks/Google Chrome Framework.framework/Helpers/Google Chrome Helper (Alerts).app/Contents/MacOS/Google Chrome Helper (Alerts) 264736 out/official/pristine/Google Chrome.app/Contents/Frameworks/Google Chrome Framework.framework/Helpers/Google Chrome Helper (GPU).app/Contents/MacOS/Google Chrome Helper (GPU) 264736 out/official/pristine/Google Chrome.app/Contents/Frameworks/Google Chrome Framework.framework/Helpers/Google Chrome Helper (Plugin).app/Contents/MacOS/Google Chrome Helper (Plugin) 264736 out/official/pristine/Google Chrome.app/Contents/Frameworks/Google Chrome Framework.framework/Helpers/Google Chrome Helper (Renderer).app/Contents/MacOS/Google Chrome Helper (Renderer) 264736 out/official/pristine/Google Chrome.app/Contents/Frameworks/Google Chrome Framework.framework/Helpers/Google Chrome Helper.app/Contents/MacOS/Google Chrome Helper 338400 out/official/aperitif/Google Chrome.app/Contents/Frameworks/Google Chrome Framework.framework/Libraries/libaperitif.dylib 0 (NA) out/official/pristine/Google Chrome.app/Contents/Frameworks/Google Chrome Framework.framework/Libraries/libaperitif.dylib 179263608 out/official/aperitif/Google Chrome.app/Contents/Frameworks/Google Chrome Framework.framework/Versions/Current/Google Chrome Framework 179263608 out/official/pristine/Google Chrome.app/Contents/Frameworks/Google Chrome Framework.framework/Versions/Current/Google Chrome Framework As reported by `du -k`: 261464 out/official/aperitif/Google Chrome.app 262524 out/official/pristine/Google Chrome.app As reported by Finder Get Info: 267,309,919 bytes (267.7 MB on disk) out/official/aperitif 268,406,343 bytes (268.8 MB on disk) out/official/pristine Bug: 1255223 Change-Id: I4e3c0fa542f2f7f1eae5df9b2c71d6840bc4a30e Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3430220 Reviewed-by: Avi Drissman <avi@chromium.org> Reviewed-by: Mark Mentovai <mark@chromium.org> Reviewed-by: Andrew Grieve <agrieve@chromium.org> Commit-Queue: Robert Sesek <rsesek@chromium.org> Cr-Commit-Position: refs/heads/main@{#978773}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
90f5399806
commit
31576eb814
PRESUBMIT.py
build/toolchain/apple
chrome
content
app
public
shell
sandbox/mac
@@ -2343,6 +2343,7 @@ def CheckSpamLogging(input_api, output_api):
|
|||||||
r"notification_event_dispatcher_impl\.cc$",
|
r"notification_event_dispatcher_impl\.cc$",
|
||||||
r"^content[\\/]common[\\/]gpu[\\/]client[\\/]"
|
r"^content[\\/]common[\\/]gpu[\\/]client[\\/]"
|
||||||
r"gl_helper_benchmark\.cc$",
|
r"gl_helper_benchmark\.cc$",
|
||||||
|
r"^content[\\/]app[\\/]aperitif_mac\.cc$",
|
||||||
r"^courgette[\\/]courgette_minimal_tool\.cc$",
|
r"^courgette[\\/]courgette_minimal_tool\.cc$",
|
||||||
r"^courgette[\\/]courgette_tool\.cc$",
|
r"^courgette[\\/]courgette_tool\.cc$",
|
||||||
r"^extensions[\\/]renderer[\\/]logging_native_handler\.cc$",
|
r"^extensions[\\/]renderer[\\/]logging_native_handler\.cc$",
|
||||||
|
@@ -28,6 +28,15 @@ LINKER_DRIVER_ARG_PREFIX = '-Wcrl,'
|
|||||||
# removal of the special driver arguments, described below). Then the driver
|
# removal of the special driver arguments, described below). Then the driver
|
||||||
# performs additional actions, based on these arguments:
|
# performs additional actions, based on these arguments:
|
||||||
#
|
#
|
||||||
|
# -Wcrl,installnametoolpath,<install_name_tool_path>
|
||||||
|
# Sets the path to the `install_name_tool` to run with
|
||||||
|
# -Wcrl,installnametool, in which case `xcrun` is not used to invoke it.
|
||||||
|
#
|
||||||
|
# -Wcrl,installnametool,<arguments,...>
|
||||||
|
# After invoking the linker, this will run install_name_tool on the linker's
|
||||||
|
# output. |arguments| are comma-separated arguments to be passed to the
|
||||||
|
# install_name_tool command.
|
||||||
|
#
|
||||||
# -Wcrl,dsym,<dsym_path_prefix>
|
# -Wcrl,dsym,<dsym_path_prefix>
|
||||||
# After invoking the linker, this will run `dsymutil` on the linker's
|
# After invoking the linker, this will run `dsymutil` on the linker's
|
||||||
# output, producing a dSYM bundle, stored at dsym_path_prefix. As an
|
# output, producing a dSYM bundle, stored at dsym_path_prefix. As an
|
||||||
@@ -69,6 +78,8 @@ class LinkerDriver(object):
|
|||||||
# The first item in the tuple is the argument's -Wcrl,<sub_argument>
|
# The first item in the tuple is the argument's -Wcrl,<sub_argument>
|
||||||
# and the second is the function to invoke.
|
# and the second is the function to invoke.
|
||||||
self._actions = [
|
self._actions = [
|
||||||
|
('installnametoolpath,', self.set_install_name_tool_path),
|
||||||
|
('installnametool,', self.run_install_name_tool),
|
||||||
('dsymutilpath,', self.set_dsymutil_path),
|
('dsymutilpath,', self.set_dsymutil_path),
|
||||||
('dsym,', self.run_dsymutil),
|
('dsym,', self.run_dsymutil),
|
||||||
('unstripped,', self.run_save_unstripped),
|
('unstripped,', self.run_save_unstripped),
|
||||||
@@ -77,6 +88,7 @@ class LinkerDriver(object):
|
|||||||
]
|
]
|
||||||
|
|
||||||
# Linker driver actions can modify the these values.
|
# Linker driver actions can modify the these values.
|
||||||
|
self._install_name_tool_cmd = ['xcrun', 'install_name_tool']
|
||||||
self._dsymutil_cmd = ['xcrun', 'dsymutil']
|
self._dsymutil_cmd = ['xcrun', 'dsymutil']
|
||||||
self._strip_cmd = ['xcrun', 'strip']
|
self._strip_cmd = ['xcrun', 'strip']
|
||||||
|
|
||||||
@@ -164,6 +176,40 @@ class LinkerDriver(object):
|
|||||||
|
|
||||||
raise ValueError('Unknown linker driver argument: %s' % (arg, ))
|
raise ValueError('Unknown linker driver argument: %s' % (arg, ))
|
||||||
|
|
||||||
|
def set_install_name_tool_path(self, install_name_tool_path):
|
||||||
|
"""Linker driver action for -Wcrl,installnametoolpath,<path>.
|
||||||
|
|
||||||
|
Sets the invocation command for install_name_tool, which allows the
|
||||||
|
caller to specify an alternate path. This action is always
|
||||||
|
processed before the run_install_name_tool action.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
install_name_tool_path: string, The path to the install_name_tool
|
||||||
|
binary to run
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
No output - this step is run purely for its side-effect.
|
||||||
|
"""
|
||||||
|
self._install_name_tool_cmd = [install_name_tool_path]
|
||||||
|
return []
|
||||||
|
|
||||||
|
def run_install_name_tool(self, args_string):
|
||||||
|
"""Linker driver action for -Wcrl,installnametool,<args>. Invokes
|
||||||
|
install_name_tool on the linker's output.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
args_string: string, Comma-separated arguments for
|
||||||
|
`install_name_tool`.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
No output - this step is run purely for its side-effect.
|
||||||
|
"""
|
||||||
|
command = list(self._install_name_tool_cmd)
|
||||||
|
command.extend(args_string.split(','))
|
||||||
|
command.append(self._get_linker_output())
|
||||||
|
subprocess.check_call(command)
|
||||||
|
return []
|
||||||
|
|
||||||
def run_dsymutil(self, dsym_path_prefix):
|
def run_dsymutil(self, dsym_path_prefix):
|
||||||
"""Linker driver action for -Wcrl,dsym,<dsym-path-prefix>. Invokes
|
"""Linker driver action for -Wcrl,dsym,<dsym-path-prefix>. Invokes
|
||||||
dsymutil on the linker's output and produces a dsym file at |dsym_file|
|
dsymutil on the linker's output and produces a dsym file at |dsym_file|
|
||||||
|
@@ -170,7 +170,8 @@ template("apple_toolchain") {
|
|||||||
|
|
||||||
# Specify an explicit path for the strip binary.
|
# Specify an explicit path for the strip binary.
|
||||||
_strippath = invoker.bin_path + "strip"
|
_strippath = invoker.bin_path + "strip"
|
||||||
linker_driver += " -Wcrl,strippath," + _strippath
|
_installnametoolpath = invoker.bin_path + "install_name_tool"
|
||||||
|
linker_driver += " -Wcrl,strippath,${_strippath} -Wcrl,installnametoolpath,${_installnametoolpath}"
|
||||||
|
|
||||||
# On iOS, the final applications are assembled using lipo (to support fat
|
# On iOS, the final applications are assembled using lipo (to support fat
|
||||||
# builds). The correct flags are passed to the linker_driver.py script
|
# builds). The correct flags are passed to the linker_driver.py script
|
||||||
|
@@ -467,18 +467,27 @@ if (is_win) {
|
|||||||
"CHROMIUM_CREATOR=$chrome_mac_creator_code",
|
"CHROMIUM_CREATOR=$chrome_mac_creator_code",
|
||||||
]
|
]
|
||||||
|
|
||||||
sources = [ "app/chrome_exe_main_mac.cc" ]
|
sources = [ "app/chrome_exe_main_mac.c" ]
|
||||||
|
|
||||||
extra_configs = [ "//build/config/compiler:wexit_time_destructors" ]
|
extra_configs = [ "//build/config/compiler:wexit_time_destructors" ]
|
||||||
|
|
||||||
|
# No libc++ needed, there’s only C code in this module.
|
||||||
|
no_default_deps = true
|
||||||
|
|
||||||
deps = [
|
deps = [
|
||||||
":chrome_app_strings_bundle_data",
|
":chrome_app_strings_bundle_data",
|
||||||
":chrome_resources",
|
":chrome_resources",
|
||||||
":chrome_versioned_bundle_data",
|
":chrome_versioned_bundle_data",
|
||||||
"//base/allocator:early_zone_registration_mac",
|
|
||||||
"//build:branding_buildflags",
|
"//build:branding_buildflags",
|
||||||
"//chrome/common:buildflags",
|
"//chrome/common:buildflags",
|
||||||
"//chrome/common:version_header",
|
"//chrome/common:version_header",
|
||||||
|
"//content/public/app:aperitif",
|
||||||
|
]
|
||||||
|
|
||||||
|
ldflags = [
|
||||||
|
# Needed for lld: https://github.com/llvm/llvm-project/issues/53550.
|
||||||
|
"-Wl,-headerpad_max_install_names",
|
||||||
|
"-Wcrl,installnametool,-change,libaperitif.dylib,@executable_path/../Frameworks/$chrome_framework_name.framework/Versions/$chrome_version_full/Libraries/libaperitif.dylib",
|
||||||
]
|
]
|
||||||
|
|
||||||
if (enable_stripping) {
|
if (enable_stripping) {
|
||||||
@@ -486,8 +495,8 @@ if (is_win) {
|
|||||||
# file. All other global symbols will be marked as private. The default
|
# file. All other global symbols will be marked as private. The default
|
||||||
# //build/config/mac:strip_all config will then remove the remaining
|
# //build/config/mac:strip_all config will then remove the remaining
|
||||||
# local and debug symbols.
|
# local and debug symbols.
|
||||||
ldflags = [ "-Wl,-exported_symbols_list," +
|
ldflags += [ "-Wl,-exported_symbols_list," +
|
||||||
rebase_path("app/app.exports", root_build_dir) ]
|
rebase_path("app/app.exports", root_build_dir) ]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_component_build) {
|
if (is_component_build) {
|
||||||
@@ -495,7 +504,7 @@ if (is_win) {
|
|||||||
# executable because dlopen() and loading all the dependent dylibs
|
# executable because dlopen() and loading all the dependent dylibs
|
||||||
# is time-consuming, see https://crbug.com/1197495.
|
# is time-consuming, see https://crbug.com/1197495.
|
||||||
deps += [ ":chrome_framework+link" ]
|
deps += [ ":chrome_framework+link" ]
|
||||||
ldflags = [ "-Wl,-rpath,@executable_path/../Frameworks" ]
|
ldflags += [ "-Wl,-rpath,@executable_path/../Frameworks" ]
|
||||||
|
|
||||||
# The Framework is packaged inside the .app bundle. But when using the
|
# The Framework is packaged inside the .app bundle. But when using the
|
||||||
# component build, all the dependent shared libraries of :chrome_dll are
|
# component build, all the dependent shared libraries of :chrome_dll are
|
||||||
@@ -511,6 +520,39 @@ if (is_win) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (verify_dynamic_libraries) {
|
||||||
|
action("verify_libraries_aperitif") {
|
||||||
|
script = "//chrome/tools/build/mac/verify_dynamic_libraries.py"
|
||||||
|
inputs = [ "$root_out_dir/libaperitif.dylib" ]
|
||||||
|
outputs = [ "$target_out_dir/run_$target_name.stamp" ]
|
||||||
|
args = [
|
||||||
|
"--stamp",
|
||||||
|
rebase_path(outputs[0], root_out_dir),
|
||||||
|
"-B",
|
||||||
|
objdump_path,
|
||||||
|
"--image",
|
||||||
|
rebase_path(inputs[0], root_out_dir),
|
||||||
|
|
||||||
|
# Do not --allow more libraries here without consulting with the
|
||||||
|
# security team (security-dev@chromium.org).
|
||||||
|
"--allow",
|
||||||
|
"/usr/lib/libsandbox.1.dylib",
|
||||||
|
"--allow",
|
||||||
|
"/usr/lib/libSystem.B.dylib",
|
||||||
|
]
|
||||||
|
deps = [ "//content/public/app:aperitif" ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bundle_data("aperitif_library") {
|
||||||
|
sources = [ "$root_out_dir/libaperitif.dylib" ]
|
||||||
|
outputs = [ "{{bundle_contents_dir}}/Libraries/{{source_file_part}}" ]
|
||||||
|
public_deps = [ "//content/public/app:aperitif" ]
|
||||||
|
if (verify_dynamic_libraries) {
|
||||||
|
public_deps += [ ":verify_libraries_aperitif" ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (verify_dynamic_libraries) {
|
if (verify_dynamic_libraries) {
|
||||||
action("verify_libraries_chrome_app") {
|
action("verify_libraries_chrome_app") {
|
||||||
script = "//chrome/tools/build/mac/verify_dynamic_libraries.py"
|
script = "//chrome/tools/build/mac/verify_dynamic_libraries.py"
|
||||||
@@ -525,6 +567,8 @@ if (is_win) {
|
|||||||
rebase_path(inputs[0], root_out_dir),
|
rebase_path(inputs[0], root_out_dir),
|
||||||
"--allow",
|
"--allow",
|
||||||
"/usr/lib/libSystem.B.dylib",
|
"/usr/lib/libSystem.B.dylib",
|
||||||
|
"--allow",
|
||||||
|
"@executable_path/../Frameworks/$chrome_framework_name.framework/Versions/$chrome_version_full/Libraries/libaperitif.dylib",
|
||||||
]
|
]
|
||||||
deps = [ ":chrome_app" ]
|
deps = [ ":chrome_app" ]
|
||||||
}
|
}
|
||||||
@@ -709,24 +753,30 @@ if (is_win) {
|
|||||||
"CHROMIUM_HELPER_BUNDLE_ID_SUFFIX=${invoker.helper_bundle_id_suffix}",
|
"CHROMIUM_HELPER_BUNDLE_ID_SUFFIX=${invoker.helper_bundle_id_suffix}",
|
||||||
]
|
]
|
||||||
|
|
||||||
sources = [ "app/chrome_exe_main_mac.cc" ]
|
sources = [ "app/chrome_exe_main_mac.c" ]
|
||||||
|
|
||||||
extra_configs = [ "//build/config/compiler:wexit_time_destructors" ]
|
extra_configs = [ "//build/config/compiler:wexit_time_destructors" ]
|
||||||
|
|
||||||
defines = [ "HELPER_EXECUTABLE" ]
|
defines = [ "HELPER_EXECUTABLE" ]
|
||||||
|
|
||||||
|
# No libc++ needed, there’s only C code in this module.
|
||||||
|
no_default_deps = true
|
||||||
|
|
||||||
deps = [
|
deps = [
|
||||||
"//base/allocator:early_zone_registration_mac",
|
|
||||||
"//build:branding_buildflags",
|
"//build:branding_buildflags",
|
||||||
"//chrome/common:version_header",
|
"//chrome/common:version_header",
|
||||||
"//sandbox/mac:seatbelt",
|
"//content/public/app:aperitif",
|
||||||
]
|
]
|
||||||
|
|
||||||
if (defined(invoker.deps)) {
|
if (defined(invoker.deps)) {
|
||||||
deps += invoker.deps
|
deps += invoker.deps
|
||||||
}
|
}
|
||||||
|
|
||||||
ldflags = []
|
ldflags = [
|
||||||
|
# Needed for lld: https://github.com/llvm/llvm-project/issues/53550.
|
||||||
|
"-Wl,-headerpad_max_install_names",
|
||||||
|
"-Wcrl,installnametool,-change,libaperitif.dylib,@executable_path/../../../../Libraries/libaperitif.dylib",
|
||||||
|
]
|
||||||
|
|
||||||
if (is_component_build) {
|
if (is_component_build) {
|
||||||
# In a component build, the framework is directly linked to the
|
# In a component build, the framework is directly linked to the
|
||||||
@@ -841,9 +891,9 @@ if (is_win) {
|
|||||||
# Do not --allow more libraries here without consulting with the
|
# Do not --allow more libraries here without consulting with the
|
||||||
# security team (security-dev@chromium.org).
|
# security team (security-dev@chromium.org).
|
||||||
"--allow",
|
"--allow",
|
||||||
"/usr/lib/libsandbox.1.dylib",
|
|
||||||
"--allow",
|
|
||||||
"/usr/lib/libSystem.B.dylib",
|
"/usr/lib/libSystem.B.dylib",
|
||||||
|
"--allow",
|
||||||
|
"@executable_path/../../../../Libraries/libaperitif.dylib",
|
||||||
]
|
]
|
||||||
deps = [ ":chrome_helper_app_${_helper_target}" ]
|
deps = [ ":chrome_helper_app_${_helper_target}" ]
|
||||||
}
|
}
|
||||||
@@ -1176,6 +1226,7 @@ if (is_win) {
|
|||||||
|
|
||||||
bundle_deps = [
|
bundle_deps = [
|
||||||
":angle_library",
|
":angle_library",
|
||||||
|
":aperitif_library",
|
||||||
":chrome_framework_helpers",
|
":chrome_framework_helpers",
|
||||||
":chrome_framework_plugins",
|
":chrome_framework_plugins",
|
||||||
":chrome_framework_resources",
|
":chrome_framework_resources",
|
||||||
@@ -1199,9 +1250,12 @@ if (is_win) {
|
|||||||
]
|
]
|
||||||
|
|
||||||
if (!is_component_build) {
|
if (!is_component_build) {
|
||||||
# Specify a sensible install_name for static builds. The library is
|
ldflags += [
|
||||||
# dlopen()ed so this is not used to resolve the module.
|
# Specify a sensible install_name for static builds. The library is
|
||||||
ldflags += [ "-Wl,-install_name,@executable_path/../Frameworks/$chrome_framework_name.framework/Versions/$chrome_version_full/$chrome_framework_name" ]
|
# dlopen()ed so this is not used to resolve the module.
|
||||||
|
"-Wl,-install_name,@executable_path/../Frameworks/$chrome_framework_name.framework/Versions/$chrome_version_full/$chrome_framework_name",
|
||||||
|
"-Wcrl,installnametool,-change,libaperitif.dylib,@loader_path/Libraries/libaperitif.dylib",
|
||||||
|
]
|
||||||
} else {
|
} else {
|
||||||
# In the component build, both the :chrome_app and various
|
# In the component build, both the :chrome_app and various
|
||||||
# :chrome_helper* targets directly link to the Framework target. Use
|
# :chrome_helper* targets directly link to the Framework target. Use
|
||||||
@@ -1213,7 +1267,10 @@ if (is_win) {
|
|||||||
"-Wl,-reexport_library,libchrome_dll.dylib",
|
"-Wl,-reexport_library,libchrome_dll.dylib",
|
||||||
]
|
]
|
||||||
|
|
||||||
data_deps = [ ":chrome_dll" ]
|
data_deps = [
|
||||||
|
":chrome_dll",
|
||||||
|
"//content/public/app:aperitif",
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1269,6 +1326,7 @@ if (is_win) {
|
|||||||
"$root_out_dir/chrome_crashpad_handler",
|
"$root_out_dir/chrome_crashpad_handler",
|
||||||
"$root_out_dir/libEGL.dylib",
|
"$root_out_dir/libEGL.dylib",
|
||||||
"$root_out_dir/libGLESv2.dylib",
|
"$root_out_dir/libGLESv2.dylib",
|
||||||
|
"$root_out_dir/libaperitif.dylib",
|
||||||
"$root_out_dir/libswiftshader_libEGL.dylib",
|
"$root_out_dir/libswiftshader_libEGL.dylib",
|
||||||
"$root_out_dir/libswiftshader_libGLESv2.dylib",
|
"$root_out_dir/libswiftshader_libGLESv2.dylib",
|
||||||
"$root_out_dir/libvk_swiftshader.dylib",
|
"$root_out_dir/libvk_swiftshader.dylib",
|
||||||
@@ -1305,6 +1363,7 @@ if (is_win) {
|
|||||||
":chrome_app",
|
":chrome_app",
|
||||||
":chrome_framework",
|
":chrome_framework",
|
||||||
"//components/crash/core/app:chrome_crashpad_handler",
|
"//components/crash/core/app:chrome_crashpad_handler",
|
||||||
|
"//content/public/app:aperitif",
|
||||||
"//third_party/angle:libEGL",
|
"//third_party/angle:libEGL",
|
||||||
"//third_party/angle:libGLESv2",
|
"//third_party/angle:libGLESv2",
|
||||||
"//third_party/breakpad:dump_syms",
|
"//third_party/breakpad:dump_syms",
|
||||||
@@ -1332,6 +1391,7 @@ if (is_win) {
|
|||||||
"$root_out_dir/$chrome_framework_name.dSYM",
|
"$root_out_dir/$chrome_framework_name.dSYM",
|
||||||
"$root_out_dir/$chrome_product_full_name.dSYM",
|
"$root_out_dir/$chrome_product_full_name.dSYM",
|
||||||
"$root_out_dir/chrome_crashpad_handler.dSYM",
|
"$root_out_dir/chrome_crashpad_handler.dSYM",
|
||||||
|
"$root_out_dir/libaperitif.dylib.dSYM",
|
||||||
"$root_out_dir/libEGL.dylib.dSYM",
|
"$root_out_dir/libEGL.dylib.dSYM",
|
||||||
"$root_out_dir/libGLESv2.dylib.dSYM",
|
"$root_out_dir/libGLESv2.dylib.dSYM",
|
||||||
"$root_out_dir/libswiftshader_libEGL.dylib.dSYM",
|
"$root_out_dir/libswiftshader_libEGL.dylib.dSYM",
|
||||||
@@ -1346,6 +1406,7 @@ if (is_win) {
|
|||||||
":chrome_app",
|
":chrome_app",
|
||||||
":chrome_framework",
|
":chrome_framework",
|
||||||
"//components/crash/core/app:chrome_crashpad_handler",
|
"//components/crash/core/app:chrome_crashpad_handler",
|
||||||
|
"//content/public/app:aperitif",
|
||||||
"//third_party/angle:libEGL",
|
"//third_party/angle:libEGL",
|
||||||
"//third_party/angle:libGLESv2",
|
"//third_party/angle:libGLESv2",
|
||||||
"//third_party/swiftshader/src/OpenGL/libEGL:swiftshader_libEGL",
|
"//third_party/swiftshader/src/OpenGL/libEGL:swiftshader_libEGL",
|
||||||
|
@@ -55,8 +55,9 @@ per-file *.plist=file://chrome/browser/ui/cocoa/OWNERS
|
|||||||
|
|
||||||
per-file chrome_crash_reporter_client*=rsesek@chromium.org
|
per-file chrome_crash_reporter_client*=rsesek@chromium.org
|
||||||
|
|
||||||
per-file chrome_exe_main_mac.cc=kerrnel@chromium.org
|
per-file chrome_exe_main_mac.c=kerrnel@chromium.org
|
||||||
per-file chrome_exe_main_mac.cc=mark@chromium.org
|
per-file chrome_exe_main_mac.c=mark@chromium.org
|
||||||
|
per-file chrome_exe_main_mac.c=rsesek@chromium.org
|
||||||
|
|
||||||
per-file main_dll_loader_win.cc=brucedawson@chromium.org
|
per-file main_dll_loader_win.cc=brucedawson@chromium.org
|
||||||
per-file main_dll_loader_win.cc=wfh@chromium.org
|
per-file main_dll_loader_win.cc=wfh@chromium.org
|
||||||
|
@@ -8,35 +8,17 @@
|
|||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <mach-o/dyld.h>
|
#include <mach-o/dyld.h>
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include "base/allocator/early_zone_registration_mac.h"
|
|
||||||
#include "build/branding_buildflags.h"
|
#include "build/branding_buildflags.h"
|
||||||
#include "build/build_config.h"
|
#include "build/build_config.h"
|
||||||
#include "chrome/common/chrome_version.h"
|
#include "chrome/common/chrome_version.h"
|
||||||
|
#include "content/public/app/aperitif_mac.h"
|
||||||
#if defined(HELPER_EXECUTABLE)
|
|
||||||
#include "sandbox/mac/seatbelt_exec.h" // nogncheck
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
// abort_report_np() records the message in a special section that both the
|
|
||||||
// system CrashReporter and Crashpad collect in crash reports. Using a Crashpad
|
|
||||||
// Annotation would be preferable, but this executable cannot depend on
|
|
||||||
// Crashpad directly.
|
|
||||||
void abort_report_np(const char* fmt, ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
typedef int (*ChromeMainPtr)(int, char**);
|
typedef int (*ChromeMainPtr)(int, char**);
|
||||||
|
|
||||||
@@ -125,85 +107,57 @@ typedef int (*ChromeMainPtr)(int, char**);
|
|||||||
// If the main executable has a significant change in size, this will need to be
|
// If the main executable has a significant change in size, this will need to be
|
||||||
// revised. Hopefully a more elegant solution will become apparent before that's
|
// revised. Hopefully a more elegant solution will become apparent before that's
|
||||||
// required.
|
// required.
|
||||||
__attribute__((used)) const char kGrossPaddingForCrbug1300598[68 * 1024] = {};
|
static __attribute__((used))
|
||||||
|
const char kGrossPaddingForCrbug1300598[68 * 1024] = {};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
[[noreturn]] void FatalError(const char* format, ...) {
|
|
||||||
va_list valist;
|
|
||||||
va_start(valist, format);
|
|
||||||
char message[4096];
|
|
||||||
if (vsnprintf(message, sizeof(message), format, valist) >= 0) {
|
|
||||||
fputs(message, stderr);
|
|
||||||
abort_report_np("%s", message);
|
|
||||||
}
|
|
||||||
va_end(valist);
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
__attribute__((visibility("default"))) int main(int argc, char* argv[]) {
|
__attribute__((visibility("default"))) int main(int argc, char* argv[]) {
|
||||||
partition_alloc::EarlyMallocZoneRegistration();
|
AperitifInitializePartitionAlloc();
|
||||||
|
|
||||||
uint32_t exec_path_size = 0;
|
char exec_path[PATH_MAX];
|
||||||
int rv = _NSGetExecutablePath(NULL, &exec_path_size);
|
uint32_t exec_path_size = sizeof(exec_path);
|
||||||
if (rv != -1) {
|
int rv = _NSGetExecutablePath(exec_path, &exec_path_size);
|
||||||
FatalError("_NSGetExecutablePath: get length failed.");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<char[]> exec_path(new char[exec_path_size]);
|
|
||||||
rv = _NSGetExecutablePath(exec_path.get(), &exec_path_size);
|
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
FatalError("_NSGetExecutablePath: get path failed.");
|
AperitifFatalError("_NSGetExecutablePath: get path failed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(HELPER_EXECUTABLE)
|
#if defined(HELPER_EXECUTABLE)
|
||||||
sandbox::SeatbeltExecServer::CreateFromArgumentsResult seatbelt =
|
// Start the sandbox before loading the framework.
|
||||||
sandbox::SeatbeltExecServer::CreateFromArguments(exec_path.get(), argc,
|
AperitifInitializeSandbox(exec_path, argc, (const char**)argv);
|
||||||
argv);
|
|
||||||
if (seatbelt.sandbox_required) {
|
|
||||||
if (!seatbelt.server) {
|
|
||||||
FatalError("Failed to create seatbelt sandbox server.");
|
|
||||||
}
|
|
||||||
if (!seatbelt.server->InitializeSandbox()) {
|
|
||||||
FatalError("Failed to initialize sandbox.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The helper lives within the versioned framework directory, so simply
|
// The helper lives within the versioned framework directory, so simply
|
||||||
// go up to find the main dylib.
|
// go up to find the main dylib.
|
||||||
const char rel_path[] = "../../../../" PRODUCT_FULLNAME_STRING " Framework";
|
static const char rel_path[] =
|
||||||
|
"../../../../" PRODUCT_FULLNAME_STRING " Framework";
|
||||||
#else
|
#else
|
||||||
const char rel_path[] = "../Frameworks/" PRODUCT_FULLNAME_STRING
|
static const char rel_path[] =
|
||||||
" Framework.framework/Versions/" CHROME_VERSION_STRING
|
"../Frameworks/" PRODUCT_FULLNAME_STRING
|
||||||
"/" PRODUCT_FULLNAME_STRING " Framework";
|
" Framework.framework/Versions/" CHROME_VERSION_STRING
|
||||||
|
"/" PRODUCT_FULLNAME_STRING " Framework";
|
||||||
#endif // defined(HELPER_EXECUTABLE)
|
#endif // defined(HELPER_EXECUTABLE)
|
||||||
|
|
||||||
// Slice off the last part of the main executable path, and append the
|
// Slice off the last part of the main executable path, and append the
|
||||||
// version framework information.
|
// version framework information.
|
||||||
const char* parent_dir = dirname(exec_path.get());
|
const char* parent_dir = dirname(exec_path);
|
||||||
if (!parent_dir) {
|
if (!parent_dir) {
|
||||||
FatalError("dirname %s: %s.", exec_path.get(), strerror(errno));
|
AperitifFatalError("dirname %s: %s.", exec_path, strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
const size_t parent_dir_len = strlen(parent_dir);
|
char framework_path[PATH_MAX];
|
||||||
const size_t rel_path_len = strlen(rel_path);
|
rv = snprintf(framework_path, sizeof(framework_path), "%s/%s", parent_dir,
|
||||||
// 2 accounts for a trailing NUL byte and the '/' in the middle of the paths.
|
rel_path);
|
||||||
const size_t framework_path_size = parent_dir_len + rel_path_len + 2;
|
if (rv < 0 || (size_t)rv >= sizeof(framework_path)) {
|
||||||
std::unique_ptr<char[]> framework_path(new char[framework_path_size]);
|
AperitifFatalError("snprintf: %d.", rv);
|
||||||
snprintf(framework_path.get(), framework_path_size, "%s/%s", parent_dir,
|
}
|
||||||
rel_path);
|
|
||||||
|
|
||||||
void* library =
|
void* library = dlopen(framework_path, RTLD_LAZY | RTLD_LOCAL | RTLD_FIRST);
|
||||||
dlopen(framework_path.get(), RTLD_LAZY | RTLD_LOCAL | RTLD_FIRST);
|
|
||||||
if (!library) {
|
if (!library) {
|
||||||
FatalError("dlopen %s: %s.", framework_path.get(), dlerror());
|
AperitifFatalError("dlopen %s: %s.", framework_path, dlerror());
|
||||||
}
|
}
|
||||||
|
|
||||||
const ChromeMainPtr chrome_main =
|
const ChromeMainPtr chrome_main = dlsym(library, "ChromeMain");
|
||||||
reinterpret_cast<ChromeMainPtr>(dlsym(library, "ChromeMain"));
|
|
||||||
if (!chrome_main) {
|
if (!chrome_main) {
|
||||||
FatalError("dlsym ChromeMain: %s.", dlerror());
|
AperitifFatalError("dlsym ChromeMain: %s.", dlerror());
|
||||||
}
|
}
|
||||||
rv = chrome_main(argc, argv);
|
rv = chrome_main(argc, argv);
|
||||||
|
|
@@ -118,6 +118,7 @@ def get_parts(config):
|
|||||||
}
|
}
|
||||||
|
|
||||||
dylibs = [
|
dylibs = [
|
||||||
|
'libaperitif.dylib',
|
||||||
'libEGL.dylib',
|
'libEGL.dylib',
|
||||||
'libGLESv2.dylib',
|
'libGLESv2.dylib',
|
||||||
'libswiftshader_libEGL.dylib',
|
'libswiftshader_libEGL.dylib',
|
||||||
|
@@ -27,6 +27,13 @@ def verify_image_libraries(image_path, allowed_libraries, binary_path):
|
|||||||
links against allowed libraries, and otherwise returns False with an error
|
links against allowed libraries, and otherwise returns False with an error
|
||||||
printed.
|
printed.
|
||||||
"""
|
"""
|
||||||
|
# If |image_path| is a dynamic library, allow the LC_DYLIB_ID implicitly.
|
||||||
|
output = subprocess.check_output(
|
||||||
|
[binary_path + 'llvm-objdump', '--macho', '--dylib-id', image_path])
|
||||||
|
dylib_id = output.decode('utf8').split('\n')[1]
|
||||||
|
if dylib_id:
|
||||||
|
allowed_libraries.append(dylib_id)
|
||||||
|
|
||||||
output = subprocess.check_output(
|
output = subprocess.check_output(
|
||||||
[binary_path + 'llvm-objdump', '--macho', '--dylibs-used', image_path])
|
[binary_path + 'llvm-objdump', '--macho', '--dylibs-used', image_path])
|
||||||
output = output.decode('utf8').strip()
|
output = output.decode('utf8').strip()
|
||||||
|
@@ -133,6 +133,17 @@ source_set("app") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_mac) {
|
||||||
|
source_set("aperitif") {
|
||||||
|
sources = [ "aperitif_mac.cc" ]
|
||||||
|
deps = [
|
||||||
|
"//base/allocator:early_zone_registration_mac",
|
||||||
|
"//sandbox/mac:seatbelt",
|
||||||
|
]
|
||||||
|
visibility = [ "//content/public/app:aperitif" ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# See comment at the top of //content/BUILD.gn for how this works.
|
# See comment at the top of //content/BUILD.gn for how this works.
|
||||||
group("for_content_tests") {
|
group("for_content_tests") {
|
||||||
visibility = [ "//content/test/*" ]
|
visibility = [ "//content/test/*" ]
|
||||||
|
63
content/app/aperitif_mac.cc
Normal file
63
content/app/aperitif_mac.cc
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
// Copyright 2022 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.
|
||||||
|
|
||||||
|
// Apéritif is by necessity linked to only a minimal number of libraries.
|
||||||
|
// Code that executes in this context has the capability of compromising the
|
||||||
|
// integrity of the sandbox by acquiring resources that would remain available
|
||||||
|
// to an unprivileged process. Consult with security-dev@chromium.org before
|
||||||
|
// adding new dependencies to Aperitif.
|
||||||
|
|
||||||
|
#include "content/public/app/aperitif_mac.h"
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
|
||||||
|
#include "base/allocator/early_zone_registration_mac.h"
|
||||||
|
#include "sandbox/mac/seatbelt_exec.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
// abort_report_np() records the message in a special section that both the
|
||||||
|
// system CrashReporter and Crashpad collect in crash reports. Using a Crashpad
|
||||||
|
// `Annotation` would be preferable, but this module cannot depend on Crashpad
|
||||||
|
// directly.
|
||||||
|
void abort_report_np(const char* fmt, ...) __abortlike __printflike(1, 2);
|
||||||
|
|
||||||
|
void AperitifFatalError(const char* format, ...) {
|
||||||
|
va_list valist;
|
||||||
|
va_start(valist, format);
|
||||||
|
char message[4096];
|
||||||
|
int rv = vsnprintf(message, sizeof(message), format, valist);
|
||||||
|
va_end(valist);
|
||||||
|
if (rv >= 0) {
|
||||||
|
fprintf(stderr, "aperitif: %s\n", message);
|
||||||
|
fflush(stderr);
|
||||||
|
abort_report_np("aperitif: %s", message);
|
||||||
|
}
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AperitifInitializePartitionAlloc() {
|
||||||
|
partition_alloc::EarlyMallocZoneRegistration();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AperitifInitializeSandbox(const char* executable_path,
|
||||||
|
int argc,
|
||||||
|
const char* const argv[]) {
|
||||||
|
sandbox::SeatbeltExecServer::CreateFromArgumentsResult seatbelt =
|
||||||
|
sandbox::SeatbeltExecServer::CreateFromArguments(executable_path, argc,
|
||||||
|
argv);
|
||||||
|
if (seatbelt.sandbox_required) {
|
||||||
|
if (!seatbelt.server) {
|
||||||
|
AperitifFatalError("Failed to create seatbelt sandbox server.");
|
||||||
|
}
|
||||||
|
if (!seatbelt.server->InitializeSandbox()) {
|
||||||
|
AperitifFatalError("Failed to initialize sandbox.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // extern "C"
|
@@ -95,3 +95,33 @@ if (is_component_build) {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_mac) {
|
||||||
|
import("//build/util/version.gni")
|
||||||
|
shared_library("aperitif") {
|
||||||
|
sources = [ "aperitif_mac.h" ]
|
||||||
|
|
||||||
|
public_deps = [ "//content/app:aperitif" ]
|
||||||
|
|
||||||
|
ldflags = [
|
||||||
|
"-Wl,-install_name,libaperitif.dylib",
|
||||||
|
"-compatibility_version",
|
||||||
|
chrome_dylib_version,
|
||||||
|
"-current_version",
|
||||||
|
chrome_dylib_version,
|
||||||
|
]
|
||||||
|
|
||||||
|
if (is_component_build) {
|
||||||
|
# Typically packaged at Content Shell.app/Contents/Frameworks/Content
|
||||||
|
# Shell Framework.framework/Versions/C/Libraries/libaperitif.dylib
|
||||||
|
# so set rpath up to the root out directory.
|
||||||
|
ldflags += [ "-Wl,-rpath,@loader_path/../../../../../../.." ]
|
||||||
|
}
|
||||||
|
|
||||||
|
allow_circular_includes_from = [
|
||||||
|
# This target is a pair with the non-public version. They always go
|
||||||
|
# together and include headers from each other.
|
||||||
|
"//content/app:aperitif",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
50
content/public/app/aperitif_mac.h
Normal file
50
content/public/app/aperitif_mac.h
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
// Copyright 2022 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#ifndef CONTENT_PUBLIC_APP_APERITIF_MAC_H_
|
||||||
|
#define CONTENT_PUBLIC_APP_APERITIF_MAC_H_
|
||||||
|
|
||||||
|
// The macOS //content Apéritif dynamic library. The main and helper
|
||||||
|
// executables, compiled from *main_mac.c are plain C files that do not
|
||||||
|
// directly link to any C++ targets nor system libraries. Not linking to system
|
||||||
|
// libraries is important for sandboxing (see
|
||||||
|
// //sandbox/mac/seatbelt_sandbox_design.md), and not including C++ keeps the
|
||||||
|
// executable size to a minimum, because the project uses its own version of
|
||||||
|
// libc++. Minimizing the size of the executables is important because
|
||||||
|
// //content embedders need to distribute several duplicate helper executables
|
||||||
|
// that each have distinct codesigning entitlements (see
|
||||||
|
// //content/public/app/mac_helpers.gni).
|
||||||
|
//
|
||||||
|
// Apéritif is a dynamic library that contains C++ functionality that needs to
|
||||||
|
// run in the executable prior to loading the main Framework. This primary
|
||||||
|
// purpose is to engage the sandbox in helper executables prior to any system
|
||||||
|
// library static initializers running.
|
||||||
|
|
||||||
|
#define CONTENT_APERITIF_EXPORT __attribute__((visibility("default")))
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Helper function to record an error message and abort.
|
||||||
|
void CONTENT_APERITIF_EXPORT __attribute__((noreturn, format(printf, 1, 2)))
|
||||||
|
AperitifFatalError(const char* format, ...);
|
||||||
|
|
||||||
|
// Performs early initialization of the Mac allocator zone.
|
||||||
|
void CONTENT_APERITIF_EXPORT AperitifInitializePartitionAlloc();
|
||||||
|
|
||||||
|
// Engages the sandbox if the command line arguments specify that the process
|
||||||
|
// is to be sandboxed.
|
||||||
|
void CONTENT_APERITIF_EXPORT
|
||||||
|
AperitifInitializeSandbox(const char* executable_path,
|
||||||
|
int argc,
|
||||||
|
const char* const argv[]);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#undef CONTENT_APERITIF_EXPORT
|
||||||
|
|
||||||
|
#endif // CONTENT_PUBLIC_APP_APERITIF_MAC_H_
|
@@ -358,7 +358,8 @@ int LaunchTests(TestLauncherDelegate* launcher_delegate,
|
|||||||
#elif BUILDFLAG(IS_MAC)
|
#elif BUILDFLAG(IS_MAC)
|
||||||
sandbox::SeatbeltExecServer::CreateFromArgumentsResult seatbelt =
|
sandbox::SeatbeltExecServer::CreateFromArgumentsResult seatbelt =
|
||||||
sandbox::SeatbeltExecServer::CreateFromArguments(
|
sandbox::SeatbeltExecServer::CreateFromArguments(
|
||||||
command_line->GetProgram().value().c_str(), argc, argv);
|
command_line->GetProgram().value().c_str(), argc,
|
||||||
|
const_cast<const char**>(argv));
|
||||||
if (seatbelt.sandbox_required) {
|
if (seatbelt.sandbox_required) {
|
||||||
CHECK(seatbelt.server->InitializeSandbox());
|
CHECK(seatbelt.server->InitializeSandbox());
|
||||||
}
|
}
|
||||||
|
@@ -480,39 +480,9 @@ if (is_android) {
|
|||||||
deps = [ "//content/shell/android:content_shell_apk" ]
|
deps = [ "//content/shell/android:content_shell_apk" ]
|
||||||
}
|
}
|
||||||
} else if (is_mac) {
|
} else if (is_mac) {
|
||||||
tweak_info_plist("content_shell_plist") {
|
group("content_shell") {
|
||||||
testonly = true
|
testonly = true
|
||||||
info_plist = "app/app-Info.plist"
|
deps = [ ":content_shell_mac_app" ]
|
||||||
args = [
|
|
||||||
"--scm=1",
|
|
||||||
"--version",
|
|
||||||
content_shell_version,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
mac_app_bundle("content_shell") {
|
|
||||||
testonly = true
|
|
||||||
output_name = content_shell_product_name
|
|
||||||
sources = [ "app/shell_main_mac.cc" ]
|
|
||||||
defines = [ "SHELL_PRODUCT_NAME=\"$content_shell_product_name\"" ]
|
|
||||||
|
|
||||||
# Must have minimal dependencies. In particular cannot depend on //base.
|
|
||||||
# Depending on //base leads to loading //base twice (once in the exe, once
|
|
||||||
# in the main framework).
|
|
||||||
deps = [
|
|
||||||
":content_shell_framework_bundle_data",
|
|
||||||
":content_shell_resources_bundle_data",
|
|
||||||
|
|
||||||
# Despite its path, this does not add a //base dependency, see comments in
|
|
||||||
# the .cc file.
|
|
||||||
"//base/allocator:early_zone_registration_mac",
|
|
||||||
"//sandbox/mac:seatbelt",
|
|
||||||
]
|
|
||||||
info_plist_target = ":content_shell_plist"
|
|
||||||
data_deps = [ ":content_shell_app" ]
|
|
||||||
|
|
||||||
if (is_component_build) {
|
|
||||||
ldflags = [ "-Wl,-rpath,@executable_path/../Frameworks" ]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
executable("content_shell") {
|
executable("content_shell") {
|
||||||
@@ -589,6 +559,51 @@ if (is_android) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (is_mac) {
|
if (is_mac) {
|
||||||
|
content_shell_framework_name = "$content_shell_product_name Framework"
|
||||||
|
content_shell_helper_name = "$content_shell_product_name Helper"
|
||||||
|
|
||||||
|
tweak_info_plist("content_shell_plist") {
|
||||||
|
testonly = true
|
||||||
|
info_plist = "app/app-Info.plist"
|
||||||
|
args = [
|
||||||
|
"--scm=1",
|
||||||
|
"--version",
|
||||||
|
content_shell_version,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
mac_app_bundle("content_shell_mac_app") {
|
||||||
|
testonly = true
|
||||||
|
output_name = content_shell_product_name
|
||||||
|
sources = [ "app/shell_main_mac.c" ]
|
||||||
|
defines = [ "SHELL_PRODUCT_NAME=\"$content_shell_product_name\"" ]
|
||||||
|
|
||||||
|
# No libc++ needed, there’s only C code in this module.
|
||||||
|
no_default_deps = true
|
||||||
|
|
||||||
|
# Must have minimal dependencies. In particular cannot depend on //base.
|
||||||
|
# Depending on //base leads to loading //base twice (once in the exe, once
|
||||||
|
# in the main framework).
|
||||||
|
deps = [
|
||||||
|
":content_shell_framework_bundle_data",
|
||||||
|
":content_shell_resources_bundle_data",
|
||||||
|
"//content/public/app:aperitif",
|
||||||
|
]
|
||||||
|
info_plist_target = ":content_shell_plist"
|
||||||
|
data_deps = [ ":content_shell_app" ]
|
||||||
|
|
||||||
|
ldflags = [
|
||||||
|
# Needed for lld: https://github.com/llvm/llvm-project/issues/53550.
|
||||||
|
"-Wl,-headerpad_max_install_names",
|
||||||
|
"-Wcrl,installnametool,-change,libaperitif.dylib,@executable_path/../Frameworks/$content_shell_framework_name.framework/Libraries/libaperitif.dylib",
|
||||||
|
]
|
||||||
|
|
||||||
|
if (is_component_build) {
|
||||||
|
ldflags += [ "-Wl,-rpath,@executable_path/../Frameworks" ]
|
||||||
|
data_deps += [ "//content/public/app:aperitif" ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bundle_data("content_shell_framework_resources") {
|
bundle_data("content_shell_framework_resources") {
|
||||||
testonly = true
|
testonly = true
|
||||||
sources = [ "$root_out_dir/content_shell.pak" ]
|
sources = [ "$root_out_dir/content_shell.pak" ]
|
||||||
@@ -629,9 +644,6 @@ if (is_mac) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
content_shell_framework_name = "$content_shell_product_name Framework"
|
|
||||||
content_shell_helper_name = "$content_shell_product_name Helper"
|
|
||||||
|
|
||||||
bundle_data("content_shell_framework_helpers") {
|
bundle_data("content_shell_framework_helpers") {
|
||||||
testonly = true
|
testonly = true
|
||||||
sources = [ "$root_out_dir/chrome_crashpad_handler" ]
|
sources = [ "$root_out_dir/chrome_crashpad_handler" ]
|
||||||
@@ -681,11 +693,13 @@ if (is_mac) {
|
|||||||
":content_shell_angle_library",
|
":content_shell_angle_library",
|
||||||
":content_shell_app",
|
":content_shell_app",
|
||||||
"//content/public/app",
|
"//content/public/app",
|
||||||
|
"//content/public/app:aperitif",
|
||||||
"//content/public/common",
|
"//content/public/common",
|
||||||
"//third_party/icu:icudata",
|
"//third_party/icu:icudata",
|
||||||
]
|
]
|
||||||
|
|
||||||
bundle_deps = [
|
bundle_deps = [
|
||||||
|
":content_shell_aperitif_library",
|
||||||
":content_shell_framework_helpers",
|
":content_shell_framework_helpers",
|
||||||
":content_shell_framework_resources",
|
":content_shell_framework_resources",
|
||||||
":content_shell_swiftshader_library",
|
":content_shell_swiftshader_library",
|
||||||
@@ -695,10 +709,12 @@ if (is_mac) {
|
|||||||
deps += [ ":content_shell_framework_plugins" ]
|
deps += [ ":content_shell_framework_plugins" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ldflags = [ "-Wcrl,installnametool,-change,libaperitif.dylib,@loader_path/Libraries/libaperitif.dylib" ]
|
||||||
|
|
||||||
if (!is_component_build) {
|
if (!is_component_build) {
|
||||||
# Specify a sensible install_name for static builds. The library is
|
# Specify a sensible install_name for static builds. The library is
|
||||||
# dlopen()ed so this is not used to resolve the module.
|
# dlopen()ed so this is not used to resolve the module.
|
||||||
ldflags = [ "-Wl,-install_name,@executable_path/../Frameworks/$output_name.framework/$output_name" ]
|
ldflags += [ "-Wl,-install_name,@executable_path/../Frameworks/$output_name.framework/$output_name" ]
|
||||||
} else {
|
} else {
|
||||||
# Both the main :content_shell and :content_shell_helper_app executables
|
# Both the main :content_shell and :content_shell_helper_app executables
|
||||||
# need to link the framework. Because they are at different directory
|
# need to link the framework. Because they are at different directory
|
||||||
@@ -706,7 +722,7 @@ if (is_mac) {
|
|||||||
# install_name_tool on one of the executables. However install_name_tool
|
# install_name_tool on one of the executables. However install_name_tool
|
||||||
# only operates in-place, which is problematic to express in GN. Instead,
|
# only operates in-place, which is problematic to express in GN. Instead,
|
||||||
# use rpath-based loading.
|
# use rpath-based loading.
|
||||||
ldflags =
|
ldflags +=
|
||||||
[ "-Wl,-install_name,@rpath/$output_name.framework/$output_name" ]
|
[ "-Wl,-install_name,@rpath/$output_name.framework/$output_name" ]
|
||||||
|
|
||||||
# Set up the rpath for the framework so that it can find dylibs in the
|
# Set up the rpath for the framework so that it can find dylibs in the
|
||||||
@@ -740,7 +756,7 @@ if (is_mac) {
|
|||||||
|
|
||||||
output_name = content_shell_helper_name + invoker.helper_name_suffix
|
output_name = content_shell_helper_name + invoker.helper_name_suffix
|
||||||
|
|
||||||
sources = [ "app/shell_main_mac.cc" ]
|
sources = [ "app/shell_main_mac.c" ]
|
||||||
defines = [
|
defines = [
|
||||||
"HELPER_EXECUTABLE",
|
"HELPER_EXECUTABLE",
|
||||||
"SHELL_PRODUCT_NAME=\"$content_shell_product_name\"",
|
"SHELL_PRODUCT_NAME=\"$content_shell_product_name\"",
|
||||||
@@ -749,15 +765,21 @@ if (is_mac) {
|
|||||||
"CONTENT_SHELL_HELPER_SUFFIX=${invoker.helper_name_suffix}",
|
"CONTENT_SHELL_HELPER_SUFFIX=${invoker.helper_name_suffix}",
|
||||||
"CONTENT_SHELL_HELPER_BUNDLE_ID_SUFFIX=${invoker.helper_bundle_id_suffix}",
|
"CONTENT_SHELL_HELPER_BUNDLE_ID_SUFFIX=${invoker.helper_bundle_id_suffix}",
|
||||||
]
|
]
|
||||||
deps = [
|
deps = [ "//content/public/app:aperitif" ]
|
||||||
"//base/allocator:early_zone_registration_mac",
|
|
||||||
"//sandbox/mac:seatbelt",
|
# No libc++ needed, there’s only C code in this module.
|
||||||
]
|
no_default_deps = true
|
||||||
|
|
||||||
info_plist_target = ":content_shell_helper_plist"
|
info_plist_target = ":content_shell_helper_plist"
|
||||||
|
|
||||||
|
ldflags = [
|
||||||
|
# Needed for lld: https://github.com/llvm/llvm-project/issues/53550.
|
||||||
|
"-Wl,-headerpad_max_install_names",
|
||||||
|
"-Wcrl,installnametool,-change,libaperitif.dylib,@executable_path/../../../../Libraries/libaperitif.dylib",
|
||||||
|
]
|
||||||
|
|
||||||
if (is_component_build) {
|
if (is_component_build) {
|
||||||
ldflags = [
|
ldflags += [
|
||||||
# The helper is in Content Shell.app/Contents/Frameworks/
|
# The helper is in Content Shell.app/Contents/Frameworks/
|
||||||
# Content Shell Framework.framework/Versions/C/Helpers/
|
# Content Shell Framework.framework/Versions/C/Helpers/
|
||||||
# Content Shell Helper.app/Contents/MacOS/
|
# Content Shell Helper.app/Contents/MacOS/
|
||||||
@@ -844,6 +866,12 @@ if (is_mac) {
|
|||||||
deps = [ ":content_shell_swiftshader_binaries" ]
|
deps = [ ":content_shell_swiftshader_binaries" ]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bundle_data("content_shell_aperitif_library") {
|
||||||
|
sources = [ "$root_out_dir/libaperitif.dylib" ]
|
||||||
|
outputs = [ "{{bundle_contents_dir}}/Libraries/{{source_file_part}}" ]
|
||||||
|
public_deps = [ "//content/public/app:aperitif" ]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mojom("content_browsertests_mojom") {
|
mojom("content_browsertests_mojom") {
|
||||||
|
68
content/shell/app/shell_main_mac.c
Normal file
68
content/shell/app/shell_main_mac.c
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <libgen.h>
|
||||||
|
#include <mach-o/dyld.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
|
||||||
|
#include "content/public/app/aperitif_mac.h"
|
||||||
|
|
||||||
|
typedef int (*ContentMainPtr)(int, char**);
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
AperitifInitializePartitionAlloc();
|
||||||
|
|
||||||
|
char exec_path[PATH_MAX];
|
||||||
|
uint32_t exec_path_size = sizeof(exec_path);
|
||||||
|
int rv = _NSGetExecutablePath(exec_path, &exec_path_size);
|
||||||
|
if (rv != 0) {
|
||||||
|
AperitifFatalError("_NSGetExecutablePath: get path failed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(HELPER_EXECUTABLE)
|
||||||
|
AperitifInitializeSandbox(exec_path, argc, (const char**)argv);
|
||||||
|
|
||||||
|
// The Helper app is in the versioned framework directory, so just go up to
|
||||||
|
// the version folder to locate the dylib.
|
||||||
|
static const char rel_path[] = "../../../../" SHELL_PRODUCT_NAME " Framework";
|
||||||
|
#else
|
||||||
|
static const char rel_path[] =
|
||||||
|
"../Frameworks/" SHELL_PRODUCT_NAME
|
||||||
|
" Framework.framework/" SHELL_PRODUCT_NAME " Framework";
|
||||||
|
#endif // defined(HELPER_EXECUTABLE)
|
||||||
|
|
||||||
|
// Slice off the last part of the main executable path, and append the
|
||||||
|
// version framework information.
|
||||||
|
const char* parent_dir = dirname(exec_path);
|
||||||
|
if (!parent_dir) {
|
||||||
|
AperitifFatalError("dirname %s: %s", exec_path, strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
char framework_path[PATH_MAX];
|
||||||
|
rv = snprintf(framework_path, sizeof(framework_path), "%s/%s", parent_dir,
|
||||||
|
rel_path);
|
||||||
|
if (rv < 0 || (size_t)rv >= sizeof(framework_path)) {
|
||||||
|
AperitifFatalError("snprintf: %d", rv);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* library = dlopen(framework_path, RTLD_LAZY | RTLD_LOCAL | RTLD_FIRST);
|
||||||
|
if (!library) {
|
||||||
|
AperitifFatalError("dlopen %s: %s", framework_path, dlerror());
|
||||||
|
}
|
||||||
|
|
||||||
|
const ContentMainPtr content_main = dlsym(library, "ContentMain");
|
||||||
|
if (!content_main) {
|
||||||
|
AperitifFatalError("dlsym ContentMain: %s", dlerror());
|
||||||
|
}
|
||||||
|
rv = content_main(argc, argv);
|
||||||
|
|
||||||
|
// exit, don't return from main, to avoid the apparent removal of main from
|
||||||
|
// stack backtraces under tail call optimization.
|
||||||
|
exit(rv);
|
||||||
|
}
|
@@ -1,102 +0,0 @@
|
|||||||
// 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.
|
|
||||||
|
|
||||||
#include <dlfcn.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <libgen.h>
|
|
||||||
#include <mach-o/dyld.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include "base/allocator/early_zone_registration_mac.h"
|
|
||||||
|
|
||||||
#if defined(HELPER_EXECUTABLE)
|
|
||||||
#include "sandbox/mac/seatbelt_exec.h" // nogncheck
|
|
||||||
#endif // defined(HELPER_EXECUTABLE)
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
using ContentMainPtr = int (*)(int, char**);
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
|
||||||
partition_alloc::EarlyMallocZoneRegistration();
|
|
||||||
|
|
||||||
uint32_t exec_path_size = 0;
|
|
||||||
int rv = _NSGetExecutablePath(NULL, &exec_path_size);
|
|
||||||
if (rv != -1) {
|
|
||||||
fprintf(stderr, "_NSGetExecutablePath: get length failed\n");
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<char[]> exec_path(new char[exec_path_size]);
|
|
||||||
rv = _NSGetExecutablePath(exec_path.get(), &exec_path_size);
|
|
||||||
if (rv != 0) {
|
|
||||||
fprintf(stderr, "_NSGetExecutablePath: get path failed\n");
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(HELPER_EXECUTABLE)
|
|
||||||
sandbox::SeatbeltExecServer::CreateFromArgumentsResult seatbelt =
|
|
||||||
sandbox::SeatbeltExecServer::CreateFromArguments(exec_path.get(), argc,
|
|
||||||
argv);
|
|
||||||
if (seatbelt.sandbox_required) {
|
|
||||||
if (!seatbelt.server) {
|
|
||||||
fprintf(stderr, "Failed to create seatbelt sandbox server.\n");
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
if (!seatbelt.server->InitializeSandbox()) {
|
|
||||||
fprintf(stderr, "Failed to initialize sandbox.\n");
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The Helper app is in the versioned framework directory, so just go up to
|
|
||||||
// the version folder to locate the dylib.
|
|
||||||
const char rel_path[] = "../../../../" SHELL_PRODUCT_NAME " Framework";
|
|
||||||
#else
|
|
||||||
const char rel_path[] =
|
|
||||||
"../Frameworks/" SHELL_PRODUCT_NAME
|
|
||||||
" Framework.framework/" SHELL_PRODUCT_NAME " Framework";
|
|
||||||
#endif // defined(HELPER_EXECUTABLE)
|
|
||||||
|
|
||||||
// Slice off the last part of the main executable path, and append the
|
|
||||||
// version framework information.
|
|
||||||
const char* parent_dir = dirname(exec_path.get());
|
|
||||||
if (!parent_dir) {
|
|
||||||
fprintf(stderr, "dirname %s: %s\n", exec_path.get(), strerror(errno));
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
const size_t parent_dir_len = strlen(parent_dir);
|
|
||||||
const size_t rel_path_len = strlen(rel_path);
|
|
||||||
// 2 accounts for a trailing NUL byte and the '/' in the middle of the paths.
|
|
||||||
const size_t framework_path_size = parent_dir_len + rel_path_len + 2;
|
|
||||||
std::unique_ptr<char[]> framework_path(new char[framework_path_size]);
|
|
||||||
snprintf(framework_path.get(), framework_path_size, "%s/%s", parent_dir,
|
|
||||||
rel_path);
|
|
||||||
|
|
||||||
void* library =
|
|
||||||
dlopen(framework_path.get(), RTLD_LAZY | RTLD_LOCAL | RTLD_FIRST);
|
|
||||||
if (!library) {
|
|
||||||
fprintf(stderr, "dlopen %s: %s\n", framework_path.get(), dlerror());
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
const ContentMainPtr content_main =
|
|
||||||
reinterpret_cast<ContentMainPtr>(dlsym(library, "ContentMain"));
|
|
||||||
if (!content_main) {
|
|
||||||
fprintf(stderr, "dlsym ContentMain: %s\n", dlerror());
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
rv = content_main(argc, argv);
|
|
||||||
|
|
||||||
// exit, don't return from main, to avoid the apparent removal of main from
|
|
||||||
// stack backtraces under tail call optimization.
|
|
||||||
exit(rv);
|
|
||||||
}
|
|
@@ -169,7 +169,7 @@ sandbox::SeatbeltExecServer::CreateFromArgumentsResult::
|
|||||||
sandbox::SeatbeltExecServer::CreateFromArgumentsResult
|
sandbox::SeatbeltExecServer::CreateFromArgumentsResult
|
||||||
SeatbeltExecServer::CreateFromArguments(const char* executable_path,
|
SeatbeltExecServer::CreateFromArguments(const char* executable_path,
|
||||||
int argc,
|
int argc,
|
||||||
char** argv) {
|
const char* const* argv) {
|
||||||
CreateFromArgumentsResult result;
|
CreateFromArgumentsResult result;
|
||||||
int seatbelt_client_fd = -1;
|
int seatbelt_client_fd = -1;
|
||||||
for (int i = 1; i < argc; ++i) {
|
for (int i = 1; i < argc; ++i) {
|
||||||
|
@@ -97,8 +97,10 @@ class SEATBELT_EXPORT SeatbeltExecServer {
|
|||||||
bool sandbox_required = false;
|
bool sandbox_required = false;
|
||||||
std::unique_ptr<SeatbeltExecServer> server;
|
std::unique_ptr<SeatbeltExecServer> server;
|
||||||
};
|
};
|
||||||
static CreateFromArgumentsResult
|
static CreateFromArgumentsResult CreateFromArguments(
|
||||||
CreateFromArguments(const char* executable_path, int argc, char** argv);
|
const char* executable_path,
|
||||||
|
int argc,
|
||||||
|
const char* const* argv);
|
||||||
|
|
||||||
// Reads the policy from the client, applies the profile, and returns whether
|
// Reads the policy from the client, applies the profile, and returns whether
|
||||||
// or not the operation succeeds.
|
// or not the operation succeeds.
|
||||||
|
Reference in New Issue
Block a user