@@ -69,13 +69,13 @@ static void ProtectGap(uptr addr, uptr size) {
69
69
70
70
Report (
71
71
" ERROR: Failed to protect the shadow gap. "
72
- " ASan cannot proceed correctly. ABORTING.\n " );
72
+ " HWASan cannot proceed correctly. ABORTING.\n " );
73
73
DumpProcessMap ();
74
74
Die ();
75
75
}
76
76
77
77
// LowMem covers as much of the first 4GB as possible.
78
- const uptr kLowMemEnd = 1UL << 32 ;
78
+ const uptr kLowMemEnd = 1UL << 32 ;
79
79
const uptr kLowShadowEnd = kLowMemEnd >> kShadowScale ;
80
80
const uptr kLowShadowStart = kLowShadowEnd >> kShadowScale ;
81
81
static uptr kHighShadowStart ;
@@ -85,7 +85,6 @@ static uptr kHighMemStart;
85
85
bool InitShadow () {
86
86
const uptr maxVirtualAddress = GetMaxUserVirtualAddress ();
87
87
88
-
89
88
// HighMem covers the upper part of the address space.
90
89
kHighShadowEnd = (maxVirtualAddress >> kShadowScale ) + 1 ;
91
90
kHighShadowStart = Max (kLowMemEnd , kHighShadowEnd >> kShadowScale );
@@ -186,50 +185,65 @@ struct AccessInfo {
186
185
bool recover;
187
186
};
188
187
189
- #if defined(__aarch64__)
190
188
static AccessInfo GetAccessInfo (siginfo_t *info, ucontext_t *uc) {
191
- // Access type is encoded in BRK immediate as 0x9XY,
192
- // where X&1 is 1 for store, 0 for load,
193
- // and X&2 is 1 if the error is recoverable.
194
- // Valid values of Y are 0 to 4, which are interpreted as log2(access_size),
195
- // and 0xF, which means that access size is stored in X1 register.
196
- // Access address is always in X0 register.
197
- AccessInfo ai;
189
+ // Access type is passed in a platform dependent way (see below) and encoded
190
+ // as 0xXY, where X&1 is 1 for store, 0 for load, and X&2 is 1 if the error is
191
+ // recoverable. Valid values of Y are 0 to 4, which are interpreted as
192
+ // log2(access_size), and 0xF, which means that access size is passed via
193
+ // platform dependent register (see below).
194
+ #if defined(__aarch64__)
195
+ // Access type is encoded in BRK immediate as 0x900 + 0xXY. For Y == 0xF,
196
+ // access size is stored in X1 register. Access address is always in X0
197
+ // register.
198
198
uptr pc = (uptr)info->si_addr ;
199
- unsigned code = ((*(u32 *)pc) >> 5 ) & 0xffff ;
199
+ const unsigned code = ((*(u32 *)pc) >> 5 ) & 0xffff ;
200
200
if ((code & 0xff00 ) != 0x900 )
201
- return AccessInfo{0 , 0 , false , false }; // Not ours.
202
- bool is_store = code & 0x10 ;
203
- bool recover = code & 0x20 ;
204
- unsigned size_log = code & 0xf ;
201
+ return AccessInfo{}; // Not ours.
202
+
203
+ const bool is_store = code & 0x10 ;
204
+ const bool recover = code & 0x20 ;
205
+ const const uptr addr = uc->uc_mcontext .regs [0 ];
206
+ const unsigned size_log = code & 0xf ;
205
207
if (size_log > 4 && size_log != 0xf )
206
- return AccessInfo{0 , 0 , false , false }; // Not ours.
207
-
208
- ai.is_store = is_store;
209
- ai.is_load = !is_store;
210
- ai.addr = uc->uc_mcontext .regs [0 ];
211
- if (size_log == 0xf )
212
- ai.size = uc->uc_mcontext .regs [1 ];
213
- else
214
- ai.size = 1U << size_log;
215
- ai.recover = recover;
216
- return ai;
217
- }
208
+ return AccessInfo{}; // Not ours.
209
+ const uptr size = size_log == 0xf ? uc->uc_mcontext .regs [1 ] : 1U << size_log;
210
+
211
+ #elif defined(__x86_64__)
212
+ // Access type is encoded in the instruction following INT3 as
213
+ // NOP DWORD ptr [EAX + 0x40 + 0xXY]. For Y == 0xF, access size is stored in
214
+ // RSI register. Access address is always in RDI register.
215
+ uptr pc = (uptr)uc->uc_mcontext .gregs [REG_RIP];
216
+ uint8_t *nop = (uint8_t *)pc;
217
+ if (*nop != 0x0f || *(nop + 1 ) != 0x1f || *(nop + 2 ) != 0x40 ||
218
+ *(nop + 3 ) < 0x40 )
219
+ return AccessInfo{}; // Not ours.
220
+ const unsigned code = *(nop + 3 );
221
+
222
+ const bool is_store = code & 0x10 ;
223
+ const bool recover = code & 0x20 ;
224
+ const uptr addr = uc->uc_mcontext .gregs [REG_RDI];
225
+ const unsigned size_log = code & 0xf ;
226
+ if (size_log > 4 && size_log != 0xf )
227
+ return AccessInfo{}; // Not ours.
228
+ const uptr size =
229
+ size_log == 0xf ? uc->uc_mcontext .gregs [REG_RSI] : 1U << size_log;
230
+
218
231
#else
219
- static AccessInfo GetAccessInfo (siginfo_t *info, ucontext_t *uc) {
220
- return AccessInfo{0 , 0 , false , false };
221
- }
232
+ # error Unsupported architecture
222
233
#endif
223
234
235
+ return AccessInfo{addr, size, is_store, !is_store, recover};
236
+ }
237
+
224
238
static bool HwasanOnSIGTRAP (int signo, siginfo_t *info, ucontext_t *uc) {
225
- SignalContext sig{info, uc};
226
239
AccessInfo ai = GetAccessInfo (info, uc);
227
240
if (!ai.is_store && !ai.is_load )
228
241
return false ;
229
242
230
243
InternalScopedBuffer<BufferedStackTrace> stack_buffer (1 );
231
244
BufferedStackTrace *stack = stack_buffer.data ();
232
245
stack->Reset ();
246
+ SignalContext sig{info, uc};
233
247
GetStackTrace (stack, kStackTraceMax , sig.pc , sig.bp , uc,
234
248
common_flags ()->fast_unwind_on_fatal );
235
249
@@ -239,7 +253,12 @@ static bool HwasanOnSIGTRAP(int signo, siginfo_t *info, ucontext_t *uc) {
239
253
if (flags ()->halt_on_error || !ai.recover )
240
254
Die ();
241
255
256
+ #if defined(__aarch64__)
242
257
uc->uc_mcontext .pc += 4 ;
258
+ #elif defined(__x86_64__)
259
+ #else
260
+ # error Unsupported architecture
261
+ #endif
243
262
return true ;
244
263
}
245
264
0 commit comments