Skip to content

Commit 72df59a

Browse files
committed
Target: implement the Darwin ARM64 support to complete the port
This implements the necessary ARM64 specific logic for mmap and munmap syscalls to be able to allocate and deallocate memory in the inferior. This gives us a complete implementation for the Darwin ARM64 target.
1 parent 6862cca commit 72df59a

File tree

3 files changed

+101
-18
lines changed

3 files changed

+101
-18
lines changed

.github/workflows/build.yml

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -143,10 +143,12 @@ jobs:
143143
${{ github.workspace }}/BinaryCache/ds2/ds2.exe
144144
145145
macos:
146-
# The macos-latest runner image runs on an M1 ARM CPU which is not currently
147-
# supported by ds2. Build on macos-13, which is x86_64-based, until Darwin
148-
# on ARM support is implemented.
149-
runs-on: macos-13
146+
runs-on: macos-latest
147+
148+
strategy:
149+
fail-fast: false
150+
matrix:
151+
processor: [ arm64, x86_64 ]
150152

151153
steps:
152154
- uses: actions/checkout@v4
@@ -157,14 +159,15 @@ jobs:
157159
cmake -B ${{ github.workspace }}/BinaryCache/ds2 \
158160
-C ${{ github.workspace }}/cmake/caches/ClangWarnings.cmake \
159161
-D CMAKE_BUILD_TYPE=Release \
162+
-D CMAKE_SYSTEM_PROCESSOR="${{ matrix.processor }}" \
160163
-G Ninja \
161164
-S ${{ github.workspace }}
162165
- name: Build
163166
run: cmake --build ${{ github.workspace }}/BinaryCache/ds2 --config Release
164167

165168
- uses: actions/upload-artifact@v4
166169
with:
167-
name: macOS-x86_64-ds2
170+
name: macOS-${{ matrix.processor }}-ds2
168171
path: |
169172
${{ github.workspace }}/BinaryCache/ds2/ds2
170173

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ platforms at various times.
1818

1919
- [x] ARM64
2020
- [x] Android
21-
- [ ] Darwin
21+
- [x] Darwin
2222
- [x] Linux
2323
- [x] MinGW
2424
- [ ] Windows

Sources/Target/Darwin/ARM64/ProcessARM64.cpp

Lines changed: 92 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,64 @@
1-
//
2-
// Copyright (c) 2014-present, Saleem Abdulrasool <compnerd@compnerd.org>
3-
// All rights reserved.
4-
//
5-
// This source code is licensed under the University of Illinois/NCSA Open
6-
// Source License found in the LICENSE file in the root directory of this
7-
// source tree. An additional grant of patent rights can be found in the
8-
// PATENTS file in the same directory.
9-
//
1+
// Copyright 2024-2025 Saleem Abdulrasool <compnerd@compnerd.org>
102

113
#include "DebugServer2/Target/Process.h"
124

5+
#include <cmath>
6+
7+
#include <stddef.h>
8+
#include <sys/mman.h>
9+
#include <sys/syscall.h>
10+
11+
namespace {
12+
template <typename T>
13+
inline void InsertBytes(ds2::ByteVector &bytes, T value) {
14+
uint8_t *data = reinterpret_cast<uint8_t *>(&value);
15+
bytes.insert(std::end(bytes), data, data + sizeof(T));
16+
}
17+
18+
namespace syscalls {
19+
inline void mmap(size_t size, int protection, ds2::ByteVector &code) {
20+
DS2ASSERT(std::log2(MAP_ANON | MAP_PRIVATE) <= 16);
21+
DS2ASSERT(std::log2(SYS_mmap) <= 16);
22+
DS2ASSERT(std::log2(protection) <= 16);
23+
24+
for (uint32_t instruction: {
25+
static_cast<uint32_t>(0xd2800000), // mov x0, 0
26+
static_cast<uint32_t>(0x580000e1), // ldr x1, .Lsize
27+
static_cast<uint32_t>(0xd2800002 | protection << 5), // mov x2, protection
28+
static_cast<uint32_t>(0xd2800003 | (MAP_ANON | MAP_PRIVATE) << 5), // mov x3, MAP_ANON | MAP_PRIVATE
29+
static_cast<uint32_t>(0x92800004), // mov x4, -1
30+
static_cast<uint32_t>(0xd2800005), // mov x5, 0
31+
static_cast<uint32_t>(0xd2800008 | SYS_mmap << 5), // mov x8, =SYS_mmap
32+
static_cast<uint32_t>(0xd4000001), // svc 0
33+
static_cast<uint32_t>(0xd43e0000), // brk #0xf000
34+
// .Lsize:
35+
// .quad size
36+
})
37+
InsertBytes(code, instruction);
38+
InsertBytes(code, size);
39+
}
40+
41+
inline void munmap(uintptr_t address, size_t size, ds2::ByteVector &code) {
42+
DS2ASSERT(std::log2(SYS_munmap) <= 16);
43+
44+
for (uint32_t instruction: {
45+
static_cast<uint32_t>(0x580000a0), // ldr x0, .Laddress
46+
static_cast<uint32_t>(0x580000c1), // ldr x1, .Lsize
47+
static_cast<uint32_t>(0xd2800008 | SYS_munmap << 5), // mov x8, =SYS_munmap
48+
static_cast<uint32_t>(0xd4000001), // svc 0
49+
static_cast<uint32_t>(0xd43e0000), // brk #0xf000
50+
// .Laddress:
51+
// .quad address
52+
// .Lsize:
53+
// .quad size
54+
})
55+
InsertBytes(code, instruction);
56+
InsertBytes(code, address);
57+
InsertBytes(code, size);
58+
}
59+
}
60+
}
61+
1362
namespace ds2 {
1463
namespace Target {
1564
namespace Darwin {
@@ -18,12 +67,43 @@ ErrorCode Process::allocateMemory(size_t size, uint32_t protection,
1867
if (address == nullptr || size == 0)
1968
return kErrorInvalidArgument;
2069

21-
*address = 0;
22-
return kErrorUnsupported;
70+
ProcessInfo info;
71+
ErrorCode error = getInfo(info);
72+
if (error != kSuccess)
73+
return error;
74+
75+
ByteVector code;
76+
syscalls::mmap(size, convertMemoryProtectionFromPOSIX(protection), code);
77+
78+
error = ptrace().execute(_pid, info, &code[0], code.size(), *address);
79+
if (error != kSuccess)
80+
return error;
81+
82+
if (*address == reinterpret_cast<uint64_t>(MAP_FAILED))
83+
return kErrorNoMemory;
84+
return kSuccess;
2385
}
2486

2587
ErrorCode Process::deallocateMemory(uint64_t address, size_t size) {
26-
return kErrorUnsupported;
88+
if (size == 0)
89+
return kErrorInvalidArgument;
90+
91+
ProcessInfo info;
92+
ErrorCode error = getInfo(info);
93+
if (error != kSuccess)
94+
return error;
95+
96+
ByteVector code;
97+
syscalls::munmap(address, size, code);
98+
99+
uint64_t result = 0;
100+
error = ptrace().execute(_pid, info, &code[0], code.size(), result);
101+
if (error != kSuccess)
102+
return error;
103+
104+
if (static_cast<int64_t>(result) < 0)
105+
return kErrorInvalidArgument;
106+
return kSuccess;
27107
}
28108
}
29109
}

0 commit comments

Comments
 (0)