The application loads examples
- Create a simple project to add print to the entry main function
1223333
, plus a c++ function called kcFunc(), and a load() method on the viewcontroller
C++ function 3 is called. Load is called. C++ function 3 is called. Finally, enter main and print 1223333
3. I don’t understand why I called load and c++ functions before entering main, which is the entrance of app. Tell me what the system did before the app started.
1.1, libraries,
Every application relies on some basic library, such as UIKit, CoreFoundation, etc. Libraries are executable binaries that can be loaded into memory by the operating system. There are two types of libraries, static libraries (.a,.lib) and dynamic libraries (.so,.dll), the main difference between the two libraries is the link.
Static library
The static library is loaded at compile time and copied to the executable in its entirety when linked. The static library does not change because it is copied directly at compile time.copy
To the target program.- Advantages: Compiled executables do not require external library support and can be used directly.
- Disadvantages: If multiple apps are used, multiple copies will be made. They cannot be shared and occupy more redundant memory. All functions are in the library, so you need to recompile them when you modify them.
The dynamic library
: a programIt does not link to the target program at compile time
The target program will onlyStores references to dynamic libraries
, dynamically loaded into memory by the system while the program is running.-
Advantage:
- Reduce the size of the packaged APP: because it does not need to be copied to the target app, it does not affect the size of the target app, which reduces the size of the APP compared to the static library
Shared memory saves resources
: The same library can be used by multiple programs- The purpose of updating the program is to update the dynamic library: because of features that are loaded at runtime, the library can be replaced at any time without the need to recompile the code
-
Disadvantages: Dynamic loading incurs a performance penalty. Using dynamic libraries also makes the application dependent on the external environment. If the environment lacks dynamic libraries, or the version of the library is incorrect, the application will not run
-
The build process
The source file
H,. M, and. CPP files are loaded
precompiled
: Replaces macros, deletes comments, expands header files, and generates.i files
compile
The compiler converts the. I file into assembly language, producing. S files
assembly
: Converts assembly files to machine code files to generate. O files
link
: References other libraries in the.o file to generate the final executable
The compilation process is shown in the figure below, which is mainly divided into the following steps:
- The generated executable file
dyly
My understanding is that the executable file is linked to the library of the mobile phone system. The executable file can be dynamically linked to some system libraries to run on the mobile phone.
Dyld full nameThe dynamic link editor
. It isApple's dynamic linker
Is an important part of Apple operating system. After the application is compiled and packaged into an executable file format, DyLD is responsible for linking and loading programs.
- Runtime register callback function:
_dyld_objc_notify_register(&map_images, load_images, unmap_image);
- Image: image file after library mapping,
- Mapping: Copy a copy from disk to memory
- Do an extension tip to find the system library files.
- 1. Breakpoint (any breakpoint)
- 2.LLDB enter the image list command
- 3. Search CoreFoundation
- 4. Copy the path to the file to find the system library.
- 5. I have this on the simulator.
2 dyld process
- 1. Add the +load method to the controller and set a breakpoint. LLDB BT printing function stack, look at the left stack printing, in fact, is one – to – one correspondence.
- The process is basically this
- 1._dyld_start
- 2.dyldbootstrap::start
- 3.dyld::_main
- Dyld ::useSimulatorDyld ::useSimulatorDyld ::useSimulatorDyld
- 5.start_sim
- 6.dyld::_main(macho_header const*, unsigned long, int, char const**, char const**, char const**, unsigned long*)
- 7.dyld::initializeMainExecutable()
- 8.ImageLoader::runInitializers(ImageLoader::LinkContext const&, ImageLoader::InitializerTimingList&)
- 9.ImageLoader::processInitializers(
- 10.ImageLoader::recursiveInitialization
- 11.dyld::notifySingle
- 12.load_images
- APP loading process
- 1. Start the app
- 2. Loading libSystem
- 3.Runtime registers the callback function with dyLD
- 4. Load new image
- 5. Run map_images and load_images
- 6. Call main
- Now let’s make a breakpoint at the main entrance. Go over the last breakpoint and go over here, and this is the entry point to the program, indicating that the controller was loaded before the program came in.
The target looks at what the program load does from dyldstart -> main
- 1. Just figure out what the paragraph does.
- 2. Download DYLD 852
The source address
- 3. Load is called before main
- Load -> LLDB bt
-
frame #12: 0x00000001130d4025 dyld
_DYLD_START + 37 ‘knows this is the dyLD entry
1. Find your goal
- 1. Find assembler _dyLD_start
- 2. Find the target, different architectures, different choices, but the main process is the same.
- 3. This function is called
dyldbootstrap::start(app_mh, argc, argv, dyld_mh, &startGlue)
- 4. Search next
dyldbootstrap
That’s the namespace, and I’m going to keep finding itstart
Method to find that it is returneddyld::_main
The result of the function. C++ syntax problems. Similar to the start method of the dyldBootstrap class.
- 5. Return _main
- 6. Go to main
1000+ lines of code for selective viewing learning
2. Enter the main function in the main flow
-
Step 1 – Conditions: Environment, platform, version, path, host information…
-
getHostInfo(mainExecutableMH, mainExecutableSlide);
Preparation of architectural information
-
- Image file platform information
-
- The file path
-
checkEnvironmentVariables(envp); // Check the environment variables set
-
defaultUninitializedFallbackPaths(envp); // If DYLD_FALLBACK is nil, set it to the default value
-
The environment variable DYLD_PRINT_OPTS is printed if set, and the environment variable DYLD_PRINT_ENV is printed if set
-
-
- Load the shared cache, system level processing.
- 2.1 call
checkSharedRegionDisable
Function checks and loads shared cache libraries (iOS cannot disable shared cache libraries)
mapSharedCache(mainExecutableSlide);
Check whether the shared cache maps to the shared region
-
3.
addDyldImageToUUIDList();
Add dyly itself to the UUID list -
4. The main program initializes sMainExecutable
-
4.1 We infer from the backwardness of result
sMainExecutable
create -
4.2. Push back to
sMainExecutable
Create by looking at the source view, combined with the function call stack, we follow in the call process to findsMainExecutable
。- Load the executable and generate an ImageLoader instance object
-
-
5. Load and link the dynamic library
- 5.1
loadInsertedDylib(*lib);
Load the inserted dynamic library and iterateDYLD_INSERT_LIBRARIES
Environment variable, callloadInsertedDylib
loading
-
5.2. Link library
- Through:
sInsertedDylibCount
ImageLoader* image = sAllImages[i+1];
link(image, sEnv.DYLD_BIND_AT_LAUNCH, true, ImageLoader::RPathChain(NULL, NULL), -1);
Link inserts a dynamic librarythis->recursiveApplyInterposing(context);
Insert any dynamically loaded image files
- Through:
- 5.1
-
6. The link of the main program
- 7. WeakBind weak reference binding main program
- 8. Initialize the main program and run all initializers
- 9. Address the main program entry
- Listen to Dyly’s main
notifyMonitoringDyldMain();
3. The main program runs process initializeMainExecutable();
Now we probe into the main program initialization what did sMainExecutable said the main program variables, view its assignment, is the method instantiateFromLoadedImage initialization
1.instantiateFromLoadedImage
->instantiateMainExecutable
- Enter the
instantiateFromLoadedImage
The function view
- Enter the
instantiateMainExecutable
The function view
- Among them
In the sniffLoadCommands
Is to get a Mach-O type fileLoad Command
And carry out all kinds of verification on it.Determine if this Mach-O file has a compressed LINKEDIT and the number of segments
- Enter the
In the sniffLoadCommands
The function view
2. Run the main program
After the main program initialization is complete and the main program is running, we return the code back here initializeMainExecutable();
- Enter the
initializeMainExecutable()
To view- Insert dynamic library traversals with runInitializers
- Main program calls runInitializers
- Global search entry
runInitializers()
To view
- 1. Initialization preparation: processInitializers Preparation Image files are ready
- 1. Enter the
processInitializers
Function source code implementation, which on the mirror list callrecursiveInitialization
Function is instantiated recursively
- 2. RecursiveInitialization dependence on the underlying file to load
- NotifySingle ->2. DoInitialization, then notifySingle
- 1. Enter the
- So let’s look for this
context.notifySingle
- To find the
(*notifySingle)(dyld_image_states, const ImageLoader* image, InitializerTimingList*);
- Global search to find here
- Global search
sNotifyObjCInit
, found no implementation found, assignment operation
- To view
registerObjCNotifiers
Call timing of_dyld_objc_notify_register
A function call
- Call this method in objC_init of the OBJC source library.
- Let me rearrange the order
- context.notifySingle -> (*sNotifyObjCInit)
- SNotifyObjcInit is assigned to init in the registerOBjCNotifiers call, that is, sNotifyObjcInit = init
- _dyly_objc_notify_register calls the registerObjCNotifiers, init = init
- _dyly_objc_notify_register passes three parameters
- &map_images
- load_images
- unmap_image
- We get load_images = init = sNotifyObjcInit
load_images
load_images
->call_load_methods()
- prepare_load_methods
-
classref_t const *classlist = _getObjc2NonlazyClassList(mhdr, &count); Get a list of all the loaded classes
-
Traversal: schedule_class_load
- (CLS ->superclass) (CLS ->superclass)
- Add_class_to_loadable_list adds this class’s load method to the list
-
classref_t *classlist = getObjc2NonlazyClassList(mhdr,&count);
-
- Enter the view
call_load_methods
Loop callcall_calss_loads()
There arecall_category_loads();
Classification of the load
- Enter the
call_calss_loads()
See what is called hereload
Method validates the class we mentioned earlierload
Method,
-
Objc_autoreleasePoolPush () pushes the pool automatically
-
class_class_loads()
-
call_category_loads()
-
Objc_autoreleasePoolPop (pool); Out of the stack
-
So load_images calls all the load functions, and the above source code analysis corresponds exactly to the printed stack information
map_images
-> map_images_nolock
-> _read_images
- Class gdb_objc_readied_classes
- Methods nameSelectors
- Agreement protocol_map
- The main role
- Initialize class: realizeClass sets RW/RO
- Processing classes: Add methods, protocols, and attributes from a class to a class
- Load the corresponding hash table
Now the sNotifyObjcInit can only be assigned if you know to start calling objC_init. NotifySingle
- Global search is completely absent
- So let’s play that for a second
doInitialization
doInitialization
-
Now let’s go back
this->doInitialization(context)
Image file initialization look at line 1657, -
Enter the
doInitialization
You see that two methods are called. 1.doImageInit()
. 2.DoModInitFunctions ()
We don’t know what they’ve been up to -
Enter the
doImageInit(context)
Check and find this.Initializer func = (Initializer)(((struct macho_routines_command*)cmd)->init_address + fSlide);
// Mach-o address offset, get a function,libSystemInitialized
LibSystem initialization must not be abandoned in advance -
Enter doModInitFunctions (context); Dylib ‘libSystem_initializer:-> -libdispatch_init :-> – _os_object_init(libdispatch.dylib)-> – _objc_init(libobjc)
-
The stack information here prints out a reminder to look at this.
Enter thedoModInitFunctions
Source code implementation, this method loaded allCxx
file
- in
libsystem
Look forlibSystem_initializer
To see the implementation \
- Based on the previous stack information, we find that the path is
libSystem_initializer
Will calllibdispatch_init
Function, and the source of this function is inlibdispatch
Open source library, inlibdispatch
In the searchlibdispatch_init
\
- Enter the
_os_object_init
Source code implementation, its source code implementation called_objc_init
function
- So the whole idea is to look at the function call stack to explain this process, and find the corresponding source code to learn.
4. Flow chart interpretation
Refer to blog – Month big guy