diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 76f82e42..975c1e1a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -143,10 +143,12 @@ jobs: ${{ github.workspace }}/BinaryCache/ds2/ds2.exe macos: - # The macos-latest runner image runs on an M1 ARM CPU which is not currently - # supported by ds2. Build on macos-13, which is x86_64-based, until Darwin - # on ARM support is implemented. - runs-on: macos-13 + runs-on: macos-latest + + strategy: + fail-fast: false + matrix: + processor: [ arm64, x86_64 ] steps: - uses: actions/checkout@v4 @@ -157,6 +159,7 @@ jobs: cmake -B ${{ github.workspace }}/BinaryCache/ds2 \ -C ${{ github.workspace }}/cmake/caches/ClangWarnings.cmake \ -D CMAKE_BUILD_TYPE=Release \ + -D CMAKE_SYSTEM_PROCESSOR="${{ matrix.processor }}" \ -G Ninja \ -S ${{ github.workspace }} - name: Build @@ -164,7 +167,7 @@ jobs: - uses: actions/upload-artifact@v4 with: - name: macOS-x86_64-ds2 + name: macOS-${{ matrix.processor }}-ds2 path: | ${{ github.workspace }}/BinaryCache/ds2/ds2 diff --git a/CMakeLists.txt b/CMakeLists.txt index ab7b674d..3a45adb6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -220,7 +220,7 @@ if(DS2_ARCHITECTURE MATCHES "ARM|ARM64") set_source_files_properties( Sources/Architecture/ARM/ThumbBranchInfo.cpp PROPERTIES - COMPILE_OPTIONS $<$:-Wno-error=comma>) + COMPILE_OPTIONS $<$,$>:-Wno-error=comma>) target_sources(ds2 PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/Headers/DebugServer2/Architecture/ARM/RegistersDescriptors.h diff --git a/README.md b/README.md index 5b7affa0..c9106d32 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ platforms at various times. - [x] ARM64 - [x] Android - - [ ] Darwin + - [x] Darwin - [x] Linux - [x] MinGW - [ ] Windows diff --git a/Sources/Target/Darwin/ARM64/ProcessARM64.cpp b/Sources/Target/Darwin/ARM64/ProcessARM64.cpp index 5e072de5..db5250f5 100644 --- a/Sources/Target/Darwin/ARM64/ProcessARM64.cpp +++ b/Sources/Target/Darwin/ARM64/ProcessARM64.cpp @@ -1,15 +1,64 @@ -// -// Copyright (c) 2014-present, Saleem Abdulrasool -// All rights reserved. -// -// This source code is licensed under the University of Illinois/NCSA Open -// Source License found in the LICENSE file in the root directory of this -// source tree. An additional grant of patent rights can be found in the -// PATENTS file in the same directory. -// +// Copyright 2024-2025 Saleem Abdulrasool #include "DebugServer2/Target/Process.h" +#include + +#include +#include +#include + +namespace { +template +inline void InsertBytes(ds2::ByteVector &bytes, T value) { + uint8_t *data = reinterpret_cast(&value); + bytes.insert(std::end(bytes), data, data + sizeof(T)); +} + +namespace syscalls { +inline void mmap(size_t size, int protection, ds2::ByteVector &code) { + DS2ASSERT(std::log2(MAP_ANON | MAP_PRIVATE) <= 16); + DS2ASSERT(std::log2(SYS_mmap) <= 16); + DS2ASSERT(std::log2(protection) <= 16); + + for (uint32_t instruction: { + static_cast(0xd2800000), // mov x0, 0 + static_cast(0x580000e1), // ldr x1, .Lsize + static_cast(0xd2800002 | protection << 5), // mov x2, protection + static_cast(0xd2800003 | (MAP_ANON | MAP_PRIVATE) << 5), // mov x3, MAP_ANON | MAP_PRIVATE + static_cast(0x92800004), // mov x4, -1 + static_cast(0xd2800005), // mov x5, 0 + static_cast(0xd2800008 | SYS_mmap << 5), // mov x8, =SYS_mmap + static_cast(0xd4000001), // svc 0 + static_cast(0xd43e0000), // brk #0xf000 + // .Lsize: + // .quad size + }) + InsertBytes(code, instruction); + InsertBytes(code, size); +} + +inline void munmap(uintptr_t address, size_t size, ds2::ByteVector &code) { + DS2ASSERT(std::log2(SYS_munmap) <= 16); + + for (uint32_t instruction: { + static_cast(0x580000a0), // ldr x0, .Laddress + static_cast(0x580000c1), // ldr x1, .Lsize + static_cast(0xd2800008 | SYS_munmap << 5), // mov x8, =SYS_munmap + static_cast(0xd4000001), // svc 0 + static_cast(0xd43e0000), // brk #0xf000 + // .Laddress: + // .quad address + // .Lsize: + // .quad size + }) + InsertBytes(code, instruction); + InsertBytes(code, address); + InsertBytes(code, size); +} +} +} + namespace ds2 { namespace Target { namespace Darwin { @@ -18,12 +67,43 @@ ErrorCode Process::allocateMemory(size_t size, uint32_t protection, if (address == nullptr || size == 0) return kErrorInvalidArgument; - *address = 0; - return kErrorUnsupported; + ProcessInfo info; + ErrorCode error = getInfo(info); + if (error != kSuccess) + return error; + + ByteVector code; + syscalls::mmap(size, convertMemoryProtectionFromPOSIX(protection), code); + + error = ptrace().execute(_pid, info, &code[0], code.size(), *address); + if (error != kSuccess) + return error; + + if (*address == reinterpret_cast(MAP_FAILED)) + return kErrorNoMemory; + return kSuccess; } ErrorCode Process::deallocateMemory(uint64_t address, size_t size) { - return kErrorUnsupported; + if (size == 0) + return kErrorInvalidArgument; + + ProcessInfo info; + ErrorCode error = getInfo(info); + if (error != kSuccess) + return error; + + ByteVector code; + syscalls::munmap(address, size, code); + + uint64_t result = 0; + error = ptrace().execute(_pid, info, &code[0], code.size(), result); + if (error != kSuccess) + return error; + + if (static_cast(result) < 0) + return kErrorInvalidArgument; + return kSuccess; } } }