remotemono
asmutil.h
1 /*
2  Copyright 2020 David "Alemarius Nexus" Lerch
3 
4  This file is part of RemoteMono.
5 
6  RemoteMono is free software: you can redistribute it and/or modify
7  it under the terms of the GNU Lesser General Public License as published
8  by the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  RemoteMono is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU Lesser General Public License for more details.
15 
16  You should have received a copy of the GNU Lesser General Public License
17  along with RemoteMono. If not, see <https://www.gnu.org/licenses/>.
18  */
19 
20 #pragma once
21 
22 #include "config.h"
23 
24 #include <BlackBone/Process/Process.h>
25 #include "impl/RMonoTypes.h"
26 
27 
28 
29 namespace remotemono
30 {
31 
32 
33 
45 inline void AsmGenGchandleGetTargetChecked(blackbone::IAsmHelper& a, blackbone::ptr_t rawAddr, bool x64)
46 {
47  // NOTE: Always expects an irmono_gchandle in zcx.
48 
49  using namespace asmjit;
50  using namespace asmjit::host;
51 
52  auto lSkip = a->newLabel();
53 
54  static_assert(REMOTEMONO_GCHANDLE_INVALID == 0);
55 
56  // zax = nullptr;
57  a->xor_(a->zax, a->zax);
58 
59  // if (zcx != REMOTEMONO_GCHANDLE_INVALID) {
60  a->jecxz(a->zcx, lSkip);
61 
62  // zax = mono_gchandle_get_target(zcx);
63  a->mov(a->zax, rawAddr);
64  if (x64) {
65  a->sub(a->zsp, 32);
66  a->call(a->zax);
67  a->add(a->zsp, 32);
68  } else {
69  a->push(a->zcx);
70  a->call(a->zax);
71  a->pop(a->zcx);
72  }
73 
74  // }
75  a->bind(lSkip);
76 }
77 
78 
93 inline void AsmGenGchandleNewChecked(blackbone::IAsmHelper& a, blackbone::ptr_t rawAddr, bool x64)
94 {
95  // NOTE: Always expects an IRMonoObjectPtrRaw in zcx.
96 
97  using namespace asmjit;
98  using namespace asmjit::host;
99 
100  auto lSkip = a->newLabel();
101 
102  static_assert(REMOTEMONO_GCHANDLE_INVALID == 0);
103 
104  // zax = REMOTEMONO_GCHANDLE_INVALID;
105  a->xor_(a->zax, a->zax);
106 
107  // if (zcx != nullptr) {
108  a->jecxz(a->zcx, lSkip);
109 
110  // zax = mono_gchandle_new(zcx, false);
111  a->mov(a->zax, rawAddr);
112  if (x64) {
113  a->xor_(a->zdx, a->zdx); // Don't pin the GCHandle
114  a->sub(a->zsp, 32);
115  a->call(a->zax);
116  a->add(a->zsp, 32);
117  } else {
118  a->push(0); // Don't pin the GCHandle
119  a->push(a->zcx);
120  a->call(a->zax);
121  a->add(a->zsp, 2*sizeof(uint32_t));
122  }
123 
124  // }
125  a->bind(lSkip);
126 }
127 
128 
129 inline void AsmGenIsValueTypeInstance (
130  blackbone::IAsmHelper& a,
131  blackbone::ptr_t objectGetClassAddr,
132  blackbone::ptr_t classIsValuetypeAddr,
133  bool x64
134 ) {
135  // bool is_value_type_instance(IRMonoObjectPtrRaw obj)
136  //
137  // obj: zcx
138 
139  using namespace asmjit;
140  using namespace asmjit::host;
141 
142  auto lSkip = a->newLabel();
143 
144  // zax = false;
145  a->xor_(a->zax, a->zax);
146 
147  // if (obj != nullptr) {
148  a->jecxz(a->zcx, lSkip);
149 
150  // zax = mono_class_is_valuetype(mono_object_get_class(obj));
151  if (x64) {
152  a->sub(a->zsp, 32);
153  a->mov(a->zax, objectGetClassAddr);
154  a->call(a->zax);
155  a->mov(a->zcx, a->zax);
156  a->mov(a->zax, classIsValuetypeAddr);
157  a->call(a->zax);
158  a->add(a->zsp, 32);
159  } else {
160  a->push(a->zcx);
161  a->mov(a->zax, objectGetClassAddr);
162  a->call(a->zax);
163  a->mov(ptr(a->zsp), a->zax);
164  a->mov(a->zax, classIsValuetypeAddr);
165  a->call(a->zax);
166  a->add(a->zsp, sizeof(uint32_t));
167  }
168 
169  // }
170  a->bind(lSkip);
171 }
172 
173 
174 inline void AsmGenObjectUnbox (
175  blackbone::IAsmHelper& a,
176  blackbone::ptr_t objectUnboxAddr,
177  bool x64
178 ) {
179  // void* object_unbox(IRMonoObjectPtrRaw obj)
180  //
181  // obj: zcx
182 
183  using namespace asmjit;
184  using namespace asmjit::host;
185 
186 
187  // zax = mono_object_unbox(obj);
188  if (x64) {
189  a->mov(a->zax, objectUnboxAddr);
190  a->sub(a->zsp, 32);
191  a->call(a->zax);
192  a->add(a->zsp, 32);
193  } else {
194  a->push(a->zcx);
195  a->mov(a->zax, objectUnboxAddr);
196  a->call(a->zax);
197  a->add(a->zsp, sizeof(uint32_t));
198  }
199 }
200 
201 
202 
203 }