2017-05-23 13 views
8

Tôi đang cố gắng triển khai macro nội dung tùy chỉnh (tương tự như những gì assert.h có), nhưng tôi muốn có thể tiếp tục thực hiện sau khi tôi nhận được và khẳng định.Xác nhận/breakpoint có thể tiếp tục trên iOS như __debugbreak() với trình biên dịch MS

Ví dụ, một ASSERT thực hiện như vậy có thể là:

#define ASSERT(expr) ((void)((!!(expr)) || (__debugbreak(), 0))) 

__debugbreak là một chức năng nội tại trong các trình biên dịch Microsoft chèn phần mềm breakpoint, tương đương với _asm int 3 trong x86. cho iOS có nhiều cách khác nhau để triển khai __debugbreak:

  • __asm__("int $3"); cho x86.
  • __asm__("bkpt #0"); cho cánh tay thông thường.
  • __asm__("brk #0"); cho arm64
  • __builtin_trap()
  • raise(SIGTRAP)

nhưng với tất cả trong số họ khi hit khẳng định của tôi, tôi có thể không chỉ đơn giản là bước qua và tiếp tục con đường tôi có thể làm gì khi làm việc với visual studio; khi một cái gì đó khẳng định trong iOS của tôi xây dựng nó bị mắc kẹt tại khẳng định và tôi không có sự lựa chọn nhưng để chấm dứt, tôi thậm chí không thể di chuyển con trỏ hướng dẫn bằng tay và bỏ qua khẳng định.

Có thể triển khai các xác nhận trên iOS có thể đột nhập vào trình gỡ lỗi và vẫn cho phép tôi tiếp tục thực hiện không?

+0

__asm ​​__ ("int $ 3"); hoạt động tốt cho tôi – Spads

+0

@Spads 'int $ 3' hoạt động trong trình mô phỏng chỉ vì nó là x86, không phải nhánh. – Pavel

+0

Điểm công bằng. Không kiểm tra trên iPhone. – Spads

Trả lời

6

Hóa ra tôi có thể đạt được những gì tôi muốn bằng cách làm một syscall:

#include <unistd.h> 

#if defined(__APPLE__) && defined(__aarch64__) 
#define __debugbreak() __asm__ __volatile__(   \ 
    " mov x0, %x0; \n" /* pid    */ \ 
    " mov x1, #0x11; \n" /* SIGSTOP   */ \ 
    " mov x16, #0x25; \n" /* syscall 37 = kill */ \ 
    " svc #0x80  \n" /* software interrupt */ \ 
    " mov x0, x0  \n" /* nop    */ \ 
    :: "r"(getpid())         \ 
    : "x0", "x1", "x16", "memory") 
#elif defined(__APPLE__) && defined(__arm__) 
#define __debugbreak() __asm__ __volatile__(   \ 
    " mov r0, %0;  \n" /* pid    */ \ 
    " mov r1, #0x11; \n" /* SIGSTOP   */ \ 
    " mov r12, #0x25; \n" /* syscall 37 = kill */ \ 
    " svc #0x80  \n" /* software interrupt */ \ 
    " mov r0, r0  \n" /* nop    */ \ 
    :: "r"(getpid())         \ 
    : "r0", "r1", "r12", "memory") 
#elif defined(__APPLE__) && (defined(__i386__) || defined(__x86_64__)) 
#define __debugbreak() __asm__ __volatile__("int $3; mov %eax, %eax") 
#endif 

#define MYASSERT(expr) do { if (!(expr)){ __debugbreak(); } } while(0) 

Có một dấu NOP mov x0, x0 vì một lý do: khi khẳng định phá vỡ, debugger sẽ dừng chính xác ở dòng khẳng định và không phải một số ngẫu nhiên dòng nơi đặt lệnh sau đây.

Trong trường hợp nếu ai đó đang tìm kiếm tương đương với IsDebuggerPresent trên iOS, bạn có thể sử dụng AmIBeingDebugged.

+1

Theo như tôi có thể nói, điều này thiếu một số điều quan trọng: gọi hệ thống để thực hiện các nhu cầu đi vào 'r12' trước khi gọi' svC# 0x80' (đó là ["ngắt phần mềm" để gọi một phương pháp hạt nhân] (https://www.theiphonewiki.com/wiki/Kernel_Syscalls)). Vì vậy, có vẻ như là do cơ hội thuần khiết bạn có một giá trị trong 'r12' hữu ích cho bạn, có thể là' ptrace'. Tôi khuyên bạn nên xem xét 'r12' trong phiên bản làm việc của bạn. – DarkDust

+0

Vâng, tôi nghĩ bạn đúng, bình luận của tôi trong chủ đề AmIBeingDebugged không hợp lệ. Tôi thấy rằng 'svC# 80' chỉ đơn giản bằng cách kiểm tra việc lắp ráp trực tiếp mà không cần kiểm tra thông số nào cần thiết. – Pavel

+0

Đối với trình mô phỏng, bạn cũng cần kiểm tra x86_64. – Spads

Các vấn đề liên quan