From a5f914aef163e27bf49ce2c29f2cef12a131132f Mon Sep 17 00:00:00 2001 From: Jiyong Park Date: Sun, 20 Jan 2019 21:02:00 +0900 Subject: [PATCH 1/2] Add bionic mount points under /bionic This change adds following files and symlinks: Files: /bionic/lib[64]/lib{c|dl|m}.so /bionic/bin/linker[64] Symlinks: /system/lib[64]/lib{c|dl|m}.so -> /bionic/lib[64]/lib{c|dl|m}.so /system/bin/linker[64] -> /bionic/bin/linker[64] /system/bin/linker_asan[64] -> /bionic/bin/linker[64] The files serve as mount points for either the bootstrap Bionic or the default Bionic from the runtime APEX. init does the bind-mounting during booting. The symlinks are there to not change the ordinary paths to the bionic files; there are many places that the paths are implied or hard-coded, e.g., dlopen("/system/lib/libc.so") or DT_INTERP pointing to /system/bin/linker in the vendor prebuilts. Bug: 120266448 Test: m blueline, cf_x86, aosp_arm The aforementioned files and symlinks are found Change-Id: I97e38c29409ac0610dde285db8df6e94a7930094 --- Android.bp | 52 +++++++++++++++ build/Android.bp | 32 +++++++++ build/bionic.go | 164 ++++++++++++++++++++++++++++++++++++++++++++++ dummy_mountpoint | 1 + libc/Android.bp | 2 +- libdl/Android.bp | 1 + libm/Android.bp | 1 + linker/Android.bp | 1 + 8 files changed, 253 insertions(+), 1 deletion(-) create mode 100644 Android.bp create mode 100644 build/Android.bp create mode 100644 build/bionic.go create mode 100644 dummy_mountpoint diff --git a/Android.bp b/Android.bp new file mode 100644 index 000000000..376c25064 --- /dev/null +++ b/Android.bp @@ -0,0 +1,52 @@ +// +// Copyright (C) 2019 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. +// + +bionic_mountpoint { + name: "libc.mountpoint", + stem: "libc.so", + src: "dummy_mountpoint", + library: true, + symlinks: ["libc.so"], +} + +bionic_mountpoint { + name: "libdl.mountpoint", + stem: "libdl.so", + src: "dummy_mountpoint", + library: true, + symlinks: ["libdl.so"], +} + +bionic_mountpoint { + name: "libm.mountpoint", + stem: "libm.so", + src: "dummy_mountpoint", + library: true, + symlinks: ["libm.so"], +} + +bionic_mountpoint { + name: "linker.mountpoint", + stem: "linker", + multilib: { + lib64: { + suffix: "64", + }, + }, + src: "dummy_mountpoint", + binary: true, + symlinks: ["linker", "linker_asan"], +} diff --git a/build/Android.bp b/build/Android.bp new file mode 100644 index 000000000..6cc160aef --- /dev/null +++ b/build/Android.bp @@ -0,0 +1,32 @@ +// +// Copyright (C) 2019 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. +// + + +bootstrap_go_package { + name: "soong-bionic", + pkgPath: "android/soong/bionic", + deps: [ + "blueprint", + "blueprint-pathtools", + "blueprint-proptools", + "soong", + "soong-android", + ], + srcs: [ + "bionic.go", + ], + pluginFor: ["soong_build"], +} diff --git a/build/bionic.go b/build/bionic.go new file mode 100644 index 000000000..3522acae8 --- /dev/null +++ b/build/bionic.go @@ -0,0 +1,164 @@ +// Copyright (C) 2019 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. + +package bionic + +import ( + "fmt" + "io" + "strings" + + "github.com/google/blueprint/proptools" + + "android/soong/android" +) + +// bionic_mountpoint is a module type that is specialized to create +// mount points for Bionic files (libc, libdl, libm, and linker). +// +// With following description, +// +// bionic_mountpoint { +// name: "libc.mountpoint", +// stem: "libc.so", +// src: "dummy_mountpoint", +// library: true, +// symlinks: ["libc.so"], +// } +// +// , the build system does following jobs: +// +// A mount point /bionic/lib[64]/libc.so is created. Its content +// is from the file 'dummy_mountpoint'. +// +// Then a symlink is created at /system/lib[64]/libc.so which points to +// the created mountpoint. +// +// At runtime, on the mount point, either bootstrap Bionic or default Bionic +// (which is from the runtime APEX) is mounted by the init process. The +// symlink exists to provide consistent legacy path for compatibility +// reason. +func init() { + android.RegisterModuleType("bionic_mountpoint", bionicMountpointFactory) +} + +type bionicMountpoint struct { + android.ModuleBase + properties bionicMountpointProperties + + outputFile android.Path + pathInPartition string + stem string +} + +type bionicMountpointProperties struct { + // The file that is installed as the mount point + Src *string + + // True if the mount point is for a Bionic library such libc.so + Library *bool + // True if the mount point is for a Bionic binary such as linker + Binary *bool + + // Base name of the mount point + Stem *string `android:"arch_variant"` + + // Append to the name of the output + Suffix *string `android:"arch_variant"` + + // Symlinks to the mountpoints from the system and recovery partitions + // Symlinks names will have the same suffix as the mount point + Symlinks []string +} + +func (m *bionicMountpoint) DepsMutator(ctx android.BottomUpMutatorContext) { + if Bool(m.properties.Library) == Bool(m.properties.Binary) { + ctx.ModuleErrorf("either binary or library must be set to true") + return + } + if m.properties.Stem == nil { + ctx.PropertyErrorf("stem", "stem must be set") + return + } + if m.properties.Src == nil { + ctx.PropertyErrorf("src", "src must be set") + } + android.ExtractSourceDeps(ctx, m.properties.Src) +} + +func (m *bionicMountpoint) GenerateAndroidBuildActions(ctx android.ModuleContext) { + if Bool(m.properties.Library) { + m.pathInPartition = "lib" + if m.Arch().ArchType.Multilib == "lib64" { + m.pathInPartition = "lib64" + } + } else if Bool(m.properties.Binary) { + m.pathInPartition = "bin" + } + + m.stem = String(m.properties.Stem) + String(m.properties.Suffix) + + m.outputFile = ctx.ExpandSource(String(m.properties.Src), "src") +} + +func (m *bionicMountpoint) AndroidMk() android.AndroidMkData { + return android.AndroidMkData { + Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) { + if !m.Arch().Native { + return + } + fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)") + fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir) + fmt.Fprintln(w, "LOCAL_MODULE :=", name) + fmt.Fprintln(w, "LOCAL_USE_CLANG_LLD := false") + fmt.Fprintln(w, "LOCAL_STRIP_MODULE := false") + if Bool(m.properties.Library) { + fmt.Fprintln(w, "LOCAL_MODULE_CLASS := SHARED_LIBRARIES") + } else if Bool(m.properties.Binary) { + fmt.Fprintln(w, "LOCAL_MODULE_CLASS := EXECUTABLES") + } + fmt.Fprintln(w, "LOCAL_MODULE_TAGS := optional") + fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", m.outputFile.String()) + fmt.Fprintln(w, "LOCAL_MODULE_TARGET_ARCH :=", m.Arch().ArchType.String()) + fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", "$(TARGET_ROOT_OUT)/bionic/" + m.pathInPartition) + fmt.Fprintln(w, "LOCAL_INSTALLED_MODULE_STEM :=", m.stem) + + if len(m.properties.Symlinks) > 0 { + symlink_dir_in_system := "$(TARGET_OUT)/" + m.pathInPartition + "/" + symlink_dir_in_recovery := "$(TARGET_RECOVERY_ROOT_OUT)/system/" + m.pathInPartition + "/" + symlink_target := "/bionic/" + m.pathInPartition + "/" + m.stem + cmds := []string{} + cmds = append(cmds, "$(hide) mkdir -p " + symlink_dir_in_system) + cmds = append(cmds, "mkdir -p " + symlink_dir_in_recovery) + for _, s := range m.properties.Symlinks { + symlink := s + String(m.properties.Suffix) + cmds = append(cmds, "ln -sf " + symlink_target + " " + symlink_dir_in_system + symlink) + cmds = append(cmds, "ln -sf " + symlink_target + " " + symlink_dir_in_recovery + symlink) + } + fmt.Fprintln(w, "LOCAL_POST_INSTALL_CMD := " + strings.Join(cmds, " && ")) + } + fmt.Fprintln(w, "include $(BUILD_PREBUILT)") + }, + } +} + +func bionicMountpointFactory() android.Module { + m := &bionicMountpoint{} + m.AddProperties(&m.properties) + android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibBoth) + return m +} + +var Bool = proptools.Bool +var String = proptools.String diff --git a/dummy_mountpoint b/dummy_mountpoint new file mode 100644 index 000000000..2d13c5523 --- /dev/null +++ b/dummy_mountpoint @@ -0,0 +1 @@ +This file serves as a mount point for bionic files either from /system partition or from /apex/com.android.runtime. This file is never meant to be accessed directly. diff --git a/libc/Android.bp b/libc/Android.bp index 226a81f0e..4cf31bc58 100644 --- a/libc/Android.bp +++ b/libc/Android.bp @@ -1548,7 +1548,7 @@ cc_library { ], }, - required: ["tzdata"], + required: ["tzdata", "libc.mountpoint"], // Leave the symbols in the shared library so that stack unwinders can produce // meaningful name resolution. diff --git a/libdl/Android.bp b/libdl/Android.bp index 262da6c7d..c17e72e27 100644 --- a/libdl/Android.bp +++ b/libdl/Android.bp @@ -105,6 +105,7 @@ cc_library { symbol_file: "libdl.map.txt", versions: ["10000"], }, + required: ["libdl.mountpoint"], } ndk_library { diff --git a/libm/Android.bp b/libm/Android.bp index 28cf1fd1f..079220bd7 100644 --- a/libm/Android.bp +++ b/libm/Android.bp @@ -515,6 +515,7 @@ cc_library { symbol_file: "libm.map.txt", versions: ["10000"], }, + required: ["libm.mountpoint"], } ndk_library { diff --git a/linker/Android.bp b/linker/Android.bp index 033860abf..8533c307a 100644 --- a/linker/Android.bp +++ b/linker/Android.bp @@ -301,6 +301,7 @@ cc_binary { }, compile_multilib: "both", xom: false, + required: ["linker.mountpoint"], } cc_library { From fbc4c8edd6aa528336ceb64938c2f1c8e7dfe2e0 Mon Sep 17 00:00:00 2001 From: Jiyong Park Date: Wed, 23 Jan 2019 15:51:25 +0900 Subject: [PATCH 2/2] Move the dynamic linker to ./bootstrap subdir The dynamic linker installed to /system partition is only for bootstraping, i.e. to be used only by early processes. The existing path /system/bin/linker[64] will be a symlink to the mount pointpoint /bionic/bin/linker[64] which will be bind-mounted with either the bootstrap linker or the default linker in the runtime APEX. Since the path is taken by the symlink, bootstrap linker is moved to ./boostrap subdirectory. Bug: 120266448 Test: m linker; the linker is found under /system/bin/bootstrap/ Change-Id: I163e0c8a1738b94565a6b60f48e65841ba058a91 --- linker/Android.bp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/linker/Android.bp b/linker/Android.bp index 8533c307a..fed921d38 100644 --- a/linker/Android.bp +++ b/linker/Android.bp @@ -283,6 +283,8 @@ cc_binary { name: "linker", symlinks: ["linker_asan"], + // The linker in the system partition is now only for bootstrapping + relative_install_path: "bootstrap", recovery_available: true, multilib: { lib32: {