【问题标题】:lldb - how to read the permissions of a memory region for a thread?lldb - 如何读取线程内存区域的权限?
【发布时间】:2021-12-29 07:48:48
【问题描述】:

Apple 表示,在 ARM64 Mac 上,内存区域可以具有线程的写入或执行权限。有人如何找出 lldb 中线程的内存区域的当前权限?我已经尝试过“内存区域”,但它返回 rwx。我正在开发一个将在我的 M1 Mac 上运行的即时编译器。为了测试,我做了一个即时编译器的小模拟。

#include <cstdio>
#include <sys/mman.h>
#include <pthread.h>
#include <libkern/OSCacheControl.h>
#include <stdlib.h>

int main(int argc, const char * argv[]) {
    
    size_t size = 1024 * 1024 * 640;
    int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
    int flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_JIT;
    int fd = -1;
    int offset = 0;
    unsigned *addr = 0;

    // allocate a mmap'ed region of memory
    addr = (unsigned *)mmap(0, size, prot, flags, fd, offset);
    if (addr == MAP_FAILED){
        printf("failure detected\n");
        exit(-1);
    }
    
    pthread_jit_write_protect_np(0);
    
    // Write instructions to the memory
    addr[0] = 0xd2800005;  // mov x5, #0x0
    addr[1] = 0x910004a5;  // add x5, x5, #0x1
    addr[2] = 0x17ffffff;  // b <address>
    
    pthread_jit_write_protect_np(1);
    sys_icache_invalidate(addr, size);
    
    // Execute the code
    int(*f)() = (int (*)()) addr;
    (*f)();
    
    return 0;
}

一旦汇编指令通过 (*f)() 调用开始执行,我可以在 Xcode 中暂停执行并输入

内存区域{指令地址}

进入调试器。由于某种原因,它不断返回“rwx”。我是否使用了正确的命令或者这可能是 lldb 的错误?

【问题讨论】:

    标签: memory permissions lldb apple-m1 region


    【解决方案1】:

    当我在 Mac 上运行你的小程序时(我在 x86_64 上但没关系,我实际上不需要运行指令......)我在 lldb 中看到:

    Process 43209 stopped
    * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
        frame #0: 0x0000000100003f20 protectit`main at protectit.cpp:31
       28       addr[2] = 0x17ffffff;  // b <address>
       29       
       30       pthread_jit_write_protect_np(1);
    -> 31       sys_icache_invalidate(addr, size);
                                      ^
       32       
       33       // Execute the code
       34       int(*f)() = (int (*)()) addr;
    Target 0: (protectit) stopped.
    (lldb) memory region addr
    [0x0000000101000000-0x0000000129000000) rwx
    

    正如您所报告的那样。然后我用 vmmap 仔细检查:

     > vmmap 43209 0x0000000101000000
    0x101000000 is in 0x101000000-0x129000000;  bytes after start: 0  bytes before end: 671088639
    
          REGION TYPE                    START - END         [ VSIZE  RSDNT  DIRTY   SWAP] PRT/MAX SHRMOD PURGE    REGION DETAIL
          MALLOC_SMALL                100800000-101000000    [ 8192K     8K     8K     0K] rw-/rwx SM=PRV          MallocHelperZone_0x1001c4000
    --->  VM_ALLOCATE                 101000000-129000000    [640.0M     4K     4K     0K] rwx/rwx SM=PRV  
          GAP OF 0x5ffed7000000 BYTES
          MALLOC_NANO              600000000000-600008000000 [128.0M    88K    88K     0K] rw-/rwx SM=PRV          DefaultMallocZone_0x1001f1000
    

    所以 vmmap 与 lldb 一致认为该区域是 rwx。

    无论 pthread_jit_write_protect_np 做什么,它似乎都不会改变底层的内存区域保护。

    【讨论】:

    • 感谢您的帮助。我猜苹果的文档是错误的。 developer.apple.com/documentation/apple-silicon/…
    • 我不确定。您指出的文档特别指出 pthread_jit_write_protect_np 仅影响调用线程访问相关内存的能力,并且在将权限更改称为线程特定方面非常一致。我不知道“线程特定保护”是如何实现的,但是更改全局权限和处理页面错误似乎是一种相当低效的方法,因此系统使用其他方法也就不足为奇了。
    • 那么我们如何读取内存区域的线程权限呢?我认为有一些 API 可以做到这一点。
    • 我在 usr/include/pthread.h 中没有看到任何相关内容,但这不是我的专业领域。
    猜你喜欢
    • 2017-04-13
    • 1970-01-01
    • 2015-08-11
    • 1970-01-01
    • 2014-12-06
    • 1970-01-01
    • 2020-11-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多