Forráskód Böngészése

Add elf alignment check for Android artifacts (#13818)

Matthew Zavislak 2 hete
szülő
commit
4f11feb708

+ 4 - 0
.github/workflows/create-test-plan.py

@@ -561,6 +561,10 @@ def spec_to_job(spec: JobSpec, key: str, trackmem_symbol_names: bool) -> JobDeta
                     "testmultiaudio-apk",
                     "testsprite-apk",
                 ]
+
+                # -fPIC is required after updating NDK from 21 to 28
+                job.cflags.append("-fPIC")
+                job.cxxflags.append("-fPIC")
         case SdlPlatform.Emscripten:
             job.clang_tidy = False  # clang-tidy does not understand -gsource-map
             job.shared = False

+ 10 - 2
.github/workflows/generic.yml

@@ -76,7 +76,7 @@ jobs:
         id: setup-ndk
         with:
           local-cache: true
-          ndk-version: r21e
+          ndk-version: r28c
       - name: 'Configure Android NDK variables'
         if: ${{ matrix.platform.android-ndk }}
         shell: sh
@@ -411,6 +411,14 @@ jobs:
           build-scripts/test-versioning.sh
           python build-scripts/check_android_jni.py
           python build-scripts/check_stdlib_usage.py
+      - name: 'Verify alignment of Android test apks'
+        if: ${{ matrix.platform.android-ndk && !matrix.platform.no-cmake }}
+        run: |
+          find ./ -iname '*.apk' | xargs -L1 ./build-scripts/check_elf_alignment.sh
+      - name: 'Verify alignment of Android .so files'
+        if: ${{ matrix.platform.android-ndk && !matrix.platform.no-cmake }}
+        run: |
+          find ./ -iname '*.so' | xargs -L1 ./build-scripts/check_elf_alignment.sh
       - name: 'Upload binary package'
         uses: actions/upload-artifact@v4
         if: ${{ always() && matrix.platform.artifact != '' && (steps.package.outcome == 'success' || steps.cpactions.outcome == 'success') && (matrix.platform.enable-artifacts || steps.tests.outcome == 'failure') }}
@@ -433,4 +441,4 @@ jobs:
         with:
           if-no-files-found: error
           name: '${{ matrix.platform.artifact }}-apks'
-          path: build/test/*.apk
+          path: build/test/*.apk

+ 127 - 0
build-scripts/check_elf_alignment.sh

@@ -0,0 +1,127 @@
+#!/bin/bash
+progname="${0##*/}"
+progname="${progname%.sh}"
+
+# usage: check_elf_alignment.sh [path to *.so files|path to *.apk]
+
+cleanup_trap() {
+  if [ -n "${tmp}" -a -d "${tmp}" ]; then
+    rm -rf ${tmp}
+  fi
+  exit $1
+}
+
+usage() {
+  echo "Host side script to check the ELF alignment of shared libraries."
+  echo "Shared libraries are reported ALIGNED when their ELF regions are"
+  echo "16 KB or 64 KB aligned. Otherwise they are reported as UNALIGNED."
+  echo
+  echo "Usage: ${progname} [input-path|input-APK|input-APEX]"
+}
+
+if [ ${#} -ne 1 ]; then
+  usage
+  exit
+fi
+
+case ${1} in
+  --help | -h | -\?)
+    usage
+    exit
+    ;;
+
+  *)
+    dir="${1}"
+    ;;
+esac
+
+if ! [ -f "${dir}" -o -d "${dir}" ]; then
+  echo "Invalid file: ${dir}" >&2
+  exit 1
+fi
+
+if [[ "${dir}" == *.apk ]]; then
+  trap 'cleanup_trap' EXIT
+
+  echo
+  echo "Recursively analyzing $dir"
+  echo
+
+  if { zipalign --help 2>&1 | grep -q "\-P <pagesize_kb>"; }; then
+    echo "=== APK zip-alignment ==="
+    zipalign -v -c -P 16 4 "${dir}" | egrep 'lib/arm64-v8a|lib/x86_64|Verification'
+    echo "========================="
+  else
+    echo "NOTICE: Zip alignment check requires build-tools version 35.0.0-rc3 or higher."
+    echo "  You can install the latest build-tools by running the below command"
+    echo "  and updating your \$PATH:"
+    echo
+    echo "    sdkmanager \"build-tools;35.0.0-rc3\""
+  fi
+
+  dir_filename=$(basename "${dir}")
+  tmp=$(mktemp -d -t "${dir_filename%.apk}_out_XXXXX")
+  unzip "${dir}" lib/* -d "${tmp}" >/dev/null 2>&1
+  dir="${tmp}"
+fi
+
+if [[ "${dir}" == *.apex ]]; then
+  trap 'cleanup_trap' EXIT
+
+  echo
+  echo "Recursively analyzing $dir"
+  echo
+
+  dir_filename=$(basename "${dir}")
+  tmp=$(mktemp -d -t "${dir_filename%.apex}_out_XXXXX")
+  deapexer extract "${dir}" "${tmp}" || { echo "Failed to deapex." && exit 1; }
+  dir="${tmp}"
+fi
+
+RED="\e[31m"
+GREEN="\e[32m"
+ENDCOLOR="\e[0m"
+
+unaligned_libs=()
+unaligned_critical_libs=()
+
+echo
+echo "=== ELF alignment ==="
+
+matches="$(find "${dir}" -type f)"
+IFS=$'\n'
+for match in $matches; do
+  # We could recursively call this script or rewrite it to though.
+  [[ "${match}" == *".apk" ]] && echo "WARNING: doesn't recursively inspect .apk file: ${match}"
+  [[ "${match}" == *".apex" ]] && echo "WARNING: doesn't recursively inspect .apex file: ${match}"
+
+  [[ $(file "${match}") == *"ELF"* ]] || continue
+
+  res="$(objdump -p "${match}" | grep LOAD | awk '{ print $NF }' | head -1)"
+  if [[ $res =~ 2\*\*(1[4-9]|[2-9][0-9]|[1-9][0-9]{2,}) ]]; then
+    echo -e "${match}: ${GREEN}ALIGNED${ENDCOLOR} ($res)"
+  else
+    unaligned_libs+=("${match}")
+    # Check if this is a critical architecture (arm64-v8a or x86_64)
+    if [[ "${match}" == *"arm64-v8a"* ]] || [[ "${match}" == *"x86_64"* ]]; then
+      unaligned_critical_libs+=("${match}")
+      echo -e "${match}: ${RED}UNALIGNED${ENDCOLOR} ($res)"
+    else
+      echo -e "${match}: UNALIGNED ($res)"
+    fi
+  fi
+done
+
+if [ ${#unaligned_libs[@]} -gt 0 ]; then
+  echo -e "Found ${#unaligned_libs[@]} unaligned libs (only arm64-v8a/x86_64 libs need to be aligned).${ENDCOLOR}"
+fi
+echo "====================="
+
+# Exit with appropriate code: 1 if critical unaligned libs found, 0 otherwise
+if [ ${#unaligned_critical_libs[@]} -gt 0 ]; then
+  echo -e "${RED}Found ${#unaligned_critical_libs[@]} critical unaligned libs.${ENDCOLOR}"
+  exit 1
+else
+  echo -e "${GREEN}ELF Verification Successful${ENDCOLOR}"
+  exit 0
+fi

+ 0 - 21
build-scripts/strip_fPIC.sh

@@ -1,21 +0,0 @@
-#!/bin/sh
-#
-# libtool assumes that the compiler can handle the -fPIC flag
-# This isn't always true (for example, nasm can't handle it)
-command=""
-while [ $# -gt 0 ]; do
-    case "$1" in
-        -?PIC)
-            # Ignore -fPIC and -DPIC options
-            ;;
-        -fno-common)
-            # Ignore -fPIC and -DPIC options
-            ;;
-        *)
-            command="$command $1"
-            ;;
-    esac
-    shift
-done
-echo $command
-exec $command