lldb给出了;“附加失败”;当试图;“运行”;macOS 11.1上的arm64二进制文件

lldb给出了;“附加失败”;当试图;“运行”;macOS 11.1上的arm64二进制文件,macos,lldb,apple-m1,Macos,Lldb,Apple M1,这是在M1 mini上运行的,使用更新的Xcode运行11.1。(所有挂起的更新都已应用。)SIP未被禁用(如果可以,则在M1上) 我们有一个程序,用于测试正在移植的应用程序中的mmap()故障。我们按照如下方式构建测试程序: cc -v -arch arm64 -m64 -Wl,-no_adhoc_codesign -o mapfail mapfail.c 然后,我们签字。它似乎已正确签名: @macarm[git:master]$ codesign -vvv mapfail mapfail

这是在M1 mini上运行的,使用更新的Xcode运行11.1。(所有挂起的更新都已应用。)SIP未被禁用(如果可以,则在M1上)

我们有一个程序,用于测试正在移植的应用程序中的
mmap()
故障。我们按照如下方式构建测试程序:

cc -v -arch arm64 -m64 -Wl,-no_adhoc_codesign -o mapfail mapfail.c
然后,我们签字。它似乎已正确签名:

@macarm[git:master]$ codesign -vvv mapfail
mapfail: valid on disk
mapfail: satisfies its Designated Requirement
@macarm[git:master]$ 
我们在系统上启用了开发人员模式。我们还将我的用户添加到
\u developer
组。我的用户不是管理员,但我作为管理员尝试了一下,得到了同样的结果

当我们运行程序时,它会出现分段错误(SIGSEGV),因此我们希望使用
lldb
对其进行调试,但这种情况会发生:

@macarm[git:master]$ lldb mapfail
(lldb) target create "mapfail"
Current executable set to '/Users/layer/mapfail' (arm64).
(lldb) run
error: process exited with status -1 (attach failed ((os/kern) invalid argument))
(lldb) 
即使在苹果开发者论坛上,搜索也没有得到任何信息

映射失败.c的代码:

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <mach/mach.h>
#include <mach/machine/vm_param.h>

#define nat long

#define UseMAP_ANON
/* define UseDevZero */

#define FIROUNDUP(a, n) (((a) + ((n) - 1)) & ~((n) - 1))
#define FIROUNDDOWN(a, n) ((a) & ~((n) - 1))

int bucket_o_zeros = -1;
int ChunkSize;

# ifdef UseMAP_ANON
#   define FIMAP_ANON MAP_ANON
# else
#   define FIMAP_ANON 0
# endif

typedef struct {
    char *base;     /* lowest address -- 64k aligned */
    char *pos;      /* 1+ highest address allocated */
    char *commit;   /* 1+ highest address committed */
} heap_descriptor;

heap_descriptor test1, test2;
unsigned nat test1_base, test1_size;

int
ok_to_map(unsigned nat base, unsigned nat top)
{
    /* check if the specified memory is free */
    unsigned nat address = base;
    vm_size_t size;
    mach_port_t object_name;
    task_t task = mach_task_self();
    struct vm_region_basic_info_64 info;
    mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT_64;
    kern_return_t retval;
    int res = 0;

    retval = vm_region_64(task, &address, &size, VM_REGION_BASIC_INFO_64,
              (vm_region_info_64_t)&info, &info_count, &object_name);
    if (retval == KERN_NO_SPACE) {
    res = 1;
    } else if ((retval == KERN_SUCCESS) && (address > top)) {
    res = 1;
    }
    if (object_name != MACH_PORT_NULL)
    mach_port_deallocate(mach_task_self(), object_name);

    printf("maping from 0x%lx to 0x%lx is %s\n", base, top, res ? "OK" : "BAD");
    return res;
}

char *
setup_heap( heap_descriptor *hd, unsigned nat base, unsigned nat size)
{
    /* allocate memory at the given address, and return the address
     * which was allocated
     */
       
    char *res = (char *)MAP_FAILED;

    /* initial setup of heap when there is nothing to map in or commit */
    base = FIROUNDDOWN(base, ChunkSize);
    size = FIROUNDUP(size, ChunkSize);

    /* we demand that OS puts memory at our base, so we can grow later */
    if (base == 0 || ok_to_map(base, base+size)) {
    res = (char *) mmap((void *) base, size, PROT_READ | PROT_WRITE | PROT_EXEC,
                MAP_PRIVATE | FIMAP_ANON | (base ? MAP_FIXED : 0),
                bucket_o_zeros, 0);
    }
    if (res != (char *) MAP_FAILED) {
    /* success - check alignment */
    if (base == 0) {
        nat diff;
        base = (unsigned nat) res;
        res = (char *) FIROUNDUP((nat) res, ChunkSize);
        diff = ((unsigned nat)res - base);
        if (diff > 0) {
        /* this had been over-requested already */
        size -= ChunkSize;
        /* must munmap the two ends */
        munmap((caddr_t) base, diff);
        munmap((caddr_t) (res + size), diff);
        }
    }
    /* initialize the heap descriptor */
    hd->pos = hd->base = res;
    hd->commit = (char *) (hd->base + size);
    return hd->base;
    } else {
    return 0;   /* failure */
    }
}

int
try_setup_heap(char *kind, heap_descriptor *hd, unsigned nat base, unsigned nat size)
{
    /* try to allocate where first requested, and then let the system decide.
     * return true or false depending on whether it worked.
     */
     
    char *result_base;

    base = FIROUNDUP(base,ChunkSize);
    size = FIROUNDUP(size,ChunkSize);

    /* ask for a specific area */
    if (setup_heap(hd, base, size)) return 1;   /* success */

    /* now ask for any location */
    if ((result_base = setup_heap(hd, 0, size + ChunkSize)) == 0) {
    fprintf(stderr,
        "Unable to reserve at %ld (0x%lx) bytes of memory for the %s heap\n",
        size, size, kind);
    return 0;
    } else {
    fprintf(stderr,
        "Unable to reserve 0x%lx for the %s heap,\n using 0x%lx instead\n",
        base, kind, (unsigned nat) result_base);
    return 1;
    }
}

int main(int argc, char **argv, char**envp)
{
    ChunkSize = getpagesize();
#if defined(UseDevZero)
    if(bucket_o_zeros == -1){
    bucket_o_zeros = open("/dev/zero", O_RDWR);
    }
#endif
    if (argc > 2) {
    sscanf(argv[1], "%lx", &test1_base);
    sscanf(argv[2], "%lx", &test1_size);
    if (try_setup_heap("test1", &test1, test1_base, test1_size)) {
        printf("test1 heap mapped from 0x%lx to 0x%lx\n",
           (unsigned nat) test1.base, (unsigned nat)test1.commit);
    } else {
        printf("test1 not mapped\n");
    }
    } else {
    unsigned nat addr = 0x100000000;
    unsigned nat size = 0x100000;
    int i, n, didit=0;;
    sscanf(argv[1], "%d", &n);
    for (i=0; i < n; i++) {
        if (try_setup_heap("test2", &test2, addr, size)) {
        printf("test1 heap mapped from 0x%lx to 0x%lx\n",
               (unsigned nat) test2.base, (unsigned nat)test2.commit);
        didit++;
        }
        addr += 0x100000000;
    }
    printf("Total mappings: %d\n", didit);
    }
}

/*
 * To compile on M1 with debugging:
 * cc -v -arch arm64 -m64 -Wl,-no_adhoc_codesign -o mapfail mapfail.c
 */
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义natlong
#定义UseMAP\u ANON
/*定义UseDevZero*/
#定义FIROUNDUP(a,n)((a)+(n)-1)和((n)-1))
#定义汇总(a,n)((a)和((n)-1))
int bucket_o_zeros=-1;
整数块大小;
#ifdef UseMAP_ANON
#定义FIMAP\u ANON映射\u ANON
#否则
#在0上定义FIMAP
#恩迪夫
类型定义结构{
字符*基;/*最低地址--64k对齐*/
char*pos;/*1+分配的最高地址*/
char*commit;/*1+已提交的最高地址*/
}堆描述符;
堆描述符test1,test2;
无符号nat test1_基,test1_大小;
int
ok_to_映射(未签名的nat基、未签名的nat顶)
{
/*检查指定的内存是否可用*/
无符号nat地址=基址;
虚拟机大小;
马赫数端口对象名称;
task_t task=mach_task_self();
结构虚拟机区域基本信息64信息;
mach\u msg\u type\u number\u t info\u count=VM\u REGION\u BASIC\u info\u count\u 64;
内核返回返回;
int res=0;
retval=vm_region_64(任务、地址和大小、vm_region_基本信息_64、,
(虚拟机区域、信息、信息计数和对象名称);
if(retval==KERN\u无空间){
res=1;
}else if((retval==KERN_SUCCESS)&&(address>top)){
res=1;
}
if(对象名称!=马赫数端口为空)
马赫数端口释放(马赫数任务自身(),对象名称);
printf(“从0x%lx映射到0x%lx是%s\n”,基、顶、分辨率?“确定”:“不正确”);
返回res;
}
煤焦*
设置\u堆(堆描述符*hd,无符号nat基,无符号nat大小)
{
/*在给定地址分配内存,并返回地址
*分配给谁
*/
char*res=(char*)映射_失败;
/*没有映射或提交内容时堆的初始设置*/
base=FIROUNDDOWN(base,ChunkSize);
size=FIROUNDUP(size,ChunkSize);
/*我们要求操作系统把内存放在我们的基础上,这样我们可以在以后增长*/
if(base==0 | | ok|u to_map(base,base+size)){
res=(char*)mmap((void*)基、大小、保护读取、保护写入、保护执行、,
MAP|u PRIVATE | FIMAP|u ANON |(基本地图?固定地图:0),
桶(0);
}
如果(res!=(char*)映射失败){
/*成功-检查对齐*/
如果(基==0){
自然差异;
base=(无符号nat)res;
res=(char*)FIROUNDUP((nat)res,ChunkSize);
diff=((无符号nat)res-base);
如果(差异>0){
/*这已经被过度要求了*/
大小-=块大小;
/*我们必须画出两端的地图*/
munmap((caddr_t)base,diff);
munmap((caddr_t)(分辨率+大小),差异;
}
}
/*初始化堆描述符*/
hd->pos=hd->base=res;
高清->提交=(字符*)(高清->基本+大小);
返回hd->base;
}否则{
返回0;/*失败*/
}
}
int
try_setup_heap(字符*种类、堆描述符*hd、无符号nat基、无符号nat大小)
{
/*尝试分配第一个请求的位置,然后让系统决定。
*根据其是否有效,返回true或false。
*/
字符*结果_基;
base=FIROUNDUP(base,ChunkSize);
size=FIROUNDUP(size,ChunkSize);
/*询问特定区域*/
if(setup_heap(hd、base、size))返回1;/*成功*/
/*现在询问任何地点*/
if((result\u base=setup\u heap(hd,0,size+ChunkSize))==0){
fprintf(标准,
“无法为%s堆保留至少%ld(0x%lx)字节的内存\n”,
大小、大小、种类);
返回0;
}否则{
fprintf(标准,
“无法为%s堆保留0x%lx,\n请改用0x%lx\n”,
基,种类,(无符号nat)结果_基);
返回1;
}
}
内部主(内部argc、字符**argv、字符**envp)
{
ChunkSize=getpagesize();
#如果已定义(UseDevZero)
如果(桶0==-1){
bucket_o_zeros=打开(“/dev/zero”,o_RDWR);
}
#恩迪夫
如果(argc>2){
sscanf(argv[1]、“%lx”和test1_base);
sscanf(argv[2]、“%lx”和test1_大小);
if(try_setup_heap(“test1”、&test1、test1_base、test1_size)){
printf(“从0x%lx映射到0x%lx的test1堆\n”,
(未签名nat)test1.base,(未签名nat)test1.commit);
}否则{
printf(“test1未映射\n”);
}
}否则{
未签名nat地址=0x100000000;
无符号nat大小=0x100000;
int i,n,didit=0;;
sscanf(argv[1]、“%d”、&n);
对于(i=0;i
二进制文件是否在调试器外部运行?我尝试了一个
int main(){return 0;}
donothing程序,用您的命令行编译了它,并对它进行了即席签名
codesign-s-a.out
,我可以运行它并删除它