This is the 14th day of my participation in the August More Text Challenge. For details, see: August More Text Challenge

_read_images Process analysis ro, rw

Last time we said readClass, we added the name to the class, so where did we add ro, rw? I’m gonna go back to _read_images and I’m gonna break it and I’m gonna dig a little bit. I typed a breakpoint in Remap Classes and ran it, but it didn’t go in.

Lazy loading and non-lazy loading

To save memory and speed, Apple doesn’t load all classes. Instead, we load our own classes on demand in a lazy way, and when we implement load, it’s non-lazy. If a load is not implemented, the class is lazily loaded and will be loaded when the class first receives the message.

Lazy load class case: data loading is delayed until the first message

  • lookUpImpOrForward
  • realizeClassMaybeSwiftMaybeRelock
  • realizeClassWithoutSwift
  • methodizeClass

Non-lazy class loading: all class data is loaded when map_images is used

  • _getObjc2NonlazyClassList
  • readClass
  • realizeClassWithoutSwift
  • methodizeClass

If you go down to objc_msgSend_fixup, it’s irrelevant to the class, so skip it. Further down, discover Protocols are also class independent. Below you see Protocol References, which also has nothing to do with classes, so keep going. Discover Categories, categories, continue to skip. I’m going to go down here and see Realize non-lazy Classes, the implementation of a non-lazily loaded class, which is related to the implementation of the class, and that’s what I’m going to do.

Because I’m going to study my own class, I need to implement the load method of that class, otherwise LGPerson won’t be able to get in here.

I added the load method and ran it, but I found it was from read_images.

I comment out the load method and I run it, and I see that LGPerson is implemented in realizeClassWithoutSwift, and I print it out and I see that it was actually called when the message was received.

And then I started to study it. After adding the method to verify that it is the class we want to study, run the program.

I ran it and it did come in.

As you go down, you see that realizeClassWithoutSwift is called.

When I go in and print out CLS, it’s LGPerson

Keep going

And I’m going to print Po, and I’m going to see baseMethodList for ro, which means that the method and all the data has been loaded in.

I’m going to go down and find where the assignment was made. I’m going to go in here, and I’m going to set ro and Rw here. Look at rw->set_ro(ro), which is why rW’s data is similar to ro, except where it is dynamically processed, such as addMethod, addProtocols.

If you go down here and you see that if it’s a metaclass, it’s going to do rawIsa, so that’s why isa for metaclass is pure ISA.

Installed DisableNonpointerIsa downwards see, see if this is true, will set instancesRequireRawIsa is true, then call setInstancesRequireRawIsaRecursively. This is why when you set DisableNonpointerIsa to YES, you get pure ISA.

Continuing down, you see that the parent class and ISA are set up

And you’ll see down here that we have subclasses set up here.

Set a condition below to determine whether it is LGPerson class, and add a condition that it is not metaclass in case the metaclass comes in.

Ro baseMethodList still has no content

Next step is to look inside methodizeClass.

Copy the previous condition in, hit a breakpoint and run.

So if I go down here, I see that I got ro’s baseMethods

Go down one line, wait for the assignment, look at the list, find the address, try to print it, and find that it’s no different than the one that was printed before.

So let’s go down here, prepareMethodLists, and type a breakpoint in there

As I continue running, I find myself inside the fixupMethodList.

When I go in, I see the setName operation, and the value of name is sel, and sel_cname is the value that converts sel to const char *.

If you go further, you see that this address is also sorted by the address of sel. Do not try to change the location of the small address, because the small address after the order is immutable. Do not change the order of large lists that are not standard size either, because stable_sort will not copy entries correctly.

Then is there sorting? Print sel before and after sorting to check whether it is sorted

Make sure that the LGPerson class comes in at runtime, and then look at it. The discovery does sort the methods.

So let’s go back to methodizeClass and see if there’s a value for baseMethods in ro. Notice that the saySomething of the class is next to the saySomething of the main class, and that the saySomething of the class is right in front of the main class. This explains why method in the method look-up is called the method of the same name as the method of the class. And it also shows you that in prepareMethodLists, you sort methods and things like that.

We saw methodizeClass Attach categories in the comment, so what happens to categories here? Before we explore, let’s understand what classification is.

classification

To study classification, take a look at the c file. When WE generate our CPP file and open it, we see _category_t on the last line and we have our LG category,

To find out what _category_t is, it’s also a structure. Why do we have instance_methods and class_methods here, instead of just writing a methodLIst or something like that? This is because the classification has no metaclass, so the methods are all written here, so they need to be written separately.

If you go down here, you see it’s LGPerson. So when I compile it statically, it’s not running yet and when I run it, I don’t know what the name is, so I’m going to write LGPerson. The 0 below indicates that there is no protocol.

Add a protocol and re-clang it. It’s not going to be zero.

Look below to see all the methods in the category, but there are no set or get methods.

Go back to the source code and check category_t to see if it’s the same as in CPP. There’s an extra _classProperties, but the comment says it doesn’t always have them.

So how is the classification written into the class? Let’s break it down next time