diff --git a/.cirrus.yml b/.cirrus.yml index 4fddac539..3a7f635d9 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -5,18 +5,16 @@ task: install_script: | pkg install -y \ git \ - meson \ - ninja \ - npm \ - py39-pip - pip install meson==0.64.0 + npm compile_script: | - meson setup \ - --default-library static \ - -Doptimization=s \ - -Dgumpp=enabled \ - -Dgumjs=enabled \ - -Db_lundef=false \ - build - meson compile -C build - test_script: ./build/tests/gum-tests + ./configure \ + --enable-gumpp \ + --enable-gumjs \ + --with-devkits=gum,gumjs \ + --enable-tests + make + gum_devkit_artifacts: + path: "build/gum/devkit/*" + gumjs_devkit_artifacts: + path: "build/bindings/gumjs/devkit/*" + test_script: make test diff --git a/.github/env/bootstrap.sh b/.github/env/bootstrap.sh deleted file mode 100755 index fe3056cc8..000000000 --- a/.github/env/bootstrap.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/sh - -build_os_arch=$1 -host_os_arch=$2 - -build_arch=$(echo $build_os_arch | cut -d"-" -f2) -host_arch=$(echo $host_os_arch | cut -d"-" -f2) - -envdir=`dirname $0` -outdir=/tmp - -set -ex - -mkdir -p $outdir/toolchain $outdir/native-sdk $outdir/cross-sdk -deps_url=https://build.frida.re/deps/20240118 -curl $deps_url/toolchain-$build_os_arch.tar.bz2 | tar -C $outdir/toolchain -xjf - -curl $deps_url/sdk-$build_os_arch.tar.bz2 | tar -C $outdir/native-sdk -xjf - -curl $deps_url/sdk-$host_os_arch.tar.bz2 | tar -C $outdir/cross-sdk -xjf - - -for machine in native cross; do - ( - echo "#!/bin/sh" - echo "export PKG_CONFIG_PATH=$outdir/$machine-sdk/lib/pkgconfig" - echo "exec $outdir/toolchain/bin/pkg-config --define-variable=frida_sdk_prefix=$outdir/$machine-sdk --static \"\$@\"" - ) > $outdir/$machine-pkg-config - chmod +x $outdir/$machine-pkg-config -done - -case ${build_arch}__${host_arch} in - x86_64__x86) - needs_exe_wrapper=false - ;; - *) - needs_exe_wrapper=true - ;; -esac - -$envdir/emit-$build_os_arch.sh $outdir/native-pkg-config false > $outdir/native.txt -$envdir/emit-$host_os_arch.sh $outdir/cross-pkg-config $needs_exe_wrapper > $outdir/cross.txt diff --git a/.github/env/emit-android-arm.sh b/.github/env/emit-android-arm.sh deleted file mode 100755 index bd237b6ac..000000000 --- a/.github/env/emit-android-arm.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/sh - -pkgconfig=$1 -needs_exe_wrapper=$2 - -bindir=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/$(uname -s | tr '[A-Z]' '[a-z]')-$(uname -m)/bin - -cat << EOF -[constants] -c_like_flags = ['-DANDROID', '-march=armv7-a', '-mfloat-abi=softfp', '-mfpu=vfpv3-d16', '-mthumb', '-ffunction-sections', '-fdata-sections'] -linker_flags = ['-Wl,--gc-sections', '-Wl,-z,noexecstack', '-Wl,-z,relro', '-Wl,-z,now'] - -[binaries] -c = '$bindir/armv7a-linux-androideabi19-clang' -cpp = '$bindir/armv7a-linux-androideabi19-clang++' -ar = '$bindir/llvm-ar' -nm = '$bindir/llvm-nm' -readelf = '$bindir/llvm-readelf' -strip = '$bindir/llvm-strip' -pkgconfig = '$pkgconfig' - -[built-in options] -c_args = c_like_flags -cpp_args = c_like_flags -c_link_args = linker_flags -cpp_link_args = linker_flags + ['-static-libstdc++'] - -[host_machine] -system = 'linux' -cpu_family = 'arm' -cpu = 'armv7eabi' -endian = 'little' - -[properties] -needs_exe_wrapper = $needs_exe_wrapper -EOF diff --git a/.github/env/emit-android-arm64.sh b/.github/env/emit-android-arm64.sh deleted file mode 100755 index 0bfd5f3f4..000000000 --- a/.github/env/emit-android-arm64.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/sh - -pkgconfig=$1 -needs_exe_wrapper=$2 - -bindir=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/$(uname -s | tr '[A-Z]' '[a-z]')-$(uname -m)/bin - -cat << EOF -[constants] -c_like_flags = ['-DANDROID', '-ffunction-sections', '-fdata-sections'] -linker_flags = ['-Wl,--gc-sections', '-Wl,-z,noexecstack', '-Wl,-z,relro', '-Wl,-z,now'] - -[binaries] -c = '$bindir/aarch64-linux-android21-clang' -cpp = '$bindir/aarch64-linux-android21-clang++' -ar = '$bindir/llvm-ar' -nm = '$bindir/llvm-nm' -readelf = '$bindir/llvm-readelf' -strip = '$bindir/llvm-strip' -pkgconfig = '$pkgconfig' - -[built-in options] -c_args = c_like_flags -cpp_args = c_like_flags -c_link_args = linker_flags -cpp_link_args = linker_flags + ['-static-libstdc++'] - -[host_machine] -system = 'linux' -cpu_family = 'aarch64' -cpu = 'aarch64' -endian = 'little' - -[properties] -needs_exe_wrapper = $needs_exe_wrapper -EOF diff --git a/.github/env/emit-android-x86.sh b/.github/env/emit-android-x86.sh deleted file mode 100755 index 6f380e326..000000000 --- a/.github/env/emit-android-x86.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/sh - -pkgconfig=$1 -needs_exe_wrapper=$2 - -bindir=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/$(uname -s | tr '[A-Z]' '[a-z]')-$(uname -m)/bin - -cat << EOF -[constants] -c_like_flags = ['-DANDROID', '-march=pentium4', '-mfpmath=sse', '-mstackrealign', '-ffunction-sections', '-fdata-sections'] -linker_flags = ['-Wl,--gc-sections', '-Wl,-z,noexecstack', '-Wl,-z,relro', '-Wl,-z,now'] - -[binaries] -c = '$bindir/i686-linux-android19-clang' -cpp = '$bindir/i686-linux-android19-clang++' -ar = '$bindir/llvm-ar' -nm = '$bindir/llvm-nm' -readelf = '$bindir/llvm-readelf' -strip = '$bindir/llvm-strip' -pkgconfig = '$pkgconfig' - -[built-in options] -c_args = c_like_flags -cpp_args = c_like_flags -c_link_args = linker_flags -cpp_link_args = linker_flags + ['-static-libstdc++'] - -[host_machine] -system = 'android' -cpu_family = 'x86' -cpu = 'i686' -endian = 'little' - -[properties] -needs_exe_wrapper = $needs_exe_wrapper -EOF diff --git a/.github/env/emit-android-x86_64.sh b/.github/env/emit-android-x86_64.sh deleted file mode 100755 index d7fb58c3a..000000000 --- a/.github/env/emit-android-x86_64.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/sh - -pkgconfig=$1 -needs_exe_wrapper=$2 - -bindir=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/$(uname -s | tr '[A-Z]' '[a-z]')-$(uname -m)/bin - -cat << EOF -[constants] -c_like_flags = ['-DANDROID', '-ffunction-sections', '-fdata-sections'] -linker_flags = ['-Wl,--gc-sections', '-Wl,-z,noexecstack', '-Wl,-z,relro', '-Wl,-z,now'] - -[binaries] -c = '$bindir/x86_64-linux-android21-clang' -cpp = '$bindir/x86_64-linux-android21-clang++' -ar = '$bindir/llvm-ar' -nm = '$bindir/llvm-nm' -readelf = '$bindir/llvm-readelf' -strip = '$bindir/llvm-strip' -pkgconfig = '$pkgconfig' - -[built-in options] -c_args = c_like_flags -cpp_args = c_like_flags -c_link_args = linker_flags -cpp_link_args = linker_flags + ['-static-libstdc++'] - -[host_machine] -system = 'android' -cpu_family = 'x86_64' -cpu = 'x86_64' -endian = 'little' - -[properties] -needs_exe_wrapper = $needs_exe_wrapper -EOF diff --git a/.github/env/emit-ios-arm64.sh b/.github/env/emit-ios-arm64.sh deleted file mode 100755 index a391dd94c..000000000 --- a/.github/env/emit-ios-arm64.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/sh - -pkgconfig=$1 -needs_exe_wrapper=$2 - -sdk=iphoneos - -cat << EOF -[constants] -common_flags = ['-target', 'arm64-apple-ios8.0', '-isysroot', '$(xcrun --sdk $sdk --show-sdk-path)'] -linker_flags = ['-Wl,-dead_strip'] - -[binaries] -c = ['$(xcrun --sdk $sdk -f clang)'] + common_flags -cpp = ['$(xcrun --sdk $sdk -f clang++)'] + common_flags -objc = ['$(xcrun --sdk $sdk -f clang)'] + common_flags -objcpp = ['$(xcrun --sdk $sdk -f clang++)'] + common_flags -ar = '$(xcrun --sdk $sdk -f ar)' -nm = '$(xcrun --sdk $sdk -f nm)' -strip = '$(xcrun --sdk $sdk -f strip)' -pkgconfig = '$pkgconfig' - -[built-in options] -c_link_args = linker_flags -cpp_link_args = linker_flags - -[host_machine] -system = 'darwin' -cpu_family = 'aarch64' -cpu = 'aarch64' -endian = 'little' - -[properties] -needs_exe_wrapper = $needs_exe_wrapper -EOF diff --git a/.github/env/emit-linux-mips.sh b/.github/env/emit-linux-mips.sh deleted file mode 100755 index a1ad4b0b7..000000000 --- a/.github/env/emit-linux-mips.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/sh - -pkgconfig=$1 -needs_exe_wrapper=$2 - -toolpfx=mips-linux-gnu- - -cat << EOF -[constants] -base_flags = ['-march=mips1', '-mfp32'] -c_like_flags = ['-ffunction-sections', '-fdata-sections'] -linker_flags = ['-static-libgcc', '-Wl,--gc-sections', '-Wl,-z,noexecstack'] - -[binaries] -c = '${toolpfx}gcc' -cpp = '${toolpfx}g++' -ar = '${toolpfx}ar' -nm = '${toolpfx}nm' -readelf = '${toolpfx}readelf' -strip = '${toolpfx}strip' -pkgconfig = '$pkgconfig' - -[built-in options] -c_args = base_flags + c_like_flags -cpp_args = base_flags + c_like_flags -c_link_args = base_flags + linker_flags -cpp_link_args = base_flags + linker_flags + ['-static-libstdc++'] - -[host_machine] -system = 'linux' -cpu_family = 'mips' -cpu = 'mips1' -endian = 'big' - -[properties] -needs_exe_wrapper = $needs_exe_wrapper -EOF diff --git a/.github/env/emit-linux-mips64.sh b/.github/env/emit-linux-mips64.sh deleted file mode 100755 index c85ad289e..000000000 --- a/.github/env/emit-linux-mips64.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/sh - -pkgconfig=$1 -needs_exe_wrapper=$2 - -toolpfx=mips64-linux-gnuabi64- - -cat << EOF -[constants] -base_flags = ['-march=mips64r2', '-mabi=64'] -c_like_flags = ['-ffunction-sections', '-fdata-sections'] -linker_flags = ['-static-libgcc', '-Wl,--gc-sections', '-Wl,-z,noexecstack'] - -[binaries] -c = '${toolpfx}gcc' -cpp = '${toolpfx}g++' -ar = '${toolpfx}ar' -nm = '${toolpfx}nm' -readelf = '${toolpfx}readelf' -strip = '${toolpfx}strip' -pkgconfig = '$pkgconfig' - -[built-in options] -c_args = base_flags + c_like_flags -cpp_args = base_flags + c_like_flags -c_link_args = base_flags + linker_flags -cpp_link_args = base_flags + linker_flags + ['-static-libstdc++'] - -[host_machine] -system = 'linux' -cpu_family = 'mips64' -cpu = 'mips64r2' -endian = 'big' - -[properties] -needs_exe_wrapper = $needs_exe_wrapper -EOF diff --git a/.github/env/emit-linux-mips64el.sh b/.github/env/emit-linux-mips64el.sh deleted file mode 100755 index 2bfde8850..000000000 --- a/.github/env/emit-linux-mips64el.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/sh - -pkgconfig=$1 -needs_exe_wrapper=$2 - -toolpfx=mips64el-linux-gnuabi64- - -cat << EOF -[constants] -base_flags = ['-march=mips64r2', '-mabi=64'] -c_like_flags = ['-ffunction-sections', '-fdata-sections'] -linker_flags = ['-static-libgcc', '-Wl,--gc-sections', '-Wl,-z,noexecstack'] - -[binaries] -c = '${toolpfx}gcc' -cpp = '${toolpfx}g++' -ar = '${toolpfx}ar' -nm = '${toolpfx}nm' -readelf = '${toolpfx}readelf' -strip = '${toolpfx}strip' -pkgconfig = '$pkgconfig' - -[built-in options] -c_args = base_flags + c_like_flags -cpp_args = base_flags + c_like_flags -c_link_args = base_flags + linker_flags -cpp_link_args = base_flags + linker_flags + ['-static-libstdc++'] - -[host_machine] -system = 'linux' -cpu_family = 'mips64' -cpu = 'mips64r2' -endian = 'little' - -[properties] -needs_exe_wrapper = $needs_exe_wrapper -EOF diff --git a/.github/env/emit-linux-mipsel.sh b/.github/env/emit-linux-mipsel.sh deleted file mode 100755 index d4950ef3e..000000000 --- a/.github/env/emit-linux-mipsel.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/sh - -pkgconfig=$1 -needs_exe_wrapper=$2 - -toolpfx=mipsel-linux-gnu- - -cat << EOF -[constants] -base_flags = ['-march=mips1', '-mfp32'] -c_like_flags = ['-ffunction-sections', '-fdata-sections'] -linker_flags = ['-static-libgcc', '-Wl,--gc-sections', '-Wl,-z,noexecstack'] - -[binaries] -c = '${toolpfx}gcc' -cpp = '${toolpfx}g++' -ar = '${toolpfx}ar' -nm = '${toolpfx}nm' -readelf = '${toolpfx}readelf' -strip = '${toolpfx}strip' -pkgconfig = '$pkgconfig' - -[built-in options] -c_args = base_flags + c_like_flags -cpp_args = base_flags + c_like_flags -c_link_args = base_flags + linker_flags -cpp_link_args = base_flags + linker_flags + ['-static-libstdc++'] - -[host_machine] -system = 'linux' -cpu_family = 'mips' -cpu = 'mips1' -endian = 'little' - -[properties] -needs_exe_wrapper = $needs_exe_wrapper -EOF diff --git a/.github/env/emit-linux-x86.sh b/.github/env/emit-linux-x86.sh deleted file mode 100755 index 0e2f3bf1b..000000000 --- a/.github/env/emit-linux-x86.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/sh - -pkgconfig=$1 -needs_exe_wrapper=$2 - -cat << EOF -[constants] -c_like_flags = ['-ffunction-sections', '-fdata-sections'] -linker_flags = ['-Wl,--gc-sections', '-Wl,-z,noexecstack', '-Wl,-z,relro', '-Wl,-z,now'] - -[binaries] -c = ['gcc', '-m32'] -cpp = ['g++', '-m32'] -ar = 'ar' -nm = 'nm' -readelf = 'readelf' -strip = 'strip' -pkgconfig = '$pkgconfig' - -[built-in options] -c_args = c_like_flags -cpp_args = c_like_flags -c_link_args = linker_flags -cpp_link_args = linker_flags - -[host_machine] -system = 'linux' -cpu_family = 'x86' -cpu = 'i686' -endian = 'little' - -[properties] -needs_exe_wrapper = $needs_exe_wrapper -EOF diff --git a/.github/env/emit-linux-x86_64.sh b/.github/env/emit-linux-x86_64.sh deleted file mode 100755 index b28c9bb0f..000000000 --- a/.github/env/emit-linux-x86_64.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/sh - -pkgconfig=$1 -needs_exe_wrapper=$2 - -cat << EOF -[constants] -c_like_flags = ['-ffunction-sections', '-fdata-sections'] -linker_flags = ['-Wl,--gc-sections', '-Wl,-z,noexecstack', '-Wl,-z,relro', '-Wl,-z,now'] - -[binaries] -c = 'gcc' -cpp = 'g++' -ar = 'ar' -nm = 'nm' -readelf = 'readelf' -strip = 'strip' -pkgconfig = '$pkgconfig' - -[built-in options] -c_args = c_like_flags -cpp_args = c_like_flags -c_link_args = linker_flags -cpp_link_args = linker_flags - -[host_machine] -system = 'linux' -cpu_family = 'x86_64' -cpu = 'x86_64' -endian = 'little' - -[properties] -needs_exe_wrapper = $needs_exe_wrapper -EOF diff --git a/.github/env/emit-macos-x86_64.sh b/.github/env/emit-macos-x86_64.sh deleted file mode 100755 index 4fff84c86..000000000 --- a/.github/env/emit-macos-x86_64.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/sh - -pkgconfig=$1 -needs_exe_wrapper=$2 - -sdk=macosx - -cat << EOF -[constants] -common_flags = ['-target', 'x86_64-apple-macos10.9', '-isysroot', '$(xcrun --sdk $sdk --show-sdk-path)'] -linker_flags = ['-Wl,-dead_strip'] - -[binaries] -c = ['$(xcrun --sdk $sdk -f clang)'] + common_flags -cpp = ['$(xcrun --sdk $sdk -f clang++)'] + common_flags -objc = ['$(xcrun --sdk $sdk -f clang)'] + common_flags -objcpp = ['$(xcrun --sdk $sdk -f clang++)'] + common_flags -ar = '$(xcrun --sdk $sdk -f ar)' -nm = '$(xcrun --sdk $sdk -f nm)' -strip = '$(xcrun --sdk $sdk -f strip)' -pkgconfig = '$pkgconfig' - -[built-in options] -c_link_args = linker_flags -cpp_link_args = linker_flags - -[host_machine] -system = 'darwin' -cpu_family = 'x86_64' -cpu = 'x86_64' -endian = 'little' - -[properties] -needs_exe_wrapper = $needs_exe_wrapper -EOF diff --git a/.github/env/emit-qnx-armeabi.sh b/.github/env/emit-qnx-armeabi.sh deleted file mode 100755 index 203e5144a..000000000 --- a/.github/env/emit-qnx-armeabi.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/sh - -pkgconfig=$1 -needs_exe_wrapper=$2 - -toolpfx=$QNX_HOST/usr/bin/arm-unknown-nto-qnx6.5.0eabi- -sysroot=$QNX_TARGET/armle-v7 - -cat << EOF -[constants] -base_flags = ['--sysroot=$sysroot', '-march=armv7-a'] -c_like_flags = ['-mno-unaligned-access', '-ffunction-sections', '-fdata-sections'] -linker_flags = ['-static-libgcc', '-Wl,--gc-sections'] - -[binaries] -c = '${toolpfx}gcc' -cpp = '${toolpfx}g++' -ar = '${toolpfx}ar' -nm = '${toolpfx}nm' -readelf = '${toolpfx}readelf' -strip = '${toolpfx}strip' -pkgconfig = '$pkgconfig' - -[built-in options] -c_args = base_flags + c_like_flags -cpp_args = base_flags + c_like_flags -c_link_args = base_flags + linker_flags -cpp_link_args = base_flags + linker_flags + ['-static-libstdc++'] - -[host_machine] -system = 'qnx' -cpu_family = 'arm' -cpu = 'armv7' -endian = 'little' - -[properties] -needs_exe_wrapper = $needs_exe_wrapper -EOF diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 085c836dd..37e8503d3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,249 +9,163 @@ on: - main env: - PYTHON_VERSION: 3.11 - MESON_VERSION: 0.64.0 + GUM_OPTIONS: '--enable-gumpp --enable-gumjs --with-devkits=gum,gumjs --enable-tests' jobs: gir: - runs-on: ubuntu-22.04 + runs-on: ubuntu-latest steps: - name: Check out repo - uses: actions/checkout@v3 - - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/checkout@v4 with: - python-version: '${{ env.PYTHON_VERSION }}' + submodules: recursive - name: Install dependencies run: | - sudo apt-get update sudo apt-get install \ - gobject-introspection \ - libdwarf-dev \ - libelf-dev \ - libgirepository1.0-dev \ - libglib2.0-dev \ - libjson-glib-dev \ - libsoup-3.0-dev \ - libsqlite3-dev \ - libunwind-dev \ - ninja-build - pip install meson==${{ env.MESON_VERSION }} + gobject-introspection \ + libdwarf-dev \ + libelf-dev \ + libgirepository1.0-dev \ + libglib2.0-dev \ + libjson-glib-dev \ + libsoup-3.0-dev \ + libsqlite3-dev \ + libunwind-dev \ + ninja-build - name: Build run: | - meson setup \ - -Doptimization=s \ - -Dgumpp=enabled \ - -Dgumjs=enabled \ - build - meson compile -C build + ./configure \ + --enable-shared \ + --without-prebuilds=toolchain,sdk \ + ${{ env.GUM_OPTIONS }} + make + - name: Upload GObject introspection data + uses: actions/upload-artifact@v4 + with: + name: gum-gir + path: | + build/gum/Gum-1.0.gir + build/gum/Gum-1.0.typelib - windows: - runs-on: windows-latest + native: strategy: matrix: - arch: [amd64_x86, amd64] + include: + - { id: windows-x86_64, runner: '"windows-latest"' } + - { id: windows-x86, runner: '"windows-latest"' } + - { id: macos-x86_64, runner: '"macos-latest"' } + - { id: macos-arm64, runner: '"macos-14"' } + - { id: linux-x86_64, runner: '"ubuntu-latest"' } + - { id: linux-x86, runner: '"ubuntu-latest"' } + - { id: freebsd-arm64, runner: '["self-hosted", "freebsd", "arm64"]' } fail-fast: false + runs-on: ${{ fromJSON(matrix.runner) }} steps: - name: Check out repo - uses: actions/checkout@v3 - - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/checkout@v4 with: - python-version: '${{ env.PYTHON_VERSION }}' - - name: Install dependencies - run: pip install meson==${{ env.MESON_VERSION }} ninja - - name: Environment - uses: ilammy/msvc-dev-cmd@v1 - with: - arch: ${{ matrix.arch }} + submodules: recursive + - name: Install gcc-multilib + if: matrix.id == 'linux-x86' + run: sudo apt-get install gcc-multilib lib32stdc++-11-dev - name: Build + if: ${{ startsWith(matrix.id, 'windows-') }} run: | - meson setup ` - --default-library static ` - -Doptimization=s ` - -Dgumpp=enabled ` - -Dgumjs=enabled ` - --force-fallback-for=zlib ` - build - meson compile -C build - - name: Test - run: | - Copy-Item build\bindings\gumpp\frida-gumpp-1.0.dll -Destination build\tests\ - .\build\tests\gum-tests.exe - - macos-x86_64: - runs-on: macos-latest - steps: - - name: Check out repo - uses: actions/checkout@v3 - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: '${{ env.PYTHON_VERSION }}' - - name: Install dependencies - run: pip install meson==${{ env.MESON_VERSION }} ninja + .\configure ${{ env.GUM_OPTIONS }} + .\make - name: Build + if: ${{ !startsWith(matrix.id, 'windows-') && matrix.id != 'linux-x86' }} run: | - meson setup \ - --default-library static \ - -Doptimization=s \ - -Dgumpp=enabled \ - -Dgumjs=enabled \ - --force-fallback-for=glib,capstone \ - build - meson compile -C build - - name: Test - run: ./build/tests/gum-tests - - linux-x86: - runs-on: ubuntu-latest - steps: - - name: Check out repo - uses: actions/checkout@v3 - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: '${{ env.PYTHON_VERSION }}' - - name: Install dependencies - run: | - sudo apt-get update - sudo apt-get install gcc-multilib lib32stdc++-11-dev - pip install meson==${{ env.MESON_VERSION }} - .github/env/bootstrap.sh linux-x86_64 linux-x86 + ./configure ${{ env.GUM_OPTIONS }} + make - name: Build + if: matrix.id == 'linux-x86' run: | - export PATH="/tmp/toolchain/bin:$PATH" - meson setup \ - --native-file /tmp/native.txt \ - --cross-file /tmp/cross.txt \ - --default-library static \ - --force-fallback-for=glib \ - -Doptimization=s \ - -Dwerror=true \ - -Dgumpp=enabled \ - -Dgumjs=enabled \ - build - meson compile -C build - - name: Test - run: ./build/tests/gum-tests - - linux-x86_64: - runs-on: ubuntu-latest - steps: - - name: Check out repo - uses: actions/checkout@v3 - - name: Set up Python - uses: actions/setup-python@v4 + CC="gcc -m32" CXX="g++ -m32" STRIP="strip" \ + ./configure --build=linux-x86 --host=linux-x86 ${{ env.GUM_OPTIONS }} + make + - name: Upload Gum devkit + uses: actions/upload-artifact@v4 with: - python-version: '${{ env.PYTHON_VERSION }}' - - name: Install dependencies - run: pip install meson==${{ env.MESON_VERSION }} ninja - - name: Build - run: | - meson setup \ - --default-library static \ - --force-fallback-for=glib \ - -Doptimization=s \ - -Dgumpp=enabled \ - -Dgumjs=enabled \ - build - meson compile -C build + name: gum-devkit-${{ matrix.id }} + path: build/gum/devkit/ + - name: Upload GumJS devkit + uses: actions/upload-artifact@v4 + with: + name: gumjs-devkit-${{ matrix.id }} + path: build/bindings/gumjs/devkit/ - name: Test - run: ./build/tests/gum-tests + run: make test - linux-mips: - runs-on: ubuntu-latest + cross: strategy: matrix: - arch: - - id: mips - pkg: g++-mips-linux-gnu - - id: mipsel - pkg: g++-mipsel-linux-gnu - - id: mips64 - pkg: g++-mips64-linux-gnuabi64 - - id: mips64el - pkg: g++-mips64el-linux-gnuabi64 + include: + - { id: windows-x86_64-mingw, opts: '--host=x86_64-w64-mingw32 --without-prebuilds=sdk:host', pkg: g++-mingw-w64-x86-64 } + - { id: windows-x86-mingw, opts: '--host=i686-w64-mingw32 --without-prebuilds=sdk:host', pkg: g++-mingw-w64-i686 } + - { id: linux-mips, opts: '--host=mips-linux-gnu', pkg: g++-mips-linux-gnu } + - { id: linux-mipsel, opts: '--host=mipsel-linux-gnu', pkg: g++-mipsel-linux-gnu } + - { id: linux-mips64, opts: '--host=mips64-linux-gnuabi64', pkg: g++-mips64-linux-gnuabi64 } + - { id: linux-mips64el, opts: '--host=mips64el-linux-gnuabi64', pkg: g++-mips64el-linux-gnuabi64 } + fail-fast: false + runs-on: ubuntu-latest steps: - name: Check out repo - uses: actions/checkout@v3 - - name: Install Python - uses: actions/setup-python@v3 + uses: actions/checkout@v4 with: - python-version: '${{ env.PYTHON_VERSION }}' - - name: Install dependencies - run: | - sudo apt-get update - sudo apt-get install ${{ matrix.arch.pkg }} - pip install meson==${{ env.MESON_VERSION }} - .github/env/bootstrap.sh linux-x86_64 linux-${{ matrix.arch.id }} + submodules: recursive + - name: Install toolchain + run: sudo apt-get install ${{ matrix.pkg }} - name: Build run: | - export PATH="/tmp/toolchain/bin:$PATH" - meson setup \ - --native-file /tmp/native.txt \ - --cross-file /tmp/cross.txt \ - --default-library static \ - -Doptimization=s \ - -Dwerror=true \ - -Dgumpp=enabled \ - -Dgumjs=enabled \ - -Dtests=enabled \ - build - meson compile -C build - - freebsd-arm64: - runs-on: [self-hosted, freebsd, arm64] - steps: - - name: Checkout monorepo - uses: actions/checkout@v3 - - name: Install dependencies - run: pip install meson==${{ env.MESON_VERSION }} - - name: Build - run: | - meson setup \ - --default-library static \ - -Doptimization=s \ - -Dgumpp=enabled \ - -Dgumjs=enabled \ - -Db_lundef=false \ - build - meson compile -C build - - name: Test - run: ./build/tests/gum-tests + ./configure ${{ matrix.opts }} ${{ env.GUM_OPTIONS }} + make + - name: Upload Gum devkit + uses: actions/upload-artifact@v4 + with: + name: gum-devkit-${{ matrix.id }} + path: build/gum/devkit/ + - name: Upload GumJS devkit + uses: actions/upload-artifact@v4 + with: + name: gumjs-devkit-${{ matrix.id }} + path: build/bindings/gumjs/devkit/ - ios-arm64: + mobile: + strategy: + matrix: + id: + - ios-arm64 + - android-x86 + - android-x86_64 + - android-arm + - android-arm64 + fail-fast: false runs-on: macos-latest steps: - name: Check out repo - uses: actions/checkout@v3 - - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/checkout@v4 with: - python-version: '${{ env.PYTHON_VERSION }}' - - name: Install dependencies - run: | - pip install meson==${{ env.MESON_VERSION }} - .github/env/bootstrap.sh macos-x86_64 ios-arm64 + submodules: recursive - name: Build run: | - export PATH="/tmp/toolchain/bin:$PATH" - meson setup \ - --native-file /tmp/native.txt \ - --cross-file /tmp/cross.txt \ - --default-library static \ - -Doptimization=s \ - -Dwerror=true \ - -Dgumpp=enabled \ - -Dgumjs=enabled \ - -Dtests=enabled \ - build - meson compile -C build - - name: Package + ./configure --host=${{ matrix.id }} ${{ env.GUM_OPTIONS }} + make + - name: Upload Gum devkit + uses: actions/upload-artifact@v4 + with: + name: gum-devkit-${{ matrix.id }} + path: build/gum/devkit/ + - name: Upload GumJS devkit + uses: actions/upload-artifact@v4 + with: + name: gumjs-devkit-${{ matrix.id }} + path: build/bindings/gumjs/devkit/ + - name: Package tests run: tar -C build/tests -czf /tmp/runner.tar.gz gum-tests data/ - - name: Test - uses: frida/corellium-action@v3 + - name: Test on Corellium iOS device + if: matrix.id == 'ios-arm64' + uses: frida/corellium-action@v4 with: token: ${{ secrets.GITHUB_TOKEN }} gateway: corellium.frida.re @@ -264,109 +178,9 @@ jobs: cd opt/frida tar xf $ASSET_PATH ./gum-tests - - android-intel: - runs-on: ubuntu-latest - strategy: - matrix: - arch: [x86, x86_64] - fail-fast: false - steps: - - name: Enable KVM group perms - run: | - echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules - sudo udevadm control --reload-rules - sudo udevadm trigger --name-match=kvm - - name: Check out repo - uses: actions/checkout@v3 - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: '${{ env.PYTHON_VERSION }}' - - name: Install dependencies - run: | - pip install meson==${{ env.MESON_VERSION }} - .github/env/bootstrap.sh linux-x86_64 android-${{ matrix.arch }} - - name: Build - run: | - export PATH="/tmp/toolchain/bin:$PATH" - meson setup \ - --native-file /tmp/native.txt \ - --cross-file /tmp/cross.txt \ - --default-library static \ - -Doptimization=s \ - -Dwerror=true \ - -Dgumpp=enabled \ - -Dgumjs=enabled \ - -Dtests=enabled \ - build - meson compile -C build - - name: AVD cache - uses: actions/cache@v2 - id: avd-cache - with: - path: | - ~/.android/avd/* - ~/.android/adb* - key: avd-${{ matrix.arch }} - - name: Create AVD and generate snapshot for caching - if: steps.avd-cache.outputs.cache-hit != 'true' - uses: reactivecircus/android-emulator-runner@v2 - with: - arch: ${{ matrix.arch }} - api-level: 27 - force-avd-creation: false - emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none - disable-animations: false - script: echo "Generated AVD snapshot for caching." - - name: Test - uses: reactivecircus/android-emulator-runner@v2 - with: - arch: ${{ matrix.arch }} - api-level: 27 - force-avd-creation: false - emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none - disable-animations: true - script: | - tar -C build/tests -czf /tmp/runner.tar.gz gum-tests data/ - adb push /tmp/runner.tar.gz /data/local/tmp/ - adb shell "su root sh -c 'set -ex; cd /data/local/tmp; tar xf runner.tar.gz; TMPDIR=/data/local/tmp ./gum-tests'" - - android-arm: - runs-on: ubuntu-latest - strategy: - matrix: - arch: [arm, arm64] - fail-fast: false - steps: - - name: Check out repo - uses: actions/checkout@v3 - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: '${{ env.PYTHON_VERSION }}' - - name: Install dependencies - run: | - pip install meson==${{ env.MESON_VERSION }} - .github/env/bootstrap.sh linux-x86_64 android-${{ matrix.arch }} - - name: Build - run: | - export PATH="/tmp/toolchain/bin:$PATH" - meson setup \ - --native-file /tmp/native.txt \ - --cross-file /tmp/cross.txt \ - --default-library static \ - -Doptimization=s \ - -Dwerror=true \ - -Dgumpp=enabled \ - -Dgumjs=enabled \ - -Dtests=enabled \ - build - meson compile -C build - - name: Package - run: tar -C build/tests -czf /tmp/runner.tar.gz gum-tests data/ - - name: Test - uses: frida/corellium-action@v3 + - name: Test on Corellium Android device + if: startsWith(matrix.id, 'android-arm') + uses: frida/corellium-action@v4 with: token: ${{ secrets.GITHUB_TOKEN }} gateway: corellium.frida.re @@ -379,28 +193,27 @@ jobs: qnx-armeabi: runs-on: ubuntu-latest - container: fridadotre/qnx:latest + container: ghcr.io/frida/qnx-tools:latest steps: - name: Check out repo - uses: actions/checkout@v3 - - name: Install dependencies - run: | - pip install meson==${{ env.MESON_VERSION }} - .github/env/bootstrap.sh linux-x86_64 qnx-armeabi + uses: actions/checkout@v4 + with: + submodules: recursive - name: Build run: | - export PATH="/tmp/toolchain/bin:$PATH" - meson setup \ - --native-file /tmp/native.txt \ - --cross-file /tmp/cross.txt \ - --default-library static \ - -Doptimization=s \ - -Dwerror=true \ - -Dgumpp=enabled \ - -Dgumjs=enabled \ - -Dtests=enabled \ - build - meson compile -C build + CFLAGS="--sysroot=$QNX_TARGET/armle-v7" \ + ./configure --host=arm-unknown-nto-qnx6.5.0eabi ${{ env.GUM_OPTIONS }} + make + - name: Upload Gum devkit + uses: actions/upload-artifact@v4 + with: + name: gum-devkit-qnx-armeabi + path: build/gum/devkit/ + - name: Upload GumJS devkit + uses: actions/upload-artifact@v4 + with: + name: gumjs-devkit-qnx-armeabi + path: build/bindings/gumjs/devkit/ - name: Test run: | tar -C build/tests -cf /tmp/runner.tar gum-tests data/ diff --git a/.github/workflows/style.yml b/.github/workflows/style.yml new file mode 100644 index 000000000..fbfd4a353 --- /dev/null +++ b/.github/workflows/style.yml @@ -0,0 +1,21 @@ +name: Style + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + check_style: + runs-on: ubuntu-latest + steps: + - name: Check out repo + uses: actions/checkout@v4 + - name: Find changed lines + id: changed_lines + uses: hestonhoffman/changed-lines@v1 + - name: Verify changed lines + run: ./tools/stylecheck.py '${{ steps.changed_lines.outputs.changed_lines }}' diff --git a/.gitignore b/.gitignore index 7e9cd3b50..10e43cf27 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ *.user +/__pycache__/ /build/ +/deps/ /gum/backend-darwin/helpers/build/ /subprojects/capstone/ /subprojects/elfutils/ @@ -15,9 +17,11 @@ /subprojects/libunwind/ /subprojects/libxml2.wrap /subprojects/libxml2/ +/subprojects/nghttp2.wrap +/subprojects/nghttp2/ /subprojects/packagecache/ -/subprojects/pcre.wrap -/subprojects/pcre/ +/subprojects/pcre2.wrap +/subprojects/pcre2/ /subprojects/proxy-libintl.wrap /subprojects/proxy-libintl/ /subprojects/quickjs/ @@ -26,3 +30,4 @@ /subprojects/xz/ /subprojects/zlib.wrap /subprojects/zlib/ +/subprojects/gvdb.wrap diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..e2e8558ab --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "releng"] + path = releng + url = https://github.com/frida/releng.git diff --git a/BSDmakefile b/BSDmakefile new file mode 100644 index 000000000..1d8e4fdac --- /dev/null +++ b/BSDmakefile @@ -0,0 +1,6 @@ +all: .DEFAULT + +.DEFAULT: + @gmake ${.MAKEFLAGS} ${.TARGETS} + +.PHONY: all diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..92f129b56 --- /dev/null +++ b/Makefile @@ -0,0 +1,16 @@ +PYTHON ?= $(shell which python3 >/dev/null && echo python3 || echo python) + +all $(MAKECMDGOALS): + @$(PYTHON) \ + -c "import sys; sys.path.insert(0, sys.argv[1]); from releng.meson_make import main; main()" \ + "$(shell pwd)" \ + ./build \ + $(MAKECMDGOALS) + +git-submodules: + @if [ ! -f releng/meson/meson.py ]; then \ + git submodule update --init --recursive; \ + fi +-include git-submodules + +.PHONY: all $(MAKECMDGOALS) diff --git a/bindings/gumjs/devkit/meson.build b/bindings/gumjs/devkit/meson.build new file mode 100644 index 000000000..b1f0684a3 --- /dev/null +++ b/bindings/gumjs/devkit/meson.build @@ -0,0 +1,26 @@ +devkit_outputs = [ + 'frida-gumjs.h', + static_lib_prefix + 'frida-gumjs' + static_lib_suffix, + 'frida-gumjs-example.c', +] + +if cc.get_argument_syntax() == 'msvc' + devkit_outputs += [ + 'frida-gumjs-example.sln', + 'frida-gumjs-example.vcxproj', + 'frida-gumjs-example.vcxproj.filters', + ] +endif + +custom_target('gumjs-devkit', + input: gumjs, + output: devkit_outputs, + command: [ + mkdevkit, + 'frida-gumjs', + f'@host_os@-@host_arch@', + meson.current_build_dir(), + ] + devkit_options, + install: true, + install_dir: get_option('libdir') / 'frida' / 'devkits' / 'gumjs' +) diff --git a/bindings/gumjs/generate-runtime.py b/bindings/gumjs/generate-runtime.py index 49a0a4d74..3311b138a 100755 --- a/bindings/gumjs/generate-runtime.py +++ b/bindings/gumjs/generate-runtime.py @@ -266,11 +266,14 @@ def libtcc_is_header(name): inputs = [ (input_dir / "runtime" / "cmodule", None, is_header, identity_transform, 'GUM_CHEADER_FRIDA'), - (input_dir / "runtime" / "cmodule-tcc", None, is_header, identity_transform, 'GUM_CHEADER_TCC'), - (libtcc_incdir, None, libtcc_is_header, identity_transform, 'GUM_CHEADER_TCC'), (gum_dir / ("arch-" + writer_arch), gum_dir.parent, gum_header_matches_writer, optimize_gum_header, 'GUM_CHEADER_FRIDA'), (capstone_incdir, None, capstone_header_matches_arch, optimize_capstone_header, 'GUM_CHEADER_FRIDA'), ] + if libtcc_incdir is not None: + inputs += [ + (input_dir / "runtime" / "cmodule-tcc", None, is_header, identity_transform, 'GUM_CHEADER_TCC'), + (libtcc_incdir, None, libtcc_is_header, identity_transform, 'GUM_CHEADER_TCC'), + ] with (output_dir / output).open('w', encoding='utf-8') as output_file: modules = [] @@ -431,7 +434,8 @@ def make_script_filename(name): if __name__ == '__main__': backends = set(sys.argv[1].split(",")) arch, endian = sys.argv[2:4] - input_dir, gum_dir, capstone_incdir, libtcc_incdir, quickcompile, output_dir = [Path(d).resolve() for d in sys.argv[4:]] + input_dir, gum_dir, capstone_incdir, libtcc_incdir, quickcompile, output_dir = \ + [Path(d).resolve() if d else None for d in sys.argv[4:]] try: generate_runtime(backends, arch, endian, input_dir, gum_dir, capstone_incdir, libtcc_incdir, quickcompile, output_dir) diff --git a/bindings/gumjs/meson.build b/bindings/gumjs/meson.build index f5a08bb69..0dc05cd6f 100644 --- a/bindings/gumjs/meson.build +++ b/bindings/gumjs/meson.build @@ -330,3 +330,7 @@ pkg.generate(filebase: 'frida-gumjs-inspector-' + api_version, ) meson.override_dependency('frida-gumjs-inspector-' + api_version, gumjs_inspector_dep) + +if 'gumjs' in get_option('devkits') + subdir('devkit') +endif diff --git a/configure b/configure new file mode 100755 index 000000000..1c3bcc37d --- /dev/null +++ b/configure @@ -0,0 +1,18 @@ +#!/bin/sh + +[ -z "$PYTHON" ] && PYTHON=$(which python3 >/dev/null && echo python3 || echo python) + +cd $(dirname $0) + +srcroot=$(pwd) + +if [ ! -f releng/meson/meson.py ]; then + git submodule update --init --recursive || exit $? +fi + +cd - >/dev/null + +exec "$PYTHON" \ + -c "import sys; sys.path.insert(0, sys.argv[1]); from releng.meson_configure import main; main()" \ + "$srcroot" \ + "$@" diff --git a/configure.bat b/configure.bat new file mode 100644 index 000000000..8543e6d38 --- /dev/null +++ b/configure.bat @@ -0,0 +1,22 @@ +@setlocal +@echo off +rem:: Based on: https://github.com/microsoft/terminal/issues/217#issuecomment-737594785 +goto :_start_ + +:set_real_dp0 +set dp0=%~dp0 +set "dp0=%dp0:~0,-1%" +goto :eof + +:_start_ +call :set_real_dp0 + +if not exist "%dp0%\releng\meson\meson.py" ( + pushd "%dp0%" & git submodule update --init --recursive & popd + if %errorlevel% neq 0 exit /b %errorlevel% +) + +endlocal & goto #_undefined_# 2>nul || title %COMSPEC% & python ^ + -c "import sys; sys.path.insert(0, sys.argv[1]); from releng.meson_configure import main; main()" ^ + "%dp0%" ^ + %* diff --git a/gum/devkit/meson.build b/gum/devkit/meson.build new file mode 100644 index 000000000..98d4d86dc --- /dev/null +++ b/gum/devkit/meson.build @@ -0,0 +1,26 @@ +devkit_outputs = [ + 'frida-gum.h', + static_lib_prefix + 'frida-gum' + static_lib_suffix, + 'frida-gum-example.c', +] + +if cc.get_argument_syntax() == 'msvc' + devkit_outputs += [ + 'frida-gum-example.sln', + 'frida-gum-example.vcxproj', + 'frida-gum-example.vcxproj.filters', + ] +endif + +custom_target('gum-devkit', + input: gum, + output: devkit_outputs, + command: [ + mkdevkit, + 'frida-gum', + f'@host_os@-@host_arch@', + meson.current_build_dir(), + ] + devkit_options, + install: true, + install_dir: get_option('libdir') / 'frida' / 'devkits' / 'gum' +) diff --git a/gum/meson.build b/gum/meson.build index 62df88702..09d434471 100644 --- a/gum/meson.build +++ b/gum/meson.build @@ -382,3 +382,7 @@ pkg.generate(gum, ) meson.override_dependency('frida-gum-' + api_version, gum_dep) + +if 'gum' in get_option('devkits') + subdir('devkit') +endif diff --git a/make.bat b/make.bat new file mode 100644 index 000000000..e8c959e06 --- /dev/null +++ b/make.bat @@ -0,0 +1,23 @@ +@setlocal +@echo off +rem:: Based on: https://github.com/microsoft/terminal/issues/217#issuecomment-737594785 +goto :_start_ + +:set_real_dp0 +set dp0=%~dp0 +set "dp0=%dp0:~0,-1%" +goto :eof + +:_start_ +call :set_real_dp0 + +if not exist "%dp0%\releng\meson\meson.py" ( + pushd "%dp0%" & git submodule update --init --recursive & popd + if %errorlevel% neq 0 exit /b %errorlevel% +) + +endlocal & goto #_undefined_# 2>nul || title %COMSPEC% & python ^ + -c "import sys; sys.path.insert(0, sys.argv[1]); from releng.meson_make import main; main()" ^ + "%dp0%" ^ + .\build ^ + %* diff --git a/meson.build b/meson.build index 0ad28b24d..110aff56c 100644 --- a/meson.build +++ b/meson.build @@ -429,6 +429,34 @@ else gir = disabler() endif +if get_option('devkits').length() != 0 + mkdevkit = find_program('./releng/mkdevkit.py') + uninstalled_dir = meson.global_build_root() / 'meson-uninstalled' + devkit_options = [ + '--cc=' + '!'.join(cc.cmd_array()), + '--c-args=' + '!'.join(get_option('c_args')), + '--pkg-config-path=' + '!'.join([uninstalled_dir] + get_option('pkg_config_path')), + ] + if cc.get_argument_syntax() == 'msvc' + static_lib_prefix = '' + static_lib_suffix = '.lib' + devkit_options += ['--lib=' + find_program('lib').full_path()] + else + static_lib_prefix = 'lib' + static_lib_suffix = '.a' + foreach tool : ['ar', 'nm', 'objcopy'] + p = find_program(tool, required: false) + if p.found() + path = p.full_path() + devkit_options += [f'--@tool@=@path@'] + endif + endforeach + endif + if host_os_family == 'darwin' + devkit_options += ['--libtool=' + find_program('libtool').full_path()] + endif +endif + if glib_dep.type_name() == 'internal' or cc.has_function('g_thread_set_callbacks', dependencies: [glib_dep]) cdata.set('HAVE_FRIDA_GLIB', 1) endif diff --git a/meson_options.txt b/meson_options.txt index 30cfb599f..1a2d7b753 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -65,6 +65,13 @@ option('frida_java_bridge', description: 'Build JavaScript bindings with Java bridge included' ) +option('devkits', + type: 'array', + choices: ['gum', 'gumjs'], + value: [], + description: 'Devkits to build' +) + option('tests', type: 'feature', value: 'auto', diff --git a/releng b/releng new file mode 160000 index 000000000..15f999bce --- /dev/null +++ b/releng @@ -0,0 +1 @@ +Subproject commit 15f999bce49093a4f77d06c8116d7661d70c7c9b diff --git a/tests/meson.build b/tests/meson.build index cbe57a35e..005ca8095 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -96,7 +96,7 @@ if host_os in ['ios', 'watchos', 'tvos'] extra_link_args += ['-Wl,-framework,Foundation'] endif -runner = executable(runner_name, runner_sources + [test_data_stamp], +raw_runner = executable(runner_name, runner_sources + [test_data_stamp], link_with: link_targets, dependencies: [gum_dep, gum_heap_dep, gum_prof_dep, tls_provider_dep, threads_dep] + extra_test_deps, link_args: extra_link_args, @@ -105,9 +105,9 @@ runner = executable(runner_name, runner_sources + [test_data_stamp], ) if host_os_family == 'darwin' - custom_target('gum-tests-signed', + runner = custom_target('gum-tests-signed', input: [ - runner, + raw_runner, 'gum-tests.xcent', ], output: 'gum-tests', @@ -119,4 +119,11 @@ if host_os_family == 'darwin' ], build_by_default: true, ) +else + runner = raw_runner endif + +test('gum', find_program('./run.py'), + args: runner.full_path(), + timeout: 120, +) diff --git a/tests/run.py b/tests/run.py new file mode 100755 index 000000000..b240fc8bb --- /dev/null +++ b/tests/run.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 + +import os +from pathlib import Path +import platform +import subprocess +import sys + + +def main(): + runner_env = { **os.environ } + + if platform.system() == 'Windows': + runner_program = Path(sys.argv[1]) + gumpp_dir = runner_program.parent.parent / "bindings" / "gumpp" + if gumpp_dir.exists(): + runner_env["PATH"] = str(gumpp_dir) + os.pathsep + runner_env["PATH"] + + process = subprocess.run(sys.argv[1:], env=runner_env) + + sys.exit(process.returncode) + + +if __name__ == "__main__": + main() diff --git a/tools/stylecheck.py b/tools/stylecheck.py new file mode 100755 index 000000000..7b37992b6 --- /dev/null +++ b/tools/stylecheck.py @@ -0,0 +1,174 @@ +#!/usr/bin/env python3 + +import json +from pathlib import Path +import re +import sys + + +MACRO_DEFINE_PATTERN = re.compile(r"^#\s*define\s") +STRING_LITERAL_PATTERN = re.compile(r"\"[^\"]+?\"") + +def function_parameters_are_aligned(match): + lines = match.group(1).rstrip().split("\n") + if lines[0].endswith(" ="): + return True + + if len(lines) < 2: + return False + + if lines[1].endswith(" ="): + return True + + offset = lines[1].find("(") + if offset == -1: + return False + + if offset == len(lines[1]) - 1: + offset = 3 + + expected_num_leading_spaces = offset + 1 + for line in lines[2:]: + num_leading_spaces = len(line) - len(line.lstrip(" ")) + if num_leading_spaces != expected_num_leading_spaces: + return False + + return True + +COMMON_MISTAKES = [ + ( + "line exceeds 80 columns", + re.compile(r"^.{81}()", re.MULTILINE), + ), + ( + "missing space before parentheses", + re.compile(r"\w()\("), + ("unless-line-matches", MACRO_DEFINE_PATTERN), + ("unless-found-inside", STRING_LITERAL_PATTERN), + ), + ( + "missing space after cast", + re.compile(r"\([^()]+\)()\w"), + ), + ( + "missing space in pointer declaration", + re.compile(r"\w+()\* \w+"), + ), + ( + "missing space in pointer declaration", + re.compile(r"\w+ \*()\w+"), + ("unless-line-matches", re.compile(r"\s+return \*")), + ), + ( + "blank line after block start", + re.compile("{\n(\n)"), + ), + ( + "blank line before block end", + re.compile("\n(\n)}"), + ), + ( + "two or more consecutive blank lines", + re.compile("\n(\n{2})"), + ), + ( + "opening brace on the same line as the statement opening it", + re.compile(r"^.+\)[^\n]*({)", re.MULTILINE), + ("unless-line-matches", MACRO_DEFINE_PATTERN), + ("unless-found-inside", STRING_LITERAL_PATTERN), + ), + ( + "incorrectly formatted function definition", + re.compile(r"^(static [^;{]+){", re.MULTILINE), + ("unless-true", function_parameters_are_aligned), + ), +] + +COMMENT_PATTERN = re.compile(r"\/\*(.+?)\*\/", re.DOTALL) + +INCLUDED_EXTENSIONS = { + ".c", + ".h", + ".cpp", + ".hpp", +} + +EXCLUDED_SOURCES = { + "gum/dlmalloc.c", + "gum/gummetalhash.c", + "gum/gummetalhash.h", + "gum/gumprintf.c", + "gum/valgrind.h", +} + + +def main(): + changed_lines = json.loads(sys.argv[1]) + + repo_dir = Path(__file__).parent.parent.resolve() + changed_files = [Path(repo_dir / f) for f in changed_lines.keys()] + files_to_check = [f for f in changed_files if f.suffix in INCLUDED_EXTENSIONS] + + num_mistakes_found = 0 + for path in files_to_check: + relpath = path.relative_to(repo_dir).as_posix() + if relpath in EXCLUDED_SOURCES: + continue + + code = path.read_text(encoding="utf-8") + lines = code.split("\n") + + comment_lines = set() + for m in COMMENT_PATTERN.finditer(code): + start_offset, end_offset = m.span(1) + start_line = offset_to_line(start_offset, code) + end_line = offset_to_line(end_offset, code) + for i in range(start_line, end_line + 1): + comment_lines.add(i) + + for (description, pattern, *predicates) in COMMON_MISTAKES: + for match in pattern.finditer(code): + match_offset = match.start(1) + line_number = offset_to_line(match_offset, code) + + if line_number in comment_lines: + continue + + prev_newline_offset = code.rfind("\n", 0, match_offset) + if prev_newline_offset == -1: + prev_newline_offset = 0 + line_offset = match_offset - prev_newline_offset + + is_actual_mistake = True + line = lines[line_number - 1] + for (condition, parameter) in predicates: + if condition == "unless-line-matches": + if parameter.match(line) is not None: + is_actual_mistake = False + elif condition == "unless-found-inside": + for m in parameter.finditer(line): + start, end = m.span() + if line_offset >= start and line_offset < end: + is_actual_mistake = False + break + elif condition == "unless-true": + if parameter(match): + is_actual_mistake = False + else: + assert False, "unexpected condition" + if not is_actual_mistake: + break + + if is_actual_mistake and line_number in changed_lines[relpath]: + print(f"{relpath}:{line_number}: {description}") + num_mistakes_found += 1 + + sys.exit(0 if num_mistakes_found == 0 else 1) + + +def offset_to_line(i, code): + return len(code[:i].split("\n")) + + +if __name__ == "__main__": + main()