Series of articles:OC Basic principle series.OC Basic knowledge series.Swift bottom exploration series.IOS Advanced advanced series

preface

In this article, we continue where we left off from the previous article on multi-environment configuration, Mach-O, and the linker, but Symbol has not talked about it yet

. Xconnfig supplement

This was covered in the previous article when we introduced multi-environment configurations.xconnfigAnd said to the.xconnfigcanUnified management environment configurationHere can be based onDifferent conditionsconfigurationDifferent Settings, ourOther Linker FlagsTo illustrate the

The framework “Man” is added when the device is an emulator and the architecture is x86.

We can see that compiling under ARM64 is successful because Other Linker Flags does not import Man

In x86_64, an error was reported telling us that Man could not be found. This is because Man was put into the project environment in x86_64

The Mach – O speak again

The previous article covered Mach-O only briefly, but I’ll add a few more

The Mach -o structure

The mach-O structure is shown as follows:The explanation is as follows:

  • 1.Mach HeaderTell the performer himselfcontainsWhat are theinformation(Which is the identity of this Mach-O.)
  • 2.Load CommandisThe configuration file.The last threeIt’s oursThe file location of the compiled code
  • 3.The configuration fileallrecordSomething necessaryFile informationFor example, Load Command _TEXT contains the following contents:
    • Text Specifies the size of the code segment
    • Text Specifies the starting position of the code segment
  • Record the otherThe necessary information, such as:UUID identifier.Version Version.Dylinker connector position.Linkdit Dynamic library information.Which libraries Dylib introduces, specify the entry asThe Main function(You don’t have to specify a Mian function as an entry point.)

【 Note 】 : Each read can be guaranteed to read a Load Command, this is because the information is arranged according to the structure alignment way, so the agreed number of bytes, can read exactly

Mach Header

The Mach Header structure is as follows:Explain a few major ones:

  • Cputype: architecture
  • Filetype: executable file or target file
  • Sizeofcmds: size

To make things easier, let’s print the Mach header

__TEXT

Let’s use the command to see main.m translated into text on x86

  • The leftisaddress, we see that the start address of main is 100003F20 and the end address is 100003F5e.
  • In the middleisMachine codeTo giveThe machine to readthe
  • On the rightisassemblyTo giveDevelopers to readthe

This is a bit like looking up a dictionary and agreeing in advance on the relationship between assembly and machine code. When machine code 55 is read, it corresponds to assembly: pushq % RBP, and so on

The Mach -o features

The previous article showed that Mach-O is readable and writable. Readable we already said, what do we mean by writable? Mach-o can only be executed because of signatures, and when we modify the Mach-O file, we need to re-sign it to be accepted by Apple systems. This is why cracking soft solutions requires a new signature.

The linker

The process of generating object files

  • 1.The linker (llVM-LD) was not executed
  • 2.The object file does not contain the inclusion information necessary for Unix programs to be loaded and executed

It’s not easy to understand, so let’s go straight to the code

The code on

We write the following code in the main.m file:So we see that we have properties defined in dot m, so let’s see if we compile to__TEXTWhat is aWe found many more things compared with the above. For example:NSLogNow it becomes oneInstruction callq address 0x100003F60

That is, at compile time:

  • The 1.Can be converted to assemblyThe first to becomeassembly.Machine code.
  • The 2.attributeintosymbolforclassified -> Place in the relocation symbol table(Relocation symbol table is the API used to put.m/.o.)
  • 3..o ->The linker -> A table -> Executable file exec

The reason we put it in the relocation symbol table is becauseIt's already in the symbol tableWhen the.o file is generated, theaddressalsoNo virtualization.The linkerinTo connectWill be rightRelocate symbol tableformerge.

Linking is the process of handling object file symbols

Command to view the relocation symbol table

Command:Objdump --macho --reloc +.o filesAfter running, the relocation symbol table is printed as follows:Here’s a diagram to illustrate:

If you don’t use it, you don’t put it in a.o file, so you can look at a.o file to see how it’s used for an API

Symbol

Let’s look at the symbol table of main.m with the command

  • L: Local layout
  • G: Global
  • D: Debug
  • O: Data
  • F: Function

I summarize the character descriptions in this section below:We see a lot of symbols up hereThe Debug modeWe will remove this part with the command. We can get throughStrip commandAlso throughThe linker argument -s

Link without putting debug symbols in the resulting executable.

  • Debug symbols: When our file goes throughThe compilerwillgenerateaDWARF formattheDebug fileIt will be placed inMach-Othe__DWARF section, in theThe connectionWhen willKill __DWARF.At the same timetheThe __DWARF section becomes a symbolAnd put itThe symbol tableIn the.

From the above two figures, we can see that the global variables are g (global symbol) and the local variables are L (local symbol), and the global symbol is changed to the local symbol: 1. Add static 2. Use the __attribute__ keyword (line 16)

Import/export symbol

We know that NSLog is from the Foundation framework, so it’s in line 19, so it’s basically importing NSLog notation, and since Foundation exported NSLog notation for other places to use (exported notation is global notation)

Let’s take a look at the exported symbols in main.m by using theWrite commands to.xcconfigCompile,

We see that there are four exported symbols, which correspond to the four global symbols in the printed symbol table above. This means that when we declare global symbols, it defaults to exported symbols and can be used elsewhere

Let’s create an OC class and look at symbols

OC classes default to export symbols

Indirect symbol table

We know thatThe dynamic libraryIs in therunThe process ofIn the load, which means thatIt is at the compile link stageOnly need toProvide symbolThat’s fine. We were talking about in the last articleThe symbol tableWhen mentioned:Indirect symbol tableSave this item for useOther dynamic librariesthesymbol, next we pass through the.xcconfigWrite command, compile to viewIndirect symbol table

In this case, we only know the last NSLog, which is the exported notation that Foundation gave me

conclusion

  • 1.Global symbols can become exported symbols for external use
  • 2.Indirect symbol tables cannot be deletedThat means thatThe dynamic libraryIn theGlobal symbols cannot be deleted, that is to sayIn the Strip dynamic libraryWhen,Cannot strip global symbol
  • 3.OC classinCompile timewillThe defaultforExport symbolsSo we are usingOC Writes the dynamic libraryIf you want to make as much as possibleThe dynamic library package is smallerWe can do it atXcconfig defines parameters without exporting symbols
    • To compile
    • We found one less than the one above_OBJC_CLASS_$_LjOneObjectThe same method can be used to make_OBJC_METACLASS_$_LjOneObjectAlso disappear

supplement

It is possible to reduce the size of the dynamic library by not exporting symbols, but there is a way to write too many classes:

  • 1.Executable file

  • The file in 2.1 can be obtainedUse class library information by viewing the current file

Output after compilation:

The red box tells the developer how many object files are generated and which library files are used for the project. You can export symbolic information and link information through map

Weak Symbol

Weak Symbol can be divided into two types

  • Weak Reference Symbol: Indicates that the undefined Symbol is a Weak Reference. If the dynamic linker cannot find the definition of the symbol, it sets it to 0. The linker sets this symbol to the weak link flag.

  • 2.Weak defintion Symbol: Indicates that this Symbol is weakly defined. If the static or dynamic linker finds another (non-weak) definition for this symbol, the weak definition is ignored. Symbols in the merged section can only be marked as weakly defined.

Weak Reference Symbol

Weak Reference Symbol Weak Reference Symbol

The system will not report an error if the incoming symbol is not defined

To illustrate some of the problems, write the following code in the main function:But writing this will return an error, because: in sayingCompilation link principleHow do you look up symbols? We are inWeakimportsymbol.h writes the declarationIn theUsed in the main function, it isUse the API, but inWhen you connectWe needKnow the address of the symbolWhere is it, or the hint won’t be foundWe can tellThe compiler, I thisSymbol - time dynamic linkingThe,Don't tubeIt’sThe specific locationEven if it is weakly referenced by thenDyld runGet up, yourselfWill findthe

The -u argument tells the compiler that this is undefined and needs to be looked up dynamically

Run it again and it will be successful, so what’s the use of this? For example, we can determine if there is this symbol in other libraries. If there is this symbol, I will call it. If there is no symbol, I will not call it. Another use for dynamic libraries is that we can declare the entire dynamic library file as a weak reference. What is the advantage of this? This means that if you do not import the library, you will not report the dynamic library could not find the error.

Weak defintion Symbol

Weak defintion Symbol Weak defintion SymbolSo here’s the weakly defined notation:If the static or dynamic linker finds another (non-weak) definition for this symbol, the weak definition is ignoredHow to understand this sentence? We understand it in code

  • 1. In.h weWeak defines the Weak_function method
  • In dot m we implement thisWeakly defined method

Method implementationandDeclarations are globalIt says it should be convertedExport symbolsNow let’s change it and look at the print

When a weakly defined method is declared, it does not affect the export as an export symbol

When we declare the same method in dot m

Normally, the execution would have reported an error because the method name was the same, but since the method was weakly defined, the compilation would not have reported an error.

Now we call this method in the main functionRun print results

Weak_function () {weak_function (); weak_function (); weak_function (); weak_Function (); weak_Function (); weak_Function (); weak_Function ()

If we declare a weakly defined symbol as a hidden symbol, then it should be a weakly defined local symbol

Reexport symbol

When we use NSLog in main, when I want other projects to use main.m, we can use NSLog, and that requires us to re-export the NSLog (in fact, NSLog is already re-exported in Foundation, otherwise it’s not usable outside).

When weExport NSLog again, you need toThe symbol of an indirect symbol is aliased

It will automatically change this NSLog to the export symbol Lj_NSLog, compile

We found that Lj_NSLog exists, but this form is not friendly enough, so we need to print it in a different way and write commands

So we see that Lj_NSLog becomes an alias for NSLog, so let’s look at the exported symbol table symbol

You can see that Lj_NSLog is exported, and it’s a re-exported symbol

Function: when we link another dynamic library in our dynamic library, one of the dynamic library is not visible to your linked program, we can use this re-export method to make the dynamic library visible, can make a symbol visible, also can make a dynamic library visible

conclusion

A few points can be learned from the symbols above:

  • 1. Symbols in the indirect symbol table cannot be deletedThe dynamic libraryIn theGlobal symbols cannot be deleted, that is to sayIn the Strip dynamic libraryWhen,Cannot strip global symbol
  • 2.Static libraryisO File totalAs well asRelocate symbol tableBecause ofRelocation symbols cannot be deleted, soOnly debug symbols in strip.0 files

[Question] Which is bigger when App is added to dynamic library or static library (only considering symbols)

Answer: Dynamic libraries are larger

The reason:

  • Static libraryApp is linking to static libraryWhen will be.o fileAs well asRelocate symbol tableIn theSymbol table for AppMedium, which meansIt becomesthemayisLocal, global, exported symbolsAccording to what we said aboveDetach from symbol table rules, in addition toA symbol in an indirect symbol tableYou can take off everything else
  • 【 Dynamic library 】App is linking to dynamic libraryWhen,Symbols areIn theIndirect symbol tableCause inOff the symbol tablewhenYou can't get away from the indirect symbol table

Expand Strip Style (symbol off)

  • 1.Debugging Symbols(.o static library/executable dynamic library)
  • 2.All Symbols
  • 3.Non-Global Symbols

Strip Style process

Static library

The dynamic library

All Symbols

Non-Global Symbols

Wrote last

This article is the last article of the year, here in advanceHappy New Year to you all!The article wrote some things did not say in detail, the back will be introduced! I hope we can communicate more and make progress together. Finally, I will post the instructions above: