119 lines
3.6 KiB
Bash
Executable File
119 lines
3.6 KiB
Bash
Executable File
#!/bin/bash
|
|
#
|
|
# Copyright (C) 2021 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.
|
|
|
|
### Usage: shares_common_elfs.sh [-m] [-a] <path/to/dump/directory/or/elf>
|
|
###
|
|
### This script is used to eliminate copies of the same ELF file(s) across
|
|
### subdirectories of 'offline_files/' by placing common ELF(s) in
|
|
### 'offline_files/common'. The build id is appended to each ELF name to allow
|
|
### for different versions of the same shared library. Unless -a is used, the
|
|
### path must be a valid ELF file.
|
|
###
|
|
### Options:
|
|
### -m
|
|
### If the ELF(s) does not currently reside in the 'common' directory, move
|
|
### the elf to 'common' and rename it.
|
|
### -a
|
|
### Eliminate copies for all ELFs in a directory. The path specified point
|
|
### to a directory and NOT an individual ELF file.
|
|
|
|
usage() {
|
|
grep '^###' $0 | sed -e 's/^###//'
|
|
exit 1
|
|
}
|
|
|
|
update_elf() {
|
|
local elf_path="$1"
|
|
local move_if_not_in_common="$2"
|
|
|
|
local basename=$(basename "$elf_path")
|
|
local maps_path=$(dirname "$elf_path")"/maps.txt"
|
|
local build_id=$(readelf -n "$elf_path" | grep -oP 'Build ID: \K([\w\d]+)')
|
|
local new_elf_name="${basename}_${build_id}"
|
|
local common_dir="${ANDROID_BUILD_TOP}/system/unwinding/libunwindstack/offline_files/common/"
|
|
|
|
if [[ -f "${common_dir}${new_elf_name}" ]]; then
|
|
# If the ELF is already found in the common directory, delete the local copy.
|
|
git rm "$elf_path"
|
|
elif [[ $move_if_not_in_common == true ]]; then
|
|
# If the ELF is not found in the common directory and the `move_if_not_common`
|
|
# flag was set, move the local ELF to the common directory.
|
|
git mv "$elf_path" "${common_dir}${new_elf_name}"
|
|
else
|
|
# The ELF was not found in the common directory so exit this function.
|
|
return 0
|
|
fi
|
|
|
|
# Replace the name of the elf we just deleted/moved to the relative
|
|
# path to that ELF in the common directory.
|
|
local elf_dir_path=$(dirname "$elf_path")
|
|
local rel_path_to_common=$(realpath --relative-to="$elf_dir_path" "$common_dir")
|
|
sed -i -e "s/${basename}/${rel_path_to_common}\/${new_elf_name}/g" "$maps_path"
|
|
}
|
|
|
|
is_an_elf() {
|
|
if [[ $(head -c 4 $1 | cut -c2-) == "ELF" ]]; then
|
|
echo true
|
|
else
|
|
echo false
|
|
fi
|
|
}
|
|
|
|
main () {
|
|
set -e # abort the script if some error occurs.
|
|
local move_if_not_in_common=false
|
|
local update_all_elfs=false
|
|
while getopts ":hma" arg; do
|
|
case $arg in
|
|
m)
|
|
move_if_not_in_common=true
|
|
;;
|
|
a)
|
|
update_all_elfs=true
|
|
;;
|
|
h | *)
|
|
usage
|
|
;;
|
|
esac
|
|
done
|
|
path=${@:$OPTIND:1}
|
|
if [[ -z $path ]]; then
|
|
usage
|
|
fi
|
|
|
|
if [[ $update_all_elfs == true ]]; then
|
|
if [[ ! -d $path || "${path: -1}" != "/" ]]; then
|
|
echo "$path is not a valid path to a directory." >&2
|
|
usage
|
|
fi
|
|
for elf_path in "${path}"*; do
|
|
if [[ $(is_an_elf $elf_path) == true ]]; then
|
|
update_elf $elf_path $move_if_not_in_common
|
|
fi
|
|
done
|
|
else
|
|
if [[ ! -f $path ]]; then
|
|
echo "$path is not a valid path to a file." >&2
|
|
usage
|
|
elif [[ $(is_an_elf $path) == false ]]; then
|
|
echo "$path is not a valid ELF file." >&2
|
|
else
|
|
update_elf $path $move_if_not_in_common
|
|
fi
|
|
fi
|
|
}
|
|
|
|
main "$@" |