2017-05-23 11 views
8

के साथ आईओएस पर __debugbreak() जैसे पुन: प्रयोज्य जोर/ब्रेकपॉइंट मैं कस्टम एसेट मैक्रो (जो assert.h के समान है) को लागू करने की कोशिश कर रहा हूं, लेकिन मैं प्राप्त करने और जोर देने के बाद निष्पादन जारी रखने में सक्षम होना चाहता हूं।एमएस कंपाइलर

उदाहरण के लिए, ऐसे ही एक ASSERT कार्यान्वयन हो सकता है:

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

__debugbreak माइक्रोसॉफ्ट compilers में एक आंतरिक समारोह है कि सॉफ्टवेयर ब्रेकपाइंट सम्मिलित करता है, 86 में _asm int 3 के बराबर है। आईओएस के लिए __debugbreak को लागू करने के विभिन्न तरीके हैं:

  • __asm__("int $3"); x86 के लिए। नियमित हाथ के लिए
  • __asm__("bkpt #0");
  • arm64 के लिए __asm__("brk #0");
  • __builtin_trap()
  • raise(SIGTRAP)

लेकिन उन सभी के साथ जब मेरे ज़ोर हिट मैं बस पर कदम नहीं कर सकते हैं और जिस तरह से मैं जब दृश्य स्टूडियो के साथ काम कर सकते हैं जारी रखने के लिए; जब मेरे आईओएस में कुछ जोर देता है तो यह जोर से अटक जाता है और मेरे पास समाप्त करने के अलावा कोई विकल्प नहीं है, मैं निर्देशक पॉइंटर को मैन्युअल रूप से भी नहीं ले जा सकता और जोर से नहीं छोड़ सकता।

क्या आईओएस पर आवेषण लागू करना संभव है जो डीबगर में टूट जाएगा और फिर भी मुझे निष्पादन जारी रखने की अनुमति देगा?

+0

__asm ​​__ ("int $ 3"); मेरे लिए ठीक काम करता है – Spads

+0

@Spads 'int $ 3' सिम्युलेटर में केवल इसलिए काम करता है क्योंकि यह x86 है, हाथ नहीं। – Pavel

+0

उचित बिंदु। इसे आईफोन पर नहीं देखा। – Spads

उत्तर

6

बाहर कर देता है मैं प्राप्त कर सकते हैं एक 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) 

एक कारण के लिए पीछे एनओपी mov x0, x0 है: जब जोर टूटता है, डिबगर ज़ोर लाइन पर बिल्कुल बंद करो और कुछ यादृच्छिक नहीं होंगे रेखा जहां निम्नलिखित निर्देश स्थित होने के लिए होता है।

यदि कोई आईओएस पर IsDebuggerPresent के समतुल्य की तलाश में है, तो आप AmIBeingDebugged का उपयोग कर सकते हैं।

+1

जहां तक ​​मैं कह सकता हूं, इसमें कुछ महत्वपूर्ण याद आ रही है: 'svC# 0x80' (जिसे "सॉफ़्टवेयर इंटरप्ट" कॉल करने के लिए कॉल करने से पहले सिस्टम कॉल को' आर 12' में जाना आवश्यक है) एक कर्नेल विधि] (https://www.theiphonewiki.com/wiki/Kernel_Syscalls))। तो ऐसा लगता है कि शुद्ध मौके से आपको 'आर 12' में एक मूल्य मिला जो आपके लिए उपयोगी है, शायद 'ptrace'। मैं आपको अपने कामकाजी संस्करण में 'आर 12' में देखने की सलाह देता हूं। – DarkDust

+0

हां, मुझे लगता है कि आप सही हैं, AmIBeingDebugged थ्रेड में मेरी टिप्पणी मान्य नहीं है। मैंने सोचा कि 'एसवीसी # 80' बस लाइव असेंबली का निरीक्षण करके बिना किसी पैराम की जांच किए। – Pavel

+0

एमुलेटर के लिए आपको x86_64 की जांच करने की आवश्यकता है। – Spads