diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/SwiftTypeMetadataAnalyzer.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/SwiftTypeMetadataAnalyzer.java
new file mode 100644
index 0000000000..73022a73e7
--- /dev/null
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/SwiftTypeMetadataAnalyzer.java
@@ -0,0 +1,57 @@
+/* ###
+ * IP: GHIDRA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package ghidra.app.plugin.core.analysis;
+
+import java.io.IOException;
+
+import ghidra.app.services.*;
+import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
+import ghidra.app.util.bin.format.swift.SwiftUtils;
+import ghidra.app.util.importer.MessageLog;
+import ghidra.program.model.address.AddressSetView;
+import ghidra.program.model.listing.Program;
+import ghidra.util.exception.CancelledException;
+import ghidra.util.task.TaskMonitor;
+
+public class SwiftTypeMetadataAnalyzer extends AbstractAnalyzer {
+
+ private static final String NAME = "Swift Type Metadata Analyzer";
+ private static final String DESCRIPTION = "Discovers Swift type metadata records.";
+
+ public SwiftTypeMetadataAnalyzer() {
+ super(NAME, DESCRIPTION, AnalyzerType.BYTE_ANALYZER);
+ setDefaultEnablement(true);
+ setPriority(AnalysisPriority.FORMAT_ANALYSIS);
+ }
+
+ @Override
+ public boolean canAnalyze(Program program) {
+ return SwiftUtils.isSwift(program);
+ }
+
+ @Override
+ public boolean added(Program program, AddressSetView set, TaskMonitor monitor, MessageLog log)
+ throws CancelledException {
+ try {
+ SwiftTypeMetadata typeMetadata = new SwiftTypeMetadata(program, monitor, log);
+ typeMetadata.markup();
+ }
+ catch (IOException e) {
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/SwiftSection.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/SwiftSection.java
new file mode 100644
index 0000000000..42fc4207dd
--- /dev/null
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/SwiftSection.java
@@ -0,0 +1,60 @@
+/* ###
+ * IP: GHIDRA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package ghidra.app.util.bin.format.swift;
+
+import java.util.List;
+
+/**
+ * Used to refer to a Swift section, which can have different names depending on the platform
+ *
+ * @see llvm/BinaryFormat/Swift.def
+ */
+public enum SwiftSection {
+
+
+ BLOCK_FIELDMD("__swift5_fieldmd", "swift5_fieldmd", ".sw5flmd"),
+ BLOCK_ASSOCTY("__swift5_assocty", "swift5_assocty", ".sw5asty"),
+ BLOCK_BUILTIN("__swift5_builtin", "swift5_builtin", ".sw5bltn"),
+ BLOCK_CAPTURE("__swift5_capture", "swift5_capture", ".sw5cptr"),
+ BLOCK_TYPEREF("__swift5_typeref", "swift5_typeref", ".sw5tyrf"),
+ BLOCK_REFLSTR("__swift5_reflstr", "swift5_reflstr", ".sw5rfst"),
+ BLOCK_CONFORM("__swift5_proto", "swift5_protocol_conformances", ".sw5prtc"),
+ BLOCK_PROTOCS("__swift5_protos", "swift5_protocols", ".sw5prt"),
+ BLOCK_ACFUNCS("__swift5_acfuncs", "swift5_accessible_functions", ".sw5acfn"),
+ BLOCK_MPENUM("__swift5_mpenum", "swift5_mpenum", ".sw5mpen"),
+ BLOCK_TYPES("__swift5_types", "swift5_types", ".sw5tymd"),
+ BLOCK_ENTRY("__swift5_entry", "swift5_entry", ".sw5entr");
+
+ private List sectionNames;
+
+ /**
+ * Create a new {@link SwiftSection}
+ *
+ * @param names The names the section goes by
+ */
+ private SwiftSection(String... names) {
+ sectionNames = List.of(names);
+ }
+
+ /**
+ * Gets a {@link List} of the {@link SwiftSection}'s names
+ *
+ * @return A {@link List} of the {@link SwiftSection}'s names
+ */
+ public List getSwiftSectionNames() {
+ return sectionNames;
+ }
+}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/SwiftStructure.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/SwiftStructure.java
new file mode 100644
index 0000000000..169791c6d6
--- /dev/null
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/SwiftStructure.java
@@ -0,0 +1,40 @@
+/* ###
+ * IP: GHIDRA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package ghidra.app.util.bin.format.swift;
+
+import ghidra.app.util.bin.StructConverter;
+
+/**
+ * Implemented by all Swift structures
+ */
+public interface SwiftStructure extends StructConverter {
+
+ public static final String DATA_TYPE_CATEGORY = "/Swift";
+
+ /**
+ * Gets the name of the {@link SwiftStructure}
+ *
+ * @return The name of the {@link SwiftStructure}
+ */
+ public String getStructureName();
+
+ /**
+ * Gets a short description of the {@link SwiftStructure}
+ *
+ * @return A short description of the {@link SwiftStructure}
+ */
+ public String getDescription();
+}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/SwiftTypeMetadata.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/SwiftTypeMetadata.java
new file mode 100644
index 0000000000..fc453f36ae
--- /dev/null
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/SwiftTypeMetadata.java
@@ -0,0 +1,506 @@
+/* ###
+ * IP: GHIDRA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package ghidra.app.util.bin.format.swift;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import ghidra.app.util.bin.*;
+import ghidra.app.util.bin.format.swift.types.*;
+import ghidra.app.util.importer.MessageLog;
+import ghidra.program.model.address.Address;
+import ghidra.program.model.data.*;
+import ghidra.program.model.data.DataUtilities.ClearDataMode;
+import ghidra.program.model.listing.Program;
+import ghidra.program.model.mem.MemoryBlock;
+import ghidra.program.model.util.CodeUnitInsertionException;
+import ghidra.util.exception.CancelledException;
+import ghidra.util.exception.DuplicateNameException;
+import ghidra.util.task.TaskMonitor;
+
+/**
+ * Parses marks up, and provide access to Swift type metadata
+ */
+public class SwiftTypeMetadata {
+
+ private Program program;
+ private TaskMonitor monitor;
+ private MessageLog log;
+
+ private List entryPoints = new ArrayList<>();
+ private List builtinTypeDescriptors = new ArrayList<>();
+ private List fieldDescriptors = new ArrayList<>();
+ private List associatedTypeDescriptors = new ArrayList<>();
+ private List captureDescriptors = new ArrayList<>();
+ private List mpEnumDescriptors = new ArrayList<>();
+ private List typeDescriptors = new ArrayList<>();
+ private List protocolDescriptors = new ArrayList<>();
+ private List protocolConformanceDescriptors =
+ new ArrayList<>();
+
+ private List markupList = new ArrayList<>();
+
+ /**
+ * Creates a new {@link SwiftTypeMetadata}
+ *
+ * @param program The {@link Program}
+ * @param monitor A cancellable task monitor
+ * @param log The log
+ * @throws IOException if there was an IO-related error
+ * @throws CancelledException if the user cancelled the operation
+ */
+ public SwiftTypeMetadata(Program program, TaskMonitor monitor, MessageLog log)
+ throws IOException, CancelledException {
+ this.program = program;
+ this.monitor = monitor;
+ this.log = log;
+
+ parse();
+ }
+
+ /**
+ * Parses the {@link SwiftTypeMetadata}
+ *
+ * @throws IOException if there was an IO-related error
+ * @throws CancelledException if the user cancelled the operation
+ */
+ private void parse() throws IOException, CancelledException {
+ try (ByteProvider provider =
+ MemoryByteProvider.createDefaultAddressSpaceByteProvider(program, false)) {
+ BinaryReader reader = new BinaryReader(provider, !program.getLanguage().isBigEndian());
+
+ parseEntryPoints(SwiftSection.BLOCK_ENTRY, reader);
+ parseBuiltinTypeDescriptors(SwiftSection.BLOCK_BUILTIN, reader);
+ parseFieldDescriptors(SwiftSection.BLOCK_FIELDMD, reader);
+ parseAssociatedTypeDescriptors(SwiftSection.BLOCK_ASSOCTY, reader);
+ parseCaptureTypeDescriptors(SwiftSection.BLOCK_CAPTURE, reader);
+ parseMultiPayloadEnumDescriptors(SwiftSection.BLOCK_MPENUM, reader);
+ parseProtocolDescriptors(SwiftSection.BLOCK_PROTOCS, reader);
+ parseProtocolConformanceDescriptors(SwiftSection.BLOCK_CONFORM, reader);
+ parseTypeDescriptors(SwiftSection.BLOCK_TYPES, reader);
+ }
+ }
+
+ /**
+ * Parses the entry point(s)
+ *
+ * @param section The {@link SwiftSection} that contains the entry point(s)
+ * @param reader A {@link BinaryReader}
+ * @throws CancelledException if the user cancelled the operation
+ */
+ private void parseEntryPoints(SwiftSection section, BinaryReader reader)
+ throws CancelledException {
+ monitor.setMessage("Parsing Swift entry point(s)...");
+ monitor.setIndeterminate(true);
+ try {
+ for (MemoryBlock block : SwiftUtils.getSwiftBlocks(section, program)) {
+ monitor.checkCancelled();
+ Address blockStart = block.getStart();
+ reader.setPointerIndex(blockStart.getOffset());
+ EntryPoint entryPoint = new EntryPoint(reader);
+ entryPoints.add(entryPoint);
+ markupList.add(new SwiftStructureInfo(entryPoint,
+ new SwiftStructureAddress(blockStart, null)));
+ }
+ }
+ catch (IOException e) {
+ log("Failed to parse entry point(s) from section '" + section + "'");
+ }
+ }
+
+ /**
+ * Parses the {@link BuiltinTypeDescriptor}s
+ *
+ * @param section The {@link SwiftSection} that contains the descriptors
+ * @param reader A {@link BinaryReader}
+ * @throws CancelledException if the user cancelled the operation
+ */
+ private void parseBuiltinTypeDescriptors(SwiftSection section, BinaryReader reader)
+ throws CancelledException {
+ monitor.setMessage("Parsing Swift builtin type descriptors...");
+ monitor.setIndeterminate(true);
+ try {
+ for (MemoryBlock block : SwiftUtils.getSwiftBlocks(section, program)) {
+ Address blockStart = block.getStart();
+ reader.setPointerIndex(blockStart.getOffset());
+ int i = 0;
+ while (i + BuiltinTypeDescriptor.SIZE <= block.getSize()) {
+ monitor.checkCancelled();
+ BuiltinTypeDescriptor descriptor = new BuiltinTypeDescriptor(reader);
+ builtinTypeDescriptors.add(descriptor);
+ markupList.add(new SwiftStructureInfo(descriptor,
+ new SwiftStructureAddress(blockStart.add(i), null)));
+ i += BuiltinTypeDescriptor.SIZE;
+ }
+ }
+ }
+ catch (IOException e) {
+ log("Failed to parse builtin type descriptors from section '" + section + "'");
+ }
+ }
+
+ /**
+ * Parses the {@link FieldDescriptor}s
+ *
+ * @param section The {@link SwiftSection} that contains the descriptors
+ * @param reader A {@link BinaryReader}
+ * @throws CancelledException if the user cancelled the operation
+ */
+ private void parseFieldDescriptors(SwiftSection section, BinaryReader reader)
+ throws CancelledException {
+ monitor.setMessage("Parsing Swift field descriptors...");
+ monitor.setIndeterminate(true);
+ try {
+ for (MemoryBlock block : SwiftUtils.getSwiftBlocks(section, program)) {
+ Address blockStart = block.getStart();
+ reader.setPointerIndex(blockStart.getOffset());
+ int i = 0;
+ while (i + FieldDescriptor.SIZE <= block.getSize()) {
+ monitor.checkCancelled();
+ FieldDescriptor descriptor = new FieldDescriptor(reader);
+ fieldDescriptors.add(descriptor);
+ markupList.add(new SwiftStructureInfo(descriptor,
+ new SwiftStructureAddress(blockStart.add(i), null)));
+ List records = descriptor.getFieldRecords();
+ i += FieldDescriptor.SIZE;
+ for (int j = 0; j < records.size(); j++) {
+ FieldRecord record = records.get(j);
+ markupList.add(new SwiftStructureInfo(record,
+ new SwiftStructureAddress(blockStart.add(i + j * FieldRecord.SIZE),
+ null)));
+ }
+ i += descriptor.getNumFields() * FieldRecord.SIZE;
+ }
+ }
+ }
+ catch (IOException e) {
+ log("Failed to parse field descriptors from section '" + section + "'");
+ }
+ }
+
+ /**
+ * Parses the {@link AssociatedTypeDescriptor}s
+ *
+ * @param section The {@link SwiftSection} that contains the descriptors
+ * @param reader A {@link BinaryReader}
+ * @throws CancelledException if the user cancelled the operation
+ */
+ private void parseAssociatedTypeDescriptors(SwiftSection section, BinaryReader reader)
+ throws CancelledException {
+ monitor.setMessage("Parsing Swift associated type descriptors...");
+ monitor.setIndeterminate(true);
+ try {
+ for (MemoryBlock block : SwiftUtils.getSwiftBlocks(section, program)) {
+ Address blockStart = block.getStart();
+ reader.setPointerIndex(blockStart.getOffset());
+ int i = 0;
+ while (i + AssociatedTypeDescriptor.SIZE <= block.getSize()) {
+ monitor.checkCancelled();
+ AssociatedTypeDescriptor descriptor = new AssociatedTypeDescriptor(reader);
+ associatedTypeDescriptors.add(descriptor);
+ markupList.add(new SwiftStructureInfo(descriptor,
+ new SwiftStructureAddress(blockStart.add(i), null)));
+ List records = descriptor.getAssociatedTypeRecords();
+ i += AssociatedTypeDescriptor.SIZE;
+ for (int j = 0; j < records.size(); j++) {
+ AssociatedTypeRecord record = records.get(j);
+ markupList.add(new SwiftStructureInfo(record,
+ new SwiftStructureAddress(
+ blockStart.add(i + j * AssociatedTypeRecord.SIZE), null)));
+ }
+ i += descriptor.getNumAssociatedTypes() * AssociatedTypeRecord.SIZE;
+ }
+ }
+ }
+ catch (IOException e) {
+ log("Failed to parse associated type descriptors from section '" + section + "'");
+ }
+ }
+
+ /**
+ * Parses the {@link CaptureDescriptor}s
+ *
+ * @param section The {@link SwiftSection} that contains the descriptors
+ * @param reader A {@link BinaryReader}
+ * @throws CancelledException if the user cancelled the operation
+ */
+ private void parseCaptureTypeDescriptors(SwiftSection section, BinaryReader reader)
+ throws CancelledException {
+ monitor.setMessage("Parsing Swift capture descriptors...");
+ monitor.setIndeterminate(true);
+ try {
+ for (MemoryBlock block : SwiftUtils.getSwiftBlocks(section, program)) {
+ Address blockStart = block.getStart();
+ reader.setPointerIndex(blockStart.getOffset());
+ int i = 0;
+ while (i + CaptureDescriptor.SIZE <= block.getSize()) {
+ monitor.checkCancelled();
+ CaptureDescriptor descriptor = new CaptureDescriptor(reader);
+ captureDescriptors.add(descriptor);
+ markupList.add(new SwiftStructureInfo(descriptor,
+ new SwiftStructureAddress(blockStart.add(i), null)));
+ List records = descriptor.getCaptureTypeRecords();
+ i += CaptureDescriptor.SIZE;
+ for (int j = 0; j < records.size(); j++) {
+ CaptureTypeRecord record = records.get(j);
+ markupList.add(new SwiftStructureInfo(record,
+ new SwiftStructureAddress(
+ blockStart.add(i + j * CaptureTypeRecord.SIZE), null)));
+ }
+ i += descriptor.getNumCaptureTypes() * CaptureTypeRecord.SIZE;
+ List sourceRecords =
+ descriptor.getMetadataSourceRecords();
+ for (int j = 0; j < sourceRecords.size(); j++) {
+ MetadataSourceRecord record = sourceRecords.get(j);
+ markupList.add(new SwiftStructureInfo(record,
+ new SwiftStructureAddress(
+ blockStart.add(i + j * MetadataSourceRecord.SIZE), null)));
+ }
+ i += descriptor.getNumMetadataSources() * MetadataSourceRecord.SIZE;
+ }
+ }
+ }
+ catch (IOException e) {
+ log("Failed to parse capture descriptors from section '" + section + "'");
+ }
+ }
+
+ /**
+ * Parses the {@link MultiPayloadEnumDescriptor}s
+ *
+ * @param section The {@link SwiftSection} that contains the descriptors
+ * @param reader A {@link BinaryReader}
+ * @throws CancelledException if the user cancelled the operation
+ */
+ private void parseMultiPayloadEnumDescriptors(SwiftSection section, BinaryReader reader)
+ throws CancelledException {
+ monitor.setMessage("Parsing Swift multipayload enum descriptors...");
+ monitor.setIndeterminate(true);
+ try {
+ for (MemoryBlock block : SwiftUtils.getSwiftBlocks(section, program)) {
+ Address blockStart = block.getStart();
+ reader.setPointerIndex(blockStart.getOffset());
+ int i = 0;
+ while (i < block.getSize()) {
+ monitor.checkCancelled();
+ MultiPayloadEnumDescriptor descriptor = new MultiPayloadEnumDescriptor(reader);
+ mpEnumDescriptors.add(descriptor);
+ markupList.add(new SwiftStructureInfo(descriptor,
+ new SwiftStructureAddress(blockStart.add(i), null)));
+ i += MultiPayloadEnumDescriptor.SIZE + descriptor.getContentsSize();
+ }
+ }
+ }
+ catch (IOException e) {
+ log("Failed to parse multipayload enum descriptors from section '" + section + "'");
+ }
+ }
+
+ /**
+ * Parses the {@link TargetProtocolDescriptor}s
+ *
+ * @param section The section name that contains the descriptors
+ * @param reader A {@link BinaryReader}
+ * @throws CancelledException if the user cancelled the operation
+ */
+ private void parseProtocolDescriptors(SwiftSection section, BinaryReader reader)
+ throws CancelledException {
+ monitor.setMessage("Parsing Swift protocol descriptors...");
+ monitor.setIndeterminate(true);
+ try {
+ List addrPairs = parsePointerTable(section, reader);
+ for (SwiftStructureAddress addrPair : addrPairs) {
+ reader.setPointerIndex(addrPair.structAddr().getOffset());
+ TargetProtocolDescriptor descriptor = new TargetProtocolDescriptor(reader);
+ protocolDescriptors.add(descriptor);
+ markupList.add(new SwiftStructureInfo(descriptor,
+ new SwiftStructureAddress(addrPair.structAddr(), addrPair.pointerAddr())));
+ }
+ }
+ catch (IOException e) {
+ log("Failed to parse protocol descriptors from section '" + section + "'");
+ }
+ }
+
+ /**
+ * Parses the {@link TargetProtocolConformanceDescriptor}s
+ *
+ * @param section The {@link SwiftSection} that contains the descriptors
+ * @param reader A {@link BinaryReader}
+ * @throws CancelledException if the user cancelled the operation
+ */
+ private void parseProtocolConformanceDescriptors(SwiftSection section, BinaryReader reader)
+ throws CancelledException {
+ monitor.setMessage("Parsing Swift protocol conformance descriptors...");
+ monitor.setIndeterminate(true);
+ try {
+ List addrPairs = parsePointerTable(section, reader);
+ for (SwiftStructureAddress addrPair : addrPairs) {
+ reader.setPointerIndex(addrPair.structAddr().getOffset());
+ TargetProtocolConformanceDescriptor descriptor =
+ new TargetProtocolConformanceDescriptor(reader);
+ protocolConformanceDescriptors.add(descriptor);
+ markupList.add(new SwiftStructureInfo(descriptor,
+ new SwiftStructureAddress(addrPair.structAddr(),
+ addrPair.pointerAddr())));
+ }
+ }
+ catch (IOException e) {
+ log("Failed to parse protocol conformance descriptors from section '" + section +
+ "'");
+ }
+ }
+
+ /**
+ * Parses the {@link TargetTypeContextDescriptor}s
+ *
+ * @param section The {@link SwiftSection} that contains the descriptors
+ * @param reader A {@link BinaryReader}
+ * @throws CancelledException if the user cancelled the operation
+ */
+ private void parseTypeDescriptors(SwiftSection section, BinaryReader reader)
+ throws CancelledException {
+ monitor.setMessage("Parsing Swift type descriptors...");
+ monitor.setIndeterminate(true);
+ try {
+ List addrPairs = parsePointerTable(section, reader);
+ for (SwiftStructureAddress addrPair : addrPairs) {
+ reader.setPointerIndex(addrPair.structAddr().getOffset());
+ long origIndex = reader.getPointerIndex();
+ TargetTypeContextDescriptor descriptor = new TargetTypeContextDescriptor(reader);
+ reader.setPointerIndex(origIndex);
+ int contextDescriptorKind = ContextDescriptorKind.getKind(descriptor.getFlags());
+ descriptor = switch (contextDescriptorKind) {
+ case ContextDescriptorKind.CLASS:
+ yield new TargetClassDescriptor(reader);
+ case ContextDescriptorKind.STRUCT:
+ yield new TargetStructDescriptor(reader);
+ case ContextDescriptorKind.ENUM:
+ yield new TargetEnumDescriptor(reader);
+ default:
+ log("Unrecognized type descriptor %d at index: 0x%x"
+ .formatted(contextDescriptorKind, origIndex));
+ yield null;
+ };
+ if (descriptor != null) {
+ typeDescriptors.add(descriptor);
+ markupList.add(new SwiftStructureInfo(descriptor,
+ new SwiftStructureAddress(addrPair.structAddr(), addrPair.pointerAddr())));
+ }
+ }
+ }
+ catch (IOException e) {
+ log("Failed to parse type descriptors from section '" + section + "'");
+ }
+ }
+
+ /**
+ * Parses a table of pointers to {@link SwiftStructure}s found in the given section
+ *
+ * @param section The {@link SwiftSection} that contains the pointer table
+ * @param reader A {@link BinaryReader}
+ * @return A {@link List} of {@link SwiftStructureAddress}s
+ * @throws CancelledException if the user cancelled the operation
+ */
+ private List parsePointerTable(SwiftSection section, BinaryReader reader)
+ throws CancelledException {
+ final int POINTER_SIZE = 4;
+ List result = new ArrayList<>();
+ try {
+ for (MemoryBlock block : SwiftUtils.getSwiftBlocks(section, program)) {
+ Address blockAddr = block.getStart();
+ for (int i = 0; i < block.getSize(); i += POINTER_SIZE) {
+ monitor.checkCancelled();
+ reader.setPointerIndex(blockAddr.getOffset() + i);
+ Address pointerAddr = blockAddr.add(i);
+ int offset = reader.readInt(pointerAddr.getOffset());
+ if (offset == 0) {
+ break;
+ }
+ Address structAddr = pointerAddr.add(offset);
+ result.add(new SwiftStructureAddress(structAddr, pointerAddr));
+ }
+ }
+ }
+ catch (IOException e) {
+ log("Failed to parse Swift struction pointers from section '" + section + "'");
+ }
+ return result;
+ }
+
+ /**
+ * Marks up this {@link SwiftTypeMetadata} with data structures and comments
+ *
+ * @throws CancelledException if the user cancelled the operation
+ */
+ public void markup() throws CancelledException {
+ monitor.setMessage("Marking up Swift structures...");
+ monitor.initialize(markupList.size());
+ for (SwiftStructureInfo structInfo : markupList) {
+ monitor.checkCancelled();
+ monitor.incrementProgress(1);
+ try {
+ SwiftStructure struct = structInfo.struct();
+ DataType dt = struct.toDataType();
+ DataUtilities.createData(program, structInfo.addr().structAddr(), dt, -1,
+ ClearDataMode.CLEAR_ALL_DEFAULT_CONFLICT_DATA);
+ if (structInfo.addr().pointerAddr() != null) {
+ PointerTypedef relativePtrDataType =
+ new PointerTypedef(null, dt, 4, null, PointerType.RELATIVE);
+ DataUtilities.createData(program, structInfo.addr().pointerAddr(),
+ relativePtrDataType, -1, ClearDataMode.CLEAR_ALL_DEFAULT_CONFLICT_DATA);
+ }
+ }
+ catch (CodeUnitInsertionException | DuplicateNameException | IOException e) {
+ log("Failed to markup: " + structInfo);
+ }
+ }
+ }
+
+ /**
+ * Convenience method to perform logging
+ *
+ * @param message The message to log
+ */
+ private void log(String message) {
+ log.appendMsg(SwiftTypeMetadata.class.getSimpleName(), message);
+ }
+
+ /**
+ * The {@link Address} of a {@link SwiftStructure} and the optional {@link Address} of its
+ * pointer
+ *
+ * @param structAddr The {@link Address} of a {@link SwiftStructure}
+ * @param pointerAddr The {@link Address} of a pointer to a {@link SwiftStructure} (could be
+ * null if there is no associated pointer}
+ */
+ private record SwiftStructureAddress(Address structAddr, Address pointerAddr) {}
+
+ /**
+ * Information about a {@link SwiftStructure}
+ *
+ * @param struct The {@link SwiftStructure}
+ * @param addr The {@link SwiftStructureAddress address} of the {@link SwiftStructure}
+ */
+ private record SwiftStructureInfo(SwiftStructure struct, SwiftStructureAddress addr) {
+
+ @Override
+ public String toString() {
+ return "%s %s".formatted(struct.getDescription(), addr);
+ }
+ }
+}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/SwiftUtils.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/SwiftUtils.java
new file mode 100644
index 0000000000..2c3097c345
--- /dev/null
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/SwiftUtils.java
@@ -0,0 +1,94 @@
+/* ###
+ * IP: GHIDRA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package ghidra.app.util.bin.format.swift;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import ghidra.app.util.bin.BinaryReader;
+import ghidra.program.model.data.*;
+import ghidra.program.model.listing.Program;
+import ghidra.program.model.mem.MemoryBlock;
+
+/**
+ * Swift-related utility methods
+ */
+public class SwiftUtils {
+
+ /**
+ * A {@link PointerTypedef pointer} to a relative 4-byte offset
+ */
+ public static final PointerTypedef PTR_RELATIVE =
+ new PointerTypedef(null, null, 4, null, PointerType.RELATIVE);
+
+ /**
+ * A {@link PointerTypedef string pointer} to a 4-byte relative offset
+ */
+ public static final PointerTypedef PTR_STRING =
+ new PointerTypedef(null, StringDataType.dataType, 4, null, PointerType.RELATIVE);
+
+ /**
+ * Checks if the given {@link Program} is a Swift program
+ *
+ * @param program The {@link Program} to check
+ * @return True if the given {@link Program} is a Swift program; otherwise, false
+ */
+ public static boolean isSwift(Program program) {
+ List prefixes = List.of("__swift", "swift", ".sw5");
+ for (MemoryBlock block : program.getMemory().getBlocks()) {
+ if (prefixes.stream().anyMatch(prefix -> block.getName().startsWith(prefix))) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Gets a {@link List} of {@link MemoryBlock}s that match the given {@link SwiftSection}
+ *
+ * @param section The {@link SwiftSection}
+ * @param program The {@link Program}
+ * @return A {@link List} of {@link MemoryBlock}s that match the given {@link SwiftSection}
+ */
+ public static List getSwiftBlocks(SwiftSection section, Program program) {
+ List result = new ArrayList<>();
+ for (MemoryBlock block : program.getMemory().getBlocks()) {
+ for (String sectionName : section.getSwiftSectionNames()) {
+ if (block.getName().equals(sectionName)) {
+ result.add(block);
+ break;
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Reads the integer at the current index and uses it as a relative pointer to read and
+ * return a string at that location. When the read completes, the {@link BinaryReader} will
+ * be positioned directly after the initial relative pointer that was read.
+ *
+ * @param reader A {@link BinaryReader} positioned at the start of relative string pointer
+ * @return The read string
+ * @throws IOException if there was an IO-related problem during the reads
+ */
+ public static String relativeString(BinaryReader reader) throws IOException {
+ long fieldIndex = reader.getPointerIndex();
+ int offset = reader.readNextInt();
+ return reader.readAsciiString(fieldIndex + offset);
+ }
+}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/AssociatedTypeDescriptor.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/AssociatedTypeDescriptor.java
new file mode 100644
index 0000000000..5b32c6e1b0
--- /dev/null
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/AssociatedTypeDescriptor.java
@@ -0,0 +1,130 @@
+/* ###
+ * IP: GHIDRA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package ghidra.app.util.bin.format.swift.types;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import ghidra.app.util.bin.BinaryReader;
+import ghidra.app.util.bin.format.swift.SwiftStructure;
+import ghidra.app.util.bin.format.swift.SwiftUtils;
+import ghidra.program.model.data.*;
+import ghidra.util.exception.DuplicateNameException;
+
+/**
+ * Represents a Swift AssociatedTypeDescriptor structure
+ *
+ * @see swift/RemoteInspection/Records.h
+ */
+public final class AssociatedTypeDescriptor implements SwiftStructure {
+
+ /**
+ * The size (in bytes) of an {@link AssociatedTypeDescriptor} structure
+ */
+ public static final int SIZE = 16;
+
+ private String conformingTypeName;
+ private String protocolTypeName;
+ private int numAssociatedTypes;
+ private int associatedTypeRecordSize;
+
+ private List associatedTypeRecords = new ArrayList<>();
+
+ /**
+ * Creates a new {@link AssociatedTypeDescriptor}
+ *
+ * @param reader A {@link BinaryReader} positioned at the start of the structure
+ * @throws IOException if there was an IO-related problem creating the structure
+ */
+ public AssociatedTypeDescriptor(BinaryReader reader) throws IOException {
+ conformingTypeName = reader.readNext(SwiftUtils::relativeString);
+ protocolTypeName = reader.readNext(SwiftUtils::relativeString);
+ numAssociatedTypes = reader.readNextInt();
+ associatedTypeRecordSize = reader.readNextInt();
+
+ for (int i = 0; i < numAssociatedTypes; i++) {
+ associatedTypeRecords.add(new AssociatedTypeRecord(reader));
+ }
+ }
+
+ /**
+ * Gets the conforming type name
+ *
+ * @return The conforming type name
+ */
+ public String getConformingTypeName() {
+ return conformingTypeName;
+ }
+
+ /**
+ * Gets the protocol type name
+ *
+ * @return The protocol type name
+ */
+ public String getProtocolTypeName() {
+ return protocolTypeName;
+ }
+
+ /**
+ * Gets the number of associated types
+ *
+ * @return The number of associated types
+ */
+ public int getNumAssociatedTypes() {
+ return numAssociatedTypes;
+ }
+
+ /**
+ * Gets the associated type record size
+ *
+ * @return The associated type record size
+ */
+ public int getAssociatedTypeRecordSize() {
+ return associatedTypeRecordSize;
+ }
+
+ /**
+ * Gets the {@link List} of {@link AssociatedTypeRecord}s
+ *
+ * @return The {@link List} of {@link AssociatedTypeRecord}s
+ */
+ public List getAssociatedTypeRecords() {
+ return associatedTypeRecords;
+ }
+
+ @Override
+ public String getStructureName() {
+ return AssociatedTypeDescriptor.class.getSimpleName();
+ }
+
+ @Override
+ public String getDescription() {
+ return "associated type descriptor";
+ }
+
+ @Override
+ public DataType toDataType() throws DuplicateNameException, IOException {
+ StructureDataType struct = new StructureDataType(getStructureName(), 0);
+ struct.add(SwiftUtils.PTR_STRING, "ConformingTypeName", "");
+ struct.add(SwiftUtils.PTR_STRING, "ProtocolTypeName", "");
+ struct.add(DWORD, "NumAssociatedTypes", "");
+ struct.add(DWORD, "AssociatedTypeRecordSize", "");
+ struct.setCategoryPath(new CategoryPath(DATA_TYPE_CATEGORY));
+ return struct;
+ }
+
+}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/AssociatedTypeRecord.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/AssociatedTypeRecord.java
new file mode 100644
index 0000000000..04b43d7999
--- /dev/null
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/AssociatedTypeRecord.java
@@ -0,0 +1,89 @@
+/* ###
+ * IP: GHIDRA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package ghidra.app.util.bin.format.swift.types;
+
+import java.io.IOException;
+
+import ghidra.app.util.bin.BinaryReader;
+import ghidra.app.util.bin.format.swift.SwiftStructure;
+import ghidra.app.util.bin.format.swift.SwiftUtils;
+import ghidra.program.model.data.*;
+import ghidra.util.exception.DuplicateNameException;
+
+/**
+ * Represents a Swift AssociatedTypeRecord structure
+ *
+ * @see swift/RemoteInspection/Records.h
+ */
+public final class AssociatedTypeRecord implements SwiftStructure {
+
+ /**
+ * The size (in bytes) of an {@link AssociatedTypeRecord} structure
+ */
+ public static final int SIZE = 8;
+
+ private String name;
+ private String substitutedTypeName;
+
+ /**
+ * Creates a new {@link AssociatedTypeRecord}
+ *
+ * @param reader A {@link BinaryReader} positioned at the start of the structure
+ * @throws IOException if there was an IO-related problem creating the structure
+ */
+ public AssociatedTypeRecord(BinaryReader reader) throws IOException {
+ name = reader.readNext(SwiftUtils::relativeString);
+ substitutedTypeName = reader.readNext(SwiftUtils::relativeString);
+ }
+
+ /**
+ * Gets the name
+ *
+ * @return The name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Gets the substituted type name
+ *
+ * @return The substituted type name
+ */
+ public String getSubstitutedTypeName() {
+ return substitutedTypeName;
+ }
+
+ @Override
+ public String getStructureName() {
+ return AssociatedTypeRecord.class.getSimpleName();
+ }
+
+ @Override
+ public String getDescription() {
+ return "associated type record";
+ }
+
+ @Override
+ public DataType toDataType() throws DuplicateNameException, IOException {
+ StructureDataType struct = new StructureDataType(getStructureName(), 0);
+ struct.add(SwiftUtils.PTR_STRING, "Name", "");
+ struct.add(SwiftUtils.PTR_STRING, "SubstitutedTypeName", "");
+ struct.setCategoryPath(new CategoryPath(DATA_TYPE_CATEGORY));
+ return struct;
+ }
+
+}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/BuiltinTypeDescriptor.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/BuiltinTypeDescriptor.java
new file mode 100644
index 0000000000..896608c967
--- /dev/null
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/BuiltinTypeDescriptor.java
@@ -0,0 +1,124 @@
+/* ###
+ * IP: GHIDRA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package ghidra.app.util.bin.format.swift.types;
+
+import java.io.IOException;
+
+import ghidra.app.util.bin.BinaryReader;
+import ghidra.app.util.bin.format.swift.*;
+import ghidra.program.model.data.*;
+import ghidra.util.exception.DuplicateNameException;
+
+/**
+ * Represents a Swift BuiltinTypeDescriptor structure
+ *
+ * @see swift/RemoteInspection/Records.h
+ */
+public final class BuiltinTypeDescriptor implements SwiftStructure {
+
+ /**
+ * The size (in bytes) of a {@link BuiltinTypeDescriptor} structure
+ */
+ public static final int SIZE = 20;
+
+ private String typeName;
+ private int size;
+ private int alignmentAndFlags;
+ private int stride;
+ private int numExtraInhabitants;
+
+ /**
+ * Creates a new {@link BuiltinTypeDescriptor}
+ *
+ * @param reader A {@link BinaryReader} positioned at the start of the structure
+ * @throws IOException if there was an IO-related problem creating the structure
+ */
+ public BuiltinTypeDescriptor(BinaryReader reader) throws IOException {
+ typeName = reader.readNext(SwiftUtils::relativeString);
+ size = reader.readNextInt();
+ alignmentAndFlags = reader.readNextInt();
+ stride = reader.readNextInt();
+ numExtraInhabitants = reader.readNextInt();
+ }
+
+ /**
+ * Gets the type name
+ *
+ * @return The type name
+ */
+ public String getTypeName() {
+ return typeName;
+ }
+
+ /**
+ * Gets the size
+ *
+ * @return The size
+ */
+ public int getSize() {
+ return size;
+ }
+
+ /**
+ * Gets the alignment and flags
+ *
+ * @return The alignment and flags
+ */
+ public int getAlignmentAndFlags() {
+ return alignmentAndFlags;
+ }
+
+ /**
+ * Gets the stride
+ *
+ * @return The stride
+ */
+ public int getStride() {
+ return stride;
+ }
+
+ /**
+ * Gets the number of extra inhabitants
+ *
+ * @return The number of extra inhabitants
+ */
+ public int getNumExtraInhabitants() {
+ return numExtraInhabitants;
+ }
+
+ @Override
+ public String getStructureName() {
+ return BuiltinTypeDescriptor.class.getSimpleName();
+ }
+
+ @Override
+ public String getDescription() {
+ return "builtin type descriptor";
+ }
+
+ @Override
+ public DataType toDataType() throws DuplicateNameException, IOException {
+ StructureDataType struct = new StructureDataType(getStructureName(), 0);
+ struct.add(SwiftUtils.PTR_STRING, "TypeName", "");
+ struct.add(DWORD, "Size", "");
+ struct.add(DWORD, "AlignmentAndFlags", "");
+ struct.add(DWORD, "Stride", "");
+ struct.add(DWORD, "NumExtraInhabitants", "");
+ struct.setCategoryPath(new CategoryPath(DATA_TYPE_CATEGORY));
+ return struct;
+ }
+
+}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/CaptureDescriptor.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/CaptureDescriptor.java
new file mode 100644
index 0000000000..96b1bb78a2
--- /dev/null
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/CaptureDescriptor.java
@@ -0,0 +1,133 @@
+/* ###
+ * IP: GHIDRA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package ghidra.app.util.bin.format.swift.types;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import ghidra.app.util.bin.BinaryReader;
+import ghidra.app.util.bin.format.swift.SwiftStructure;
+import ghidra.program.model.data.CategoryPath;
+import ghidra.program.model.data.DataType;
+import ghidra.program.model.data.StructureDataType;
+import ghidra.util.exception.DuplicateNameException;
+
+/**
+ * Represents a Swift CaptureDescriptor structure
+ *
+ * @see swift/RemoteInspection/Records.h
+ */
+public final class CaptureDescriptor implements SwiftStructure {
+
+ /**
+ * The size (in bytes) of a {@link CaptureDescriptor} structure
+ */
+ public static final int SIZE = 12;
+
+ private int numCaptureTypes;
+ private int numMetadataSources;
+ private int numBindings;
+
+ private List captureTypeRecords = new ArrayList<>();
+ private List metadataSourceRecords = new ArrayList<>();
+
+ /**
+ * Creates a new {@link CaptureDescriptor}
+ *
+ * @param reader A {@link BinaryReader} positioned at the start of the structure
+ * @throws IOException if there was an IO-related problem creating the structure
+ */
+ public CaptureDescriptor(BinaryReader reader) throws IOException {
+ numCaptureTypes = reader.readNextInt();
+ numMetadataSources = reader.readNextInt();
+ numBindings = reader.readNextInt();
+
+ for (int i = 0; i < numCaptureTypes; i++) {
+ captureTypeRecords.add(new CaptureTypeRecord(reader));
+ }
+
+ for (int i = 0; i < numMetadataSources; i++) {
+ metadataSourceRecords.add(new MetadataSourceRecord(reader));
+ }
+ }
+
+ /**
+ * Gets the number of capture types
+ *
+ * @return The number of capture types
+ */
+ public int getNumCaptureTypes() {
+ return numCaptureTypes;
+ }
+
+ /**
+ * Gets the number of metadata sources
+ *
+ * @return The number of metadata sources
+ */
+ public int getNumMetadataSources() {
+ return numMetadataSources;
+ }
+
+ /**
+ * Gets the number of bindings
+ *
+ * @return The number of bindings
+ */
+ public int getNumBindings() {
+ return numBindings;
+ }
+
+ /**
+ * Gets the {@link List} of {@link CaptureTypeRecord}s
+ *
+ * @return The {@link List} of {@link CaptureTypeRecord}s
+ */
+ public List getCaptureTypeRecords() {
+ return captureTypeRecords;
+ }
+
+ /**
+ * Gets the {@link List} of {@link MetadataSourceRecord}s
+ *
+ * @return The {@link List} of {@link MetadataSourceRecord}s
+ */
+ public List getMetadataSourceRecords() {
+ return metadataSourceRecords;
+ }
+
+ @Override
+ public String getStructureName() {
+ return CaptureDescriptor.class.getSimpleName();
+ }
+
+ @Override
+ public String getDescription() {
+ return "capture descriptor";
+ }
+
+ @Override
+ public DataType toDataType() throws DuplicateNameException, IOException {
+ StructureDataType struct = new StructureDataType(getStructureName(), 0);
+ struct.add(DWORD, "NumCaptureTypes", "");
+ struct.add(DWORD, "NumMetadataSources", "");
+ struct.add(DWORD, "NumBindings", "");
+ struct.setCategoryPath(new CategoryPath(DATA_TYPE_CATEGORY));
+ return struct;
+ }
+
+}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/CaptureTypeRecord.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/CaptureTypeRecord.java
new file mode 100644
index 0000000000..8101cc3c55
--- /dev/null
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/CaptureTypeRecord.java
@@ -0,0 +1,77 @@
+/* ###
+ * IP: GHIDRA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package ghidra.app.util.bin.format.swift.types;
+
+import java.io.IOException;
+
+import ghidra.app.util.bin.BinaryReader;
+import ghidra.app.util.bin.format.swift.*;
+import ghidra.program.model.data.*;
+import ghidra.util.exception.DuplicateNameException;
+
+/**
+ * Represents a Swift CaptureTypeRecord structure
+ *
+ * @see swift/RemoteInspection/Records.h
+ */
+public final class CaptureTypeRecord implements SwiftStructure {
+
+ /**
+ * The size (in bytes) of a {@link CaptureTypeRecord} structure
+ */
+ public static final int SIZE = 4;
+
+ private String mangledTypeName;
+
+ /**
+ * Creates a new {@link CaptureTypeRecord}
+ *
+ * @param reader A {@link BinaryReader} positioned at the start of the structure
+ * @throws IOException if there was an IO-related problem creating the structure
+ */
+ public CaptureTypeRecord(BinaryReader reader) throws IOException {
+ mangledTypeName = reader.readNext(SwiftUtils::relativeString);
+
+ }
+
+ /**
+ * Gets the mangled type name
+ *
+ * @return The mangled type name
+ */
+ public String getMangledTypeName() {
+ return mangledTypeName;
+ }
+
+ @Override
+ public String getStructureName() {
+ return CaptureTypeRecord.class.getSimpleName();
+ }
+
+ @Override
+ public String getDescription() {
+ return "capture type record";
+ }
+
+ @Override
+ public DataType toDataType() throws DuplicateNameException, IOException {
+ StructureDataType struct = new StructureDataType(getStructureName(), 0);
+ struct.add(SwiftUtils.PTR_STRING, "MangledTypeName", "");
+ struct.setCategoryPath(new CategoryPath(DATA_TYPE_CATEGORY));
+ return struct;
+ }
+
+}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/ContextDescriptorKind.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/ContextDescriptorKind.java
new file mode 100644
index 0000000000..48faf502c2
--- /dev/null
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/ContextDescriptorKind.java
@@ -0,0 +1,94 @@
+/* ###
+ * IP: GHIDRA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package ghidra.app.util.bin.format.swift.types;
+
+/**
+ * Swift ContextDescriptorKind values
+ *
+ * @see swift/ABI/MetadataValues.h
+ */
+public class ContextDescriptorKind {
+
+ /**
+ * The mask to apply to the {@link TargetContextDescriptor#getFlags() flags} to get the
+ * {@link ContextDescriptorKind} value
+ */
+ private static int KIND_MASK = 0x1f;
+
+ /**
+ * Gets the {@link ContextDescriptorKind} value from the
+ * {@link TargetContextDescriptor#getFlags() flags}
+ *
+ * @param flags The {@link TargetContextDescriptor#getFlags() flags} that contain the kind
+ * @return The {@link ContextDescriptorKind} value
+ */
+ public static int getKind(int flags) {
+ return flags & KIND_MASK;
+ }
+
+ //---------------------------------------------------------------------------------------------
+
+ /**
+ * This context descriptor represents a module
+ */
+ public static final int MODULE = 0;
+
+ /**
+ * This context descriptor represents an extension
+ */
+ public static final int EXTENSION = 1;
+
+ /**
+ * This context descriptor represents an anonymous possibly-generic context such as a function
+ * body
+ */
+ public static final int ANONYMOUS = 2;
+
+ /**
+ * This context descriptor represents a protocol context
+ */
+ public static final int PROTOCOL = 3;
+
+ /**
+ * This context descriptor represents an opaque type alias
+ */
+ public static final int OPAQUE_TYPE = 4;
+
+ /**
+ * First kind that represents a type of any sort
+ */
+ public static final int TYPE_FIRST = 16;
+
+ /**
+ * This context descriptor represents a class
+ */
+ public static final int CLASS = TYPE_FIRST;
+
+ /**
+ * This context descriptor represents a struct
+ */
+ public static final int STRUCT = TYPE_FIRST + 1;
+
+ /**
+ * This context descriptor represents an enum
+ */
+ public static final int ENUM = TYPE_FIRST + 2;
+
+ /**
+ * Last kind that represents a type of any sort
+ */
+ public static final int TYPE_LAST = 31;
+}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/EntryPoint.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/EntryPoint.java
new file mode 100644
index 0000000000..31055a01f4
--- /dev/null
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/EntryPoint.java
@@ -0,0 +1,72 @@
+/* ###
+ * IP: GHIDRA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package ghidra.app.util.bin.format.swift.types;
+
+import java.io.IOException;
+
+import ghidra.app.util.bin.BinaryReader;
+import ghidra.app.util.bin.format.swift.SwiftStructure;
+import ghidra.app.util.bin.format.swift.SwiftUtils;
+import ghidra.program.model.data.DataType;
+import ghidra.util.exception.DuplicateNameException;
+
+/**
+ * Represents a Swift entry point
+ */
+public final class EntryPoint implements SwiftStructure {
+
+ /**
+ * The size (in bytes) of an {@link EntryPoint} structure
+ */
+ public static final int SIZE = 4;
+
+ private int entryPoint;
+
+ /**
+ * Creates a new {@link EntryPoint}
+ *
+ * @param reader A {@link BinaryReader} positioned at the start of the structure
+ * @throws IOException if there was an IO-related problem creating the structure
+ */
+ public EntryPoint(BinaryReader reader) throws IOException {
+ entryPoint = reader.readNextInt();
+ }
+
+ /**
+ * Gets the entry point
+ *
+ * @return The entry point
+ */
+ public int getEntryPoint() {
+ return entryPoint;
+ }
+
+ @Override
+ public String getStructureName() {
+ return EntryPoint.class.getSimpleName();
+ }
+
+ @Override
+ public String getDescription() {
+ return "entry point";
+ }
+
+ @Override
+ public DataType toDataType() throws DuplicateNameException, IOException {
+ return SwiftUtils.PTR_RELATIVE;
+ }
+
+}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/FieldDescriptor.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/FieldDescriptor.java
new file mode 100644
index 0000000000..5798be7c99
--- /dev/null
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/FieldDescriptor.java
@@ -0,0 +1,141 @@
+/* ###
+ * IP: GHIDRA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package ghidra.app.util.bin.format.swift.types;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import ghidra.app.util.bin.BinaryReader;
+import ghidra.app.util.bin.format.swift.*;
+import ghidra.program.model.data.*;
+import ghidra.util.exception.DuplicateNameException;
+
+/**
+ * Represents a Swift FieldDescriptor structure
+ *
+ * @see swift/RemoteInspection/Records.h
+ */
+public final class FieldDescriptor implements SwiftStructure {
+
+ /**
+ * The size (in bytes) of a {@link FieldDescriptor} structure
+ */
+ public static final int SIZE = 16;
+
+ private String mangledTypeName;
+ private int superclass;
+ private int kind;
+ private int fieldRecordSize;
+ private int numFields;
+
+ private List fieldRecords = new ArrayList<>();
+
+ /**
+ * Creates a new {@link FieldDescriptor}
+ *
+ * @param reader A {@link BinaryReader} positioned at the start of the structure
+ * @throws IOException if there was an IO-related problem creating the structure
+ */
+ public FieldDescriptor(BinaryReader reader) throws IOException {
+ mangledTypeName = reader.readNext(SwiftUtils::relativeString);
+ superclass = reader.readNextInt();
+ kind = reader.readNextUnsignedShort();
+ fieldRecordSize = reader.readNextUnsignedShort();
+ numFields = reader.readNextInt();
+
+ for (int i = 0; i < numFields; i++) {
+ fieldRecords.add(new FieldRecord(reader));
+ }
+ }
+
+ /**
+ * Gets the mangled type name
+ *
+ * @return The mangled type name
+ */
+ public String getMangledTypeName() {
+ return mangledTypeName;
+ }
+
+ /**
+ * Gets the superclass
+ *
+ * @return The superclass
+ */
+ public int getSuperclass() {
+ return superclass;
+ }
+
+ /**
+ * Gets the kind
+ *
+ * @return The kind
+ */
+ public int getKind() {
+ return kind;
+ }
+
+ /**
+ * Gets the field record size
+ *
+ * @return The field record size
+ */
+ public int getFieldRecordSize() {
+ return fieldRecordSize;
+ }
+
+ /**
+ * Gets the number of fields
+ *
+ * @return The number of fields
+ */
+ public int getNumFields() {
+ return numFields;
+ }
+
+ /**
+ * Gets the {@link List} of {@link FieldRecord}s
+ *
+ * @return The {@link List} of {@link FieldRecord}s
+ */
+ public List getFieldRecords() {
+ return fieldRecords;
+ }
+
+ @Override
+ public String getStructureName() {
+ return FieldDescriptor.class.getSimpleName();
+ }
+
+ @Override
+ public String getDescription() {
+ return "field descriptor";
+ }
+
+ @Override
+ public DataType toDataType() throws DuplicateNameException, IOException {
+ StructureDataType struct = new StructureDataType(getStructureName(), 0);
+ struct.add(SwiftUtils.PTR_STRING, "MangledTypeName", "");
+ struct.add(SwiftUtils.PTR_RELATIVE, "Superclass", "");
+ struct.add(WORD, "Kind", "");
+ struct.add(WORD, "FieldRecordSize", "");
+ struct.add(DWORD, "NumFields", "");
+ struct.setCategoryPath(new CategoryPath(DATA_TYPE_CATEGORY));
+ return struct;
+ }
+
+}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/FieldRecord.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/FieldRecord.java
new file mode 100644
index 0000000000..b4a9a9a067
--- /dev/null
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/FieldRecord.java
@@ -0,0 +1,100 @@
+/* ###
+ * IP: GHIDRA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package ghidra.app.util.bin.format.swift.types;
+
+import java.io.IOException;
+
+import ghidra.app.util.bin.BinaryReader;
+import ghidra.app.util.bin.format.swift.*;
+import ghidra.program.model.data.*;
+import ghidra.util.exception.DuplicateNameException;
+
+/**
+ * Represents a Swift FieldRecord structure
+ *
+ * @see swift/RemoteInspection/Records.h
+ */
+public final class FieldRecord implements SwiftStructure {
+
+ /**
+ * The size (in bytes) of a {@link FieldRecord} structure
+ */
+ public static final int SIZE = 12;
+
+ private int flags;
+ private String mangledTypeName;
+ private String fieldName;
+
+ /**
+ * Creates a new {@link FieldRecord}
+ *
+ * @param reader A {@link BinaryReader} positioned at the start of the structure
+ * @throws IOException if there was an IO-related problem creating the structure
+ */
+ public FieldRecord(BinaryReader reader) throws IOException {
+ flags = reader.readNextInt();
+ mangledTypeName = reader.readNext(SwiftUtils::relativeString);
+ fieldName = reader.readNext(SwiftUtils::relativeString);
+ }
+
+ /**
+ * Gets the flags
+ *
+ * @return The flags
+ */
+ public int getFlags() {
+ return flags;
+ }
+
+ /**
+ * Gets the mangled type name
+ *
+ * @return The mangled type name
+ */
+ public String getMangledTypeName() {
+ return mangledTypeName;
+ }
+
+ /**
+ * Gets the field name
+ *
+ * @return The field name
+ */
+ public String getFieldName() {
+ return fieldName;
+ }
+
+ @Override
+ public String getStructureName() {
+ return FieldRecord.class.getSimpleName();
+ }
+
+ @Override
+ public String getDescription() {
+ return "field record";
+ }
+
+ @Override
+ public DataType toDataType() throws DuplicateNameException, IOException {
+ StructureDataType struct = new StructureDataType(getStructureName(), 0);
+ struct.add(DWORD, "Flags", "");
+ struct.add(SwiftUtils.PTR_STRING, "MangledTypeName", "");
+ struct.add(SwiftUtils.PTR_STRING, "FieldName", "");
+ struct.setCategoryPath(new CategoryPath(DATA_TYPE_CATEGORY));
+ return struct;
+ }
+
+}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/MetadataSourceRecord.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/MetadataSourceRecord.java
new file mode 100644
index 0000000000..2d3d89df38
--- /dev/null
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/MetadataSourceRecord.java
@@ -0,0 +1,88 @@
+/* ###
+ * IP: GHIDRA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package ghidra.app.util.bin.format.swift.types;
+
+import java.io.IOException;
+
+import ghidra.app.util.bin.BinaryReader;
+import ghidra.app.util.bin.format.swift.*;
+import ghidra.program.model.data.*;
+import ghidra.util.exception.DuplicateNameException;
+
+/**
+ * Represents a Swift MetadataSourceRecord structure
+ *
+ * @see swift/RemoteInspection/Records.h
+ */
+public final class MetadataSourceRecord implements SwiftStructure {
+
+ /**
+ * The size (in bytes) of a {@link MetadataSourceRecord} structure
+ */
+ public static final int SIZE = 8;
+
+ private String mangledTypeName;
+ private String mangledMetadataSource;
+
+ /**
+ * Creates a new {@link MetadataSourceRecord}
+ *
+ * @param reader A {@link BinaryReader} positioned at the start of the structure
+ * @throws IOException if there was an IO-related problem creating the structure
+ */
+ public MetadataSourceRecord(BinaryReader reader) throws IOException {
+ mangledTypeName = reader.readNext(SwiftUtils::relativeString);
+ mangledMetadataSource = reader.readNext(SwiftUtils::relativeString);
+ }
+
+ /**
+ * Gets the mangled type name
+ *
+ * @return The mangled type name
+ */
+ public String getMangledTypeName() {
+ return mangledTypeName;
+ }
+
+ /**
+ * Gets the mangled metadata source
+ *
+ * @return The mangled metadata source
+ */
+ public String getMangledMetadataSource() {
+ return mangledMetadataSource;
+ }
+
+ @Override
+ public String getStructureName() {
+ return MetadataSourceRecord.class.getSimpleName();
+ }
+
+ @Override
+ public String getDescription() {
+ return "metadata source record";
+ }
+
+ @Override
+ public DataType toDataType() throws DuplicateNameException, IOException {
+ StructureDataType struct = new StructureDataType(getStructureName(), 0);
+ struct.add(SwiftUtils.PTR_STRING, "MangledTypeName", "");
+ struct.add(SwiftUtils.PTR_STRING, "MangledMetadataSource", "");
+ struct.setCategoryPath(new CategoryPath(DATA_TYPE_CATEGORY));
+ return struct;
+ }
+
+}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/MultiPayloadEnumDescriptor.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/MultiPayloadEnumDescriptor.java
new file mode 100644
index 0000000000..f8aa845839
--- /dev/null
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/MultiPayloadEnumDescriptor.java
@@ -0,0 +1,98 @@
+/* ###
+ * IP: GHIDRA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package ghidra.app.util.bin.format.swift.types;
+
+import java.io.IOException;
+
+import ghidra.app.util.bin.BinaryReader;
+import ghidra.app.util.bin.format.swift.SwiftStructure;
+import ghidra.app.util.bin.format.swift.SwiftUtils;
+import ghidra.program.model.data.DataType;
+import ghidra.util.exception.DuplicateNameException;
+
+/**
+ * Represents a Swift MultiPayloadEnumDescriptor structure
+ *
+ * @see swift/RemoteInspection/Records.h
+ */
+public final class MultiPayloadEnumDescriptor implements SwiftStructure {
+
+ /**
+ * The size (in bytes) of a {@link MultiPayloadEnumDescriptor} structure. This size does not
+ * take into account the size of the contents array.
+ *
+ * @see #getContentsSize()
+ */
+ public static final int SIZE = 4;
+
+ private String typeName;
+ private int[] contents;
+
+ /**
+ * Creates a new {@link MultiPayloadEnumDescriptor}
+ *
+ * @param reader A {@link BinaryReader} positioned at the start of the structure
+ * @throws IOException if there was an IO-related problem creating the structure
+ */
+ public MultiPayloadEnumDescriptor(BinaryReader reader) throws IOException {
+ typeName = reader.readNext(SwiftUtils::relativeString);
+ int size = (reader.readNextInt() >> 16) & 0xffff;
+ reader.setPointerIndex(reader.getPointerIndex() - 4);
+ contents = reader.readNextIntArray(size);
+ }
+
+ /**
+ * Gets the type name
+ *
+ * @return The type name
+ */
+ public String getTypeName() {
+ return typeName;
+ }
+
+ /**
+ * Gets the contents
+ *
+ * @return The contents
+ */
+ public int[] getContents() {
+ return contents;
+ }
+
+ /**
+ * Gets the size of the contents in bytes
+ *
+ * @return The size of the contents in bytes
+ */
+ public long getContentsSize() {
+ return contents.length * Integer.BYTES;
+ }
+
+ @Override
+ public String getStructureName() {
+ return MultiPayloadEnumDescriptor.class.getSimpleName();
+ }
+
+ @Override
+ public String getDescription() {
+ return "multipayload enum descriptor";
+ }
+
+ @Override
+ public DataType toDataType() throws DuplicateNameException, IOException {
+ return SwiftUtils.PTR_STRING;
+ }
+}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/TargetClassDescriptor.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/TargetClassDescriptor.java
new file mode 100644
index 0000000000..26073e7b25
--- /dev/null
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/TargetClassDescriptor.java
@@ -0,0 +1,138 @@
+/* ###
+ * IP: GHIDRA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package ghidra.app.util.bin.format.swift.types;
+
+import java.io.IOException;
+
+import ghidra.app.util.bin.BinaryReader;
+import ghidra.app.util.bin.format.swift.SwiftUtils;
+import ghidra.program.model.data.CategoryPath;
+import ghidra.program.model.data.DataType;
+import ghidra.program.model.data.StructureDataType;
+import ghidra.util.exception.DuplicateNameException;
+
+/**
+ * Represents a Swift TargetClassDescriptor structure
+ *
+ * @see swift/ABI/Metadata.h
+ */
+public final class TargetClassDescriptor extends TargetTypeContextDescriptor {
+
+ private int superclassType;
+ private int metadataNegativeSizeInWords;
+ private int metadataPositiveSizeInWords;
+ private int numImmediateMembers;
+ private int numFields;
+
+ /**
+ * Creates a new {@link TargetClassDescriptor}
+ *
+ * @param reader A {@link BinaryReader} positioned at the start of the structure
+ * @throws IOException if there was an IO-related problem creating the structure
+ */
+ public TargetClassDescriptor(BinaryReader reader) throws IOException {
+ super(reader);
+ superclassType = reader.readNextInt();
+ metadataNegativeSizeInWords = reader.readNextInt();
+ metadataPositiveSizeInWords = reader.readNextInt();
+ numImmediateMembers = reader.readNextInt();
+ numFields = reader.readNextInt();
+ }
+
+ /**
+ * Gets the type of the superclass, expressed as a mangled type name that can refer to the
+ * generic arguments of the subclass type
+ *
+ * @return The type of the superclass, expressed as a mangled type name that can refer to the
+ * generic arguments of the subclass type
+ */
+ public int getSuperclassType() {
+ return superclassType;
+ }
+
+ /**
+ * If this descriptor does not have a resilient superclass, this is the negative size of
+ * metadata objects of this class (in words). If this descriptor has a resilient superclass,
+ * this is a reference to a cache holding the metadata's extents.
+ *
+ * @return The negative size of metadata objects of this class (in words) or a reference to a
+ * cache holding the metadata's extents
+ */
+ public int getMetadataNegativeSizeInWords() {
+ return metadataNegativeSizeInWords;
+ }
+
+ /**
+ * If this descriptor does not have a resilient superclass, this is the positive size of
+ * metadata objects of this class (in words). Otherwise, these flags are used to do things like
+ * indicate the presence of an Objective-C resilient class stub.
+ *
+ * @return The positive size of metadata objects of this class (in words) or flags used to do
+ * things like indicate the presence of an Objective-C resilient class stub.
+ */
+ public int getMetadataPositiveSizeInWords() {
+ return metadataPositiveSizeInWords;
+ }
+
+ /**
+ * Gets the number of additional members added by this class to the class metadata
+ *
+ * @return The number of additional members added by this class to the class metadata
+ */
+ public int getNumImmediateMembers() {
+ return numImmediateMembers;
+ }
+
+ /**
+ * Gets the number of stored properties in the class, not including its superclasses. If there
+ * is a field offset vector, this is its length.
+ *
+ * @return The number of stored properties in the class, not including its superclasses.
+ * If there is a field offset vector, this is its length.
+ */
+ public int getNumFields() {
+ return numFields;
+ }
+
+ @Override
+ public String getStructureName() {
+ return TargetClassDescriptor.class.getSimpleName();
+ }
+
+ @Override
+ public String getDescription() {
+ return "class descriptor";
+ }
+
+ @Override
+ public DataType toDataType() throws DuplicateNameException, IOException {
+ StructureDataType struct = new StructureDataType(getStructureName(), 0);
+ struct.add(super.toDataType(), super.getStructureName(), "");
+ struct.add(SwiftUtils.PTR_STRING, "SuperclassType",
+ "The type of the superclass, expressed as a mangled type name that can refer to the generic arguments of the subclass type");
+ struct.add(DWORD, "MetadataNegativeSizeInWords",
+ "If this descriptor does not have a resilient superclass, this is the negative size of metadata objects of this class (in words)");
+ struct.add(DWORD, "MetadataPositiveSizeInWords",
+ "If this descriptor does not have a resilient superclass, this is the positive size of metadata objects of this class (in words)");
+ struct.add(DWORD, "NumImmediateMembers",
+ "The number of additional members added by this class to the class metadata");
+ struct.add(DWORD, "NumFields",
+ "The number of stored properties in the class, not including its superclasses. If there is a field offset vector, this is its length.");
+ struct.setCategoryPath(new CategoryPath(DATA_TYPE_CATEGORY));
+ return struct;
+ }
+
+}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/TargetContextDescriptor.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/TargetContextDescriptor.java
new file mode 100644
index 0000000000..ec464f2a6e
--- /dev/null
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/TargetContextDescriptor.java
@@ -0,0 +1,94 @@
+/* ###
+ * IP: GHIDRA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package ghidra.app.util.bin.format.swift.types;
+
+import java.io.IOException;
+
+import ghidra.app.util.bin.BinaryReader;
+import ghidra.app.util.bin.format.swift.*;
+import ghidra.program.model.data.*;
+import ghidra.util.exception.DuplicateNameException;
+
+/**
+ * Represents a Swift TargetContextDescriptor structure
+ *
+ * @see swift/ABI/Metadata.h
+ */
+public class TargetContextDescriptor implements SwiftStructure {
+
+ private int flags;
+ private int parent;
+
+ /**
+ * Create a new {@link TargetContextDescriptor}
+ *
+ * @param reader A {@link BinaryReader} positioned at the start of the structure
+ * @throws IOException if there was an IO-related problem creating the structure
+ */
+ public TargetContextDescriptor(BinaryReader reader) throws IOException {
+ flags = reader.readNextInt();
+ parent = reader.readNextInt();
+ }
+
+ /**
+ * Gets the flags
+ *
+ * @return The flags
+ */
+ public int getFlags() {
+ return flags;
+ }
+
+ /**
+ * Gets the parent's relative offset
+ *
+ * @return The parent's relative offset
+ */
+ public int getParent() {
+ return parent;
+ }
+
+ @Override
+ public String getStructureName() {
+ return getMyStructureName();
+ }
+
+ @Override
+ public String getDescription() {
+ return "context descriptor";
+ }
+
+ /**
+ * Gets this class's structure name (will not be affected by subclass's name)
+ *
+ * @return This class's structure name
+ */
+ private final String getMyStructureName() {
+ return TargetContextDescriptor.class.getSimpleName();
+ }
+
+ @Override
+ public DataType toDataType() throws DuplicateNameException, IOException {
+ StructureDataType struct = new StructureDataType(getMyStructureName(), 0);
+ struct.add(DWORD, "Flags",
+ "Flags describing the context, including its kind and format version");
+ struct.add(SwiftUtils.PTR_RELATIVE, "Parent",
+ "The parent context, or null if this is a top-level context");
+ struct.setCategoryPath(new CategoryPath(DATA_TYPE_CATEGORY));
+ return struct;
+ }
+
+}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/TargetEnumDescriptor.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/TargetEnumDescriptor.java
new file mode 100644
index 0000000000..3b3b3f71ec
--- /dev/null
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/TargetEnumDescriptor.java
@@ -0,0 +1,88 @@
+/* ###
+ * IP: GHIDRA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package ghidra.app.util.bin.format.swift.types;
+
+import java.io.IOException;
+
+import ghidra.app.util.bin.BinaryReader;
+import ghidra.program.model.data.CategoryPath;
+import ghidra.program.model.data.DataType;
+import ghidra.program.model.data.StructureDataType;
+import ghidra.util.exception.DuplicateNameException;
+
+/**
+ * Represents a Swift TargetEnumDescriptor structure
+ *
+ * @see swift/ABI/Metadata.h
+ */
+public final class TargetEnumDescriptor extends TargetTypeContextDescriptor {
+
+ private int numPayloadCasesAndPayloadSizeOffset;
+ private int numEmptyCases;
+
+ /**
+ * Creates a new {@link TargetEnumDescriptor}
+ *
+ * @param reader A {@link BinaryReader} positioned at the start of the structure
+ * @throws IOException if there was an IO-related problem creating the structure
+ */
+ public TargetEnumDescriptor(BinaryReader reader) throws IOException {
+ super(reader);
+ numPayloadCasesAndPayloadSizeOffset = reader.readNextInt();
+ numEmptyCases = reader.readNextInt();
+ }
+
+ /**
+ * Gets the number of non-empty cases in the enum are in the low 24 bits; the offset of the
+ * payload size in the metadata record in words, if any, is stored in the high 8 bits;
+
+ * @return The number of non-empty cases in the enum and the offset of the payload size
+ */
+ public int getNumPayloadCasesAndPayloadSizeOffset() {
+ return numPayloadCasesAndPayloadSizeOffset;
+ }
+
+ /**
+ * Gets the number of empty cases in the enum
+ *
+ * @return The number of empty cases in the enum
+ */
+ public int getNumEmptyCases() {
+ return numEmptyCases;
+ }
+
+ @Override
+ public String getStructureName() {
+ return TargetEnumDescriptor.class.getSimpleName();
+ }
+
+ @Override
+ public String getDescription() {
+ return "enum descriptor";
+ }
+
+ @Override
+ public DataType toDataType() throws DuplicateNameException, IOException {
+ StructureDataType struct = new StructureDataType(getStructureName(), 0);
+ struct.add(super.toDataType(), super.getStructureName(), "");
+ struct.add(DWORD, "NumPayloadCasesAndPayloadSizeOffset",
+ "The number of non-empty cases in the enum are in the low 24 bits; the offset of the payload size in the metadata record in words, if any, is stored in the high 8 bits.");
+ struct.add(DWORD, "NumEmptyCases", "The number of empty cases in the enum");
+ struct.setCategoryPath(new CategoryPath(DATA_TYPE_CATEGORY));
+ return struct;
+ }
+
+}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/TargetProtocolConformanceDescriptor.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/TargetProtocolConformanceDescriptor.java
new file mode 100644
index 0000000000..74d81c3afc
--- /dev/null
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/TargetProtocolConformanceDescriptor.java
@@ -0,0 +1,109 @@
+/* ###
+ * IP: GHIDRA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package ghidra.app.util.bin.format.swift.types;
+
+import java.io.IOException;
+
+import ghidra.app.util.bin.BinaryReader;
+import ghidra.app.util.bin.format.swift.*;
+import ghidra.program.model.data.*;
+import ghidra.util.exception.DuplicateNameException;
+
+/**
+ * Represents a Swift TargetProtocolConformanceDescriptor structure
+ *
+ * @see swift/ABI/Metadata.h
+ */
+public final class TargetProtocolConformanceDescriptor implements SwiftStructure {
+
+ private int protocolDescriptor;
+ private int nominalTypeDescriptor;
+ private int protocolWitnessTable;
+ private int conformanceFlags;
+
+ /**
+ * Creates a new {@link TargetProtocolConformanceDescriptor}
+ *
+ * @param reader A {@link BinaryReader} positioned at the start of the structure
+ * @throws IOException if there was an IO-related problem creating the structure
+ */
+ public TargetProtocolConformanceDescriptor(BinaryReader reader) throws IOException {
+ protocolDescriptor = reader.readNextInt();
+ nominalTypeDescriptor = reader.readNextInt();
+ protocolWitnessTable = reader.readNextInt();
+ conformanceFlags = reader.readNextInt();
+ }
+
+ /**
+ * Gets the protocol being conformed to
+ *
+ * @return The protocol being conformed to
+ */
+ public int getProtocolDescriptor() {
+ return protocolDescriptor;
+ }
+
+ /**
+ * Gets some description of the type that conforms to the protocol
+ *
+ * @return Some description of the type that conforms to the protocol
+ */
+ public int getNominalTypeDescriptor() {
+ return nominalTypeDescriptor;
+ }
+
+ /**
+ * Gets the witness table pattern, which may also serve as the witness table
+ *
+ * @return The witness table pattern, which may also serve as the witness table
+ */
+ public int getProtocolWitnessTable() {
+ return protocolWitnessTable;
+ }
+
+ /**
+ * Gets various flags, including the kind of conformance
+ *
+ * @return Various flags, including the kind of conformance
+ */
+ public int getConformanceFlags() {
+ return conformanceFlags;
+ }
+
+ @Override
+ public String getStructureName() {
+ return TargetProtocolConformanceDescriptor.class.getSimpleName();
+ }
+
+ @Override
+ public String getDescription() {
+ return "protocol conformance descriptor";
+ }
+
+ @Override
+ public DataType toDataType() throws DuplicateNameException, IOException {
+ StructureDataType struct = new StructureDataType(getStructureName(), 0);
+ struct.add(DWORD, "ProtocolDescriptor", "The protocol being conformed to");
+ struct.add(SwiftUtils.PTR_RELATIVE, "NominalTypeDescriptor",
+ "Some description of the type that conforms to the protocol");
+ struct.add(DWORD, "ProtocolWitnessTable",
+ "The witness table pattern, which may also serve as the witness table");
+ struct.add(DWORD, "ConformanceFlags", "Various flags, including the kind of conformance");
+ struct.setCategoryPath(new CategoryPath(DATA_TYPE_CATEGORY));
+ return struct;
+ }
+
+}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/TargetProtocolDescriptor.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/TargetProtocolDescriptor.java
new file mode 100644
index 0000000000..3aa6ce1c07
--- /dev/null
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/TargetProtocolDescriptor.java
@@ -0,0 +1,118 @@
+/* ###
+ * IP: GHIDRA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package ghidra.app.util.bin.format.swift.types;
+
+import java.io.IOException;
+
+import ghidra.app.util.bin.BinaryReader;
+import ghidra.app.util.bin.format.swift.SwiftUtils;
+import ghidra.program.model.data.CategoryPath;
+import ghidra.program.model.data.DataType;
+import ghidra.program.model.data.StructureDataType;
+import ghidra.util.exception.DuplicateNameException;
+
+/**
+ * Represents a Swift TargetProtocolDescriptor structure
+ *
+ * @see swift/ABI/Metadata.h
+ */
+public final class TargetProtocolDescriptor extends TargetContextDescriptor {
+
+ private String name;
+ private int numRequirementsInSig;
+ private int numRequirements;
+ private int associatedTypeNames;
+
+ /**
+ * Creates a new {@link TargetProtocolDescriptor}
+ *
+ * @param reader A {@link BinaryReader} positioned at the start of the structure
+ * @throws IOException if there was an IO-related problem creating the structure
+ */
+ public TargetProtocolDescriptor(BinaryReader reader) throws IOException {
+ super(reader);
+ name = reader.readNext(SwiftUtils::relativeString);
+ numRequirementsInSig = reader.readNextInt();
+ numRequirements = reader.readNextInt();
+ associatedTypeNames = reader.readNextInt();
+ }
+
+ /**
+ * Gets the name of the protocol
+ *
+ * @return The name of the protocol
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Gets the number of generic requirements in the requirement signature of the protocol
+ *
+ * @return The number of generic requirements in the requirement signature of the protocol
+ */
+ public int getNumRequirementsInSignature() {
+ return numRequirementsInSig;
+ }
+
+ /**
+ * Gets the number of requirements in the protocol
+ *
+ * @return The number of requirements in the protocol
+ */
+ public int getNumRequirements() {
+ return numRequirements;
+ }
+
+ /**
+ * Gets the associated type names
+ *
+ * @return The associated type names
+ */
+ public int getAssociatedTypeNames() {
+ return associatedTypeNames; // TODO: it's a list...improve
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+
+ @Override
+ public String getStructureName() {
+ return TargetProtocolDescriptor.class.getSimpleName();
+ }
+
+ @Override
+ public String getDescription() {
+ return "protocol descriptor";
+ }
+
+ @Override
+ public DataType toDataType() throws DuplicateNameException, IOException {
+ StructureDataType struct = new StructureDataType(getStructureName(), 0);
+ struct.add(super.toDataType(), super.getStructureName(), "");
+ struct.add(SwiftUtils.PTR_STRING, "Name", "The name of the protocol");
+ struct.add(DWORD, "NumRequirementsInSignature",
+ "The number of generic requirements in the requirement signature of the protocol");
+ struct.add(DWORD, "NumRequirements", "The number of requirements in the protocol");
+ struct.add(DWORD, "AssociatedTypeNames",
+ "Associated type names, as a space-separated list in the same order as the requirements");
+ struct.setCategoryPath(new CategoryPath(DATA_TYPE_CATEGORY));
+ return struct;
+ }
+
+}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/TargetStructDescriptor.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/TargetStructDescriptor.java
new file mode 100644
index 0000000000..092bd49739
--- /dev/null
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/TargetStructDescriptor.java
@@ -0,0 +1,92 @@
+/* ###
+ * IP: GHIDRA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package ghidra.app.util.bin.format.swift.types;
+
+import java.io.IOException;
+
+import ghidra.app.util.bin.BinaryReader;
+import ghidra.program.model.data.CategoryPath;
+import ghidra.program.model.data.DataType;
+import ghidra.program.model.data.StructureDataType;
+import ghidra.util.exception.DuplicateNameException;
+
+/**
+ * Represents a Swift TargetStructDescriptor structure
+ *
+ * @see swift/ABI/Metadata.h
+ */
+public final class TargetStructDescriptor extends TargetTypeContextDescriptor {
+
+ private int numFields;
+ private int fieldOffsetVectorOffset;
+
+ /**
+ * Creates a new {@link TargetStructDescriptor}
+ *
+ * @param reader A {@link BinaryReader} positioned at the start of the structure
+ * @throws IOException if there was an IO-related problem creating the structure
+ */
+ public TargetStructDescriptor(BinaryReader reader) throws IOException {
+ super(reader);
+ numFields = reader.readNextInt();
+ fieldOffsetVectorOffset = reader.readNextInt();
+ }
+
+ /**
+ * Gets the number of stored properties in the struct. If there is a field offset vector,
+ * this is its length.
+
+ * @return The number of stored properties in the struct. If there is a field offset vector,
+ * this is its length.
+ */
+ public int getNumFields() {
+ return numFields;
+ }
+
+ /**
+ * Gets the offset of the field offset vector for this struct's stored properties in its
+ * metadata, if any. 0 means there is no field offset vector.
+ *
+ * @return The offset of the field offset vector for this struct's stored properties in its
+ * metadata, if any. 0 means there is no field offset vector.
+ */
+ public int getFieldOffsetVectorOffset() {
+ return fieldOffsetVectorOffset;
+ }
+
+ @Override
+ public String getStructureName() {
+ return TargetStructDescriptor.class.getSimpleName();
+ }
+
+ @Override
+ public String getDescription() {
+ return "struct descriptor";
+ }
+
+ @Override
+ public DataType toDataType() throws DuplicateNameException, IOException {
+ StructureDataType struct = new StructureDataType(getStructureName(), 0);
+ struct.add(super.toDataType(), super.getStructureName(), "");
+ struct.add(DWORD, "NumFields",
+ "The number of stored properties in the struct. If there is a field offset vector, this is its length.");
+ struct.add(DWORD, "FieldOffsetVectorOffset",
+ "The offset of the field offset vector for this struct's stored properties in its metadata, if any. 0 means there is no field offset vector.");
+ struct.setCategoryPath(new CategoryPath(DATA_TYPE_CATEGORY));
+ return struct;
+ }
+
+}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/TargetTypeContextDescriptor.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/TargetTypeContextDescriptor.java
new file mode 100644
index 0000000000..3b2f10ea9c
--- /dev/null
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/swift/types/TargetTypeContextDescriptor.java
@@ -0,0 +1,112 @@
+/* ###
+ * IP: GHIDRA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package ghidra.app.util.bin.format.swift.types;
+
+import java.io.IOException;
+
+import ghidra.app.util.bin.BinaryReader;
+import ghidra.app.util.bin.format.swift.SwiftUtils;
+import ghidra.program.model.data.*;
+import ghidra.util.exception.DuplicateNameException;
+
+/**
+ * Represents a Swift TargetTypeContextDescriptor structure
+ *
+ * @see swift/ABI/Metadata.h
+ */
+public class TargetTypeContextDescriptor extends TargetContextDescriptor {
+
+ private String name;
+ private int accessFunctionPtr;
+ private int fields;
+
+ /**
+ * Creates a new {@link TargetTypeContextDescriptor}
+ *
+ * @param reader A {@link BinaryReader} positioned at the start of the structure
+ * @throws IOException if there was an IO-related problem creating the structure
+ */
+ public TargetTypeContextDescriptor(BinaryReader reader) throws IOException {
+ super(reader);
+ name = reader.readNext(SwiftUtils::relativeString);
+ accessFunctionPtr = reader.readNextInt();
+ fields = reader.readNextInt();
+ }
+
+ /**
+ * Gets the name of the type
+ *
+ * @return The name of the type
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Gets the pointer to the metadata access function for this type
+ *
+ * @return The pointer to the metadata access function for this type
+ */
+ public int getAccessFunctionPtr() {
+ return accessFunctionPtr;
+ }
+
+ /**
+ * Gets the pointer to the field descriptor for the type, if any
+ *
+ * @return The pointer to the field descriptor for the type, if any
+ */
+ public int getFields() {
+ return fields;
+ }
+
+ @Override
+ public String getStructureName() {
+ return getMyStructureName();
+ }
+
+ @Override
+ public String getDescription() {
+ return "type context descriptor";
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+
+ /**
+ * Gets this class's structure name (will not be affected by subclass's name)
+ *
+ * @return This class's structure name
+ */
+ private final String getMyStructureName() {
+ return TargetTypeContextDescriptor.class.getSimpleName();
+ }
+
+ @Override
+ public DataType toDataType() throws DuplicateNameException, IOException {
+ StructureDataType struct = new StructureDataType(getMyStructureName(), 0);
+ struct.add(super.toDataType(), super.getStructureName(), "");
+ struct.add(SwiftUtils.PTR_STRING, "Name", "The name of the type");
+ struct.add(SwiftUtils.PTR_RELATIVE, "AccessFunctionPtr",
+ "A pointer to the metadata access function for this type");
+ struct.add(SwiftUtils.PTR_RELATIVE, "Fields",
+ "A pointer to the field descriptor for the type, if any");
+ struct.setCategoryPath(new CategoryPath(DATA_TYPE_CATEGORY));
+ return struct;
+ }
+}