Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/106.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 如何在运行时获取构建UUID和映像基址_Ios_Uuid - Fatal编程技术网

Ios 如何在运行时获取构建UUID和映像基址

Ios 如何在运行时获取构建UUID和映像基址,ios,uuid,Ios,Uuid,要获取构建UUID,您可以在dSYM生成的文件中检查该UUID,并在iOS中检查映像基址 当涉及到低层次的东西时,不是很好,任何人都可以启发?这可以通过我从一些同事那里找到的一个类来实现,他们在合理的实验室中找到了这个类,并根据他们的需要进行了重构 在这里,您可以获得构建UUID、映像基址和应用程序名称 /** * @internal * * Async-safe binary image list element. */ typedef struct bin_image {

要获取构建UUID,您可以在dSYM生成的文件中检查该UUID,并在iOS中检查映像基址


当涉及到低层次的东西时,不是很好,任何人都可以启发?

这可以通过我从一些同事那里找到的一个类来实现,他们在合理的实验室中找到了这个类,并根据他们的需要进行了重构

在这里,您可以获得构建UUID、映像基址和应用程序名称

    /**
 * @internal
 *
 * Async-safe binary image list element.
 */
typedef struct bin_image {
    /** The binary image's header address. */
    uintptr_t header;

    /** The binary image's name/path. */
    char *name;

    /** The previous image in the list, or NULL */
    struct bin_image *prev;

    /** The next image in the list, or NULL. */
    struct bin_image *next;
} bin_image_t;

/**
 * @internal
 *
 * Async-safe binary image list. May be used to iterate over the binary images currently
 * available in-process.
 */
typedef struct bs_image_list {
    /** The lock used by writers. No lock is required for readers. */
    OSSpinLock write_lock;

    /** The head of the list, or NULL if the list is empty. Must only be used to iterate or delete entries. */
    bin_image_t *head;

    /** The tail of the list, or NULL if the list is empty. Must only be used to append new entries. */
    bin_image_t *tail;

    /** The list reference count. No nodes will be deallocated while the count is greater than 0. If the count
     * reaches 0, all nodes in the free list will be deallocated. */
    int32_t refcount;

    /** The node free list. */
    bin_image_t *free;
} bs_image_list_t;

/**
 * @internal
 *
 * Shared dyld image list.
 */
static bs_image_list_t shared_image_list = { 0 };

/**
 * @internal
 *
 * Maintains a linked list of binary images with support for async-safe iteration. Writing may occur concurrently with
 * async-safe reading, but is not async-safe.
 *
 * Atomic compare and swap is used to ensure a consistent view of the list for readers. To simplify implementation, a
 * write mutex is held for all updates; the implementation is not designed for efficiency in the face of contention
 * between readers and writers, and it's assumed that no contention should realistically occur.
 * @{
 */

/**
 * Initialize a new binary image list and issue a memory barrier
 *
 * @param list The list structure to be initialized.
 *
 * @warning This method is not async safe.
 */
static void image_list_init (bs_image_list_t *list) {
    memset(list, 0, sizeof(*list));

    list->write_lock = OS_SPINLOCK_INIT;
}

/**
 * Free any binary image list resources.
 *
 * @warning This method is not async safe.
 */
static void image_list_free (bs_image_list_t *list) {
    bin_image_t *next = list->head;
    while (next != NULL) {
        /* Save the current pointer and fetch the next pointer. */
        bin_image_t *cur = next;
        next = cur->next;

        /* Deallocate the current item. */
        if (cur->name != NULL)
            free(cur->name);
        free(cur);
    }
}

/**
 * Append a new binary image record to @a list.
 *
 * @param list The list to which the image record should be appended.
 * @param header The image's header address.
 * @param name The image's name.
 *
 * @warning This method is not async safe.
 */
static void image_list_append (bs_image_list_t *list, uintptr_t header, const char *name) {
    /* Initialize the new entry. */
    bin_image_t *new = calloc(1, sizeof(bin_image_t));
    new->header = header;
    new->name = strdup(name);

    /* Update the image record and issue a memory barrier to ensure a consistent view. */
    OSMemoryBarrier();

    /* Lock the list from other writers. */
    OSSpinLockLock(&list->write_lock); {

        /* If this is the first entry, initialize the list. */
        if (list->tail == NULL) {

            /* Update the list tail. This need not be done atomically, as tail is never accessed by a lockless reader. */
            list->tail = new;

            /* Atomically update the list head; this will be iterated upon by lockless readers. */
            if (!OSAtomicCompareAndSwapPtrBarrier(NULL, new, (void **) (&list->head))) {
                /* Should never occur */
                NSLog(@"An async image head was set with tail == NULL despite holding lock.");
            }
        }

        /* Otherwise, append to the end of the list */
        else {
            /* Atomically slot the new record into place; this may be iterated on by a lockless reader. */
            if (!OSAtomicCompareAndSwapPtrBarrier(NULL, new, (void **) (&list->tail->next))) {
                NSLog(@"Failed to append to image list despite holding lock");
            }

            /* Update the prev and tail pointers. This is never accessed without a lock, so no additional barrier
             * is required here. */
            new->prev = list->tail;
            list->tail = new;
        }
    } OSSpinLockUnlock(&list->write_lock);
}

/**
 * Remove a binary image record from @a list.
 *
 * @param header The header address of the record to be removed. The first record matching this address will be removed.
 *
 * @warning This method is not async safe.
 */
static void image_list_remove (bs_image_list_t *list, uintptr_t header) {
    /* Lock the list from other writers. */
    OSSpinLockLock(&list->write_lock); {
        /* Find the record. */
        bin_image_t *item = list->head;
        while (item != NULL) {
            if (item->header == header)
                break;

            item = item->next;
        }

        /* If not found, nothing to do */
        if (item == NULL) {
            OSSpinLockUnlock(&list->write_lock);
            return;
        }

        /*
         * Atomically make the item unreachable by readers.
         *
         * This serves as a synchronization point -- after the CAS, the item is no longer reachable via the list.
         */
        if (item == list->head) {
            if (!OSAtomicCompareAndSwapPtrBarrier(item, item->next, (void **) &list->head)) {
                NSLog(@"Failed to remove image list head despite holding lock");
            }
        } else {
            /* There MUST be a non-NULL prev pointer, as this is not HEAD. */
            if (!OSAtomicCompareAndSwapPtrBarrier(item, item->next, (void **) &item->prev->next)) {
                NSLog(@"Failed to remove image list item despite holding lock");
            }
        }

        /* Now that the item is unreachable, update the prev/tail pointers. These are never accessed without a lock,
         * and need not be updated atomically. */
        if (item->next != NULL) {
            /* Item is not the tail (otherwise next would be NULL), so simply update the next item's prev pointer. */
            item->next->prev = item->prev;
        } else {
            /* Item is the tail (next is NULL). Simply update the tail record. */
            list->tail = item->prev;
        }

        /* If a reader is active, simply spin until inactive. */
        while (list->refcount > 0) {
        }

        if (item->name != NULL)
            free(item->name);
        free(item);
    } OSSpinLockUnlock(&list->write_lock);
}

/**
 * Retain or release the list for reading. This method is async-safe.
 *
 * This must be issued prior to attempting to iterate the list, and must called again once reads have completed.
 *
 * @param list The list to be be retained or released for reading.
 * @param enable If true, the list will be retained. If false, released.
 */
static void image_list_set_reading (bs_image_list_t *list, bool enable) {
    if (enable) {
        /* Increment and issue a barrier. Once issued, no items will be deallocated while a reference is held. */
        OSAtomicIncrement32Barrier(&list->refcount);
    } else {
        /* Increment and issue a barrier. Once issued, items may again be deallocated. */
        OSAtomicDecrement32Barrier(&list->refcount);
    }
}

/**
 * Return the next image record. This method is async-safe. If no additional images are available, will return NULL;
 *
 * @param list The list to be iterated.
 * @param current The current image record, or NULL to start iteration.
 */
static bin_image_t *image_list_next (bs_image_list_t *list, bin_image_t *current) {
    if (current != NULL)
        return current->next;

    return list->head;
}

/**
 * @internal
 * dyld image add notification callback.
 */
static void image_add_callback (const struct mach_header *mh, intptr_t vmaddr_slide) {
    Dl_info info;

    /* Look up the image info */
    if (dladdr(mh, &info) == 0) {
        NSLog(@"%s: dladdr(%p, ...) failed", __FUNCTION__, mh);
        return;
    }

    /* Register the image */
    image_list_append(&shared_image_list, (uintptr_t) mh, info.dli_fname);
}

/**
 * @internal
 *
 * Write a binary image frame
 *
 * @param file Output file
 * @param name binary image path (or name).
 * @param image_base Mach-O image base.
 */
static void process_binary_image (const char *name, const void *header,
                                    struct uuid_command *out_uuid, uintptr_t *out_baseaddr) {
    uint32_t ncmds;
    const struct mach_header *header32 = (const struct mach_header *) header;
    const struct mach_header_64 *header64 = (const struct mach_header_64 *) header;

    struct load_command *cmd;

    /* Check for 32-bit/64-bit header and extract required values */
    switch (header32->magic) {
            /* 32-bit */
        case MH_MAGIC:
        case MH_CIGAM:
            ncmds = header32->ncmds;
            cmd = (struct load_command *) (header32 + 1);
            break;

            /* 64-bit */
        case MH_MAGIC_64:
        case MH_CIGAM_64:
            ncmds = header64->ncmds;
            cmd = (struct load_command *) (header64 + 1);
            break;

        default:
            NSLog(@"Invalid Mach-O header magic value: %x", header32->magic);
            return;
    }

    /* Compute the image size and search for a UUID */
    struct uuid_command *uuid = NULL;

    for (uint32_t i = 0; cmd != NULL && i < ncmds; i++) {
        /* DWARF dSYM UUID */
        if (cmd->cmd == LC_UUID && cmd->cmdsize == sizeof(struct uuid_command))
            uuid = (struct uuid_command *) cmd;

        cmd = (struct load_command *) ((uint8_t *) cmd + cmd->cmdsize);
    }

    /* Base address */
    uintptr_t base_addr;
    base_addr = (uintptr_t) header;

    *out_baseaddr = base_addr;
    if(out_uuid && uuid)
        memcpy(out_uuid, uuid, sizeof(struct uuid_command));
}

+ (void)registerCallback {
    _dyld_register_func_for_add_image(image_add_callback);
}

+ (NSArray *)loadedImages {
    NSMutableArray *array = [NSMutableArray array];
    int i;
    struct uuid_command uuid = { 0 };
    uintptr_t baseaddr;
    char uuidstr[64] = { 0 };

    image_list_set_reading(&shared_image_list, true);

    bin_image_t *image = NULL;
    while ((image = image_list_next(&shared_image_list, image)) != NULL) {

        process_binary_image(image->name, (const void *) (image->header), &uuid, &baseaddr);

        for(i=0; i<16; i++) {
            sprintf(&uuidstr[2*i], "%02x", uuid.uuid[i]);
        }

        [array addObject:[NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:[NSString stringWithCString:image->name encoding:NSASCIIStringEncoding], [NSString stringWithCString:uuidstr encoding:NSASCIIStringEncoding], [NSNumber numberWithUnsignedLong:(long unsigned) baseaddr], nil]
                                                     forKeys:[NSArray arrayWithObjects:@"name", @"uuid", @"baseaddr", nil]]];
    }

    return [NSArray arrayWithArray:array];
}
/**
*@内部
*
*异步安全二进制映像列表元素。
*/
typedef结构bin_图像{
/**二进制图像的头地址*/
uintptr_t头;
/**二进制图像的名称/路径*/
字符*名称;
/**列表中的上一个图像,或为空*/
结构bin_图像*prev;
/**列表中的下一个图像,或为空*/
结构bin_图像*下一步;
}Binu图像;
/**
*@内部
*
*异步安全二进制映像列表。可用于迭代当前的二进制图像
*可在过程中使用。
*/
类型定义结构bs_图像_列表{
/**写入程序使用的锁。读卡器不需要锁*/
OSSpinLock写锁;
/**列表的标题,如果列表为空,则为NULL。只能用于迭代或删除条目*/
Binu图像头;
/**列表的尾部,如果列表为空,则为NULL。只能用于附加新条目*/
bin_image_t*tail;
/**列表引用计数。当计数大于0时,不会释放任何节点。如果
*达到0时,将释放空闲列表中的所有节点*/
int32_t refcount;
/**节点空闲列表*/
bin_image_t*免费;
}bs_图像_列表_t;
/**
*@内部
*
*共享dyld图像列表。
*/
静态bs_image_list_t shared_image_list={0};
/**
*@内部
*
*维护二进制图像的链接列表,支持异步安全迭代。写作可以与写作同时进行
*异步安全读取,但不是异步安全的。
*
*原子比较和交换用于确保读卡器的列表视图一致。为了简化实现,需要一个
*为所有更新保留写互斥锁;实现的目的不是为了在面临争用时提高效率
*在读者和作者之间,假设现实中不应该发生争论。
* @{
*/
/**
*初始化一个新的二进制图像列表并发出一个内存屏障
*
*@param list要初始化的列表结构。
*
*@警告此方法不是异步安全的。
*/
静态无效图像列表初始化(bs\U图像列表*list){
memset(list,0,sizeof(*list));
list->write\u lock=OS\u SPINLOCK\u INIT;
}
/**
*释放任何二进制图像列表资源。
*
*@警告此方法不是异步安全的。
*/
静态无效图像列表空闲(bs\U图像列表*t列表){
bin\u image\u t*next=列表->标题;
while(下一步!=NULL){
/*保存当前指针并获取下一个指针*/
bin_image_t*cur=下一步;
下一步=当前->下一步;
/*取消分配当前项*/
如果(cur->name!=NULL)
免费(cur->name);
免费(cur);
}
}
/**
*将新的二进制图像记录附加到@a列表。
*
*@param list图像记录应附加到的列表。
*@param header图像的头地址。
*@param name图像的名称。
*
*@警告此方法不是异步安全的。
*/
静态无效图像列表追加(bs\U图像列表*列表,uintptr头,常量字符*名称){
/*初始化新条目*/
bin_image_t*new=calloc(1,sizeof(bin_image_t));
新建->页眉=页眉;
新建->名称=strdup(名称);
/*更新图像记录并发出内存屏障以确保一致的视图*/
OSMemoryBarrier();
/*锁定其他写入程序的列表*/
OSSpinLockLock(列表->写入锁定)(&list->write_lock){
/*如果这是第一个条目,则初始化列表*/
如果(列表->尾部==NULL){
/*更新列表尾部。这不需要以原子方式完成,因为尾部永远不会被无锁读取器访问*/
列表->尾部=新建;
/*原子地更新列表头;这将由无锁读卡器进行迭代*/
if(!OSAtomicCompareAndSwapPtrBarrier(NULL,new,(void**)(&list->head))){
/*不应该发生*/
NSLog(@“一个异步映像头被设置为tail==NULL,尽管持有锁。”);
}
}
/*否则,请附加到列表的末尾*/
否则{
/*原子地将新记录放入适当的位置;这可以由无锁读取器进行迭代*/
如果(!OSAtomicCompareAndSwapPtrBarrier(NULL,new,(void**)(&list->tail->next))){
NSLog(@“尽管保持锁定,但未能附加到映像列表”);
}
/*更新prev和tail指针。如果没有锁,这是永远无法访问的,因此没有额外的障碍
*这是必需的*/
新建->上一个=列表->尾部;
列表->尾部=新建;
}
}OSSpinLockUnlock(列表->写入锁定)(&list);
}
/**
*从@a列表中删除二进制图像记录。
*
*@param header要删除的记录的头地址。将删除与此地址匹配的第一条记录。
*
*@警告此方法不是异步安全的。
*/
静态无效图像列表移除(bs\U图像列表*list,uintptr\t头){
/*锁定其他写入程序的列表*/
OSSpinLockLock(列表->写入锁定)(&list->write_lock){
/*找到记录*/
bin\u image\u t*item=列表->标题;
while(项!=NULL){
如果(项目->标题==标题)
打破
项目=项目->下一步;
}
/*如果找不到,无事可做*/
如果(项==NULL){
OSSpinLockUnlock(列表->写入锁定)(&list);
返回;
}
/*
*原子化地使读者无法访问该项目。
*
*这是一个同步点——在CAS之后,该项不再可以通过列表访问。
*/
如果(项目==列表->标题){
- (NSString *)executableUUID {
  // This now requires the testing of this feature to be done on an actual device, since it returns always empty strings on the simulator
#if !TARGET_IPHONE_SIMULATOR
  const uint8_t *command = (const uint8_t *)(&_mh_execute_header + 1);
  for (uint32_t idx = 0; idx < _mh_execute_header.ncmds; ++idx) {
    const struct load_command *load_command = (const struct load_command *)command;
    if (load_command->cmd == LC_UUID) {
      const struct uuid_command *uuid_command = (const struct uuid_command *)command;
      const uint8_t *uuid = uuid_command->uuid;
      return [[NSString stringWithFormat:@"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
               uuid[0], uuid[1], uuid[2], uuid[3],
               uuid[4], uuid[5], uuid[6], uuid[7],
               uuid[8], uuid[9], uuid[10], uuid[11],
               uuid[12], uuid[13], uuid[14], uuid[15]]
              lowercaseString];
    } else {
      command += load_command->cmdsize;
    }
  }
#endif
  return @"";
}
#import <mach-o/dyld.h>
#import <mach-o/loader.h>

static NSUUID *ExecutableUUID(void)
{
    const struct mach_header *executableHeader = NULL;
    for (uint32_t i = 0; i < _dyld_image_count(); i++)
    {
        const struct mach_header *header = _dyld_get_image_header(i);
        if (header->filetype == MH_EXECUTE)
        {
            executableHeader = header;
            break;
        }
    }

    if (!executableHeader)
        return nil;

    BOOL is64bit = executableHeader->magic == MH_MAGIC_64 || executableHeader->magic == MH_CIGAM_64;
    uintptr_t cursor = (uintptr_t)executableHeader + (is64bit ? sizeof(struct mach_header_64) : sizeof(struct mach_header));
    const struct segment_command *segmentCommand = NULL;
    for (uint32_t i = 0; i < executableHeader->ncmds; i++, cursor += segmentCommand->cmdsize)
    {
        segmentCommand = (struct segment_command *)cursor;
        if (segmentCommand->cmd == LC_UUID)
        {
            const struct uuid_command *uuidCommand = (const struct uuid_command *)segmentCommand;
            return [[NSUUID alloc] initWithUUIDBytes:uuidCommand->uuid];
        }
    }

    return nil;
}