static plcrash_error_t map_sections()

in Source/PLCrashAsyncObjCSection.mm [430:498]


static plcrash_error_t map_sections (plcrash_async_macho_t *image, plcrash_async_objc_cache_t *context) {
    if (image == context->lastImage)
        return PLCRASH_ESUCCESS;
    
    /* Clean up the info from the previous image. Free the memory objects and reset the
     * image pointer. The image pointer is reset so that it's not stale in case we return
     * early due to an error. */
    free_mapped_sections(context);
    context->lastImage = NULL;
    
    plcrash_error_t err;
    const char *segname;
    
    /* Map in the __objc_const section, which is where all the read-only class data lives. */
    err = map_data_section(image, &segname, kObjCConstSectionName, &context->objcConstMobj);
    if (err != PLCRASH_ESUCCESS) {
        if (err != PLCRASH_ENOTFOUND)
            PLCF_DEBUG("pl_async_macho_map_section(%p, %s, %s, %p) failure %d", image, segname, kObjCConstSectionName, &context->objcConstMobj, err);
        goto cleanup;
    }
    context->objcConstMobjInitialized = true;

    /* Map in the __objc_const_ax section. */
    err = plcrash_async_macho_map_section(image, kDataSegmentName, kObjCConstAxSectionName, &context->objcConstAxMobj);
    if (err != PLCRASH_ESUCCESS && err != PLCRASH_ENOTFOUND)
        PLCF_DEBUG("pl_async_macho_map_section(%s, %s, %s, %p) failure %d", PLCF_DEBUG_IMAGE_NAME(image), kDataSegmentName, kObjCConstAxSectionName, &context->objcConstAxMobj, err);
    context->objcConstAxMobjInitialized = err == PLCRASH_ESUCCESS;
    
    /* Map in the class list section. */
    err = map_data_section(image, &segname, kClassListSectionName, &context->classMobj);
    if (err != PLCRASH_ESUCCESS) {
        if (err != PLCRASH_ENOTFOUND)
            PLCF_DEBUG("pl_async_macho_map_section(%s, %s, %s, %p) failure %d", PLCF_DEBUG_IMAGE_NAME(image), segname, kClassListSectionName, &context->classMobj, err);
        goto cleanup;
    }
    context->classMobjInitialized = true;
    
    /* Map in the category list section. */
    err = map_data_section(image, &segname, kCategoryListSectionName, &context->catMobj);
    if (err != PLCRASH_ESUCCESS) {
        if (err != PLCRASH_ENOTFOUND)
            PLCF_DEBUG("pl_async_macho_map_section(%s, %s, %s, %p) failure %d", PLCF_DEBUG_IMAGE_NAME(image), segname, kCategoryListSectionName, &context->catMobj, err);
        goto cleanup;
    }
    context->catMobjInitialized = true;
    
    /* Map in the __objc_data section, which is where the actual classes live. */
    err = plcrash_async_macho_map_section(image, kDataSegmentName, kObjCDataSectionName, &context->objcDataMobj);
    if (err != PLCRASH_ESUCCESS) {
        /* If the class list was found, the data section must also be found. */
        PLCF_DEBUG("pl_async_macho_map_section(%s, %s, %s, %p) failure %d", PLCF_DEBUG_IMAGE_NAME(image), kDataSegmentName, kObjCDataSectionName, &context->objcDataMobj, err);
        goto cleanup;
    }
    context->objcDataMobjInitialized = true;

    /* Map in the __data section. */
    err = plcrash_async_macho_map_section(image, kDataSegmentName, kDataSectionName, &context->dataMobj);
    if (err != PLCRASH_ESUCCESS && err != PLCRASH_ENOTFOUND)
        PLCF_DEBUG("pl_async_macho_map_section(%s, %s, %s, %p) failure %d", PLCF_DEBUG_IMAGE_NAME(image), kDataSegmentName, kDataSectionName, &context->dataMobj, err);
    context->dataMobjInitialized = err == PLCRASH_ESUCCESS;
    
    /* Only after all mappings succeed do we set the image. If any failed, the image won't be set,
     * and any mappings that DO succeed will be cleaned up on the next call (or when freeing the
     * context. */
    context->lastImage = image;
    
cleanup:
    return err;
}