@@ -212,12 +212,120 @@ uint64_t ReadCapstoneReg(HostThreadContext* context, arm64_reg reg) {
212
212
return context->x [29 ];
213
213
case ARM64_REG_X30:
214
214
return context->x [30 ];
215
+ case ARM64_REG_W0:
216
+ return uint32_t (context->x [0 ]);
217
+ case ARM64_REG_W1:
218
+ return uint32_t (context->x [1 ]);
219
+ case ARM64_REG_W2:
220
+ return uint32_t (context->x [2 ]);
221
+ case ARM64_REG_W3:
222
+ return uint32_t (context->x [3 ]);
223
+ case ARM64_REG_W4:
224
+ return uint32_t (context->x [4 ]);
225
+ case ARM64_REG_W5:
226
+ return uint32_t (context->x [5 ]);
227
+ case ARM64_REG_W6:
228
+ return uint32_t (context->x [6 ]);
229
+ case ARM64_REG_W7:
230
+ return uint32_t (context->x [7 ]);
231
+ case ARM64_REG_W8:
232
+ return uint32_t (context->x [8 ]);
233
+ case ARM64_REG_W9:
234
+ return uint32_t (context->x [9 ]);
235
+ case ARM64_REG_W10:
236
+ return uint32_t (context->x [10 ]);
237
+ case ARM64_REG_W11:
238
+ return uint32_t (context->x [11 ]);
239
+ case ARM64_REG_W12:
240
+ return uint32_t (context->x [12 ]);
241
+ case ARM64_REG_W13:
242
+ return uint32_t (context->x [13 ]);
243
+ case ARM64_REG_W14:
244
+ return uint32_t (context->x [14 ]);
245
+ case ARM64_REG_W15:
246
+ return uint32_t (context->x [15 ]);
247
+ case ARM64_REG_W16:
248
+ return uint32_t (context->x [16 ]);
249
+ case ARM64_REG_W17:
250
+ return uint32_t (context->x [17 ]);
251
+ case ARM64_REG_W18:
252
+ return uint32_t (context->x [18 ]);
253
+ case ARM64_REG_W19:
254
+ return uint32_t (context->x [19 ]);
255
+ case ARM64_REG_W20:
256
+ return uint32_t (context->x [20 ]);
257
+ case ARM64_REG_W21:
258
+ return uint32_t (context->x [21 ]);
259
+ case ARM64_REG_W22:
260
+ return uint32_t (context->x [22 ]);
261
+ case ARM64_REG_W23:
262
+ return uint32_t (context->x [23 ]);
263
+ case ARM64_REG_W24:
264
+ return uint32_t (context->x [24 ]);
265
+ case ARM64_REG_W25:
266
+ return uint32_t (context->x [25 ]);
267
+ case ARM64_REG_W26:
268
+ return uint32_t (context->x [26 ]);
269
+ case ARM64_REG_W27:
270
+ return uint32_t (context->x [27 ]);
271
+ case ARM64_REG_W28:
272
+ return uint32_t (context->x [28 ]);
273
+ case ARM64_REG_W29:
274
+ return uint32_t (context->x [29 ]);
275
+ case ARM64_REG_W30:
276
+ return uint32_t (context->x [30 ]);
215
277
default :
216
278
assert_unhandled_case (reg);
217
279
return 0 ;
218
280
}
219
281
}
220
282
283
+ bool TestCapstonePstate (arm64_cc cond, uint32_t pstate) {
284
+ // https://devblogs.microsoft.com/oldnewthing/20220815-00/?p=106975
285
+ // Upper 4 bits of pstate are NZCV
286
+ const bool N = !!(pstate & 0x80000000 );
287
+ const bool Z = !!(pstate & 0x40000000 );
288
+ const bool C = !!(pstate & 0x20000000 );
289
+ const bool V = !!(pstate & 0x10000000 );
290
+ switch (cond) {
291
+ case ARM64_CC_EQ:
292
+ return (Z == true );
293
+ case ARM64_CC_NE:
294
+ return (Z == false );
295
+ case ARM64_CC_HS:
296
+ return (C == true );
297
+ case ARM64_CC_LO:
298
+ return (C == false );
299
+ case ARM64_CC_MI:
300
+ return (N == true );
301
+ case ARM64_CC_PL:
302
+ return (N == false );
303
+ case ARM64_CC_VS:
304
+ return (V == true );
305
+ case ARM64_CC_VC:
306
+ return (V == false );
307
+ case ARM64_CC_HI:
308
+ return ((C == true ) && (Z == false ));
309
+ case ARM64_CC_LS:
310
+ return ((C == false ) || (Z == true ));
311
+ case ARM64_CC_GE:
312
+ return (N == V);
313
+ case ARM64_CC_LT:
314
+ return (N != V);
315
+ case ARM64_CC_GT:
316
+ return ((Z == false ) && (N == V));
317
+ case ARM64_CC_LE:
318
+ return ((Z == true ) || (N != V));
319
+ case ARM64_CC_AL:
320
+ return true ;
321
+ case ARM64_CC_NV:
322
+ return false ;
323
+ default :
324
+ assert_unhandled_case (cond);
325
+ return false ;
326
+ }
327
+ }
328
+
221
329
uint64_t A64Backend::CalculateNextHostInstruction (ThreadDebugInfo* thread_info,
222
330
uint64_t current_pc) {
223
331
auto machine_code_ptr = reinterpret_cast <const uint8_t *>(current_pc);
@@ -233,23 +341,52 @@ uint64_t A64Backend::CalculateNextHostInstruction(ThreadDebugInfo* thread_info,
233
341
case ARM64_INS_B:
234
342
case ARM64_INS_BL: {
235
343
assert_true (detail.operands [0 ].type == ARM64_OP_IMM);
236
- uint64_t target_pc = static_cast <uint64_t >(detail.operands [0 ].imm );
237
- return current_pc + target_pc;
344
+ const int64_t pc_offset = static_cast <int64_t >(detail.operands [0 ].imm );
345
+ const bool test_passed =
346
+ TestCapstonePstate (detail.cc , thread_info->host_context .cpsr );
347
+ if (test_passed) {
348
+ return current_pc + pc_offset;
349
+ } else {
350
+ return current_pc + insn.size ;
351
+ }
238
352
} break ;
239
- case ARM64_INS_BLR :
240
- case ARM64_INS_BR : {
353
+ case ARM64_INS_BR :
354
+ case ARM64_INS_BLR : {
241
355
assert_true (detail.operands [0 ].type == ARM64_OP_REG);
242
- uint64_t target_pc =
356
+ const uint64_t target_pc =
243
357
ReadCapstoneReg (&thread_info->host_context , detail.operands [0 ].reg );
244
358
return target_pc;
245
359
} break ;
246
360
case ARM64_INS_RET: {
247
- assert_zero (detail.op_count );
248
- // Jump to link register
249
- return thread_info->host_context .x [30 ];
361
+ assert_true (detail.operands [0 ].type == ARM64_OP_REG);
362
+ const uint64_t target_pc =
363
+ ReadCapstoneReg (&thread_info->host_context , detail.operands [0 ].reg );
364
+ return target_pc;
365
+ } break ;
366
+ case ARM64_INS_CBNZ: {
367
+ assert_true (detail.operands [0 ].type == ARM64_OP_REG);
368
+ assert_true (detail.operands [1 ].type == ARM64_OP_IMM);
369
+ const int64_t pc_offset = static_cast <int64_t >(detail.operands [1 ].imm );
370
+ const bool test_passed = (0 != ReadCapstoneReg (&thread_info->host_context ,
371
+ detail.operands [0 ].reg ));
372
+ if (test_passed) {
373
+ return current_pc + pc_offset;
374
+ } else {
375
+ return current_pc + insn.size ;
376
+ }
377
+ } break ;
378
+ case ARM64_INS_CBZ: {
379
+ assert_true (detail.operands [0 ].type == ARM64_OP_REG);
380
+ assert_true (detail.operands [1 ].type == ARM64_OP_IMM);
381
+ const int64_t pc_offset = static_cast <int64_t >(detail.operands [1 ].imm );
382
+ const bool test_passed = (0 == ReadCapstoneReg (&thread_info->host_context ,
383
+ detail.operands [0 ].reg ));
384
+ if (test_passed) {
385
+ return current_pc + pc_offset;
386
+ } else {
387
+ return current_pc + insn.size ;
388
+ }
250
389
} break ;
251
- case ARM64_INS_CBNZ:
252
- case ARM64_INS_CBZ:
253
390
default : {
254
391
// Not a branching instruction - just move over it.
255
392
return current_pc + insn.size ;
0 commit comments