Skip to content

Commit

Permalink
fix: crashpad build for Windows ARM64 via LLVM-MINGW (#101)
Browse files Browse the repository at this point in the history
* Add GAS version of capture_context_win_arm64.asm (for llvm-mingw)

* Use capture_context_win_arm64.S on mingw targeting arm64

* ci: tweak build matrix

* ci: add llvm-mingw x64 build

* ci: add llvm-mingw arm64 build

* compat/mingw/werapi.h: Fix compat with recent mingw headers

* ci: Bump actions/checkout to v4

To fix "Node.js 16 actions are deprecated"
  • Loading branch information
past-due committed Jun 5, 2024
1 parent 08528d5 commit 202c1c2
Show file tree
Hide file tree
Showing 7 changed files with 192 additions and 23 deletions.
58 changes: 41 additions & 17 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand All @@ -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: |
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
58 changes: 58 additions & 0 deletions cmake/scripts/install-llvm-mingw.ps1
Original file line number Diff line number Diff line change
@@ -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
5 changes: 5 additions & 0 deletions cmake/toolchains/mingw_arm64.cmake
Original file line number Diff line number Diff line change
@@ -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")
6 changes: 4 additions & 2 deletions compat/mingw/werapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ typedef HANDLE HREPORT;
#define WER_MAX_PREFERRED_MODULES_BUFFER 256
#endif

#define PWER_SUBMIT_RESULT WER_SUBMIT_RESULT*

#include_next <werapi.h>

#ifndef PWER_SUBMIT_RESULT
#define PWER_SUBMIT_RESULT WER_SUBMIT_RESULT*
#endif

#endif // CRASHPAD_COMPAT_MINGW_WERAPI_H_
12 changes: 9 additions & 3 deletions util/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
74 changes: 74 additions & 0 deletions util/misc/capture_context_win_arm64.S
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 202c1c2

Please sign in to comment.