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;
}