#include #include uint64_t get_tpidr(void) { uint64_t tpidr = 0; __asm__ volatile("mrs %0, tpidr_el0" : "=r"(tpidr)); return tpidr; } uint64_t get_tpidr2(void) { uint64_t tpidr2 = 0; // S3_3_C13_C0_5 means tpidr2, and will work with older tools. __asm__ volatile("mrs %0, S3_3_C13_C0_5" : "=r"(tpidr2)); return tpidr2; } void set_tpidr(uint64_t value) { __asm__ volatile("msr tpidr_el0, %0" ::"r"(value)); } void set_tpidr2(uint64_t value) { __asm__ volatile("msr S3_3_C13_C0_5, %0" ::"r"(value)); } bool use_tpidr2 = false; const uint64_t tpidr_pattern = 0x1122334455667788; const uint64_t tpidr2_pattern = 0x8877665544332211; void expr_func() { set_tpidr(~tpidr_pattern); if (use_tpidr2) set_tpidr2(~tpidr2_pattern); } int main(int argc, char *argv[]) { use_tpidr2 = argc > 1; uint64_t original_tpidr = get_tpidr(); // Accessing this on a core without it produces SIGILL. Only do this if // requested. uint64_t original_tpidr2 = 0; if (use_tpidr2) original_tpidr2 = get_tpidr2(); set_tpidr(tpidr_pattern); if (use_tpidr2) set_tpidr2(tpidr2_pattern); // Set break point at this line. // lldb will now set its own pattern(s) for us to find. uint64_t new_tpidr = get_tpidr(); volatile bool tpidr_was_set = new_tpidr == 0x1111222233334444; uint64_t new_tpidr2 = 0; volatile bool tpidr2_was_set = false; if (use_tpidr2) { new_tpidr2 = get_tpidr2(); tpidr2_was_set = new_tpidr2 == 0x4444333322221111; } set_tpidr(original_tpidr); if (use_tpidr2) set_tpidr2(original_tpidr2); return 0; // Set break point 2 at this line. }