How to statically parse AssociatedTypeDescriptors

Hello! I'm trying to statically parse the Swift runtime data structures in the __swift_x sections in MachOs for use in reverse engineering tools and I am confused by AssociatedTypeDescriptors. The first field is supposed to be a relative offset that points at the ConformingTypeName offset, but when I do the math I always am pointing to non-ascii data i.e. "\x01\xdf"

When I build a little test binary w/ DWARF info it's pointing to bin data, but there is a symbol in the symbol table for that address

Screenshot 2022-09-03 at 2.15.44 PM

The NEXT rel offset in the data structure is the ProtocolTypeName offset, which points to the string "$s4test5StackP" and w/ DWARF also has a symbol of "_symbolic $s4test5StackP"

So my primary question is how am I supposed to parse the ConformingTypeName as I've never seen it point to a string and if I have a stripped binary I won't have any symbols pointing to the offset of ConformingTypeName either?

Moving on to the AssociatedTypeRecord for the Name I get "Element" and for the SubstitutedTypeName I just get the letter "x". I was able to figure out that that's a mangled name missing the prefix "_$s" and when adding that I get:

❯ xcrun swift-demangle '_$sx'
_$sx ---> A

Is there a reason you strip the prefix of the string for this one, but not others?

Many thanks!

Here is the test Swift binary's code I am testing on:

protocol Stack {
    associatedtype Element // 'Element' is a placeholder type, that will be specified by protocol conforming types (like struct, class, or enumeration).
    var items: [Element] {get set}
    mutating func push(_ item: Element)
    mutating func pop() -> Element
}

struct Inventory<T>: Stack{
    typealias Element = T // Specifying 'String' in place of 'T' type for the Inventory data model.

    // Replacing 'String' in place of 'T' everywhere.
    var items: [T] = []
    mutating func push(_ item: T) {
        items.append(item)
    }
    mutating func pop() -> T {
        return items.removeLast()
    }
}

let computerInventory: Inventory<String> = Inventory.init(items: ["Apple M1"])
print(computerInventory.items) // Prints: ["Apple M1"]

Looking at the function makeSymbolicMangledNameStringRef it looks like "\x01" = "\x1F" are 'symbolic references'? So I think it is acting like it's supposed to

Take a look at swift/Mangling.rst at main · apple/swift · GitHub. This is a symbolic reference pointing at the nominal type descriptor of test.Inventory<T>

"x" in this case refers to the first generic argument of a type. When you use Swift's runtime demangler with a combination of this mangled string and a fully realized generic environment, it'll return the actual type of the first generic arg. E.g. in this case test.Inventory<Int>, "x" refers to Int.

From the same mangling document:

type ::= 'x' // generic param, depth=0, idx=0
swift/Mangling.rst at main · apple/swift · GitHub

2 Likes

Many thanks!!