_objc_init

Environ_init Initializes the environment variable

    for (size_t i = 0; i < sizeof(Settings)/sizeof(Settings[0]); i++) {
        const option_t *opt = &Settings[i];
        _objc_inform("%s: %s", opt->env, opt->help);
        _objc_inform("%s is set", opt->env);
    }
Copy the code

Print the following

What is OBJC_DISABLE_NONPOINTER_ISA?

Setting environment Variables

Static_init jump all static C++ function calls

getLibobjcInitializers jump

runtime_init jump

UnattachedCategories jump Static UnattachedCategories UnattachedCategories;

Class table allocated by allocatedClasses jump

init

Exception_init The exception is thrown

installUncaughtSignalExceptionHandler

Array out of bounds project did not crash to intercept an exception

// Key code pointer passing can change synchronously, similar to pointer copying
    _dyld_objc_notify_register(&map_images, load_images, unmap_image);
Copy the code
map_images jump

map_images_nolock jump

_read_images key

InitializeTaggedPointerObfuscator initialize token Pointers fuzzy (confused)

// Key code
 // namedClasses      
// Preoptimized classes don't go in this table.       
// 4/3 is NXMapTable's load factor
// Total volume: 8 * 4/3
//NXCreateMapTable add: x = 8 * 4/3 * 3/4

int namedClassesSize =  (isPreoptimized() ? unoptimizedTotalClasses : totalClasses) * 4 / 3; 

gdb_objc_realized_classes = NXCreateMapTable(NXStrValueMapPrototype,namedClassesSize);  / / NXCreateMapTable create tables

 ts.log("IMAGE TIMES: first time tasks"); Gdb_objc_realized_classes table// A separate table
    objc::unattachedCategories.init(32);
    objc::allocatedClasses.init();

Copy the code
What is the difference between gDB_objC_realized_classes and allocatedClasses?

The gDB_objC_realized_CLASSES master table can be the master table of allocatedClasses that has not been opened, whether implemented or not

Under the _read_images breakpoint

The output

sel_registerNameNoLock jump

__sel_registerName jump

search_builtins jump _dyld_get_objc_selector

_read_images-resolvedfutureclasses resolvedFutureClasses

In the loading process, some classes are deleted after reading, but if the deletion is not clean, there will be some confusion (wild Pointers), that is, residual classes.

The Po print

_getObjc2ClassRefs jump
readClass

          // Key code
            class_rw_t *rw = newCls->data();
            const class_ro_t *old_ro = rw->ro();
            memcpy(newCls, cls, sizeof(objc_class));

            // Manually set address-discriminated ptrauthed fields
            // so that newCls gets the correct signatures.
            newCls->setSuperclass(cls->getSuperclass());
            newCls->initIsa(cls->getIsa());

            rw->set_ro((class_ro_t *)newCls->data());
            newCls->setData(rw);
            freeIfMutable((char *)old_ro->getName());
            free((void *)old_ro);

            addRemappedClass(cls, newCls);
Copy the code

The output

Add judgment condition

The console outputs only readclass-HL-hlPerson

addNamedClass jump

addClassTableEntry jump

To be continued…

NXMapInsert jump is called in addNamedClass

_read_images
// Key code
      for (i = 0; i < count; i++) {
            Class cls = (Class)classlist[i];
// This is the address -> name -> class
            Class newCls = readClass(cls, headerIsBundle, headerIsPreoptimized);
// Put out feelers
            if(newCls ! = cls && newCls) {// Class was moved but not deleted. Currently this occurs 
                // only when the new class resolved a future class.
                // Non-lazily realize the class below.
                resolvedFutureClasses = (Class *)
                    realloc(resolvedFutureClasses, 
                            (resolvedFutureClassCount+1) * sizeof(Class)); resolvedFutureClasses[resolvedFutureClassCount++] = newCls; }}Copy the code

And then we put out feelers

1
    // Realize non-lazy classes (for +load methods and static instances)
    for (EACH_HEADER) {
        classref_t const *classlist = hi->nlclslist(&count);
        for (i = 0; i < count; i++) {
            Class cls = remapClass(classlist[i]);
            if(! cls)continue;
            
            //HL
            const char *mangledName = cls->nonlazyMangledName();

            const char *HLPersonName = "HLPerson";
            
            if (strcmp(mangledName, HLPersonName) == 0) {
                
                printf("Realize non-lazy-%s - HL - %s\n",__func__,mangledName);

            }
            //HL

2
 if (resolvedFutureClasses) {
        for (i = 0; i < resolvedFutureClassCount; i++) {
            Class cls = resolvedFutureClasses[i];
            
            //HL
            const char *mangledName = cls->nonlazyMangledName();

            const char *HLPersonName = "HLPerson";
            
            if (strcmp(mangledName, HLPersonName) == 0) {
                
                printf("resolvedFutureClasses-%s - HL - %s\n",__func__,mangledName);

            }
            //HL
Copy the code

I missed both of them

RealizeClassWithoutSwift core focus

//rw assigns (ro assigns -> rw)
        rw = objc::zalloc<class_rw_t>();
        rw->set_ro(ro);
        rw->flags = RW_REALIZED|RW_REALIZING|isMeta;
        cls->setData(rw);
Copy the code

Need the original Isa setInstancesRequireRawIsa / / collection instance

  • DisableNonpointerIsa // Environment variable

Inheritance chain ISA goes bit

supercls = realizeClassWithoutSwift(remapClass(cls->getSuperclass()), nil); metacls = realizeClassWithoutSwift(remapClass(cls->ISA()), nil);

  • Add the judgment

  • The *$2 address is not printed

  • print

prepareMethodLists jump

fixupMethodList jump

meth.name jump

Print ro does not print the value of *$2

When does rwe get assigned?

realizeAndInitializeIfNeeded_locked jump

realizeClassMaybeSwiftAndLeaveLocked jump

realizeClassMaybeSwiftMaybeRelock jump

Verify that class methods and instance method objects can be loaded as long as the message is sent

Lazy-loading class case data loading is delayed until the first message

lookUpImpOrForward realizeClassMaybeSwiftMaybeRelock realizeClassWithoutSwift methodizeClass

Load all class data when map_images is not lazily loaded

redClass _getObjc2NonlazyClassList realizeClassWithoutSwift methodizeClass

How are categories loaded? How is it called?

attachToClass

methodizeClass 
    // Install methods and properties that the class implements itself.
    method_list_t *list = ro->baseMethods();
    if (list) {
        prepareMethodLists(cls, &list, 1.YES, isBundleClass(cls), nullptr);
        if (rwe) rwe->methods.attachLists(&list, 1);
    }

 auto rwe = rw->ext();

txt jump
    class_rw_ext_t *ext() const {
        return get_ro_or_rwe().dyn_cast<class_rw_ext_t *>(&ro_or_rw_ext);
    }

    class_rw_ext_t *extAllocIfNeeded() {
        auto v = get_ro_or_rwe();
        if (fastpath(v.is<class_rw_ext_t *>())) {
            return v.get<class_rw_ext_t *>(&ro_or_rw_ext);
        } else {
            return extAlloc(v.get<constclass_ro_t *>(&ro_or_rw_ext)); }}Copy the code

extAllocIfNeeded jump

  • 1. AttachCategories When adding categories
  • 2. Class_setVersion Sets the class version
  • 3. AddMethods_finish When the method is added
  • 4. Class_addProtocol Adds a protocol to the class
  • 5, _class_addProperty
  • 6, objc_duplicateClass

When was the classification loaded?

  • AttachCategories Call focus
  • 1, attachToClass
  • 2, load_categories_nolock

Why rWE, RW, RO? What is the connection between the three?

Ro clear m Shahe path loaded over readonly RO Copy an inch in rW RW dirty memory run time function

  • 1. Add classification and add methods
  • 2, API addMethods

Ro is readonly, you can’t change it, so you have to use RW but not every class has to use classification, so you get dirty memory, and that’s where you use RWE. Class has method protocol property name parent class

  • read_image clas->data

auto ro = (const class_ro_t *)cls->data();

Print realizeClassWithoutSwift – realizeClassWithoutSwift – hl-hlperson

class_getClassMethod jump

Restore by format

auto ro = (const class_ro_t *)cls->data();
Copy the code

Automatically find the current type and assign each value, unless the current format address does not match and cannot be resolved, so RO reads the address pointer from the Mach-O and can assign all the corresponding data of class_ro_t.

Rwe assignment

extAllocIfNeeded

attachCategories

MethodizeClass calls attachToClass three times

methodizeClass – previously = nil

realizeClassWithoutSwift – previously

attachLists

Observe whether the classification has entered the main class

After printing 21 methods, there is still no classification method

Observe that (method_list_t *) $0 = 0x00007FFF80AD89c8 is consistent with [63] = 0x00007FFF80AD89c8

p mlists + ATTACH_BUFSIZ – mcount

p addedLists

The two values are the same

conclusion

  • 1. Load methods for both: _read_images non-rechargeable classes – realizeClassWithoutSwift – load_categories_NOLock – attachCategories
  • 2: _read_images – realizeClassWithoutSwift – methodizeClass – attachToClass – not go attachCategories
  • 3: Category no + main class Load (data()) _read_images – realizeClassWithoutSwift – methodizeClass – attachToClass – No go attachCategories
  • -> Delay initialization until the first message is sent -> data()
  • 5: Both load methods – lots of categories (not all categories have loads)