diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5161a689e..c622d9563 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -11,10 +11,33 @@ jobs: strategy: fail-fast: false matrix: - platform: [ubuntu-latest, windows-latest, macos-latest] + include: + - name: Ubuntu + platform: ubuntu-latest + - name: Windows (x64) + platform: windows-latest + - name: Windows (arm64) + platform: windows-latest + CMAKE_DEFINES: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/win_arm64.cmake -A arm64 + - name: LLVM-MINGW (x64) + platform: windows-latest + MINGW: 1 + MINGW_PKG_PREFIX: x86_64-w64-mingw32 + MINGW_ASM_MASM_COMPILER: llvm-ml;-m64 + CMAKE_DEFINES: -DCRASHPAD_ZLIB_SYSTEM=OFF -DCRASHPAD_BUILD_TOOLS=OFF -G Ninja + - name: LLVM-MINGW (arm64) + platform: windows-latest + MINGW: 1 + MINGW_PKG_PREFIX: aarch64-w64-mingw32 + CMAKE_DEFINES: -DCRASHPAD_ZLIB_SYSTEM=OFF -DCRASHPAD_BUILD_TOOLS=OFF -DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/mingw_arm64.cmake -G Ninja + - name: macOS + platform: macos-latest + name: ${{ matrix.name }} runs-on: ${{ matrix.platform }} + env: + CMAKE_DEFINES: ${{ matrix.CMAKE_DEFINES }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: submodules: "recursive" @@ -24,32 +47,33 @@ jobs: sudo apt update sudo apt install zlib1g-dev libcurl4-openssl-dev libssl-dev libunwind-dev pkg-config + - name: Installing LLVM-MINGW Dependencies + if: ${{ runner.os == 'Windows' && matrix.MINGW == '1' }} + shell: powershell + env: + MINGW_PKG_PREFIX: ${{ matrix.MINGW_PKG_PREFIX }} + MINGW_ASM_MASM_COMPILER: ${{ matrix.MINGW_ASM_MASM_COMPILER }} + run: . "cmake\scripts\install-llvm-mingw.ps1" + - name: Build crashpad + shell: bash run: | - cmake -B cmake-build -D CRASHPAD_BUILD_TOOLS=On + echo "CMAKE_DEFINES=${CMAKE_DEFINES}" + cmake -B cmake-build -D CRASHPAD_BUILD_TOOLS=On ${CMAKE_DEFINES} cmake --build cmake-build --parallel - name: Build crashpad with client-side stack traces + shell: bash run: | - cmake -B cmake-build-stacks -D CRASHPAD_ENABLE_STACKTRACE=ON + echo "CMAKE_DEFINES=${CMAKE_DEFINES}" + cmake -B cmake-build-stacks -D CRASHPAD_ENABLE_STACKTRACE=ON ${CMAKE_DEFINES} cmake --build cmake-build-stacks --parallel - - name: Build crashpad Windows ARM64 - if: ${{ runner.os == 'Windows' }} - run: | - cmake -B cmake-build-arm64 -DCMAKE_TOOLCHAIN_FILE="cmake/toolchains/win_arm64.cmake" -DCRASHPAD_BUILD_TOOLS=On - cmake --build cmake-build-arm64 --config RelWithDebInfo -- /p:Platform=ARM64 - - - name: Build crashpad with client-side stack traces Windows ARM64 - if: ${{ runner.os == 'Windows' }} - run: | - cmake -B cmake-build-stacks-arm64 -DCMAKE_TOOLCHAIN_FILE="cmake/toolchains/win_arm64.cmake" -DCRASHPAD_ENABLE_STACKTRACE=ON - cmake --build cmake-build-stacks-arm64 --config RelWithDebInfo -- /p:Platform=ARM64 - build-ios: + name: 'iOS' runs-on: macos-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: submodules: "recursive" - run: | diff --git a/CMakeLists.txt b/CMakeLists.txt index 63cbd229e..edf23ce25 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,7 +49,7 @@ function(crashpad_install_dev) endif() endfunction() -if(WIN32) +if(WIN32 AND NOT (MINGW AND "${CMAKE_SYSTEM_PROCESSOR}" MATCHES "[Aa][Rr][Mm]64")) if("${CMAKE_SYSTEM_PROCESSOR}" MATCHES ARM64) enable_language(ASM_MARMASM) else() diff --git a/cmake/scripts/install-llvm-mingw.ps1 b/cmake/scripts/install-llvm-mingw.ps1 new file mode 100755 index 000000000..3e6d40e08 --- /dev/null +++ b/cmake/scripts/install-llvm-mingw.ps1 @@ -0,0 +1,58 @@ +Start-Sleep -Milliseconds 1 # See: https://stackoverflow.com/a/49859001 + +$LLVM_MINGW_RELEASE = "20240518"; +$LLVM_MINGW_PKG = "llvm-mingw-${LLVM_MINGW_RELEASE}-ucrt-x86_64" +$LLVM_MINGW_DL_URL = "https://github.com/mstorsjo/llvm-mingw/releases/download/${LLVM_MINGW_RELEASE}/${LLVM_MINGW_PKG}.zip" +$LLVM_MINGW_DL_SHA512 = "4758b41533930f9b4d646f60406f37a644dedd662d0adb8586f544c1b875fc86ece51ce2bb7b060075c3d081533f1a7aafa816ccdee2101e507aa047024d8d3f" +$DL_BASEDIR = "$env:GITHUB_WORKSPACE\dl" +$LLVM_MINGW_DL_PATH = "${DL_BASEDIR}\llvm-mingw.zip" +if (!(Test-Path -Path "$DL_BASEDIR")) { New-Item -ItemType Directory -Force -Path "$DL_BASEDIR" } + +# Download LLVM-mingw +$CurlArguments = '-s', '-Lf', '-o', "${LLVM_MINGW_DL_PATH}", "${LLVM_MINGW_DL_URL}" +& curl.exe @CurlArguments +$dl_zip_hash = Get-FileHash -LiteralPath "${LLVM_MINGW_DL_PATH}" -Algorithm SHA512 +if ($dl_zip_hash.Hash -eq $LLVM_MINGW_DL_SHA512) { + Write-Host "Successfully downloaded LLVM-mingw .zip" +} +Else { + Write-Error "The downloaded LLVM-mingw zip hash '$($dl_zip_hash.Hash)' does not match the expected hash: '$LLVM_MINGW_DL_SHA512'" +} + +# Extract LLVM-mingw +Write-Host "Extracting LLVM-mingw..." +$LLVM_MINGW_INSTALL_PATH = "$env:GITHUB_WORKSPACE\buildtools\llvm-mingw" +New-Item -ItemType Directory -Force -Path "${LLVM_MINGW_INSTALL_PATH}" +Expand-Archive -LiteralPath "${LLVM_MINGW_DL_PATH}" -DestinationPath "${LLVM_MINGW_INSTALL_PATH}" +# Export the LLVM-mingw install path +$LLVM_MINGW_INSTALL_PATH = "${LLVM_MINGW_INSTALL_PATH}\${LLVM_MINGW_PKG}" +"LLVM_MINGW_INSTALL_PATH=${LLVM_MINGW_INSTALL_PATH}" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append +# Prepend bin path to the system PATH +Write-Host "Path to LLVM-mingw bin folder: ${LLVM_MINGW_INSTALL_PATH}\bin" +"${LLVM_MINGW_INSTALL_PATH}\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + +# Download ninja-build +$NINJA_DL_URL = "https://github.com/ninja-build/ninja/releases/download/v1.12.1/ninja-win.zip" +$NINJA_DL_SHA512 = "d6715c6458d798bcb809f410c0364dabd937b5b7a3ddb4cd5aba42f9fca45139b2a8a3e7fd9fbd88fd75d298ed99123220b33c7bdc8966a9d5f2a1c9c230955f" +$NINJA_DL_PATH = "${DL_BASEDIR}\ninja-win.zip" +$CurlArguments = '-s', '-Lf', '-o', "${NINJA_DL_PATH}", "${NINJA_DL_URL}" +& curl.exe @CurlArguments +$ninja_zip_hash = Get-FileHash -LiteralPath "${NINJA_DL_PATH}" -Algorithm SHA512 +if ($ninja_zip_hash.Hash -eq $NINJA_DL_SHA512) { + Write-Host "Successfully downloaded Ninja-Build .zip" +} +Else { + Write-Error "The downloaded Ninja-build zip hash '$($ninja_zip_hash.Hash)' does not match the expected hash: '$NINJA_DL_SHA512'" +} + +Write-Host "Extracting Ninja-Build..." +$NINJA_INSTALL_PATH = "$env:GITHUB_WORKSPACE\buildtools\ninja" +New-Item -ItemType Directory -Force -Path "${NINJA_INSTALL_PATH}" +Expand-Archive -LiteralPath "${NINJA_DL_PATH}" -DestinationPath "${NINJA_INSTALL_PATH}" + +# Export the NINJA executable path +"NINJA_INSTALL_PATH=${NINJA_INSTALL_PATH}" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append +"PATH=${NINJA_INSTALL_PATH}; $env:PATH" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + +# export CMAKE_DEFINES to the runner environment +"CMAKE_DEFINES=${env:CMAKE_DEFINES} -DCMAKE_C_COMPILER=${env:MINGW_PKG_PREFIX}-gcc -DCMAKE_CXX_COMPILER=${env:MINGW_PKG_PREFIX}-g++ -DCMAKE_RC_COMPILER=${env:MINGW_PKG_PREFIX}-windres -DCMAKE_ASM_MASM_COMPILER=${env:MINGW_ASM_MASM_COMPILER}" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append \ No newline at end of file diff --git a/cmake/toolchains/mingw_arm64.cmake b/cmake/toolchains/mingw_arm64.cmake new file mode 100644 index 000000000..de26e51a8 --- /dev/null +++ b/cmake/toolchains/mingw_arm64.cmake @@ -0,0 +1,5 @@ +# Toolchain file that should provide required and non-conflicting build- +# parameters to allow normal and cross-compilation to ARM64 targets on +# Windows using any generator. +SET(CMAKE_SYSTEM_PROCESSOR "ARM64") +SET(CMAKE_SYSTEM_NAME "Windows") diff --git a/compat/mingw/werapi.h b/compat/mingw/werapi.h index 2007a0538..9f0443c01 100644 --- a/compat/mingw/werapi.h +++ b/compat/mingw/werapi.h @@ -21,8 +21,10 @@ typedef HANDLE HREPORT; #define WER_MAX_PREFERRED_MODULES_BUFFER 256 #endif -#define PWER_SUBMIT_RESULT WER_SUBMIT_RESULT* - #include_next +#ifndef PWER_SUBMIT_RESULT +#define PWER_SUBMIT_RESULT WER_SUBMIT_RESULT* +#endif + #endif // CRASHPAD_COMPAT_MINGW_WERAPI_H_ diff --git a/util/CMakeLists.txt b/util/CMakeLists.txt index b9161b475..a260f5d6c 100644 --- a/util/CMakeLists.txt +++ b/util/CMakeLists.txt @@ -375,9 +375,15 @@ if(WIN32) win/xp_compat.h ) if("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "arm|ARM64") - target_sources(crashpad_util PRIVATE - misc/capture_context_win_arm64.asm - ) + if (MINGW) + target_sources(crashpad_util PRIVATE + misc/capture_context_win_arm64.S + ) + else() + target_sources(crashpad_util PRIVATE + misc/capture_context_win_arm64.asm + ) + endif() else() target_sources(crashpad_util PRIVATE misc/capture_context_win.asm diff --git a/util/misc/capture_context_win_arm64.S b/util/misc/capture_context_win_arm64.S new file mode 100644 index 000000000..35af0e6c3 --- /dev/null +++ b/util/misc/capture_context_win_arm64.S @@ -0,0 +1,74 @@ +// Copyright 2019 The Crashpad Authors +// +// 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. + +// namespace crashpad { +// void CaptureContext(CONTEXT* context); +// } // namespace crashpad + +#include "arm64_pac_bti.S" + +#define CAPTURECONTEXT_SYMBOL _ZN8crashpad14CaptureContextEP8_CONTEXT + + .text + .globl CAPTURECONTEXT_SYMBOL + .balign 4, 0x0 + //.type CAPTURECONTEXT_SYMBOL, %function + +CAPTURECONTEXT_SYMBOL: + CRASHPAD_AARCH64_VALID_CALL_TARGET + + // Save general purpose registers in context.regs[i]. + // The original x0 can't be recovered. + stp x0, x1, [x0, #0x008] + stp x2, x3, [x0, #0x018] + stp x4, x5, [x0, #0x028] + stp x6, x7, [x0, #0x038] + stp x8, x9, [x0, #0x048] + stp x10, x11, [x0, #0x058] + stp x12, x13, [x0, #0x068] + stp x14, x15, [x0, #0x078] + stp x16, x17, [x0, #0x088] + stp x18, x19, [x0, #0x098] + stp x20, x21, [x0, #0x0a8] + stp x22, x23, [x0, #0x0b8] + stp x24, x25, [x0, #0x0c8] + stp x26, x27, [x0, #0x0d8] + stp x28, x29, [x0, #0x0e8] + + // The original LR can't be recovered. + str LR, [x0, #0x0f8] + + // Use x1 as a scratch register. + mov x1, SP + str x1, [x0, #0x100] // context.sp + + // The link register holds the return address for this function. + str LR, [x0, #0x108] // context.pc + + // pstate should hold SPSR but NZCV are the only bits we know about. + mrs x1, NZCV + + // Enable Control flags, such as CONTEXT_ARM64, CONTEXT_CONTROL, + // CONTEXT_INTEGER + ldr w1, =0x00400003 + + // Set ControlFlags /0x000/ and pstate /0x004/ at the same time. + str x1, [x0, #0x000] + + // Restore x1 from the saved context. + ldr x1, [x0, #0x010] + + // TODO(https://crashpad.chromium.org/bug/300): save floating-point registers + + ret