DebugServer2
Loading...
Searching...
No Matches
Syscalls.h
1//
2// Copyright (c) 2014-present, Facebook, Inc.
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//
10
11#pragma once
12
13#include <asm-generic/unistd.h>
14#include <sys/mman.h>
15
16namespace ds2 {
17namespace Host {
18namespace Linux {
19namespace ARM64 {
20namespace Syscalls {
21
22namespace {
23static inline uint32_t MakeMovImmInstr(uint8_t reg, int32_t val) {
24 DS2ASSERT(reg <= 31);
25 DS2ASSERT(0 <= val && val <= 65535);
26 static const uint32_t base = 0xd2800000;
27 return base | (static_cast<uint16_t>(val) << 5) | reg;
28}
29
30static inline uint32_t MakeMovNegImmInstr(uint8_t reg, int32_t val) {
31 DS2ASSERT(reg <= 31);
32 DS2ASSERT(-65535 <= val && val <= 0);
33 static const uint32_t base = 0x92800000;
34 return base | (static_cast<uint16_t>(-val - 1) << 5) | reg;
35}
36
37static inline uint32_t MakeLdrRelInstr(uint8_t reg, int32_t offset) {
38 DS2ASSERT(reg <= 31);
39 DS2ASSERT(offset % 4 == 0);
40 static const uint32_t base = 0x58000000;
41 return base | (static_cast<uint16_t>(offset / 4) << 5) | reg;
42}
43
44static inline uint32_t MakeSvcInstr(uint16_t idx) {
45 static const uint32_t base = 0xd4000001;
46 return base | (idx << 5);
47}
48
49static inline uint32_t MakeBrkInstr(uint16_t idx) {
50 static const uint32_t base = 0xd4200000;
51 return base | (idx << 5);
52}
53
54template <typename T>
55static inline void InsertBytes(ByteVector &codestr, T value) {
56 auto valueBytes = reinterpret_cast<uint8_t *>(&value);
57 codestr.insert(codestr.end(), valueBytes, valueBytes + sizeof(T));
58}
59} // namespace
60
61static inline void PrepareMmapCode(size_t size, int protection,
62 ByteVector &codestr) {
63 static_assert(sizeof(size) == 8, "size_t should be 8-bytes long on ARM64");
64
65 for (uint32_t instr : {
66 MakeMovImmInstr(8, __NR_mmap), // mov x8, __NR_mmap
67 MakeMovImmInstr(0, 0), // mov x0, address
68 MakeLdrRelInstr(1, 7 * sizeof(uint32_t)), // ldr x1, <pc+28>
69 MakeMovImmInstr(2, protection), // mov x2, prot
70 MakeMovImmInstr(3, MAP_ANON | MAP_PRIVATE), // mov x3, flags
71 MakeMovNegImmInstr(4, -1), // mov x4, -1
72 MakeMovImmInstr(5, 0), // mov x5, 0
73 MakeSvcInstr(0), // svc #0
74 MakeBrkInstr(0x100), // brk #0x100
75 }) {
76 InsertBytes(codestr, instr);
77 }
78
79 // Append the raw data that `MakeLdrRelInstr` instructions will reference.
80 InsertBytes(codestr, size); // .quad XXXXXXXXXXXXXXXX
81}
82
83static inline void PrepareMunmapCode(uint64_t address, size_t size,
84 ByteVector &codestr) {
85 static_assert(sizeof(size) == 8, "size_t should be 8-bytes long on ARM64");
86
87 for (uint32_t instr : {
88 MakeMovImmInstr(8, __NR_munmap), // mov x8, __NR_munmap
89 MakeLdrRelInstr(0, 4 * sizeof(uint32_t)), // ldr x0, <pc+16>
90 MakeLdrRelInstr(1, 5 * sizeof(uint32_t)), // ldr x1, <pc+20>
91 MakeSvcInstr(0), // svc #0
92 MakeBrkInstr(0x100), // brk #0x100
93 }) {
94 InsertBytes(codestr, instr);
95 }
96
97 // Append the raw data that `MakeLdrRelInstr` instructions will reference.
98 InsertBytes(codestr, address); // .quad XXXXXXXXXXXXXXXX
99 InsertBytes(codestr, size); // .quad XXXXXXXXXXXXXXXX
100}
101} // namespace Syscalls
102} // namespace ARM64
103} // namespace Linux
104} // namespace Host
105} // namespace ds2