assembly m1 mac,从程序集调用nanosleep

mtb9vblg  于 2023-01-02  发布在  Mac
关注(0)|答案(1)|浏览(215)

我想从汇编调用nanosleep之类的东西,只使用SVC调用,但如何使用我所拥有的有限信息来实现这一点并不明显,下面是macos系统调用签名列表:https://opensource.apple.com/source/xnu/xnu-1504.3.12/bsd/kern/syscalls.master
我试着弄清楚C调用nanosleep时会做什么,我可以把它简化成这样:

struct timespec {  long tv_sec;  long tv_nsec; };

int nanosleep(const struct timespec *__rqtp, struct timespec *__rmtp)
__asm("_" "nanosleep" );

int main() {
    struct timespec remaining, request = { 3, 1 };
    int response = nanosleep(&request, &remaining); }

我不确定__asm是做什么的,因为它看起来不像汇编。无论如何,我在苹果的libc源代码中找到了nanosleep的实现。它依赖于对clock_get_time的调用,而这在libc中没有定义。我在XNU源代码中找到了对clock_get_time的提及,但这是在一个.defs文件中,我不知道它是什么,它似乎也没有实现。
无论如何,是否有关于SVC调用的更好的文档,或者我可以在哪里找到libc SVC实现的程序集?
任何信息或想法都非常感谢。

bqucvtff

bqucvtff1#

首先,让我们把问题的标题去掉,从汇编调用nanosleep的方式如下:

mov x8, 3
stp x8, xzr, [sp, -0x10]!   // 3 seconds, 0 nanoseconds
mov x0, sp
mov x1, 0
bl _nanosleep
add sp, sp, 0x10

您只需要使用libc实现,对于大多数情况,您真的不应该深入到更深的层次,因为a)在arm 64上,操作系统强制您链接libSystem(因此链接libc),b)因为达尔文内核ABI(s)不稳定。
也就是说,让我们看看它是如何工作的引擎盖下。
latest Libc source drop中,我们发现nanosleepgen/nanosleep.c中实际上有两种实现:一个用于#if __DARWIN_UNIX03,使用clock_get_time,另一个用于另一种情况,使用mach_absolute_timemach_wait_until。生产中实际使用的是前者:

int nanosleep(const struct timespec *requested_time, struct timespec *remaining_time) {
    kern_return_t kret;
    int ret;
    mach_timespec_t current;
    mach_timespec_t completion;
   
    if (__unix_conforming == 0)
        __unix_conforming = 1;

#ifdef VARIANT_CANCELABLE
    pthread_testcancel();
#endif /* VARIANT_CANCELABLE */

    if ((requested_time == NULL) || (requested_time->tv_sec < 0) || (requested_time->tv_nsec >= NSEC_PER_SEC)) {
        errno = EINVAL;
        return -1;
    }

    if (remaining_time != NULL) {
        /* once we add requested_time, this will be the completion time */
        kret = clock_get_time(clock_port, &completion);
        if (kret != KERN_SUCCESS) {
            fprintf(stderr, "clock_get_time() failed: %s\n", mach_error_string(kret));
            errno = EINVAL;
            return -1;
        }
    }
    ret = SEMWAIT_SIGNAL(clock_sem, MACH_PORT_NULL, 1, 1, (int64_t)requested_time->tv_sec, (int32_t)requested_time->tv_nsec);    
    if (ret < 0) {
        if (errno == ETIMEDOUT) {
            return 0;
        } else if (errno == EINTR) {
            if (remaining_time != NULL) {
                ret = clock_get_time(clock_port, &current);
                if (ret != KERN_SUCCESS) {
                    fprintf(stderr, "clock_get_time() failed: %s\n", mach_error_string(ret));
                    return -1;
                }
                /* This depends on the layout of a mach_timespec_t and timespec_t being equivalent */
                ADD_MACH_TIMESPEC(&completion, requested_time);
                /* We have to compare first, since mach_timespect_t contains unsigned integers */
                if(CMP_MACH_TIMESPEC(&completion, &current) > 0) {
                    SUB_MACH_TIMESPEC(&completion, &current);
                    remaining_time->tv_sec = completion.tv_sec;
                    remaining_time->tv_nsec = completion.tv_nsec;
                } else {
                    bzero(remaining_time, sizeof(*remaining_time));
                }
            }
        } else {
            errno = EINVAL;
        }
    }
    return -1;
}

最后得到/usr/lib/system/libsystem_c.dylib(由/usr/lib/libSystem.B.dylib重新导出)。我们可以使用dlopen/dlsym转储字节,从dyld_shared_cache中提取dylib,或者从ramdisk中获取它来查看程序集:

;-- _nanosleep:
0x0000e4d4      7f2303d5       pacibsp
0x0000e4d8      ff0301d1       sub sp, sp, 0x40
0x0000e4dc      f44f02a9       stp x20, x19, [sp, 0x20]
0x0000e4e0      fd7b03a9       stp x29, x30, [sp, 0x30]
0x0000e4e4      fdc30091       add x29, sp, 0x30
0x0000e4e8      f30301aa       mov x19, x1
0x0000e4ec      f40300aa       mov x20, x0
0x0000e4f0      ff7f01a9       stp xzr, xzr, [sp, 0x10]
0x0000e4f4      a80300d0       adrp x8, reloc.__unix_conforming
0x0000e4f8      080140f9       ldr x8, [x8]
0x0000e4fc      090140b9       ldr w9, [x8]
0x0000e500      69000035       cbnz w9, 0xe50c
0x0000e504      29008052       mov w9, 1
0x0000e508      090100b9       str w9, [x8]
0x0000e50c      e5b00194       bl sym.imp.pthread_testcancel
0x0000e510      140300b4       cbz x20, 0xe570
0x0000e514      840240f9       ldr x4, [x20]
0x0000e518      c402f8b7       tbnz x4, 0x3f, 0xe570
0x0000e51c      850640f9       ldr x5, [x20, 8]
0x0000e520      08409952       mov w8, 0xca00
0x0000e524      4873a772       movk w8, 0x3b9a, lsl 16
0x0000e528      bf0008eb       cmp x5, x8
0x0000e52c      22020054       b.hs 0xe570
0x0000e530      330300b4       cbz x19, 0xe594
0x0000e534      48040090       adrp x8, 0x96000
0x0000e538      08112c91       add x8, x8, 0xb04
0x0000e53c      000140b9       ldr w0, [x8]
0x0000e540      e1430091       add x1, sp, 0x10
0x0000e544      c7ae0194       bl sym.imp.clock_get_time
0x0000e548      40020034       cbz w0, 0xe590
0x0000e54c      080400d0       adrp x8, sym._gCRAnnotations
0x0000e550      08210f91       add x8, x8, 0x3c8
0x0000e554      130140f9       ldr x19, [x8]
0x0000e558      c2af0194       bl sym.imp.mach_error_string
0x0000e55c      e00300f9       str x0, [sp]
0x0000e560      610300f0       adrp x1, 0x7d000
0x0000e564      21682b91       add x1, x1, 0xada
0x0000e568      e00313aa       mov x0, x19
0x0000e56c      73100094       bl sym._fprintf
0x0000e570      84ad0194       bl sym.imp.__error
0x0000e574      c8028052       mov w8, 0x16
0x0000e578      080000b9       str w8, [x0]
0x0000e57c      00008012       mov w0, -1
0x0000e580      fd7b43a9       ldp x29, x30, [sp, 0x30]
0x0000e584      f44f42a9       ldp x20, x19, [sp, 0x20]
0x0000e588      ff030191       add sp, sp, 0x40
0x0000e58c      ff0f5fd6       retab
0x0000e590      841640a9       ldp x4, x5, [x20]
0x0000e594      48040090       adrp x8, 0x96000
0x0000e598      08012c91       add x8, x8, 0xb00
0x0000e59c      000140b9       ldr w0, [x8]
0x0000e5a0      01008052       mov w1, 0
0x0000e5a4      22008052       mov w2, 1
0x0000e5a8      23008052       mov w3, 1
0x0000e5ac      d1ad0194       bl sym.imp.__semwait_signal
0x0000e5b0      60feff36       tbz w0, 0x1f, 0xe57c
0x0000e5b4      73ad0194       bl sym.imp.__error
0x0000e5b8      080040b9       ldr w8, [x0]
0x0000e5bc      1ff10071       cmp w8, 0x3c
0x0000e5c0      61000054       b.ne 0xe5cc
0x0000e5c4      00008052       mov w0, 0
0x0000e5c8      eeffff17       b 0xe580
0x0000e5cc      6dad0194       bl sym.imp.__error
0x0000e5d0      080040b9       ldr w8, [x0]
0x0000e5d4      1f110071       cmp w8, 4
0x0000e5d8      c1fcff54       b.ne 0xe570
0x0000e5dc      13fdffb4       cbz x19, 0xe57c
0x0000e5e0      48040090       adrp x8, 0x96000
0x0000e5e4      08112c91       add x8, x8, 0xb04
0x0000e5e8      000140b9       ldr w0, [x8]
0x0000e5ec      e1630091       add x1, sp, 0x18
0x0000e5f0      9cae0194       bl sym.imp.clock_get_time
0x0000e5f4      60010034       cbz w0, 0xe620
0x0000e5f8      080400d0       adrp x8, sym._gCRAnnotations
0x0000e5fc      08210f91       add x8, x8, 0x3c8
0x0000e600      130140f9       ldr x19, [x8]
0x0000e604      97af0194       bl sym.imp.mach_error_string
0x0000e608      e00300f9       str x0, [sp]
0x0000e60c      610300f0       adrp x1, 0x7d000
0x0000e610      21682b91       add x1, x1, 0xada
0x0000e614      e00313aa       mov x0, x19
0x0000e618      48100094       bl sym._fprintf
0x0000e61c      d8ffff17       b 0xe57c
0x0000e620      ea3f9952       mov w10, 0xc9ff
0x0000e624      4a73a772       movk w10, 0x3b9a, lsl 16
0x0000e628      880a40b9       ldr w8, [x20, 8]
0x0000e62c      ec274229       ldp w12, w9, [sp, 0x10]
0x0000e630      0bc08652       mov w11, 0x3600
0x0000e634      ab8cb872       movk w11, 0xc465, lsl 16
0x0000e638      2801080b       add w8, w9, w8
0x0000e63c      09010b0b       add w9, w8, w11
0x0000e640      1f010a6b       cmp w8, w10
0x0000e644      2bc1881a       csel w11, w9, w8, gt
0x0000e648      89d58c1a       cinc w9, w12, gt
0x0000e64c      8c0240b9       ldr w12, [x20]
0x0000e650      e81b40b9       ldr w8, [sp, 0x18]
0x0000e654      29010c0b       add w9, w9, w12
0x0000e658      3f01086b       cmp w9, w8
0x0000e65c      69000054       b.ls 0xe668
0x0000e660      ec1f40b9       ldr w12, [sp, 0x1c]
0x0000e664      05000014       b 0xe678
0x0000e668      c3010054       b.lo 0xe6a0
0x0000e66c      ec1f40b9       ldr w12, [sp, 0x1c]
0x0000e670      7f010c6b       cmp w11, w12
0x0000e674      6d010054       b.le 0xe6a0
0x0000e678      6b010c6b       subs w11, w11, w12
0x0000e67c      a5000054       b.pl 0xe690
0x0000e680      4a010b0b       add w10, w10, w11
0x0000e684      4b050011       add w11, w10, 1
0x0000e688      29050051       sub w9, w9, 1
0x0000e68c      e92f0229       stp w9, w11, [sp, 0x10]
0x0000e690      2801084b       sub w8, w9, w8
0x0000e694      697d4093       sxtw x9, w11
0x0000e698      682600a9       stp x8, x9, [x19]
0x0000e69c      b8ffff17       b 0xe57c
0x0000e6a0      7f7e00a9       stp xzr, xzr, [x19]
0x0000e6a4      b6ffff17       b 0xe57c

我不认为这是你真的想自己实现的东西。
但是不管怎样,您注意到它使用了clock_get_time,而clock_get_time并没有在那个库中定义,实际上clock_get_time/usr/lib/system/libsystem_kernel.dylib中:

;-- _clock_get_time:
0x00006440      7f2303d5       pacibsp
0x00006444      ff8301d1       sub sp, sp, 0x60
0x00006448      f44f04a9       stp x20, x19, [sp, 0x40]
0x0000644c      fd7b05a9       stp x29, x30, [sp, 0x50]
0x00006450      fd430191       add x29, sp, 0x50
0x00006454      f30301aa       mov x19, x1
0x00006458      f40300aa       mov x20, x0
0x0000645c      ff7f02a9       stp xzr, xzr, [sp, 0x20]
0x00006460      ff3b00b9       str wzr, [sp, 0x38]
0x00006464      ff1b00f9       str xzr, [sp, 0x30]
0x00006468      f5eaff97       bl sym._mig_get_reply_port
0x0000646c      480100f0       adrp x8, 0x31000
0x00006470      008547fd       ldr d0, [x8, 0xf08]
0x00006474      e00700fd       str d0, [sp, 8]
0x00006478      f4030229       stp w20, w0, [sp, 0x10]
0x0000647c      480100f0       adrp x8, 0x31000
0x00006480      008947fd       ldr d0, [x8, 0xf10]
0x00006484      e00f00fd       str d0, [sp, 0x18]
0x00006488      057c60d3       lsl x5, x0, 0x20
0x0000648c      e303142a       mov w3, w20
0x00006490      037c60b3       bfi x3, x0, 0x20, 0x20
0x00006494      e0230091       add x0, sp, 8
0x00006498      610080d2       mov x1, 3
0x0000649c      4100c0f2       movk x1, 2, lsl 32
0x000064a0      62a282d2       mov x2, 0x1513
0x000064a4      0203c0f2       movk x2, 0x18, lsl 32
0x000064a8      047dc0d2       mov x4, 0x3e800000000
0x000064ac      86068052       mov w6, 0x34
0x000064b0      070080d2       mov x7, 0
0x000064b4      e8300094       bl sym._mach_msg2_internal
0x000064b8      f40300aa       mov x20, x0
0x000064bc      c8ff9f52       mov w8, 0xfffe
0x000064c0      e8ffbd72       movk w8, 0xefff, lsl 16
0x000064c4      0800080b       add w8, w0, w8
0x000064c8      1f390071       cmp w8, 0xe
0x000064cc      29008052       mov w9, 1
0x000064d0      2821c81a       lsl w8, w9, w8
0x000064d4      69008852       mov w9, 0x4003
0x000064d8      0801090a       and w8, w8, w9
0x000064dc      0499407a       ccmp w8, 0, 4, ls
0x000064e0      21040054       b.ne 0x6564
0x000064e4      94020035       cbnz w20, 0x6534
0x000064e8      e81f40b9       ldr w8, [sp, 0x1c]
0x000064ec      1f1d0171       cmp w8, 0x47
0x000064f0      80020054       b.eq 0x6540
0x000064f4      1f311171       cmp w8, 0x44c
0x000064f8      81020054       b.ne 0x6548
0x000064fc      e80b40b9       ldr w8, [sp, 8]
0x00006500      c802f837       tbnz w8, 0x1f, 0x6558
0x00006504      e80f40b9       ldr w8, [sp, 0xc]
0x00006508      1fb10071       cmp w8, 0x2c
0x0000650c      20020054       b.eq 0x6550
0x00006510      1f910071       cmp w8, 0x24
0x00006514      21020054       b.ne 0x6558
0x00006518      e82b40b9       ldr w8, [sp, 0x28]
0x0000651c      e91340b9       ldr w9, [sp, 0x10]
0x00006520      3f010071       cmp w9, 0
0x00006524      0409407a       ccmp w8, 0, 4, eq
0x00006528      69258012       mov w9, -0x12c
0x0000652c      1411891a       csel w20, w8, w9, ne
0x00006530      0b000014       b 0x655c
0x00006534      e01740b9       ldr w0, [sp, 0x14]
0x00006538      9bf6ff97       bl sym._mig_dealloc_reply_port
0x0000653c      0a000014       b 0x6564
0x00006540      74268012       mov w20, -0x134
0x00006544      06000014       b 0x655c
0x00006548      94258012       mov w20, -0x12d
0x0000654c      04000014       b 0x655c
0x00006550      e81340b9       ldr w8, [sp, 0x10]
0x00006554      28010034       cbz w8, 0x6578
0x00006558      74258012       mov w20, -0x12c
0x0000655c      e0230091       add x0, sp, 8
0x00006560      9dedff97       bl sym._mach_msg_destroy
0x00006564      e00314aa       mov x0, x20
0x00006568      fd7b45a9       ldp x29, x30, [sp, 0x50]
0x0000656c      f44f44a9       ldp x20, x19, [sp, 0x40]
0x00006570      ff830191       add sp, sp, 0x60
0x00006574      ff0f5fd6       retab
0x00006578      f42b40b9       ldr w20, [sp, 0x28]
0x0000657c      14ffff35       cbnz w20, 0x655c
0x00006580      e8c342f8       ldur x8, [sp, 0x2c]
0x00006584      680200f9       str x8, [x19]
0x00006588      f7ffff17       b 0x6564

同样,这可能是您不希望自己在汇编中实现的东西。
但是这个实现是从哪里来的呢?您已经发现XNU只包含一个.defs文件。(Mach接口生成器)定义文件,可用于生成客户端和服务器端代码。为此,您可以使用Xcode附带的mig实用程序(也称为open source)。对于clocks文件,调用类似于以下内容:

mig -novouchers -DLIBSYSCALL_INTERFACE=1 -DPRIVATE=1 -DKERNEL_SERVER=1 -arch arm64e xnu-8792.61.2/osfmk/mach/clock.defs

这将生成一个clock.hclockServer.cclockUser.c.我们只关心最后一个,因为它包含clock_get_time的用户级代码:

/* Routine clock_get_time */
mig_external kern_return_t clock_get_time
(
    clock_serv_t clock_serv,
    mach_timespec_t *cur_time
)
{

#ifdef  __MigPackStructs
#pragma pack(push, 4)
#endif
    typedef struct {
        mach_msg_header_t Head;
    } Request __attribute__((unused));
#ifdef  __MigPackStructs
#pragma pack(pop)
#endif

#ifdef  __MigPackStructs
#pragma pack(push, 4)
#endif
    typedef struct {
        mach_msg_header_t Head;
        NDR_record_t NDR;
        kern_return_t RetCode;
        mach_timespec_t cur_time;
        mach_msg_trailer_t trailer;
    } Reply __attribute__((unused));
#ifdef  __MigPackStructs
#pragma pack(pop)
#endif

#ifdef  __MigPackStructs
#pragma pack(push, 4)
#endif
    typedef struct {
        mach_msg_header_t Head;
        NDR_record_t NDR;
        kern_return_t RetCode;
        mach_timespec_t cur_time;
    } __Reply __attribute__((unused));
#ifdef  __MigPackStructs
#pragma pack(pop)
#endif
    /*
     * typedef struct {
     *  mach_msg_header_t Head;
     *  NDR_record_t NDR;
     *  kern_return_t RetCode;
     * } mig_reply_error_t;
     */

    union {
        Request In;
        Reply Out;
    } Mess;

    Request *InP = &Mess.In;
    Reply *Out0P = &Mess.Out;

    mach_msg_return_t msg_result;

#ifdef  __MIG_check__Reply__clock_get_time_t__defined
    kern_return_t check_result;
#endif  /* __MIG_check__Reply__clock_get_time_t__defined */

    __DeclareSendRpc(1000, "clock_get_time")

    InP->Head.msgh_reply_port = mig_get_reply_port();
    InP->Head.msgh_bits =
        MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE);
    InP->Head.msgh_size = (mach_msg_size_t)sizeof(Request);
    InP->Head.msgh_request_port = clock_serv;
    InP->Head.msgh_id = 1000;
    InP->Head.msgh_reserved = 0;

    __BeforeSendRpc(1000, "clock_get_time")
    msg_result = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, (mach_msg_size_t)sizeof(Request), (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
    __AfterSendRpc(1000, "clock_get_time")
    if (msg_result != MACH_MSG_SUCCESS) {
        __MachMsgErrorWithoutTimeout(msg_result);
    }
    if (msg_result != MACH_MSG_SUCCESS) {
        { return msg_result; }
    }

#if defined(__MIG_check__Reply__clock_get_time_t__defined)
    check_result = __MIG_check__Reply__clock_get_time_t((__Reply__clock_get_time_t *)Out0P);
    if (check_result != MACH_MSG_SUCCESS) {
        mach_msg_destroy(&Out0P->Head);
        { return check_result; }
    }
#endif  /* defined(__MIG_check__Reply__clock_get_time_t__defined) */

    *cur_time = Out0P->cur_time;

    return KERN_SUCCESS;
}

(我在这里省略了__MIG_check__Reply__clock_get_time_t,但是它是在同一个文件中生成的,就在那个函数的上面。)
这里需要注意的一点是对mach_msg的调用。在程序集中,我们可以看到mach_msg2_internal被调用,但生成的代码只是调用mach_msg。如果你按原样使用该代码,并尝试在macOS 13或iOS 16上运行它,它不会起作用。这种情况的原因与达尔文的内部安全机制以及苹果操作系统最新主要版本中的缓解措施密切相关。如果你“We“我们对不久前Luca Todesco covered that in hix Hexacon presentation背后的故事很感兴趣。
但是通过将-DKERNEL_SERVER=1传递给mig,我们实际上让它在文件的开头为我们生成了一个小存根:

#include <TargetConditionals.h>
#if defined(MACH_SEND_AUX_TOO_SMALL) && (defined(__arm64__) || defined(__LP64__))
#undef mach_msg
#define mach_msg mig_mach_msg
static inline mach_msg_return_t
mig_mach_msg(
    mach_msg_header_t *msg,
    mach_msg_option_t option,
    mach_msg_size_t send_size,
    mach_msg_size_t rcv_size,
    mach_port_name_t rcv_name,
    mach_msg_timeout_t timeout,
    mach_port_name_t notify)
{
    (void)notify;
    return mach_msg2(msg, option | MACH64_SEND_KOBJECT_CALL,
        *msg, send_size, rcv_size, rcv_name, timeout, 0);
}
#endif

mach_msg2也没有在公共SDK中定义(并且不是任何库中的符号),但是我们可以从XNU源代码中的osfmk/mach/message.h一起窃取:

typedef uint64_t mach_msg_option64_t;
#define MACH64_SEND_MSG                  MACH_SEND_MSG
#define MACH64_MSG_VECTOR        0x0000000100000000ull
#define MACH64_SEND_KOBJECT_CALL 0x0000000200000000ull

#if defined(__LP64__) || defined(__arm64__)
__API_AVAILABLE(macos(13.0), ios(16.0), tvos(16.0), watchos(9.0))
__IOS_PROHIBITED __WATCHOS_PROHIBITED __TVOS_PROHIBITED
extern mach_msg_return_t mach_msg2_internal(
    void *data,
    mach_msg_option64_t option64,
    uint64_t msgh_bits_and_send_size,
    uint64_t msgh_remote_and_local_port,
    uint64_t msgh_voucher_and_id,
    uint64_t desc_count_and_rcv_name,
    uint64_t rcv_size_and_priority,
    uint64_t timeout);

__API_AVAILABLE(macos(13.0), ios(16.0), tvos(16.0), watchos(9.0))
__IOS_PROHIBITED __WATCHOS_PROHIBITED __TVOS_PROHIBITED
static inline mach_msg_return_t
mach_msg2(
    void *data,
    mach_msg_option64_t option64,
    mach_msg_header_t header,
    mach_msg_size_t send_size,
    mach_msg_size_t rcv_size,
    mach_port_t rcv_name,
    uint64_t timeout,
    uint32_t priority)
{
    mach_msg_base_t *base;
    mach_msg_size_t descriptors;

    if (option64 & MACH64_MSG_VECTOR) {
        base = (mach_msg_base_t *)((mach_msg_vector_t *)data)->msgv_data;
    } else {
        base = (mach_msg_base_t *)data;
    }

    if ((option64 & MACH64_SEND_MSG) &&
        (base->header.msgh_bits & MACH_MSGH_BITS_COMPLEX)) {
        descriptors = base->body.msgh_descriptor_count;
    } else {
        descriptors = 0;
    }

#define MACH_MSG2_SHIFT_ARGS(lo, hi) ((uint64_t)hi << 32 | (uint32_t)lo)
    return mach_msg2_internal(data, option64,
               MACH_MSG2_SHIFT_ARGS(header.msgh_bits, send_size),
               MACH_MSG2_SHIFT_ARGS(header.msgh_remote_port, header.msgh_local_port),
               MACH_MSG2_SHIFT_ARGS(header.msgh_voucher_port, header.msgh_id),
               MACH_MSG2_SHIFT_ARGS(descriptors, rcv_name),
               MACH_MSG2_SHIFT_ARGS(rcv_size, priority), timeout);
#undef MACH_MSG2_SHIFT_ARGS
}
#endif

然后通过mach_msg2_internalmach_msg2_internallibsyscall/mach/mach_msg.c中定义并编译为libsystem_kernel.dylib,然后向下调用mach_msg2_trap,最后,svc发生在mach_msg2_trap中:

;-- _mach_msg2_trap:
0x00000d68      d0058092       mov x16, -0x2f
0x00000d6c      011000d4       svc 0x80
0x00000d70      c0035fd6       ret

我猜你现在可以在macOS 13或iOS 16上构建自己的nanosleep了。不过它在之前的版本上不起作用(你必须在那里使用普通的mach_msg),而且在这些版本上起作用的实现在macOS 13和iOS 16上也不起作用,所以你可能真的不应该这样做。调用libc实现就行了。

相关问题