{"id":16668870,"url":"https://github.com/doronz88/swift_reversing","last_synced_at":"2025-04-07T13:08:25.778Z","repository":{"id":103942079,"uuid":"468308823","full_name":"doronz88/swift_reversing","owner":"doronz88","description":"My ongoing premier on reversing Swift","archived":false,"fork":false,"pushed_at":"2025-01-05T23:24:03.000Z","size":38,"stargazers_count":79,"open_issues_count":1,"forks_count":13,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-03-31T12:04:56.499Z","etag":null,"topics":["documentation","ida","ida-pro","reverse-engineering","swift"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/doronz88.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-03-10T11:12:03.000Z","updated_at":"2025-03-21T13:55:38.000Z","dependencies_parsed_at":null,"dependency_job_id":"f92c2bec-fb61-4e5f-a8c2-1f5e9d470606","html_url":"https://github.com/doronz88/swift_reversing","commit_stats":{"total_commits":9,"total_committers":2,"mean_commits":4.5,"dds":"0.11111111111111116","last_synced_commit":"7a82452a4674f9694cdd1f6e07668412ecba475e"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/doronz88%2Fswift_reversing","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/doronz88%2Fswift_reversing/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/doronz88%2Fswift_reversing/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/doronz88%2Fswift_reversing/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/doronz88","download_url":"https://codeload.github.com/doronz88/swift_reversing/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247657281,"owners_count":20974345,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["documentation","ida","ida-pro","reverse-engineering","swift"],"created_at":"2024-10-12T11:27:45.637Z","updated_at":"2025-04-07T13:08:25.761Z","avatar_url":"https://github.com/doronz88.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Reversing Swift\n\nThis documentation was created to better understand the underlying layer of swift code execution.\nHere we'll cover how each Swift \"concept\" is actually translated into binary form.\n\nYou may run the following python script in IDA (Alt+F7) to help you\nreverse the code more efficiently: [`swift.py`](https://github.com/doronz88/ida-scripts/blob/main/swift.py)\n\nThe script adds the `Ctrl+5` HotKey to quickly parse the `Swift::String` occurences within the current function.  \n\n\u003e **NOTE:** This script is practically is and probably always will be a work-in-progress,\n\u003e adding more and more types to make our lives better at reversing swift.\n\u003e Please submit PRs if you find stuff you're missing.\n\n## Swift segments\n\n**NOTE: Read this \u003chttps://github.com/swiftlang/swift/blob/main/docs/Lexicon.md\u003e before starting with this section**\n\nOne of the most important ideas introduced in Swift was the use of \"relative pointers\".\nThis idea enables these pointers not to be rebased thus improving efficiency.\nThis can be demonstrated in: \u003chttps://github.com/swiftlang/swift/blob/main/include/swift/Basic/RelativePointer.h\u003e.\n\nAs stated:\n\n```none\nSome data structures emitted by the Swift compiler use relative indirect addresses in order to minimize startup cost for a process. By referring to the offset of the global offset table entry for a symbol, instead of directly referring to the symbol, compiler-emitted data structures avoid requiring unnecessary relocation at dynamic linking time.\n```\n\nThese relative pointers make use of int32 types (instead of 8 bytes which would be the traditional pointer!).\nAs a simple pseudocode, you can think of an offset like this:\n\n```c\ndstAddress = ptr_auth(currentAddress + (int32)offset)\n```\n\nWhen analyzing a binary that makes use of the Swift runtime, you will be able to find lots of `swift5_*` segments.\nThese segments (together with `__const`) provide Swift with all it needs.\n\nFollowing, you'll see a description of those.\n\n### `__TEXT.__swift5_protos`\n\nContains a list of relative pointers that each of them point to a **Protocol Descriptor**.\n\n  Each of them consist of what we know as a **Swift Protocol**. These pointers point to `__TEXT.__const`.\n\n  The implementation of each **Protocol Descriptor (Swift Protocol)** can be found at: \u003chttps://github.com/swiftlang/swift/blob/main/include/swift/ABI/Metadata.h#L3193-L3241\u003e (more on this later when we dig deep into the Swift Protocols). The structure of a **Protocol Descriptor** is:\n\n  ```swift\n  type ProtocolDescriptor struct {\n      Flags                      uint32\n      Parent                     int32\n      Name                       int32\n      NumRequirementsInSignature uint32\n      NumRequirements            uint32\n      AssociatedTypeNames        int32\n  }\n  ```\n\n  Or, to be more specific with Swift types:\n\n  ```swift\n  type ProtocolDescriptor struct {\n      Flags                      ContextDescriptorFlags \n      Parent                     TargetRelativeContextPointer \n      Name                       TargetRelativeDirectPointer\n      NumRequirementsInSignature uint32\n      NumRequirements            uint32\n      AssociatedTypeNames        RelativeDirectPointer\n  }\n  ```\n\n### `__TEXT.__swift5_proto`\n\nThis section is a list of relative pointers to **Protocol Conformance Descriptors** (\u003chttps://github.com/swiftlang/swift/blob/main/include/swift/ABI/Metadata.h#L2773-L2784\u003e).\n  Each of these point to the `__TEXT.__const` section. A script to parse this sectio can be found in: \u003chttps://github.com/doronz88/ida-scripts/blob/main/fix_proto_conf_desc.py\u003e.\n\n  ```c\n    /// The Protocol Descriptor being conformed to.\n    TargetRelativeContextPointer\u003cRuntime, TargetProtocolDescriptor\u003e Protocol; \n  \n    // Some description of the type that conforms to the protocol.\n    TargetTypeReference\u003cRuntime\u003e TypeRef;\n\n    // The witness table pattern, which may also serve as the witness table.\n    RelativeDirectPointer\u003cconst TargetWitnessTable\u003cRuntime\u003e\u003e WitnessTablePattern;\n\n    // Various flags, including the kind of conformance.\n    ConformanceFlags Flags;\n  ```\n\n  Which can be understood as:\n\n  ```swift\n  type ProtocolConformanceDescriptor struct {\n      ProtocolDescriptor    int32 //relative ptr\n      NominalTypeDescriptor int32 //relative ptr\n      ProtocolWitnessTable  int32 //relative ptr\n      ConformanceFlags      uint32\n  }\n  ```\n\n  \u003e **NOTE:** Protocol Descriptor is the protocol they **conform** to.\n\n### `__TEXT.__swift5_types`\n\n  Types can take many forms (\u003chttps://github.com/swiftlang/swift/blob/main/include/swift/ABI/Metadata.h#L4840-L4872\u003e) that are resolved in runtime.\n  Thus, even if the structs are **the same size** they mean different things which means there isn't a unique solution for parsing this segment.\n\n  (Again, thanks Scott Knight for his work, this is directly taken from his research)\n\n  ```swift\n  type EnumDescriptor struct {\n      Flags                               uint32\n      Parent                              int32\n      Name                                int32\n      AccessFunction                      int32\n      FieldDescriptor                     int32\n      NumPayloadCasesAndPayloadSizeOffset uint32\n      NumEmptyCases                       uint32\n  }\n\n  type StructDescriptor struct {\n      Flags                   uint32\n      Parent                  int32\n      Name                    int32\n      AccessFunction          int32\n      FieldDescriptor         int32\n      NumFields               uint32\n      FieldOffsetVectorOffset uint32\n  }\n\n  type ClassDescriptor struct {\n      Flags                       uint32\n      Parent                      int32\n      Name                        int32\n      AccessFunction              int32\n      FieldDescriptor             int32\n      SuperclassType              int32\n      MetadataNegativeSizeInWords uint32\n      MetadataPositiveSizeInWords uint32\n      NumImmediateMembers         uint32\n      NumFields                   uint32\n  }\n  ```\n\n  The reader is encouraged to find the types of **TargetExtensionContextDescriptor**, **TargetAnonymousContextDescriptor**, **TargetOpaqueTypeDescriptor**.\n\n### `__TEXT.__swift5_typeref`\n\nThis section contains the symbolic references needed by the runtime to perform instantiations and reflections. \n\nFor instance, the first argument of methods such as `swift_instantiateConcreteTypeFromMangledName` (which will return the metadata) will point to the `__data` section which will contain a relative pointer to the `swift5_typeref` section. \n\nThese symbolic references follow a pattern. From our research, we found in Swift docs that depending on the first byte of the symbolic reference what we find has different meanings. \n\nBecause a type can contain other types (imagine an array of elements - you have the ContiguousArray type and what is being contained), when we see a symbolic reference definition we may see concatenated references.\n\n__NOTE: THIS IS WIP, SOME STUFF MAY BE INACCURATE OR HAS MISSING INFO__\n\n(usually we'll see a symbol name referencing the first byte of the symbolic reference which will make our lifes easier when parsing with an ida-script)\n\n```\nswitch(first_byte):\n  case 0x01:\n    Direct reference to a context type descriptor\n    1 byte - type (0x01)\n    4 bytes - relative pointer\n    1 byte - if value 0x79 it means the symbolic reference is not finished. If it is 0x47 or 0 it means the symbolic reference is complete and no further parsing is needed.\n\n  case 0x02:\n    Indirect reference to a context type descriptor\n    1 byte - type (0x02)\n    4 bytes - relative pointer\n    1 byte - if value 0x79 it means the symbolic reference is not finished. If it is 0x47 or 0 it means the symbolic reference is complete and no further parsing is needed.\n\n  case 0xFF: \n    1 byte - type (0xFF)\n    1 byte - usually with value 7 but don't know what is that\n    4 bytes - relative pointer to the metadata access function\n\n```\n\n  \u003e **NOTE:** We don't know what __0x53__ type is. If anyone has any idea, please feel free to add it. We know that are more types but atm we'll leave it like this.\n\n### `__TEXT.__swift5_fieldmd`\n\n  (Taken from Scott Knight research)\n\n  This section contains an array of field descriptors. A field descriptor contains a collection of field records for a single class, struct or enum declaration. Each field descriptor can be a different length depending on how many field records the type contains.\n\n  ```swift\n  type FieldRecord struct {\n      Flags           uint32\n      MangledTypeName int32\n      FieldName       int32\n  }\n\n  type FieldDescriptor struct {\n      MangledTypeName int32\n      Superclass      int32\n      Kind            uint16\n      FieldRecordSize uint16\n      NumFields       uint32\n      FieldRecords    []FieldRecord\n  }\n  ```\n\n## Primitive types\n\n```c\ntypedef long long s64;\ntypedef unsigned long long u64;\n\ntypedef s64 Int;\ntypedef u64 Bool;\n\nstruct Swift_String\n{\n  u64 _countAndFlagsBits;\n  void *_object;\n};\n\nunion Swift_ElementAny {\n    Swift_String stringElement;\n};\n\nstruct Swift_Any {\n    Swift_ElementAny element;\n    u64 unknown;\n    s64 type;\n};\n\nstruct Swift_ArrayAny {\n    s64 length;\n    Swift_Any *items;\n};\n```\n\n### Swift_String\n\nThe swift strings specifically are one of the most common types to handle. Though they sound as pretty straight forward, their allocation may be a bit tricky to track for newcomers.\n\nIn general, depeding on the `_countAndFlagsBits` and the `_object`, we can tell where the string is really allocated.\n\n- If `string-\u003e_object \u003e\u003e 60 == 0xE`, then it is stored in-place, inside the two `_countAndFlagsBits` and `_object` members\n- If `string-\u003e_countAndFlagsBits \u003e\u003e 60 == 0xD`, then the actual object is in: `(string-\u003e_object \u0026 0xffffffffffffff) + 0x20`\n\n## Advanced types\n\n### Struct\n\nStructs are a kind of \"optimized classes\", whereas the actual struct data is stored\neither on local registers or inside a global residing inside the `__common` section of the binary.\n\nIn general, as long as the struct's size \u003c= `sizeof(u64) * 4`, it's whole data structure is returned on registers `X0`-`X3` from the init method and if we are required to re-purpose this registers, they are then immediately copied to their corresponding global residing inside the `__common` section.\nAny struct bigger than that, is returned on register `X8` and is also immediately copied to the same global region. Meaning - it's enough to declare the global residing in this region with it's correct type in order to correctly reverse usages of that return value.\n\nPlease note `Swift::String` is also one such example of a Swift struct, whereas it has two members named:\n\n- `_countAndFlagsBits` containing it's length OR'ed with flags bitmask\n- `_object` containing the actual c-string\n\nThis means each time the data structure is returned, it's returned on `X0`-`X1` and passed on two registers each time aswell.\n\n### Class\n\nClass representation is somwhat more resembling C++. Each class contains a hidden `__allocating_init(RTTI *classRTTI)` method which allocates the required memory using `swift_allocObject` and only then calls the user's `init()` method. The RTTI reference is passed to the constructor and is stored as the first value inside the class (resembling C++'s `vptr` behavior).\nUnlike C++, each declared method is virtual by definition, meaning, in order to reverse the usage of each class we'll have to create a correct struct for it.\n\nFor example:\n\n```c\nstruct SomeClassRTTI {\n    // This is actually an ObjC type!\n    Class classObject;\n\n    // More metadata about class layout...\n    Unknown metadata;\n\n    // methods\n    (void (*)(SomeClass *self)) someMethod1;\n    (void (*)(SomeClass *self)) someMethod2;\n};\n\nstruct SomeClass {\n    SomeClassRTTI *rtti;\n\n    u64 ivar1;\n    u64 ivar2;\n    // ...\n};\n```\n\nGetters and setters on the other hand, aren't represented their and are compiled as they would in C++ - normal global functions getting their `self` objects from `X20`.\n\n## Swift Protocols\n\nSwift Protocols are mere interfaces that define how a type has to be adapted to **conform** to a protocol.\nYou can think a protocol like rules that the type has to comply with. As we saw earlier, these can be found in `swift5_protos`.\n\nApple states that:\n\n```none\nA protocol defines a blueprint of methods, properties, and other requirements that suit a particular task or piece of functionality. The protocol can then be adopted by a class, structure, or enumeration to provide an actual implementation of those requirements. Any type that satisfies the requirements of a protocol is said to conform to that protocol.\n```\n\nNote that types can have multiple **conforming** protocols. These are marked like this:\n\n```none\nstruct SomeStructure: FirstProtocol, AnotherProtocol {\n    // structure definition goes here\n}\n```\n\nOnce we understood that, we have to understand what can be defined in a protocol. Protocols can have properties and methods.\n\nFor instance, here we have a protocol that have only properties:\n\n```swift\nprotocol SomeProtocol {\n    var mustBeSettable: Int { get set }\n    var doesNotNeedToBeSettable: Int { get }\n}\n```\n\nWhen defining properties for protocols, what we are really doing is establishing the **Property Requirements** for the protocol.\nThese will be the **type, name and also specify whether each property must be gettable or gettable and settable**.\n\nFor example, here we can see a protocol and a class that conforms to that protocol (**note that both have to have the same name and type of the property**):\n\n```swift\nprotocol FullyNamed {\n    var fullName: String { get }\n}\n\nstruct Person: FullyNamed {\n    var fullName: String\n}\nlet john = Person(fullName: \"John Appleseed\")\n// john.fullName is \"John Appleseed\"\n```\n\nProtocols can also define methods. As previously with the properties, we'll also need to define **Method requirements**.\nFor example, in the following protocol we will be defining a protocol with a single method that has to return a Double type:\n\n```swift\nprotocol RandomNumberGenerator {\n    func random() -\u003e Double\n}\n```\n\nNote that the class that **conforms** to this protocol has no obligations regarding to how the `random()` is computed, efficiency, how random is that number or whether Double type can be from 0.0 to 1.0 or -50.0 to 50.0. It's a mere specification of the function name and the return type.\n\nAs stated earlier, protocols can be found at `swift5_protos` section as a list of **relative pointers** to `__const` section.\nWithin them, you'll be able to find the raw bytes of what we've just described.\n\n```swift\ntype TargetProtocolDescriptor struct {\n\tTargetContextDescriptor\n\tNameOffset                 RelativeDirectPointer // The name of the protocol.\n\tNumRequirementsInSignature uint32                // The number of generic requirements in the requirement signature of the protocol.\n\tNumRequirements            uint32                /* The number of requirements in the protocol. If any requirements beyond MinimumWitnessTableSizeInWords are present\n\t * in the witness table template, they will be not be overwritten with defaults. */\n\tAssociatedTypeNamesOffset RelativeDirectPointer // Associated type names, as a space-separated list in the same order as the requirements.\n}\n```\n\nAfter that definition, you'll encounter the list of generic signature requirements (determined by the **NumRequirementsInSignature**) and after that, the **requirement** list of size **NumRequirements**.\n\nHere are the structures that define both of them:\n\n```swift\ntype TargetGenericRequirementDescriptor struct {\n\tFlags                                  GenericRequirementFlags\n\tParamOff                               RelativeDirectPointer\n\tTypeOrProtocolOrConformanceOrLayoutOff RelativeIndirectablePointer \n}\n```\n\n```swift\ntype TargetProtocolRequirement struct {\n\tFlags                 ProtocolRequirementFlags\n\tDefaultImplementation RelativeDirectPointer // The optional default implementation of the protocol.\n}\n```\n\nOnce protocols are defined, classes can **conform** to them. There may be cases in which default implementations want to be provided. That is why **protocol extensions** exist. We can create a protocol and afterwards, define an extension for it. Following the previous example:\n\n```swift\nprotocol RandomNumberGenerator {\n    func random() -\u003e Double\n}\n\nextension RandomNumberGenerator {\n  func random() {\n    return 1.0\n  }\n}\n```\n\nSo, unless if the conforming class provides their own implementation of `random()`, `1.0` will be returned when called.\n\n## Witness tables\n\n### Protocol Witness Tables\n\nProtocols allow developers to add polymorphism to types through composition, even to value types like structs or enums. Protocol methods are dispatched via Protocol Witness Tables.\n\nThe mechanism for these is the same as virtual tables: Protocol-conforming types contain metadata (stored in an existential container*), which includes a pointer to their witness table, which is itself a table of function pointers.\n\nWhen executing a function on a protocol type, Swift inspects the existential container, looks up the witness table, and dispatches to the memory address of the function to execute.\n\nFor example, we may see a situation in which we'll iterate over a list of types that conform to a protocol. Because we won't know at compile time which will be the method to be called, this will have to be dispatched via the PWT (Protocol Witness Tables).\n\n### Value Witness Tables\n\nDefines the functions to interact with the type. These functions are defined:\n\n```\ninitializeBufferWithCopyOfBuffer\ndestroy\ninitializeWithCopy\nassignWithCopy\ninitializeWithTake\nassignWwithTake\ngetEnumTagSinglePayload\nstoreEnumTagSinglePayload\n```\n\nThese functions are needed to interact with the ValueBuffer that's inside the `Existential Container`.\n\n## Existential containers\n\nWhen a function or an array (or whatever) needs an argument that adheres to a protocol, Swift needs to adapt stuff to make sure that the argument has the same size regardless of what's passed. Remember that even though two types adhere to a protocol it doesn't mean they have the same size.\n\nLet's imagine we have this protocol:\n\n```\nprotocol StructProtocol {\n    var a: Int { get }\n    func struct_func_1() -\u003e Int\n    func struct_func_2() -\u003e Int\n}\n```\n\nAnd we have these types:\n\n```\nstruct StructTest: structs {\n    var a: Int\n    var b: Int\n    var c: Int\n    func struct_func_1() -\u003e Int{\n        return 1;\n    }\n    func struct_func_2() -\u003e Int{\n        return 2;\n    }\n}\n\nstruct StructTest_second: structs {\n    var a: Int\n    var b: Int\n    var c: Int\n    var d: Int\n    func struct_func_1() -\u003e Int{\n        return 8;\n    }\n    func struct_func_2() -\u003e Int{\n        return 9;\n    }\n    func struct_func_11() -\u003e Int{\n        return 10;\n    }\n}\n```\n\nLet's assume we have this situation:\n\n```\nvar structTesting: StructTest = StructTest(a: 0x41, b: 0x42, c:0x43)\nvar structsArray:[structs]\nstructsArray.append(structTesting)\n```\n\nWhat is it going to happen? Since both structs have different sizes how does Swift manage this? \n\nThis is where `Existential Containers` come into action. `Existential Containers` is a form of creating a type with a generic structure that it can adapt to any type to any conforming protocol. A visual representation of this would be:\n\n```\n8 byte - payload_1 // ptr to heap if the attributes do not fit in the ValueBuffer (ptr is created if size \u003e24 bytes)\n8 byte - payload_2 // 0 if ptr to heap\n8 byte - payload_3 // 0 if ptr to heap\n8 byte - pointer to Value Witness Table (VWT)\n8 byte - pointer to the Protocol Witness Table (PWT)\n```\n\nTo continue with the example, when we first append the `structTesting` this will happen:\n\nBecause `structTesting` attributes can fit in the the `Value Buffer`(first 3 - 8 bytes) we can store inline. \n\nA struct will be created in the stack like this:\n\n```\nexistentialContainer cont = {}\nexistentialContainer.vwt = \u0026type metadata for StructTest\nexistentialContainer.pwt = \u0026protocol witness table for StructTest\nexistentialContainer.valueBuffer[0] = structTesting.a\nexistentialContainer.valueBuffer[1] = structTesting.b\nexistentialContainer.valueBuffer[2] = structTesting.c\nArray.append(existentialContainer,array type metadata)\n\n```\n\nWhen debugging/reading assembly remember that `self` is in `x20` in Swift calling convention.\n\nTherefore, when the first append occurs the array will look like this:\n\n---\n0x0 - metadata\n\n0x8 - ?\n\n0x10 - array size\n\n0x18 - ?\n\n0x20 - 0x41\n\n0x28 - 0x42\n\n0x30 - 0x43\n\n0x38 - VWT\n\n0x40 - PWT\n\n---\n\nLet's assume we create StructTest_second which contains attributes that do not fit the ValueBuffer:\n\n```\nvar structTesting2: StructTest_second = StructTest(a: 0x41, b: 0x42, c:0x43, d:0x44)\nstructsArray.append(structTesting2)\n```\n\nWhich layout are we going to have? Let's see:\n\n---\n0x0 - metadata\n\n0x8 - ?\n\n0x10 - array size\n\n0x18 - ?\n\n0x20 - 0x41\n\n0x28 - 0x42\n\n0x30 - 0x43\n\n0x38 - VWT\n\n0x40 - PWT\n\n0x48 - PTR TO HEAP WITH THE CONTENTS //if we inspect this we'll see the values\n\n0x50 - 0\n\n0x58 - 0\n\n0x60 - VWT\n \n0x68 - PWT\n\n---\n\nNow as you can see, even though both structs are different size, they are adapted to fit using Existential Containers :) \n\n__NOTE: If we were to interact with the ValueBuffer we would make use of the VWT. If we were to iterate over this array and call functions on the array elements, we would go look for them in the PWT.__\n\n## Protocol conformance descriptors\n\nProtocol conformances are the act of a class, struct, or enum adopting and implementing the requirements specified by a protocol.\n\n```swift\nprotocol MyProtocol {\n // protocol requirements\n  func myMethod() \n}\n\nclass MyClass: MyProtocol { \n  func myMethod() {\n     print(\"implementation\")\n  }\n}\n```\n\n\u003e **NOTE:** Remember that a class, enum or struct can **conform** to more than one Protocol.\n\nSo, yes, you are right, we'll find them referenced at `swift5_proto` as a list of relative pointers.\n\n## Type metadata\n\nThe swift runtime keeps a record for every used type. This type metatdata is then used for RTTI, template methods, allocate the object's space, etc.\nFor further information please read:\n\n\u003chttps://github.com/apple/swift/blob/main/docs/ABI/TypeMetadata.rst\u003e\n\nMany of the global swift objects are stored globally in the `__common` section. When initializing a global of any type, the following snippet is generated (assuming we allocate the global `globalVar` of type `globalVar_t`)\n\n```c\n// repalce TYPE with the actual type\nvoid *typeMetadata = __swift_instantiateConcreteTypeFromMangledName(\u0026demangling cache variable for type metadata for globalVar_t);\n__swift_allocate_value_buffer(typeMetadata, \u0026globalVar);\n__swift_project_value_buffer(typeMetadata, \u0026globalVar);\n```\n\nThese two functions, `__swift_allocate_value_buffer` and `__swift_project_value_buffer` are basically to allocate the variable memory space and get a pointer to it, after consulting with the type metadata, if it allows the actual data to be in-place or use a pointer to an external space.\n\n\u003e **NOTE:** Sometimes IDA cannot parse the pointer `__swift_instantiateConcreteTypeFromMangledName` is referring to.\n  That is due the fact it's an int32 relative pointer as we discussed earlier, so you'll just have to fix it manually to discover the actual type.\n\nAlso, on many occasions, these allocations will be used on the stack dynamically. In that case you'll see a lot of calls to `__chkstk_darwin()`, whereas the spaces between them are the used local variables.\n\n## va_list\n\nWhen calling a function which receives a variadic length of arguments, such as `print`, the compiler will use `_allocateUninitializedArray\u003cA\u003e(_:)` to create an array of type `Array\u003cAny\u003e` to create this as a single parameter. We represent this datatype as `Swift_ArrayAny`.\n\nLet's examine now a call to `print(_:separator:terminator:)`.\n\nWe'll need to make this function signature as:\n\n```c\nvoid __fastcall print___separator_terminator__(Swift_ArrayAny *printString, Swift_String seperator, Swift_String terminator);\n```\n\nIn addition, if the function receives multiple protocols in the form of: `\u003cA, B, C\u003e`, then multiple type metadata are passed.\n\n### Template functions\n\nMany of the Swift functions often handle tempaltes. This is usually seen in method signature as: `doSomething\u003cA\u003e()`. In order to trigger the correct method to handle such invocations, the compiler adds an additional argument as the last one which acts the \"type metadata\" - from which the witness table is extracted. While reversing, assuming we are only focused on understanding the code-flow, this parameter is usually not very important.\n\nThe templates signatures usually look something like this:\n\n```c\n// _finalizeUninitializedArray\u003cA\u003e(_:)\nSwift_ArrayAny *__fastcall _allocateUninitializedArray_A(u64 count, void *arrayType);\n```\n\nAnd triggering these functions looks like this:\n\n```c\n// typeAny = \u0026type metadata for Any + 8\n// The type witness is located at offset 8 from the actual type information\n_finalizeUninitializedArray\u003cA\u003e(_:)(array, typeAny);\n```\n\n## Error handling\n\nIf a method raises an error, it will write its error object into `X21`. It is then raised using `swift_unexpectedError()`.\nIf the user raised an error explicitly, it will instead use `swift_allocError()` to allocate the error using the corresponding type metadata.\n\n## References\n\n- \u003chttps://hex-rays.com/blog/igors-tip-of-the-week-51-custom-calling-conventions/\u003e\n- \u003chttps://www.swift.org/documentation/\u003e\n- \u003chttps://github.com/apple/swift/blob/main/docs/ABI/\u003e\n- \u003chttps://github.com/blacktop/go-macho/blob/master/swift.go/\u003e\n- \u003chttps://knight.sc/reverse%20engineering/2019/07/17/swift-metadata.html/\u003e\n- \u003chttps://blog.jacobstechtavern.com/p/compiler-cocaine-the-swift-method\u003e\n- \u003chttps://docs.swift.org/swift-book/documentation/the-swift-programming-language/protocols/\u003e\n- \u003chttps://knight.sc/reverse%20engineering/2019/07/17/swift-metadata.html\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdoronz88%2Fswift_reversing","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdoronz88%2Fswift_reversing","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdoronz88%2Fswift_reversing/lists"}