GP-6281: More Swift type metadata markup (mostly TrailingObjects)

This commit is contained in:
Ryan Kurtz
2025-11-24 05:54:54 -05:00
parent e64ffd03a9
commit bbd2285583
57 changed files with 3874 additions and 413 deletions

View File

@@ -77,6 +77,10 @@ public interface StructConverter {
* Reusable 64-bit image base offset datatype.
*/
public final static DataType IBO64 = IBO64DataType.dataType;
/**
* Reusable boolean data type.
*/
public final static DataType BOOL = BooleanDataType.dataType;
/**
* Reusable Unsigned LEB128 dynamic length data type

View File

@@ -4,9 +4,9 @@
* 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.
@@ -51,9 +51,7 @@ public enum SwiftSection {
}
/**
* Gets a {@link List} of the {@link SwiftSection}'s names
*
* @return A {@link List} of the {@link SwiftSection}'s names
* {@return a {@link List} of the {@link SwiftSection}'s names}
*/
public List<String> getSwiftSectionNames() {
return sectionNames;

View File

@@ -4,9 +4,9 @@
* 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.
@@ -168,19 +168,19 @@ public class SwiftTypeMetadata {
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();
for (MemoryBlock block : SwiftUtils.getSwiftBlocks(section, program)) {
monitor.checkCancelled();
Address blockStart = block.getStart();
try {
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 + "'");
catch (IOException e) {
log("Failed to parse entry point at %s: %s".formatted(blockStart, e.getMessage()));
}
}
}
@@ -386,20 +386,20 @@ public class SwiftTypeMetadata {
*/
private void parseProtocolDescriptors(SwiftSection section, BinaryReader reader)
throws CancelledException {
monitor.setMessage("Parsing Swift protocol descriptors...");
monitor.setIndeterminate(true);
try {
List<SwiftStructureAddress> addrPairs = parsePointerTable(section, reader);
for (SwiftStructureAddress addrPair : addrPairs) {
reader.setPointerIndex(addrPair.structAddr().getOffset());
List<SwiftStructureAddress> addrPairs = parsePointerTable(section, reader);
monitor.initialize(addrPairs.size(), "Parsing Swift protocol descriptors...");
for (SwiftStructureAddress addrPair : addrPairs) {
monitor.increment();
reader.setPointerIndex(addrPair.structAddr().getOffset());
try {
TargetProtocolDescriptor descriptor = new TargetProtocolDescriptor(reader);
protocolDescriptors.add(descriptor);
markupList.add(new SwiftStructureInfo(descriptor,
new SwiftStructureAddress(addrPair.structAddr(), addrPair.pointerAddr())));
markupList.add(new SwiftStructureInfo(descriptor, addrPair));
}
catch (IOException e) {
log("Failed to parse protocol descriptors at %s: %s"
.formatted(addrPair.structAddr(), e.getMessage()));
}
}
catch (IOException e) {
log("Failed to parse protocol descriptors from section '" + section + "'");
}
}
@@ -412,23 +412,21 @@ public class SwiftTypeMetadata {
*/
private void parseProtocolConformanceDescriptors(SwiftSection section, BinaryReader reader)
throws CancelledException {
monitor.setMessage("Parsing Swift protocol conformance descriptors...");
monitor.setIndeterminate(true);
try {
List<SwiftStructureAddress> addrPairs = parsePointerTable(section, reader);
for (SwiftStructureAddress addrPair : addrPairs) {
List<SwiftStructureAddress> addrPairs = parsePointerTable(section, reader);
monitor.initialize(addrPairs.size(), "Parsing Swift protocol conformance descriptors...");
for (SwiftStructureAddress addrPair : addrPairs) {
monitor.increment();
try {
reader.setPointerIndex(addrPair.structAddr().getOffset());
TargetProtocolConformanceDescriptor descriptor =
new TargetProtocolConformanceDescriptor(reader);
protocolConformanceDescriptors.add(descriptor);
markupList.add(new SwiftStructureInfo(descriptor,
new SwiftStructureAddress(addrPair.structAddr(),
addrPair.pointerAddr())));
markupList.add(new SwiftStructureInfo(descriptor, addrPair));
}
catch (IOException e) {
log("Failed to parse protocol conformance descriptor at %s: %s"
.formatted(addrPair.structAddr(), e.getMessage()));
}
}
catch (IOException e) {
log("Failed to parse protocol conformance descriptors from section '" + section +
"'");
}
}
@@ -441,37 +439,37 @@ public class SwiftTypeMetadata {
*/
private void parseTypeDescriptors(SwiftSection section, BinaryReader reader)
throws CancelledException {
monitor.setMessage("Parsing Swift type descriptors...");
monitor.setIndeterminate(true);
try {
List<SwiftStructureAddress> addrPairs = parsePointerTable(section, reader);
for (SwiftStructureAddress addrPair : addrPairs) {
List<SwiftStructureAddress> addrPairs = parsePointerTable(section, reader);
monitor.initialize(addrPairs.size(), "Parsing Swift type descriptors...");
for (SwiftStructureAddress addrPair : addrPairs) {
monitor.increment();
try {
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:
ContextDescriptorKind kind = descriptor.getFlags().getKind();
descriptor = switch (kind) {
case Class:
yield new TargetClassDescriptor(reader);
case ContextDescriptorKind.STRUCT:
case Struct:
yield new TargetStructDescriptor(reader);
case ContextDescriptorKind.ENUM:
case Enum:
yield new TargetEnumDescriptor(reader);
default:
log("Unrecognized type descriptor %d at index: 0x%x"
.formatted(contextDescriptorKind, origIndex));
.formatted(kind.getValue(), origIndex));
yield null;
};
if (descriptor != null) {
typeDescriptors.put(descriptor.getName(), descriptor);
markupList.add(new SwiftStructureInfo(descriptor,
new SwiftStructureAddress(addrPair.structAddr(), addrPair.pointerAddr())));
markupList.add(new SwiftStructureInfo(descriptor, addrPair));
}
}
}
catch (IOException e) {
log("Failed to parse type descriptors from section '" + section + "'");
catch (IOException e) {
log("Failed to parse type descriptor at %s: %s".formatted(addrPair,
e.getMessage()));
}
}
}
@@ -487,6 +485,8 @@ public class SwiftTypeMetadata {
throws CancelledException {
final int POINTER_SIZE = 4;
List<SwiftStructureAddress> result = new ArrayList<>();
monitor.setMessage("Parsing Swift protocol conformance descriptors...");
monitor.setIndeterminate(true);
try {
for (MemoryBlock block : SwiftUtils.getSwiftBlocks(section, program)) {
Address blockAddr = block.getStart();
@@ -503,7 +503,7 @@ public class SwiftTypeMetadata {
}
}
catch (IOException e) {
log("Failed to parse Swift struction pointers from section '" + section + "'");
log("Failed to parse Swift structure pointers from section '" + section + "'");
}
return result;
}
@@ -514,27 +514,45 @@ public class SwiftTypeMetadata {
* @throws CancelledException if the user cancelled the operation
*/
public void markup() throws CancelledException {
monitor.setMessage("Marking up Swift structures...");
monitor.initialize(markupList.size());
monitor.initialize(markupList.size(), "Marking up Swift structures...");
for (SwiftStructureInfo structInfo : markupList) {
monitor.checkCancelled();
monitor.incrementProgress(1);
monitor.increment();
try {
SwiftTypeMetadataStructure struct = structInfo.struct();
DataType dt = struct.toDataType();
DataUtilities.createData(program, structInfo.addr().structAddr(), dt, -1,
ClearDataMode.CLEAR_ALL_DEFAULT_CONFLICT_DATA);
try {
DataUtilities.createData(program, structInfo.addr().structAddr(), dt, -1,
ClearDataMode.CLEAR_ALL_DEFAULT_CONFLICT_DATA);
}
catch (CodeUnitInsertionException e) {
// Probably multiple pointers to same structure
}
for (SwiftTypeMetadataStructure trailingStruct : struct.getTrailingObjects()) {
Address trailingAddr = structInfo.addr()
.structAddr()
.add(trailingStruct.getBase() - struct.getBase());
DataType trailingDt = trailingStruct.toDataType();
try {
DataUtilities.createData(program, trailingAddr, trailingDt, -1,
ClearDataMode.CLEAR_ALL_DEFAULT_CONFLICT_DATA);
}
catch (CodeUnitInsertionException e) {
// Probably multiple pointers to same structure
}
}
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);
try {
DataUtilities.createData(program, structInfo.addr().pointerAddr(),
relativePtrDataType, -1, ClearDataMode.CLEAR_ALL_DEFAULT_CONFLICT_DATA);
}
catch (CodeUnitInsertionException e) {
// Unexpected, but safe to ignore
}
}
}
catch (CodeUnitInsertionException e) {
// Probably just called more than once
}
catch (DuplicateNameException | IOException e) {
catch (IllegalArgumentException | DuplicateNameException | IOException e) {
log("Failed to markup: " + structInfo);
}
}

View File

@@ -4,9 +4,9 @@
* 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.
@@ -15,41 +15,52 @@
*/
package ghidra.app.util.bin.format.swift;
import java.util.List;
import ghidra.app.util.bin.StructConverter;
import ghidra.program.model.data.CategoryPath;
/**
* Implemented by all Swift type metadata structures
*/
public abstract class SwiftTypeMetadataStructure implements StructConverter {
public static final String DATA_TYPE_CATEGORY = "/SwiftTypeMetadata";
public static final String CATEGORY = "/SwiftTypeMetadata";
public static final CategoryPath CATEGORY_PATH = new CategoryPath(CATEGORY);
private long base;
/**
* Creates a new {@link SwiftTypeMetadataStructure}
*
* @param base The base "address" of this {@link SwiftTypeMetadataStructure}
*/
public SwiftTypeMetadataStructure(long base) {
this.base = base;
}
/**
* Gets the base "address" of this {@link SwiftTypeMetadataStructure}
*
* @return The base "address" of this {@link SwiftTypeMetadataStructure}
* {@return the base "address" of this {@link SwiftTypeMetadataStructure}}
*/
public long getBase() {
return base;
}
/**
* Gets the name of the {@link SwiftTypeMetadataStructure}
*
* @return The name of the {@link SwiftTypeMetadataStructure}
* {@return a {@link List} of {@link SwiftTypeMetadataStructure structures} that trail this
* {@link SwiftTypeMetadataStructure structure}}
*/
public List<SwiftTypeMetadataStructure> getTrailingObjects() {
return List.of();
}
/**
* {@return the name of the {@link SwiftTypeMetadataStructure}}
*/
public abstract String getStructureName();
/**
* Gets a short description of the {@link SwiftTypeMetadataStructure}
*
* @return A short description of the {@link SwiftTypeMetadataStructure}
* {@return a short description of the {@link SwiftTypeMetadataStructure}}
*/
public abstract String getDescription();
}

View File

@@ -32,10 +32,21 @@ public class SwiftUtils {
public static final String SWIFT_COMPILER = "swift";
/**
* A {@link PointerTypedef pointer} to a relative 4-byte offset
* A {@link TypeDef pointer} to a relative 4-byte offset
*/
public static final PointerTypedef PTR_RELATIVE =
new PointerTypedef(null, null, 4, null, PointerType.RELATIVE);
public static final TypeDef PTR_RELATIVE =
new PointerTypedefBuilder(Pointer32DataType.dataType, null)
.type(PointerType.RELATIVE)
.build();
/**
* A {@link TypeDef pointer} to a relative 4-byte offset (low bit masked off)
*/
public static final TypeDef PTR_RELATIVE_MASKED =
new PointerTypedefBuilder(Pointer32DataType.dataType, null)
.type(PointerType.RELATIVE)
.bitMask(~1)
.build();
/**
* A {@link PointerTypedef string pointer} to a 4-byte relative offset
@@ -44,10 +55,9 @@ public class SwiftUtils {
new PointerTypedef(null, StringDataType.dataType, 4, null, PointerType.RELATIVE);
/**
* Checks if the given {@link Program} is a Swift program
* {@return true if the given {@link Program} is a Swift program; otherwise, false}
*
* @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<String> prefixes = List.of("__swift", "swift", ".sw5");
@@ -60,11 +70,10 @@ public class SwiftUtils {
}
/**
* Checks if the given {@link List} of section names contains a Swift section name
* {@return true if the given {@link List} of section names contains a Swift section name;
* otherwise, false}
*
* @param sectionNames The {@link List} of section names to check
* @return True if the given {@link List} of section names contains a Swift section name; otherwise,
* false
*/
public static boolean isSwift(List<String> sectionNames) {
List<String> prefixes = List.of("__swift", "swift", ".sw5");
@@ -77,11 +86,10 @@ public class SwiftUtils {
}
/**
* Gets a {@link List} of {@link MemoryBlock}s that match the given {@link SwiftSection}
* {@return 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<MemoryBlock> getSwiftBlocks(SwiftSection section, Program program) {
List<MemoryBlock> result = new ArrayList<>();

View File

@@ -22,11 +22,12 @@ import java.util.List;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.swift.SwiftTypeMetadataStructure;
import ghidra.app.util.bin.format.swift.SwiftUtils;
import ghidra.program.model.data.*;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.StructureDataType;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift AssociatedTypeDescriptor structure
* Represents a Swift {@code AssociatedTypeDescriptor} structure
*
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/RemoteInspection/Records.h">swift/RemoteInspection/Records.h</a>
*/
@@ -63,45 +64,35 @@ public final class AssociatedTypeDescriptor extends SwiftTypeMetadataStructure {
}
/**
* Gets the conforming type name
*
* @return The conforming type name
* {@return the conforming type name}
*/
public String getConformingTypeName() {
return conformingTypeName;
}
/**
* Gets the protocol type name
*
* @return 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
* {@return the number of associated types}
*/
public int getNumAssociatedTypes() {
return numAssociatedTypes;
}
/**
* Gets the associated type record size
*
* @return 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
* {@return The {@link List} of {@link AssociatedTypeRecord}s}
*/
public List<AssociatedTypeRecord> getAssociatedTypeRecords() {
return associatedTypeRecords;
@@ -119,12 +110,11 @@ public final class AssociatedTypeDescriptor extends SwiftTypeMetadataStructure {
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(getStructureName(), 0);
StructureDataType struct = new StructureDataType(CATEGORY_PATH, 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;
}

View File

@@ -20,11 +20,12 @@ import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.swift.SwiftTypeMetadataStructure;
import ghidra.app.util.bin.format.swift.SwiftUtils;
import ghidra.program.model.data.*;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.StructureDataType;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift AssociatedTypeRecord structure
* Represents a Swift {@code AssociatedTypeRecord} structure
*
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/RemoteInspection/Records.h">swift/RemoteInspection/Records.h</a>
*/
@@ -51,18 +52,14 @@ public final class AssociatedTypeRecord extends SwiftTypeMetadataStructure {
}
/**
* Gets the name
*
* @return The name
* {@return the name}
*/
public String getName() {
return name;
}
/**
* Gets the substituted type name
*
* @return The substituted type name
* {@return the substituted type name}
*/
public String getSubstitutedTypeName() {
return substitutedTypeName;
@@ -80,10 +77,9 @@ public final class AssociatedTypeRecord extends SwiftTypeMetadataStructure {
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(getStructureName(), 0);
StructureDataType struct = new StructureDataType(CATEGORY_PATH, getStructureName(), 0);
struct.add(SwiftUtils.PTR_STRING, "Name", "");
struct.add(SwiftUtils.PTR_STRING, "SubstitutedTypeName", "");
struct.setCategoryPath(new CategoryPath(DATA_TYPE_CATEGORY));
return struct;
}

View File

@@ -20,11 +20,12 @@ import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.swift.SwiftTypeMetadataStructure;
import ghidra.app.util.bin.format.swift.SwiftUtils;
import ghidra.program.model.data.*;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.StructureDataType;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift BuiltinTypeDescriptor structure
* Represents a Swift {@code BuiltinTypeDescriptor} structure
*
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/RemoteInspection/Records.h">swift/RemoteInspection/Records.h</a>
*/
@@ -57,45 +58,35 @@ public final class BuiltinTypeDescriptor extends SwiftTypeMetadataStructure {
}
/**
* Gets the type name
*
* @return The type name
* {@return the type name}
*/
public String getTypeName() {
return typeName;
}
/**
* Gets the size
*
* @return The size
* {@return the size}
*/
public int getSize() {
return size;
}
/**
* Gets the alignment and flags
*
* @return The alignment and flags
* {@return the alignment and flags}
*/
public int getAlignmentAndFlags() {
return alignmentAndFlags;
}
/**
* Gets the stride
*
* @return The stride
* {@return the stride}
*/
public int getStride() {
return stride;
}
/**
* Gets the number of extra inhabitants
*
* @return The number of extra inhabitants
* {@return the number of extra inhabitants}
*/
public int getNumExtraInhabitants() {
return numExtraInhabitants;
@@ -113,13 +104,12 @@ public final class BuiltinTypeDescriptor extends SwiftTypeMetadataStructure {
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(getStructureName(), 0);
StructureDataType struct = new StructureDataType(CATEGORY_PATH, 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;
}

View File

@@ -21,11 +21,12 @@ import java.util.List;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.swift.SwiftTypeMetadataStructure;
import ghidra.program.model.data.*;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.StructureDataType;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift CaptureDescriptor structure
* Represents a Swift {@code CaptureDescriptor} structure
*
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/RemoteInspection/Records.h">swift/RemoteInspection/Records.h</a>
*/
@@ -65,45 +66,35 @@ public final class CaptureDescriptor extends SwiftTypeMetadataStructure {
}
/**
* Gets the number of capture types
*
* @return 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
* {@return the number of metadata sources}
*/
public int getNumMetadataSources() {
return numMetadataSources;
}
/**
* Gets the number of bindings
*
* @return 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
* {@return the {@link List} of {@link CaptureTypeRecord}s}
*/
public List<CaptureTypeRecord> getCaptureTypeRecords() {
return captureTypeRecords;
}
/**
* Gets the {@link List} of {@link MetadataSourceRecord}s
*
* @return The {@link List} of {@link MetadataSourceRecord}s
* {@return the {@link List} of {@link MetadataSourceRecord}s}
*/
public List<MetadataSourceRecord> getMetadataSourceRecords() {
return metadataSourceRecords;
@@ -121,11 +112,10 @@ public final class CaptureDescriptor extends SwiftTypeMetadataStructure {
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(getStructureName(), 0);
StructureDataType struct = new StructureDataType(CATEGORY_PATH, getStructureName(), 0);
struct.add(DWORD, "NumCaptureTypes", "");
struct.add(DWORD, "NumMetadataSources", "");
struct.add(DWORD, "NumBindings", "");
struct.setCategoryPath(new CategoryPath(DATA_TYPE_CATEGORY));
return struct;
}

View File

@@ -20,11 +20,12 @@ import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.swift.SwiftTypeMetadataStructure;
import ghidra.app.util.bin.format.swift.SwiftUtils;
import ghidra.program.model.data.*;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.StructureDataType;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift CaptureTypeRecord structure
* Represents a Swift {@code CaptureTypeRecord} structure
*
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/RemoteInspection/Records.h">swift/RemoteInspection/Records.h</a>
*/
@@ -50,9 +51,7 @@ public final class CaptureTypeRecord extends SwiftTypeMetadataStructure {
}
/**
* Gets the mangled type name
*
* @return The mangled type name
* {@return the mangled type name}
*/
public String getMangledTypeName() {
return mangledTypeName;
@@ -70,9 +69,8 @@ public final class CaptureTypeRecord extends SwiftTypeMetadataStructure {
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(getStructureName(), 0);
StructureDataType struct = new StructureDataType(CATEGORY_PATH, getStructureName(), 0);
struct.add(SwiftUtils.PTR_STRING, "MangledTypeName", "");
struct.setCategoryPath(new CategoryPath(DATA_TYPE_CATEGORY));
return struct;
}

View File

@@ -0,0 +1,153 @@
/* ###
* 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.SwiftTypeMetadataStructure;
import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift {@code ConformanceFlags} structure
*
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/ABI/MetadataValues.h">swift/ABI/MetadataValues.h</a>
*/
public class ConformanceFlags extends SwiftTypeMetadataStructure {
/**
* The size (in bytes) of a {@link ConformanceFlags} structure
*/
public static final int SIZE = 4;
private int flags;
/**
* Create a new {@link ConformanceFlags}
*
* @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 ConformanceFlags(BinaryReader reader) throws IOException {
super(reader.getPointerIndex());
flags = reader.readNextInt();
}
/**
* {@return the flags}
*/
public int getFlags() {
return flags;
}
/**
* {@return the {@link TypeReferenceKind}}
*/
public TypeReferenceKind getKind() {
return TypeReferenceKind.valueOf((flags >> 3) & 0x3);
}
/**
* {@return whether or not it is retroactive}
*/
public boolean isRetroactive() {
return ((flags >> 6) & 0x1) != 0;
}
/**
* {@return whether or not it is synthesized non-unique}
*/
public boolean isSynthesizedNonUnique() {
return ((flags >> 7) & 0x1) != 0;
}
/**
* {@return the number of conditional requirements}
*/
public int getNumConditionalRequirements() {
return (flags >> 8) & 0x8;
}
/**
* {@return whether or not it has resilient witnesses}
*/
public boolean hasResilientWitnesses() {
return ((flags >> 16) & 0x1) != 0;
}
/**
* {@return whether or not it a generic witness table}
*/
public boolean hasGenericWitnessTable() {
return ((flags >> 17) & 0x1) != 0;
}
/**
* {@return whether or not it is conformance of protocol}
*/
public boolean isConformanceOfProtocol() {
return ((flags >> 18) & 0x1) != 0;
}
/**
* {@return whether or not it has global actor isolation}
*/
public boolean hasGlobalActorIsolation() {
return ((flags >> 19) & 0x1) != 0;
}
/**
* {@return the number of conditional pack descriptors}
*/
public int getNumConditionalPackDescriptor() {
return (flags >> 24) & 0x8;
}
@Override
public String getStructureName() {
return ConformanceFlags.class.getSimpleName();
}
@Override
public String getDescription() {
return "conformance flags";
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(CATEGORY_PATH, getStructureName(), SIZE);
struct.setPackingEnabled(true);
try {
struct.addBitField(DWORD, 3, "UnusedLowBits", "historical conformance kind");
struct.addBitField(getKind().toDataType(), 3, "TypeMetadataKind",
"8 type reference kinds");
struct.addBitField(BOOL, 1, "IsRetroactive", null);
struct.addBitField(BOOL, 1, "IsSynthesizedNonUnique", null);
struct.addBitField(DWORD, 8, "NumConditionalRequirements", null);
struct.addBitField(BOOL, 1, "HasResilientWitnesses", null);
struct.addBitField(BOOL, 1, "HasGenericWitnessTable", null);
struct.addBitField(BOOL, 1, "IsConformanceOfProtocol", null);
struct.addBitField(BOOL, 1, "HasGlobalActorIsolation", null);
struct.addBitField(DWORD, 4, "reserved", null);
struct.addBitField(DWORD, 8, "NumConditionalPackDescriptor", null);
}
catch (InvalidDataTypeException e) {
throw new IOException(e);
}
return struct;
}
}

View File

@@ -0,0 +1,231 @@
/* ###
* 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.SwiftTypeMetadataStructure;
import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift {@code ContextDescriptorFlags} structure
*
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/ABI/MetadataValues.h">swift/ABI/MetadataValues.h</a>
*/
public class ContextDescriptorFlags extends SwiftTypeMetadataStructure {
/**
* The size (in bytes) of a {@link ContextDescriptorFlags} structure
*/
public static final int SIZE = 4;
private int flags;
/**
* Create a new {@link ContextDescriptorFlags}
*
* @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 ContextDescriptorFlags(BinaryReader reader) throws IOException {
super(reader.getPointerIndex());
flags = reader.readNextInt();
}
/**
* {@return the flags}
*/
public int getFlags() {
return flags;
}
/**
* {@return the {@link ContextDescriptorKind}}
*/
public ContextDescriptorKind getKind() {
return ContextDescriptorKind.valueOf(flags & 0x1f);
}
/**
* {@return whether or not the context has information about invertable protocols, which will
* show up as a trailing field in the context descriptor}
*/
public boolean hasInvertableProtocols() {
return (flags & 0x20) != 0;
}
/**
* {@return whether this is a unique record describing the referenced context}
*/
public boolean isUnique() {
return (flags & 0x40) != 0;
}
/**
* {@return whether the context being described is generic}
*/
public boolean isGeneric() {
return (flags & 0x80) != 0;
}
/**
* {@return whether there's something unusual about how the metadata is initialized}
*/
public MetadataInitializationKind getMetadataInitialization() {
return MetadataInitializationKind.valueOf((flags >> 16) & 0x3);
}
/**
* {@return whether or not the type has extended import information}
*/
public boolean hasImportInfo() {
return ((flags >> 18) & 0x1) != 0;
}
/**
* {@return whether or not the generic type descriptor has a pointer to a list of canonical
* prespecializations, or the non-generic type descriptor has a pointer to its singleton
* metadata}
*/
public boolean hasCanonicalMetadataPrespecializationsOrSingletonMetadataPonter() {
return ((flags >> 19) & 0x1) != 0;
}
/**
* {@return whether or not the metadata contains a pointer to a layout string}
*/
public boolean hasLayoutString() {
return ((flags >> 20) & 0x1) != 0;
}
/**
* {@return whether or not the class has a default override table}
*/
public boolean hasClassDefaultOverrideTable() {
return ((flags >> 22) & 0x1) != 0;
}
/**
* {@return whether or not the class is an actor}
*/
public boolean isClassActor() {
return ((flags >> 23) & 0x1) != 0;
}
/**
* {@return whether or not the class is a default actor}
*/
public boolean isClassDefaultActor() {
return ((flags >> 24) & 0x1) != 0;
}
/**
* {@return the kind of reference that this class makes to its resilient superclass descriptor.
* A TypeReferenceKind.}
*/
public int getClassResilientSuperclassReferenceKind() {
return (flags >> 25) & 0x7;
}
/**
* {@return whether the immediate class members in this metadata are allocated at negative
* offsets}
*/
public boolean areClassImmediateMembersNegative() {
return ((flags >> 28) & 0x1) != 0;
}
/**
* {@return Whether or not the context descriptor is for a class with resilient ancestry}
*/
public boolean hasClassResilientSuperclass() {
return ((flags >> 29) & 0x1) != 0;
}
/**
* {@return whether or not the context descriptor includes metadata for dynamically installing
* method overrides at metadata instantiation time}
*/
public boolean hasClassOverrideTable() {
return ((flags >> 30) & 0x1) != 0;
}
/**
* {@return whether or not the context descriptor includes metadata for dynamically constructing
* a class's vtables at metadata instantiation time}
*/
public boolean hasClassVTable() {
return ((flags >> 31) & 0x1) != 0;
}
@Override
public String getStructureName() {
return ContextDescriptorFlags.class.getSimpleName();
}
@Override
public String getDescription() {
return "context descriptor flags";
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(CATEGORY_PATH, getStructureName(), SIZE);
struct.setPackingEnabled(true);
try {
struct.addBitField(ContextDescriptorKind.values()[0].toDataType(), 5, "kind",
"Kind of context descriptor");
struct.addBitField(BOOL, 1, "hasInvertableProtocols",
"Whether or not the context has information about invertable protocols, which will show up as a trailing field in the context descriptor.");
struct.addBitField(BOOL, 1, "isUnique",
"Whether this is a unique record describing the referenced context.");
struct.addBitField(BOOL, 1, "isGeneric",
"Whether the context being described is generic.");
struct.addBitField(DWORD, 8, "reserved", null);
struct.addBitField(MetadataInitializationKind.values()[0].toDataType(), 2,
"MetadataInitialization",
"Whether there's something unusual about how the metadata is initialized.");
struct.addBitField(BOOL, 1, "HasImportInfo",
"Set if the type has extended import information.");
struct.addBitField(BOOL, 1,
"HasCanonicalMetadataPrespecializationsOrSingletonMetadataPonter",
"Set if the generic type descriptor has a pointer to a list of canonical prespecializations, or the non-generic type descriptor has a pointer to its singleton metadata.");
struct.addBitField(BOOL, 1, "HasLayoutString",
"Set if the metadata contains a pointer to a layout string.");
struct.addBitField(DWORD, 1, "reserved", null);
struct.addBitField(BOOL, 1, "Class_HasDefaultOverrideTable", null);
struct.addBitField(BOOL, 1, "Class_IsActor", "Set if the class is an actor.");
struct.addBitField(BOOL, 1, "Class_IsDefaultActor",
"Set if the class is a default actor class.");
struct.addBitField(DWORD, 3, "Class_ResilientSuperclassReferenceKind",
"The kind of reference that this class makes to its resilient superclass descriptor. A TypeReferenceKind.");
struct.addBitField(BOOL, 1, "Class_AreImmediateMembersNegative",
"Whether the immediate class members in this metadata are allocated at negative offsets.");
struct.addBitField(BOOL, 1, "Class_HasResilientSuperclass",
"Set if the context descriptor is for a class with resilient ancestry.");
struct.addBitField(BOOL, 1, "Class_HasOverrideTable",
"Set if the context descriptor includes metadata for dynamically installing method overrides at metadata instantiation time.");
struct.addBitField(BOOL, 1, "Class_HasVTable",
"Set if the context descriptor includes metadata for dynamically constructing a class's vtables at metadata instantiation time.");
}
catch (InvalidDataTypeException e) {
throw new IOException(e);
}
return struct;
}
}

View File

@@ -15,80 +15,98 @@
*/
package ghidra.app.util.bin.format.swift.types;
import java.io.IOException;
import java.util.Arrays;
import ghidra.app.util.bin.StructConverter;
import ghidra.app.util.bin.format.swift.SwiftTypeMetadataStructure;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.EnumDataType;
import ghidra.util.exception.DuplicateNameException;
/**
* Swift ContextDescriptorKind values
* Swift {@code ContextDescriptorKind} values
*
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/ABI/MetadataValues.h">swift/ABI/MetadataValues.h</a>
*/
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;
}
//---------------------------------------------------------------------------------------------
public enum ContextDescriptorKind implements StructConverter {
/**
* This context descriptor represents a module
*/
public static final int MODULE = 0;
Module(0),
/**
* This context descriptor represents an extension
*/
public static final int EXTENSION = 1;
Extension(1),
/**
* This context descriptor represents an anonymous possibly-generic context such as a function
* body
*/
public static final int ANONYMOUS = 2;
Anonymous(2),
/**
* This context descriptor represents a protocol context
*/
public static final int PROTOCOL = 3;
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;
OpaqueType(4),
/**
* This context descriptor represents a class
*/
public static final int CLASS = TYPE_FIRST;
Class(16),
/**
* This context descriptor represents a struct
*/
public static final int STRUCT = TYPE_FIRST + 1;
Struct(17),
/**
* This context descriptor represents an enum
*/
public static final int ENUM = TYPE_FIRST + 2;
Enum(18);
private int value;
/**
* Last kind that represents a type of any sort
* Creates a new {@link ContextDescriptorKind}
*
* @param value The kind value
*/
public static final int TYPE_LAST = 31;
private ContextDescriptorKind(int value) {
this.value = value;
}
/**
* {@return the kind value}
*/
public int getValue() {
return value;
}
/**
* {@return the {@link ContextDescriptorKind} with the given kind value, or {@code null} if it
* does not exist}
*
* @param value The kind value to get the value of
*/
public static ContextDescriptorKind valueOf(int value) {
return Arrays.stream(values()).filter(e -> e.getValue() == value).findFirst().orElse(null);
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
EnumDataType dt = new EnumDataType(SwiftTypeMetadataStructure.CATEGORY_PATH,
ContextDescriptorKind.class.getSimpleName(), 1);
for (ContextDescriptorKind kind : values()) {
dt.add(kind.name(), kind.getValue());
}
return dt;
}
}

View File

@@ -4,9 +4,9 @@
* 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.
@@ -47,9 +47,7 @@ public final class EntryPoint extends SwiftTypeMetadataStructure {
}
/**
* Gets the entry point
*
* @return The entry point
* {@return the entry point}
*/
public int getEntryPoint() {
return entryPoint;

View File

@@ -0,0 +1,90 @@
/* ###
* 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.SwiftTypeMetadataStructure;
import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift {@code ExtraClassDescriptorFlags} enum
*
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/ABI/MetadataValues.h">swift/ABI/MetadataValues.h</a>
*/
public class ExtraClassDescriptorFlags extends SwiftTypeMetadataStructure {
/**
* The size (in bytes) of a {@link ExtraClassDescriptorFlags} structure
*/
public static final int SIZE = 4;
private int flags;
/**
* Creates a new {@link ExtraClassDescriptorFlags}
*
* @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 ExtraClassDescriptorFlags(BinaryReader reader) throws IOException {
super(reader.getPointerIndex());
flags = reader.readNextInt();
}
/**
* {@return the flags}
*/
public int getFlags() {
return flags;
}
/**
* {@return whether or not the context descriptor includes a pointer to an Objective-C resilient class stub structure}
* <p>
* Only meaningful for class descriptors when Objective-C interop is enabled.
*/
public boolean hasObjcResilientClassStub() {
return (flags & 0x1) != 0;
}
@Override
public String getStructureName() {
return ExtraClassDescriptorFlags.class.getSimpleName();
}
@Override
public String getDescription() {
return "extra class descriptor flags";
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(CATEGORY_PATH, getStructureName(), SIZE);
struct.setPackingEnabled(true);
try {
struct.addBitField(BOOL, 1, "HasObjCResilientClassStub",
"Set if the context descriptor includes a pointer to an Objective-C resilient class stub structure. Only meaningful for class descriptors when Objective-C interop is enabled.");
struct.addBitField(DWORD, 31, "reserved", null);
}
catch (InvalidDataTypeException e) {
throw new IOException(e);
}
return struct;
}
}

View File

@@ -22,11 +22,12 @@ import java.util.List;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.swift.SwiftTypeMetadataStructure;
import ghidra.app.util.bin.format.swift.SwiftUtils;
import ghidra.program.model.data.*;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.StructureDataType;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift FieldDescriptor structure
* Represents a Swift {@code FieldDescriptor} structure
*
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/RemoteInspection/Records.h">swift/RemoteInspection/Records.h</a>
*/
@@ -65,54 +66,42 @@ public final class FieldDescriptor extends SwiftTypeMetadataStructure {
}
/**
* Gets the mangled type name
*
* @return The mangled type name
* {@return the mangled type name}
*/
public String getMangledTypeName() {
return mangledTypeName;
}
/**
* Gets the superclass
*
* @return The superclass
* {@return the superclass}
*/
public int getSuperclass() {
return superclass;
}
/**
* Gets the kind
*
* @return The kind
* {@return the kind}
*/
public int getKind() {
return kind;
}
/**
* Gets the field record size
*
* @return The field record size
* {@return the field record size}
*/
public int getFieldRecordSize() {
return fieldRecordSize;
}
/**
* Gets the number of fields
*
* @return 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
* {@return the {@link List} of {@link FieldRecord}s}
*/
public List<FieldRecord> getFieldRecords() {
return fieldRecords;
@@ -130,13 +119,12 @@ public final class FieldDescriptor extends SwiftTypeMetadataStructure {
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(getStructureName(), 0);
StructureDataType struct = new StructureDataType(CATEGORY_PATH, 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;
}

View File

@@ -20,11 +20,12 @@ import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.swift.SwiftTypeMetadataStructure;
import ghidra.app.util.bin.format.swift.SwiftUtils;
import ghidra.program.model.data.*;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.StructureDataType;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift FieldRecord structure
* Represents a Swift {@code FieldRecord} structure
*
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/RemoteInspection/Records.h">swift/RemoteInspection/Records.h</a>
*/
@@ -53,27 +54,21 @@ public final class FieldRecord extends SwiftTypeMetadataStructure {
}
/**
* Gets the flags
*
* @return The flags
* {@return the flags}
*/
public int getFlags() {
return flags;
}
/**
* Gets the mangled type name
*
* @return The mangled type name
* {@return the mangled type name}
*/
public String getMangledTypeName() {
return mangledTypeName;
}
/**
* Gets the field name
*
* @return The field name
* {@return the field name}
*/
public String getFieldName() {
return fieldName;
@@ -91,11 +86,10 @@ public final class FieldRecord extends SwiftTypeMetadataStructure {
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(getStructureName(), 0);
StructureDataType struct = new StructureDataType(CATEGORY_PATH, 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;
}

View File

@@ -0,0 +1,110 @@
/* ###
* 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.SwiftTypeMetadataStructure;
import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift {@code GenericRequirementFlags} structure
*
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/ABI/MetadataValues.h">swift/ABI/MetadataValues.h</a>
*/
public class GenericContextDescriptorFlags extends SwiftTypeMetadataStructure {
/**
* The size (in bytes) of a {@link GenericContextDescriptorFlags} structure
*/
public static final int SIZE = 2;
private short flags;
/**
* Create a new {@link GenericContextDescriptorFlags}
*
* @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 GenericContextDescriptorFlags(BinaryReader reader) throws IOException {
super(reader.getPointerIndex());
flags = reader.readNextShort();
}
/**
* {@return the flags}
*/
public short getFlags() {
return flags;
}
/**
* {@return whether or not the generic context has at least one type parameter pack, in which
* case the generic context will have a trailing GenericPackShapeHeader}
*/
public boolean hasTypePacks() {
return (flags & 0x1) != 0;
}
/**
* {@return whether or not the generic context has any conditional conformances to inverted
* protocols, in which case the generic context will have a trailing InvertibleProtocolSet and
* conditional requirements}
*/
public boolean hasConditionalInvertedProtocols() {
return (flags & 0x2) != 0;
}
/**
* {@return whether or not the generic context has at least one value parameter, in which case
* the generic context will have a trailing GenericValueHeader}
*/
public boolean hasValues() {
return (flags & 0x4) != 0;
}
@Override
public String getStructureName() {
return GenericContextDescriptorFlags.class.getSimpleName();
}
@Override
public String getDescription() {
return "generic context descriptor flags";
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(CATEGORY_PATH, getStructureName(), SIZE);
struct.setPackingEnabled(true);
try {
struct.addBitField(BOOL, 1, "TypePacks",
"Has at least one type parameter pack and a trailing GenericPackShapeHeader.");
struct.addBitField(BOOL, 1, "ConditionalInvertedProtocols",
"Has any conditional conformances to inverted protocols and a trailing InvertibleProtocolSet and conditional requirements.");
struct.addBitField(BOOL, 1, "Values",
"Has at least one value parameter, and a trailing GenericValueHeader.");
struct.addBitField(WORD, 13, "reserved", null);
}
catch (InvalidDataTypeException e) {
throw new IOException(e);
}
return struct;
}
}

View File

@@ -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.SwiftTypeMetadataStructure;
import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift {@code GenericParamDescriptor} structure
*
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/ABI/MetadataValues.h">swift/ABI/MetadataValues.h</a>
*/
public class GenericParamDescriptor extends SwiftTypeMetadataStructure {
/**
* The size (in bytes) of a {@link GenericParamDescriptor} structure
*/
public static final int SIZE = 1;
private int value;
/**
* Create a new {@link GenericParamDescriptor}
*
* @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 GenericParamDescriptor(BinaryReader reader) throws IOException {
super(reader.getPointerIndex());
value = reader.readNextUnsignedByte();
}
/**
* {@return the value}
*/
public int getValue() {
return value;
}
/**
* {@return the {@link GenericParamKind}}
*/
public GenericParamKind getKind() {
return GenericParamKind.valueOf(value & 0x3f);
}
/**
* {@return whether or not the subject type of the requirement has a key argument}
*/
public boolean hasKeyArgument() {
return (value & 0x80) != 0;
}
@Override
public String getStructureName() {
return GenericParamDescriptor.class.getSimpleName();
}
@Override
public String getDescription() {
return "generic param descriptor";
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(CATEGORY_PATH, getStructureName(), SIZE);
struct.setPackingEnabled(true);
try {
struct.addBitField(GenericParamKind.values()[0].toDataType(), 7, "kind", null);
struct.addBitField(BOOL, 1, "HasKeyArgument", null);
}
catch (InvalidDataTypeException e) {
throw new IOException(e);
}
return struct;
}
}

View File

@@ -0,0 +1,75 @@
/* ###
* 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.Arrays;
import ghidra.app.util.bin.StructConverter;
import ghidra.app.util.bin.format.swift.SwiftTypeMetadataStructure;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.EnumDataType;
import ghidra.util.exception.DuplicateNameException;
/**
* Swift {@code GenericParamKind} values
*
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/ABI/MetadataValues.h">swift/ABI/MetadataValues.h</a>
*/
public enum GenericParamKind implements StructConverter {
Type(0),
TypePack(1),
Value(2);
private int value;
/**
* Creates a new {@link GenericRequirementKind}
*
* @param value The kind value
*/
private GenericParamKind(int value) {
this.value = value;
}
/**
* {@return the kind value}
*/
public int getValue() {
return value;
}
/**
* {@return the {@link GenericParamKind} with the given kind value, or {@code null} if it
* does not exist}
*
* @param value The kind value to get the value of
*/
public static GenericParamKind valueOf(int value) {
return Arrays.stream(values()).filter(e -> e.getValue() == value).findFirst().orElse(null);
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
EnumDataType dt = new EnumDataType(SwiftTypeMetadataStructure.CATEGORY_PATH,
GenericParamKind.class.getSimpleName(), 1);
for (GenericParamKind kind : values()) {
dt.add(kind.name(), kind.getValue());
}
return dt;
}
}

View File

@@ -0,0 +1,115 @@
/* ###
* 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.SwiftTypeMetadataStructure;
import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift {@code GenericRequirementFlags} structure
*
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/ABI/MetadataValues.h">swift/ABI/MetadataValues.h</a>
*/
public class GenericRequirementFlags extends SwiftTypeMetadataStructure {
/**
* The size (in bytes) of a {@link GenericRequirementFlags} structure
*/
public static final int SIZE = 4;
private int flags;
/**
* Create a new {@link GenericRequirementFlags}
*
* @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 GenericRequirementFlags(BinaryReader reader) throws IOException {
super(reader.getPointerIndex());
flags = reader.readNextInt();
}
/**
* {@return the flags}
*/
public int getFlags() {
return flags;
}
/**
* {@return the {@link GenericRequirementKind}}
*/
public GenericRequirementKind getKind() {
return GenericRequirementKind.valueOf(flags & 0x1f);
}
/**
* {@return whether or not the subject type of the requirement is a pack}
*/
public boolean isPackRequirement() {
return (flags & 0x20) != 0;
}
/**
* {@return whether or not the subject type of the requirement has a key argument}
*/
public boolean hasKeyArgument() {
return (flags & 0x80) != 0;
}
/**
* {@return whether or not the subject type of the requirement is a value}
*/
public boolean isValueRequirement() {
return (flags & 0x100) != 0;
}
@Override
public String getStructureName() {
return GenericRequirementFlags.class.getSimpleName();
}
@Override
public String getDescription() {
return "generic requirement flags";
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(CATEGORY_PATH, getStructureName(), SIZE);
struct.setPackingEnabled(true);
try {
struct.addBitField(GenericRequirementKind.values()[0].toDataType(), 5, "kind", null);
struct.addBitField(BOOL, 1, "isPackRequirement",
"If true, the subject type of the requirement is a pack.");
struct.addBitField(BOOL, 1, "legacy",
"Don't set 0x40 for compatibility with pre-Swift 5.8 runtimes");
struct.addBitField(BOOL, 1, "hasKeyArgument", null);
struct.addBitField(BOOL, 1, "isValueRequirement",
"If true, the subject type of the requirement is a value.");
struct.addBitField(DWORD, 23, "reserved", null);
}
catch (InvalidDataTypeException e) {
throw new IOException(e);
}
return struct;
}
}

View File

@@ -0,0 +1,79 @@
/* ###
* 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.Arrays;
import ghidra.app.util.bin.StructConverter;
import ghidra.app.util.bin.format.swift.SwiftTypeMetadataStructure;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.EnumDataType;
import ghidra.util.exception.DuplicateNameException;
/**
* Swift {@code GenericRequirementKind} values
*
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/ABI/MetadataValues.h">swift/ABI/MetadataValues.h</a>
*/
public enum GenericRequirementKind implements StructConverter {
Protocol(0),
SameType(1),
BaseClass(2),
SameConformance(3),
SameShape(4),
IntertedProtocol(5),
Layout(0x1f);
private int value;
/**
* Creates a new {@link GenericRequirementKind}
*
* @param value The kind value
*/
private GenericRequirementKind(int value) {
this.value = value;
}
/**
* {@return the kind value}
*/
public int getValue() {
return value;
}
/**
* {@return the {@link GenericRequirementKind} with the given kind value, or {@code null} if it
* does not exist}
*
* @param value The kind value to get the value of
*/
public static GenericRequirementKind valueOf(int value) {
return Arrays.stream(values()).filter(e -> e.getValue() == value).findFirst().orElse(null);
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
EnumDataType dt = new EnumDataType(SwiftTypeMetadataStructure.CATEGORY_PATH,
GenericRequirementKind.class.getSimpleName(), 1);
for (GenericRequirementKind kind : values()) {
dt.add(kind.name(), kind.getValue());
}
return dt;
}
}

View File

@@ -0,0 +1,73 @@
/* ###
* 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.Arrays;
import ghidra.app.util.bin.StructConverter;
import ghidra.app.util.bin.format.swift.SwiftTypeMetadataStructure;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.EnumDataType;
import ghidra.util.exception.DuplicateNameException;
/**
* Swift {@code GenericRequirementLayoutKind} values
*
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/ABI/MetadataValues.h">swift/ABI/MetadataValues.h</a>
*/
public enum GenericRequirementLayoutKind implements StructConverter {
Class(0);
private int value;
/**
* Creates a new {@link GenericRequirementLayoutKind}
*
* @param value The kind value
*/
private GenericRequirementLayoutKind(int value) {
this.value = value;
}
/**
* {@return the kind value}
*/
public int getValue() {
return value;
}
/**
* {@return the {@link GenericRequirementLayoutKind} with the given kind value, or {@code null}
* if it does not exist}
*
* @param value The kind value to get the value of
*/
public static GenericRequirementLayoutKind valueOf(int value) {
return Arrays.stream(values()).filter(e -> e.getValue() == value).findFirst().orElse(null);
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
EnumDataType dt = new EnumDataType(SwiftTypeMetadataStructure.CATEGORY_PATH,
GenericRequirementLayoutKind.class.getSimpleName(), 1);
for (GenericRequirementLayoutKind kind : values()) {
dt.add(kind.name(), kind.getValue());
}
return dt;
}
}

View File

@@ -0,0 +1,75 @@
/* ###
* 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.Arrays;
import ghidra.app.util.bin.StructConverter;
import ghidra.app.util.bin.format.swift.SwiftTypeMetadataStructure;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.EnumDataType;
import ghidra.util.exception.DuplicateNameException;
/**
* Swift {@code MetadataInitializationKind} values
*
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/ABI/MetadataValues.h">swift/ABI/MetadataValues.h</a>
*/
public enum MetadataInitializationKind implements StructConverter {
NoMetadataInitialization(0),
SingletonMetadataInitialization(1),
ForeignMetadataInitialization(2);
private int value;
/**
* Creates a new {@link MetadataInitializationKind}
*
* @param value The kind value
*/
private MetadataInitializationKind(int value) {
this.value = value;
}
/**
* {@return the kind value}
*/
public int getValue() {
return value;
}
/**
* {@return the {@link MetadataInitializationKind} with the given kind value, or {@code null} if it
* does not exist}
*
* @param value The kind value to get the value of
*/
public static MetadataInitializationKind valueOf(int value) {
return Arrays.stream(values()).filter(e -> e.getValue() == value).findFirst().orElse(null);
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
EnumDataType dt = new EnumDataType(SwiftTypeMetadataStructure.CATEGORY_PATH,
MetadataInitializationKind.class.getSimpleName(), 1);
for (MetadataInitializationKind kind : values()) {
dt.add(kind.name(), kind.getValue());
}
return dt;
}
}

View File

@@ -20,11 +20,12 @@ import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.swift.SwiftTypeMetadataStructure;
import ghidra.app.util.bin.format.swift.SwiftUtils;
import ghidra.program.model.data.*;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.StructureDataType;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift MetadataSourceRecord structure
* Represents a Swift {@code MetadataSourceRecord} structure
*
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/RemoteInspection/Records.h">swift/RemoteInspection/Records.h</a>
*/
@@ -51,18 +52,14 @@ public final class MetadataSourceRecord extends SwiftTypeMetadataStructure {
}
/**
* Gets the mangled type name
*
* @return The mangled type name
* {@return the mangled type name}
*/
public String getMangledTypeName() {
return mangledTypeName;
}
/**
* Gets the mangled metadata source
*
* @return The mangled metadata source
* {@return the mangled metadata source}
*/
public String getMangledMetadataSource() {
return mangledMetadataSource;
@@ -80,10 +77,9 @@ public final class MetadataSourceRecord extends SwiftTypeMetadataStructure {
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(getStructureName(), 0);
StructureDataType struct = new StructureDataType(CATEGORY_PATH, getStructureName(), 0);
struct.add(SwiftUtils.PTR_STRING, "MangledTypeName", "");
struct.add(SwiftUtils.PTR_STRING, "MangledMetadataSource", "");
struct.setCategoryPath(new CategoryPath(DATA_TYPE_CATEGORY));
return struct;
}

View File

@@ -0,0 +1,119 @@
/* ###
* 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.SwiftTypeMetadataStructure;
import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift {@code MethodDescriptorFlags} structure
*
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/ABI/MetadataValues.h">swift/ABI/MetadataValues.h</a>
*/
public class MethodDescriptorFlags extends SwiftTypeMetadataStructure {
/**
* The size (in bytes) of a {@link MethodDescriptorFlags} structure
*/
public static final int SIZE = 4;
private int flags;
/**
* Create a new {@link MethodDescriptorFlags}
*
* @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 MethodDescriptorFlags(BinaryReader reader) throws IOException {
super(reader.getPointerIndex());
flags = reader.readNextInt();
}
/**
* {@return the flags}
*/
public int getFlags() {
return flags;
}
/**
* {@return the {@link MethodDescriptorKind}}
*/
public MethodDescriptorKind getKind() {
return MethodDescriptorKind.valueOf(flags & 0x0f);
}
/**
* {@return whether or not the method is an instance method}
*/
public boolean isInstance() {
return (flags & 0x10) != 0;
}
/**
* {@return whether or not the method is dynamic}
*/
public boolean isDynamic() {
return (flags & 0x20) != 0;
}
/**
* {@return whether or not the method is async}
*/
public boolean isAnsyc() {
return (flags & 0x40) != 0;
}
/**
* {@return the extra descriminator}
*/
public int getExtraDescriminator() {
return (flags >> 16) & 0xffff;
}
@Override
public String getStructureName() {
return MethodDescriptorFlags.class.getSimpleName();
}
@Override
public String getDescription() {
return "method descriptor flags";
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(CATEGORY_PATH, getStructureName(), SIZE);
struct.setPackingEnabled(true);
try {
struct.addBitField(MethodDescriptorKind.values()[0].toDataType(), 4, "kind", null);
struct.addBitField(BOOL, 1, "IsInstance", null);
struct.addBitField(BOOL, 1, "IsDynamic", null);
struct.addBitField(BOOL, 1, "IsAsync", null);
struct.addBitField(DWORD, 9, "reserved", null);
struct.addBitField(DWORD, 16, "ExtraDescriminator", null);
}
catch (InvalidDataTypeException e) {
throw new IOException(e);
}
return struct;
}
}

View File

@@ -0,0 +1,78 @@
/* ###
* 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.Arrays;
import ghidra.app.util.bin.StructConverter;
import ghidra.app.util.bin.format.swift.SwiftTypeMetadataStructure;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.EnumDataType;
import ghidra.util.exception.DuplicateNameException;
/**
* Swift {@code MethodDescriptorFlags.Kind} values
*
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/ABI/MetadataValues.h">swift/ABI/MetadataValues.h</a>
*/
public enum MethodDescriptorKind implements StructConverter {
Method(0),
Init(1),
Getter(2),
Setter(3),
ModifyCoroutine(4),
ReadCoroutine(5);
private int value;
/**
* Creates a new {@link MethodDescriptorKind}
*
* @param value The kind value
*/
private MethodDescriptorKind(int value) {
this.value = value;
}
/**
* {@return the kind value}
*/
public int getValue() {
return value;
}
/**
* {@return the {@link MethodDescriptorKind} with the given kind value, or {@code null} if it
* does not exist}
*
* @param value The kind value to get the value of
*/
public static MethodDescriptorKind valueOf(int value) {
return Arrays.stream(values()).filter(e -> e.getValue() == value).findFirst().orElse(null);
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
EnumDataType dt = new EnumDataType(SwiftTypeMetadataStructure.CATEGORY_PATH,
MethodDescriptorKind.class.getSimpleName(), 1);
for (MethodDescriptorKind kind : values()) {
dt.add(kind.name(), kind.getValue());
}
return dt;
}
}

View File

@@ -24,7 +24,7 @@ import ghidra.program.model.data.DataType;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift MultiPayloadEnumDescriptor structure
* Represents a Swift {@code MultiPayloadEnumDescriptor} structure
*
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/RemoteInspection/Records.h">swift/RemoteInspection/Records.h</a>
*/
@@ -32,7 +32,7 @@ public final class MultiPayloadEnumDescriptor extends SwiftTypeMetadataStructure
/**
* The size (in bytes) of a {@link MultiPayloadEnumDescriptor} structure. This size does not
* take into account the size of the <code>contents</code> array.
* take into account the size of the {@code contents} array.
*
* @see #getContentsSize()
*/
@@ -56,27 +56,21 @@ public final class MultiPayloadEnumDescriptor extends SwiftTypeMetadataStructure
}
/**
* Gets the type name
*
* @return The type name
* {@return the type name}
*/
public String getTypeName() {
return typeName;
}
/**
* Gets the contents
*
* @return 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
* {@return The size of the contents in bytes}
*/
public long getContentsSize() {
return contents.length * Integer.BYTES;

View File

@@ -0,0 +1,111 @@
/* ###
* 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.SwiftTypeMetadataStructure;
import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift {@code ProtocolRequirementFlags} structure
*
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/ABI/MetadataValues.h">swift/ABI/MetadataValues.h</a>
*/
public class ProtocolRequirementFlags extends SwiftTypeMetadataStructure {
/**
* The size (in bytes) of a {@link ProtocolRequirementFlags} structure
*/
public static final int SIZE = 4;
private int flags;
/**
* Create a new {@link ProtocolRequirementFlags}
*
* @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 ProtocolRequirementFlags(BinaryReader reader) throws IOException {
super(reader.getPointerIndex());
flags = reader.readNextInt();
}
/**
* {@return the flags}
*/
public int getFlags() {
return flags;
}
/**
* {@return the {@link ProtocolRequirementKind}}
*/
public ProtocolRequirementKind getKind() {
return ProtocolRequirementKind.valueOf(flags & 0x0f);
}
/**
* {@return whether or not the protocol requirement is instance}
*/
public boolean isInstance() {
return (flags & 0x10) != 0;
}
/**
* {@return whether or not the protocol requirement is async}
*/
public boolean isAnsyc() {
return (flags & 0x20) != 0;
}
/**
* {@return the extra descriminator}
*/
public int getExtraDescriminator() {
return (flags >> 16) & 0xffff;
}
@Override
public String getStructureName() {
return ProtocolRequirementFlags.class.getSimpleName();
}
@Override
public String getDescription() {
return "protocol requirements flags";
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(CATEGORY_PATH, getStructureName(), SIZE);
struct.setPackingEnabled(true);
try {
struct.addBitField(getKind().toDataType(), 4, "kind", null);
struct.addBitField(BOOL, 1, "IsInstance", null);
struct.addBitField(BOOL, 1, "IsAsync", null);
struct.addBitField(DWORD, 10, "reserved", null);
struct.addBitField(DWORD, 16, "ExtraDescriminator", null);
}
catch (InvalidDataTypeException e) {
throw new IOException(e);
}
return struct;
}
}

View File

@@ -0,0 +1,81 @@
/* ###
* 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.Arrays;
import ghidra.app.util.bin.StructConverter;
import ghidra.app.util.bin.format.swift.SwiftTypeMetadataStructure;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.EnumDataType;
import ghidra.util.exception.DuplicateNameException;
/**
* Swift {@code ProtocolRequirementFlags.Kind} values
*
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/ABI/MetadataValues.h">swift/ABI/MetadataValues.h</a>
*/
public enum ProtocolRequirementKind implements StructConverter {
BaseProtocol(0),
Method(1),
Init(2),
Getter(3),
Setter(4),
ReadCoroutine(5),
ModifyCoroutine(6),
AssociatedTypeAccessFunction(7),
AssociatedConformanceAccessFunction(8);
private int value;
/**
* Creates a new {@link ProtocolRequirementKind}
*
* @param value The kind value
*/
private ProtocolRequirementKind(int value) {
this.value = value;
}
/**
* {@return the kind value}
*/
public int getValue() {
return value;
}
/**
* {@return the {@link ProtocolRequirementKind} with the given kind value, or {@code null} if it
* does not exist}
*
* @param value The kind value to get the value of
*/
public static ProtocolRequirementKind valueOf(int value) {
return Arrays.stream(values()).filter(e -> e.getValue() == value).findFirst().orElse(null);
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
EnumDataType dt = new EnumDataType(SwiftTypeMetadataStructure.CATEGORY_PATH,
ProtocolRequirementKind.class.getSimpleName(), 1);
for (ProtocolRequirementKind kind : values()) {
dt.add(kind.name(), kind.getValue());
}
return dt;
}
}

View File

@@ -16,14 +16,17 @@
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.SwiftTypeMetadataStructure;
import ghidra.app.util.bin.format.swift.SwiftUtils;
import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift TargetClassDescriptor structure
* Represents a Swift {@code TargetClassDescriptor} structure
*
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/ABI/Metadata.h">swift/ABI/Metadata.h</a>
*/
@@ -31,11 +34,24 @@ public final class TargetClassDescriptor extends TargetTypeContextDescriptor {
private int superclassType;
private int metadataNegativeSizeInWords;
private int resilientMetadataBounds;
private int metadataPositiveSizeInWords;
private ExtraClassDescriptorFlags extraClassFlags;
private int numImmediateMembers;
private int numFields;
private int fieldOffsetVectorOffset;
// Trailing Objects
private TargetTypeGenericContextDescriptorHeader genericHeader;
private TargetResilientSuperclass resilientSuperclass;
private TargetSingletonMetadataInitialization singleton;
private TargetForeignMetadataInitialization foreign;
private TargetVTableDescriptorHeader vtableHeader;
private List<TargetMethodDescriptor> methodDescriptors = new ArrayList<>();
private TargetOverrideTableHeader overrideHeader;
private List<TargetMethodOverrideDescriptor> methodOverrideDescriptors = new ArrayList<>();
private TargetObjCResilientClassStubInfo objcResilientClassStub;
/**
* Creates a new {@link TargetClassDescriptor}
*
@@ -45,79 +61,231 @@ public final class TargetClassDescriptor extends TargetTypeContextDescriptor {
public TargetClassDescriptor(BinaryReader reader) throws IOException {
super(reader);
superclassType = reader.readNextInt();
metadataNegativeSizeInWords = reader.readNextInt();
metadataPositiveSizeInWords = reader.readNextInt();
resilientMetadataBounds = reader.readNextInt();
metadataNegativeSizeInWords = resilientMetadataBounds; // union
extraClassFlags = new ExtraClassDescriptorFlags(reader);
metadataPositiveSizeInWords = extraClassFlags.getFlags(); // union
numImmediateMembers = reader.readNextInt();
numFields = reader.readNextInt();
fieldOffsetVectorOffset = reader.readNextInt();
if (flags.isGeneric()) {
genericHeader = new TargetTypeGenericContextDescriptorHeader(reader);
}
if (flags.hasClassResilientSuperclass()) {
resilientSuperclass = new TargetResilientSuperclass(reader);
}
switch (flags.getMetadataInitialization()) {
case NoMetadataInitialization:
break;
case SingletonMetadataInitialization:
singleton = new TargetSingletonMetadataInitialization(reader, flags);
break;
case ForeignMetadataInitialization:
foreign = new TargetForeignMetadataInitialization(reader);
break;
}
if (flags.hasClassVTable()) {
vtableHeader = new TargetVTableDescriptorHeader(reader);
for (int i = 0; i < vtableHeader.getVTableSize(); i++) {
methodDescriptors.add(new TargetMethodDescriptor(reader));
}
}
if (flags.hasClassOverrideTable()) {
overrideHeader = new TargetOverrideTableHeader(reader);
for (int i = 0; i < overrideHeader.getNumEntries(); i++) {
methodOverrideDescriptors.add(new TargetMethodOverrideDescriptor(reader));
}
}
if (flags.hasClassResilientSuperclass() &&
extraClassFlags.hasObjcResilientClassStub()) {
objcResilientClassStub = new TargetObjCResilientClassStubInfo(reader);
}
if (flags.isGeneric() &&
flags.hasCanonicalMetadataPrespecializationsOrSingletonMetadataPonter()) {
throw new IOException("Unimplemented TargetCanonicalSpecializedMetadatas detected.");
}
if (flags.hasInvertableProtocols()) {
throw new IOException("Unimplemented InvertibleProtocolSet detected.");
}
if (!flags.isGeneric() &&
flags.hasCanonicalMetadataPrespecializationsOrSingletonMetadataPonter()) {
throw new IOException("Unimplemented TargetSingletonMetadataPointer detected.");
}
if (flags.hasClassDefaultOverrideTable()) {
throw new IOException("Unimplemented TargetMethodDefaultOverride detected.");
}
}
/**
* 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
* {@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
* {@return a reference to a cache holding the metadata's extents if this descriptor has a
* resilient superclass; otherwise, 0}
*/
public int getResilientMetadataBounds() {
return flags.hasClassResilientSuperclass() ? resilientMetadataBounds : 0;
}
/**
* {@return the negative size of metadata objects of this class (in words) if this descriptor
* does not have a resilient superclass}
*/
public int getMetadataNegativeSizeInWords() {
return metadataNegativeSizeInWords;
return !flags.hasClassResilientSuperclass() ? metadataNegativeSizeInWords : 0;
}
/**
* 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.
* {@return flags used to do things like indicate the presence of an Objective-C resilient class
* stub if this descriptor has a resilient superclass; otherwise, {@code null}}
*/
public ExtraClassDescriptorFlags getExtraClassDescriptorFlags() {
return flags.hasClassResilientSuperclass() ? extraClassFlags : null;
}
/**
* {@return the positive size of metadata objects of this class (in words) if this descriptor
* does not have a resilient superclass}
*/
public int getMetadataPositiveSizeInWords() {
return metadataPositiveSizeInWords;
return !flags.hasClassResilientSuperclass() ? metadataPositiveSizeInWords : 0;
}
/**
* 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
* {@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.
* {@return the number of stored properties in the class, not including its superclasses}
* <p>
* 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 class's stored properties in its
* metadata, in words. 0 means there is no field offset vector.
*
* @return THe offset of the field offset vector for this class's stored properties in its
* metadata, in words. 0 means there is no field offset vector.
* {@return the offset of the field offset vector for this class's stored properties in its
* metadata, in words (0 means there is no field offset vector)}
*/
public int getFieldOffsetVectorOffset() {
return fieldOffsetVectorOffset;
}
/**
* {@return the {@link TargetTypeGenericContextDescriptorHeader}, or {@code null} if it doesn't
* exist}
*/
public TargetTypeGenericContextDescriptorHeader getGenericHeader() {
return genericHeader;
}
/**
* {@return the {@link TargetResilientSuperclass}, or {@code null} if it doesn't exist}
*/
public TargetResilientSuperclass getResilientSuperclass() {
return resilientSuperclass;
}
/**
* {@return the {@link TargetSingletonMetadataInitialization}, or {@code null} if it doesn't
* exist}
*/
public TargetSingletonMetadataInitialization getTargetSingletonMetadataInitialization() {
return singleton;
}
/**
* {@return the {@link TargetForeignMetadataInitialization}, or {@code null} if it doesn't
* exist}
*/
public TargetForeignMetadataInitialization getTargetForeignMetadataInitialization() {
return foreign;
}
/**
* {@return the {@link TargetVTableDescriptorHeader}, or {@code null} if it doesn't exist}
*/
public TargetVTableDescriptorHeader getVTableDescriptorHeader() {
return vtableHeader;
}
/**
* {@return the {@link List} of method descriptors}
*/
public List<TargetMethodDescriptor> getMethodDescriptors() {
return methodDescriptors;
}
/**
* {@return the {@link TargetOverrideTableHeader}, or {@code null} if it doesn't exist}
*/
public TargetOverrideTableHeader getTargetOverrideTableHeader() {
return overrideHeader;
}
/**
* {@return the {@link List} of method override descriptors}
*/
public List<TargetMethodOverrideDescriptor> getMethodOverrideDescriptors() {
return methodOverrideDescriptors;
}
/**
* {@return the {@link TargetObjCResilientClassStubInfo}, or {@code null} if it doesn't exist}
*/
public TargetObjCResilientClassStubInfo getObjcResilientClassStub() {
return objcResilientClassStub;
}
@Override
public List<SwiftTypeMetadataStructure> getTrailingObjects() {
List<SwiftTypeMetadataStructure> ret = new ArrayList<>();
if (genericHeader != null) {
ret.add(genericHeader);
ret.addAll(genericHeader.getTrailingObjects());
}
if (resilientSuperclass != null) {
ret.add(resilientSuperclass);
}
if (singleton != null) {
ret.add(singleton);
}
if (foreign != null) {
ret.add(foreign);
}
if (vtableHeader != null) {
ret.add(vtableHeader);
ret.addAll(methodDescriptors);
}
if (overrideHeader != null) {
ret.add(overrideHeader);
ret.addAll(methodOverrideDescriptors);
}
if (objcResilientClassStub != null) {
ret.add(objcResilientClassStub);
}
return ret;
}
@Override
public String getStructureName() {
return TargetClassDescriptor.class.getSimpleName();
@@ -130,22 +298,32 @@ public final class TargetClassDescriptor extends TargetTypeContextDescriptor {
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(getStructureName(), 0);
UnionDataType union1 = new UnionDataType(CATEGORY_PATH,
"Union_MetadataNegativeSizeInWords_ResilientMetadataBounds");
union1.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)");
union1.add(SwiftUtils.PTR_RELATIVE, "ResilientMetadataBounds",
"If this descriptor has a resilient superclass, this is a reference to a cache holding the metadata's extends.");
UnionDataType union2 =
new UnionDataType(CATEGORY_PATH, "Union_MetadataPositiveSizeInWords/ExtraClassFlags");
union2.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)");
union2.add(extraClassFlags.toDataType(), "ExtraClassFlags",
"Otherwise, these flags are used to do things like indicating the presence of an Objective-C resilient class stub.");
StructureDataType struct = new StructureDataType(CATEGORY_PATH, 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(union1, "MetadataNegativeSizeInWords/ResilientMetadataBounds", null);
struct.add(union2, "MetadataPositiveSizeInWords/ExtraClassFlags", null);
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.add(DWORD, "FieldOffsetVectorOffset",
"The offset of the field offset vector for this class's stored properties in its metadata, in words. 0 means there is no field offset vector.");
struct.setCategoryPath(new CategoryPath(DATA_TYPE_CATEGORY));
return struct;
}
}

View File

@@ -20,11 +20,12 @@ import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.swift.SwiftTypeMetadataStructure;
import ghidra.app.util.bin.format.swift.SwiftUtils;
import ghidra.program.model.data.*;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.StructureDataType;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift TargetContextDescriptor structure
* Represents a Swift {@code TargetContextDescriptor} structure
*
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/ABI/Metadata.h">swift/ABI/Metadata.h</a>
*/
@@ -35,7 +36,7 @@ public class TargetContextDescriptor extends SwiftTypeMetadataStructure {
*/
public static final int SIZE = 8;
private int flags;
protected ContextDescriptorFlags flags;
private int parent;
/**
@@ -46,23 +47,19 @@ public class TargetContextDescriptor extends SwiftTypeMetadataStructure {
*/
public TargetContextDescriptor(BinaryReader reader) throws IOException {
super(reader.getPointerIndex());
flags = reader.readNextInt();
flags = new ContextDescriptorFlags(reader);
parent = reader.readNextInt();
}
/**
* Gets the flags
*
* @return The flags
* {@return the flags}
*/
public int getFlags() {
public ContextDescriptorFlags getFlags() {
return flags;
}
/**
* Gets the parent's relative offset
*
* @return The parent's relative offset
* {@return the parent's relative offset}
*/
public int getParent() {
return parent;
@@ -79,9 +76,7 @@ public class TargetContextDescriptor extends SwiftTypeMetadataStructure {
}
/**
* Gets this class's structure name (will not be affected by subclass's name)
*
* @return This class's structure name
* {@return this class's structure name (will not be affected by subclass's name)}
*/
private final String getMyStructureName() {
return TargetContextDescriptor.class.getSimpleName();
@@ -89,12 +84,11 @@ public class TargetContextDescriptor extends SwiftTypeMetadataStructure {
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(getMyStructureName(), 0);
struct.add(DWORD, "Flags",
StructureDataType struct = new StructureDataType(CATEGORY_PATH, getMyStructureName(), 0);
struct.add(flags.toDataType(), "Flags",
"Flags describing the context, including its kind and format version");
struct.add(SwiftUtils.PTR_RELATIVE, "Parent",
struct.add(SwiftUtils.PTR_RELATIVE_MASKED, "Parent",
"The parent context, or null if this is a top-level context");
struct.setCategoryPath(new CategoryPath(DATA_TYPE_CATEGORY));
return struct;
}

View File

@@ -16,15 +16,17 @@
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.program.model.data.CategoryPath;
import ghidra.app.util.bin.format.swift.SwiftTypeMetadataStructure;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.StructureDataType;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift TargetEnumDescriptor structure
* Represents a Swift {@code TargetEnumDescriptor} structure
*
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/ABI/Metadata.h">swift/ABI/Metadata.h</a>
*/
@@ -33,6 +35,11 @@ public final class TargetEnumDescriptor extends TargetTypeContextDescriptor {
private int numPayloadCasesAndPayloadSizeOffset;
private int numEmptyCases;
// Trailing objects
private TargetTypeGenericContextDescriptorHeader genericHeader;
private TargetSingletonMetadataInitialization singleton;
private TargetForeignMetadataInitialization foreign;
/**
* Creates a new {@link TargetEnumDescriptor}
*
@@ -43,6 +50,35 @@ public final class TargetEnumDescriptor extends TargetTypeContextDescriptor {
super(reader);
numPayloadCasesAndPayloadSizeOffset = reader.readNextInt();
numEmptyCases = reader.readNextInt();
if (flags.isGeneric()) {
genericHeader = new TargetTypeGenericContextDescriptorHeader(reader);
}
switch (flags.getMetadataInitialization()) {
case NoMetadataInitialization:
break;
case SingletonMetadataInitialization:
singleton = new TargetSingletonMetadataInitialization(reader, flags);
break;
case ForeignMetadataInitialization:
foreign = new TargetForeignMetadataInitialization(reader);
break;
}
if (flags.isGeneric() &&
flags.hasCanonicalMetadataPrespecializationsOrSingletonMetadataPonter()) {
throw new IOException("Unimplemented TargetCanonicalSpecializedMetadatas detected.");
}
if (flags.hasInvertableProtocols()) {
throw new IOException("Unimplemented InvertibleProtocolSet detected.");
}
if (!flags.isGeneric() &&
flags.hasCanonicalMetadataPrespecializationsOrSingletonMetadataPonter()) {
throw new IOException("Unimplemented TargetSingletonMetadataPointer detected.");
}
}
/**
@@ -56,14 +92,52 @@ public final class TargetEnumDescriptor extends TargetTypeContextDescriptor {
}
/**
* Gets the number of empty cases in the enum
*
* @return The number of empty cases in the enum
* {@return the number of empty cases in the enum}
*/
public int getNumEmptyCases() {
return numEmptyCases;
}
/**
* {@return the {@link TargetTypeGenericContextDescriptorHeader}, or {@code null} if it doesn't
* exist}
*/
public TargetTypeGenericContextDescriptorHeader getGenericHeader() {
return genericHeader;
}
/**
* {@return the {@link TargetSingletonMetadataInitialization}, or {@code null} if it doesn't
* exist}
*/
public TargetSingletonMetadataInitialization getTargetSingletonMetadataInitialization() {
return singleton;
}
/**
* {@return the {@link TargetForeignMetadataInitialization}, or {@code null} if it doesn't
* exist}
*/
public TargetForeignMetadataInitialization getTargetForeignMetadataInitialization() {
return foreign;
}
@Override
public List<SwiftTypeMetadataStructure> getTrailingObjects() {
List<SwiftTypeMetadataStructure> ret = new ArrayList<>();
if (genericHeader != null) {
ret.add(genericHeader);
ret.addAll(genericHeader.getTrailingObjects());
}
if (singleton != null) {
ret.add(singleton);
}
if (foreign != null) {
ret.add(foreign);
}
return ret;
}
@Override
public String getStructureName() {
return TargetEnumDescriptor.class.getSimpleName();
@@ -76,12 +150,11 @@ public final class TargetEnumDescriptor extends TargetTypeContextDescriptor {
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(getStructureName(), 0);
StructureDataType struct = new StructureDataType(CATEGORY_PATH, 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;
}

View File

@@ -0,0 +1,71 @@
/* ###
* 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.SwiftTypeMetadataStructure;
import ghidra.app.util.bin.format.swift.SwiftUtils;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.StructureDataType;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift {@code TargetForeignMetadataInitialization} structure
*
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/ABI/Metadata.h">swift/ABI/Metadata.h</a>
*/
public class TargetForeignMetadataInitialization extends SwiftTypeMetadataStructure {
private int completionFunction;
/**
* Creates a new {@link TargetForeignMetadataInitialization}
*
* @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 TargetForeignMetadataInitialization(BinaryReader reader) throws IOException {
super(reader.getPointerIndex());
completionFunction = reader.readNextInt();
}
/**
* {@return the completion function (the pattern will always be null)}
*/
public int getCompletionFunction() {
return completionFunction;
}
@Override
public String getStructureName() {
return TargetForeignMetadataInitialization.class.getSimpleName();
}
@Override
public String getDescription() {
return "foreign metadata initialization";
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(CATEGORY_PATH, getStructureName(), 0);
struct.add(SwiftUtils.PTR_RELATIVE, "CompletionFunction",
"The completion function. The pattern will always be null.");
return struct;
}
}

View File

@@ -0,0 +1,144 @@
/* ###
* 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.SwiftTypeMetadataStructure;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.StructureDataType;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift {@code TargetGenericContextDescriptorHeader} structure
*
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/ABI/GenericContext.h">swift/ABI/GenericContext.h</a>
*/
public class TargetGenericContextDescriptorHeader extends SwiftTypeMetadataStructure {
private int numParams;
private int numRequirements;
private int numKeyArguments;
private GenericContextDescriptorFlags flags;
private List<GenericParamDescriptor> params = new ArrayList<>();
private List<TargetGenericRequirementsDescriptor> requirements = new ArrayList<>();
/**
* Creates a new {@link TargetGenericContextDescriptorHeader}
*
* @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 TargetGenericContextDescriptorHeader(BinaryReader reader) throws IOException {
super(reader.getPointerIndex());
numParams = reader.readNextUnsignedShort();
numRequirements = reader.readNextUnsignedShort();
numKeyArguments = reader.readNextUnsignedShort();
flags = new GenericContextDescriptorFlags(reader);
for (int i = 0; i < numParams; i++) {
params.add(new GenericParamDescriptor(reader));
}
// It seems we have to round to the next 4 byte boundary after reading the params???
reader.setPointerIndex((reader.getPointerIndex() + 3) & (~3));
for (int i = 0; i < numRequirements; i++) {
requirements.add(new TargetGenericRequirementsDescriptor(reader));
}
}
/**
* {@return the number of (source-written) generic parameters, and thus the number of
* GenericParamDescriptors associated with this context}
*/
public int getNumParams() {
return numParams;
}
/**
* {@return the number of GenericRequirementDescriptors in this generic signature}
*/
public int getNumRequirements() {
return numRequirements;
}
/**
* {@return the size of the "key" area of the argument layout, in words}
* <p>
* Key arguments include shape classes, generic parameters, and conformance requirements which
* are part of the identity of the context.
*/
public int getNumKeyArguments() {
return numKeyArguments;
}
/**
* {@return the flags}
*/
public GenericContextDescriptorFlags getFlags() {
return flags;
}
/**
* {@return the {@link List} of generic parameter descriptors}
*/
public List<GenericParamDescriptor> getParams() {
return params;
}
/**
* {@return the {@link List} of generic requirements descriptors}
*/
public List<TargetGenericRequirementsDescriptor> getRequirements() {
return requirements;
}
@Override
public List<SwiftTypeMetadataStructure> getTrailingObjects() {
List<SwiftTypeMetadataStructure> ret = new ArrayList<>();
ret.addAll(params);
ret.addAll(requirements);
return ret;
}
@Override
public String getStructureName() {
return TargetGenericContextDescriptorHeader.class.getSimpleName();
}
@Override
public String getDescription() {
return "generic context descriptor header";
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(CATEGORY_PATH, getStructureName(), 0);
struct.add(WORD, "NumParams",
"The number of (source-written) generic parameters, and thus the number of GenericParamDescriptors associated with this context.");
struct.add(WORD, "NumRequirements",
"The number of GenericRequirementDescriptors in this generic signature.");
struct.add(WORD, "NumKeyArguments",
"The size of the key area of the argument layout, in words.");
struct.add(flags.toDataType(), "Flags", "");
return struct;
}
}

View File

@@ -0,0 +1,132 @@
/* ###
* 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.SwiftTypeMetadataStructure;
import ghidra.app.util.bin.format.swift.SwiftUtils;
import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException;
public class TargetGenericRequirementsDescriptor extends SwiftTypeMetadataStructure {
private GenericRequirementFlags flags;
private int param;
private int thing;
private GenericRequirementLayoutKind layout;
private int genericParamIndex;
private int protocols; // TODO: Make this a real InvertibleProtocolSet
/**
* Creates a new {@link TargetGenericRequirementsDescriptor}
*
* @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 TargetGenericRequirementsDescriptor(BinaryReader reader) throws IOException {
super(reader.getPointerIndex());
flags = new GenericRequirementFlags(reader);
param = reader.readNextInt();
thing = reader.readNextInt();
layout = GenericRequirementLayoutKind.valueOf(thing); // union
genericParamIndex = thing & 0xffff; // union
protocols = (thing) & 0xffff; // union
}
/**
* {@return the flags}
*/
public GenericRequirementFlags getFlags() {
return flags;
}
/**
* {@return the type that's constrained, described as a mangled name}
*/
public int getParam() {
return param;
}
/**
* {@return the thing (same-type, class, protocol, conformance) the param is constrained to}
*/
public int getThing() {
return thing;
}
/**
* {@return the layout if the requirement has Layout kind; otherwise, {@code null}}
*/
public GenericRequirementLayoutKind getLayout() {
return layout;
}
/**
* {@return the index of the generic parameter whose set of invertible protocols has disabled
* checks}
* <p>
* Only valid if the requirement has {@link GenericRequirementKind#IntertedProtocol} kind
*/
public int getGenericParamIndex() {
return genericParamIndex;
}
/**
* {@return the set of invertible protocols whose check is disabled}
* <p>
* Only valid if the requirement has {@link GenericRequirementKind#IntertedProtocol} kind
*/
public int getProtocols() {
return protocols;
}
@Override
public String getStructureName() {
return TargetGenericRequirementsDescriptor.class.getSimpleName();
}
@Override
public String getDescription() {
return "generic requirements descriptor";
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType invertedProtocolsStruct = new StructureDataType(CATEGORY_PATH, "InvertedProtocols", 0);
invertedProtocolsStruct.add(WORD, "GenericParamIndex",
"The index of the generic parameter to which this applies.");
invertedProtocolsStruct.add(WORD, "Protocols",
"The set of invertiable protocols whose check is disabled.");
UnionDataType union =
new UnionDataType(CATEGORY_PATH, "Union_TargetGenericRequirementsDescriptor");
union.add(SwiftUtils.PTR_RELATIVE, "Type", "A mangled representation of the same-type or base class the param is constrained to.");
union.add(SwiftUtils.PTR_RELATIVE, "Protocol", "The protocol the param is constrained to.");
union.add(SwiftUtils.PTR_RELATIVE, "Conformance", "The conformance the param is constrained to use.");
union.add(GenericRequirementLayoutKind.values()[0].toDataType(), "Layout",
"The kind of layout constraint.");
union.add(invertedProtocolsStruct, invertedProtocolsStruct.getName(), null);
StructureDataType struct = new StructureDataType(CATEGORY_PATH, getStructureName(), 0);
struct.add(flags.toDataType(), "Flags", null);
struct.add(SwiftUtils.PTR_RELATIVE, "Param",
"The type that's constrained, described as a mangled name.");
struct.add(union, union.getName(), null);
return struct;
}
}

View File

@@ -0,0 +1,104 @@
/* ###
* 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.SwiftTypeMetadataStructure;
import ghidra.app.util.bin.format.swift.SwiftUtils;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.StructureDataType;
import ghidra.util.exception.DuplicateNameException;
public class TargetGenericWitnessTable extends SwiftTypeMetadataStructure {
private int witnessTableSizeInWords;
private int witnessTablePrivateSizeInWordsAndRequiresInstantiation;
private int instantiator;
private int privateData;
/**
* Creates a new {@link TargetGenericWitnessTable}
*
* @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 TargetGenericWitnessTable(BinaryReader reader) throws IOException {
super(reader.getPointerIndex());
witnessTableSizeInWords = reader.readNextUnsignedShort();
witnessTablePrivateSizeInWordsAndRequiresInstantiation = reader.readNextUnsignedShort();
instantiator = reader.readNextInt();
privateData = reader.readNextInt();
}
/**
* {@return the size of the witness table in words}
* <p>
* The amount is copied from the witness table template into the instantiated witness table.
*/
public int getWitnessTableSizeInWords() {
return witnessTableSizeInWords;
}
/**
* {@return the amount of private storage to allocate before the address point, in words}
* <p>
* This memory is zeroed out in the instantiated witness table template. The low bit is used to
* indicate whether this witness table is known to require instantiation.
*/
public int getWitnessTablePrivateSizeInWordsAndRequiresInstantiation() {
return witnessTablePrivateSizeInWordsAndRequiresInstantiation;
}
/**
* {@return the instantiation function, which is called after the template is copied}
*/
public int getInstantiator() {
return instantiator;
}
/**
* {@return the private data for the instantiator}
* <p>
* Might be null with building with {@code -disable-preallocated-instantiation-caches}.
*/
public int getPrivateData() {
return privateData;
}
@Override
public String getStructureName() {
return TargetGenericWitnessTable.class.getSimpleName();
}
@Override
public String getDescription() {
return "generic witness table";
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(CATEGORY_PATH, getStructureName(), 0);
struct.add(WORD, "WitnessTableSizeInWords", "The size of the witness table in words.");
struct.add(WORD, "WitnessTablePrivateSizeInWordsAndRequiresInstantiation",
"The amount of private storage to allocate before the address point, in words.");
struct.add(SwiftUtils.PTR_RELATIVE, "Instantiator",
"The instantiation function, which is called after the template is copied.");
struct.add(SwiftUtils.PTR_RELATIVE, "PrivateData", "Private data for the instantiator.");
return struct;
}
}

View File

@@ -0,0 +1,85 @@
/* ###
* 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.SwiftTypeMetadataStructure;
import ghidra.app.util.bin.format.swift.SwiftUtils;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.StructureDataType;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift {@code TargetMethodDescriptor} structure
*
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/ABI/Metadata.h">swift/ABI/Metadata.h</a>
*/
public class TargetMethodDescriptor extends SwiftTypeMetadataStructure {
/**
* The size (in bytes) of a {@link TargetMethodDescriptor} structure
*/
public static final int SIZE = 8;
private MethodDescriptorFlags flags;
private int impl;
/**
* Creates a new {@link TargetMethodDescriptor}
*
* @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 TargetMethodDescriptor(BinaryReader reader) throws IOException {
super(reader.getPointerIndex());
flags = new MethodDescriptorFlags(reader);
impl = reader.readNextInt();
}
/**
* {@return the flags}
*/
public MethodDescriptorFlags getFlags() {
return flags;
}
/**
* {@return the method implementation's relative offset}
*/
public int getImpl() {
return impl;
}
@Override
public String getStructureName() {
return TargetMethodDescriptor.class.getSimpleName();
}
@Override
public String getDescription() {
return "method descriptor";
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(CATEGORY_PATH, getStructureName(), 0);
struct.add(flags.toDataType(), "Flags", "Flags describing the method");
struct.add(SwiftUtils.PTR_RELATIVE, "Impl", "The method implementation");
return struct;
}
}

View File

@@ -0,0 +1,96 @@
/* ###
* 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.SwiftTypeMetadataStructure;
import ghidra.app.util.bin.format.swift.SwiftUtils;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.StructureDataType;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift {@code TargetMethodOverrideDescriptor} structure
*
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/ABI/Metadata.h">swift/ABI/Metadata.h</a>
*/
public class TargetMethodOverrideDescriptor extends SwiftTypeMetadataStructure {
/**
* The size (in bytes) of a {@link TargetMethodOverrideDescriptor} structure
*/
public static final int SIZE = 8;
private int classPtr;
private int methodPtr;
private int impl;
/**
* Creates a new {@link TargetMethodOverrideDescriptor}
*
* @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 TargetMethodOverrideDescriptor(BinaryReader reader) throws IOException {
super(reader.getPointerIndex());
classPtr = reader.readNextInt();
methodPtr = reader.readNextInt();
impl = reader.readNextInt();
}
/**
* {@return the class containing the base method}
*/
public int getClassPtr() {
return classPtr;
}
/**
* {@return the base method}
*/
public int getMethodPtr() {
return methodPtr;
}
/**
* {@return the implementation of the override}
*/
public int getImpl() {
return impl;
}
@Override
public String getStructureName() {
return TargetMethodOverrideDescriptor.class.getSimpleName();
}
@Override
public String getDescription() {
return "method override descriptor";
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(CATEGORY_PATH, getStructureName(), 0);
struct.add(SwiftUtils.PTR_RELATIVE_MASKED, "Class",
"The class containing the base method.");
struct.add(SwiftUtils.PTR_RELATIVE_MASKED, "Method", "The base method.");
struct.add(SwiftUtils.PTR_RELATIVE, "Impl", "The implementation of the override");
return struct;
}
}

View File

@@ -0,0 +1,79 @@
/* ###
* 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.SwiftTypeMetadataStructure;
import ghidra.app.util.bin.format.swift.SwiftUtils;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.StructureDataType;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift {@code TargetObjCResilientClassStubInfo} structure
*
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/ABI/Metadata.h">swift/ABI/Metadata.h</a>
*/
public class TargetObjCResilientClassStubInfo extends SwiftTypeMetadataStructure {
private int stub;
/**
* Create a new {@link TargetObjCResilientClassStubInfo}
*
* @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 TargetObjCResilientClassStubInfo(BinaryReader reader) throws IOException {
super(reader.getPointerIndex());
stub = reader.readNextInt();
}
/**
* {@return a relative pointer to an Objective-C resilient class stub}
*/
public int getStub() {
return stub;
}
@Override
public String getStructureName() {
return getMyStructureName();
}
@Override
public String getDescription() {
return "objc resilient class stub";
}
/**
* {@return this class's structure name (will not be affected by subclass's name)}
*/
private final String getMyStructureName() {
return TargetObjCResilientClassStubInfo.class.getSimpleName();
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(CATEGORY_PATH, getMyStructureName(), 0);
struct.add(SwiftUtils.PTR_RELATIVE, "Stub",
"A relative pointer to an Objective-C resilient class stub.");
return struct;
}
}

View File

@@ -0,0 +1,71 @@
/* ###
* 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.SwiftTypeMetadataStructure;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.StructureDataType;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift {@code TargetOverrideTableHeader} structure
*
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/ABI/Metadata.h">swift/ABI/Metadata.h</a>
*/
public class TargetOverrideTableHeader extends SwiftTypeMetadataStructure {
private long numEntries;
/**
* Creates a new {@link TargetOverrideTableHeader}
*
* @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 TargetOverrideTableHeader(BinaryReader reader) throws IOException {
super(reader.getPointerIndex());
numEntries = reader.readNextUnsignedInt();
}
/**
* {@return the number of MethodOverrideDescriptor records following the vtable override header
* in the class's nominal type descriptor}
*/
public long getNumEntries() {
return numEntries;
}
@Override
public String getStructureName() {
return TargetOverrideTableHeader.class.getSimpleName();
}
@Override
public String getDescription() {
return "override table header";
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(CATEGORY_PATH, getStructureName(), 0);
struct.add(DWORD, "NumEntries",
"The number of MethodOverrideDescriptor records following the vtable override header in the class's nominal type descriptor.");
return struct;
}
}

View File

@@ -16,24 +16,33 @@
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.SwiftTypeMetadataStructure;
import ghidra.app.util.bin.format.swift.SwiftUtils;
import ghidra.program.model.data.*;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.StructureDataType;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift TargetProtocolConformanceDescriptor structure
* Represents a Swift {@code TargetProtocolConformanceDescriptor} structure
*
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/ABI/Metadata.h">swift/ABI/Metadata.h</a>
*/
public final class TargetProtocolConformanceDescriptor extends SwiftTypeMetadataStructure {
private int protocolDescriptor;
private int nominalTypeDescriptor;
private int protocolWitnessTable;
private int conformanceFlags;
private int protocol;
private int typeRef;
private int witnessTablePattern;
private ConformanceFlags flags;
// Trailing objects
private TargetRelativeContextPointer retroactiveContext;
private TargetResilientWitnessHeader resilientWitnessHeader;
private List<TargetResilientWitness> resilientWitnesses = new ArrayList<>();
private TargetGenericWitnessTable genericWitnessTable;
/**
* Creates a new {@link TargetProtocolConformanceDescriptor}
@@ -43,46 +52,98 @@ public final class TargetProtocolConformanceDescriptor extends SwiftTypeMetadata
*/
public TargetProtocolConformanceDescriptor(BinaryReader reader) throws IOException {
super(reader.getPointerIndex());
protocolDescriptor = reader.readNextInt();
nominalTypeDescriptor = reader.readNextInt();
protocolWitnessTable = reader.readNextInt();
conformanceFlags = reader.readNextInt();
protocol = reader.readNextInt();
typeRef = reader.readNextInt();
witnessTablePattern = reader.readNextInt();
flags = new ConformanceFlags(reader);
if (flags.isRetroactive()) {
retroactiveContext = new TargetRelativeContextPointer(reader);
}
if (flags.hasResilientWitnesses()) {
resilientWitnessHeader = new TargetResilientWitnessHeader(reader);
for (int i = 0; i < resilientWitnessHeader.getNumWitnesses(); i++) {
resilientWitnesses.add(new TargetResilientWitness(reader));
}
}
if (flags.hasGenericWitnessTable()) {
genericWitnessTable = new TargetGenericWitnessTable(reader);
}
}
/**
* Gets the protocol being conformed to
*
* @return The protocol being conformed to
* {@return the protocol being conformed to}
*/
public int getProtocolDescriptor() {
return protocolDescriptor;
public int getProtocol() {
return protocol;
}
/**
* Gets some description of the type that conforms to the protocol
*
* @return 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;
public int getTypeRef() {
return typeRef;
}
/**
* 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
* {@return the witness table pattern, which may also serve as the witness table}
*/
public int getProtocolWitnessTable() {
return protocolWitnessTable;
public int getWitnessTablePattern() {
return witnessTablePattern;
}
/**
* Gets various flags, including the kind of conformance
*
* @return Various flags, including the kind of conformance
* {@return various flags, including the kind of conformance}
*/
public int getConformanceFlags() {
return conformanceFlags;
public ConformanceFlags getConformanceFlags() {
return flags;
}
/**
* {@return the {@link TargetRelativeContextPointer retroactive context}, or {@code null} if it
* doesn't exist}
*/
public TargetRelativeContextPointer getRetroactiveContext() {
return retroactiveContext;
}
/**
* {@return the {@link TargetResilientWitnessHeader}, or {@code null} if it doesn't exist}
*/
public TargetResilientWitnessHeader getResilientWitnessHeader() {
return resilientWitnessHeader;
}
/**
* {@return the {@link List} of resilient witnesses}
*/
public List<TargetResilientWitness> getResilientWitnesses() {
return resilientWitnesses;
}
/**
* {@return the {@link TargetGenericWitnessTable}, or {@code null} if it doesn't exist}
*/
public TargetGenericWitnessTable getGenericWitnessTable() {
return genericWitnessTable;
}
@Override
public List<SwiftTypeMetadataStructure> getTrailingObjects() {
List<SwiftTypeMetadataStructure> ret = new ArrayList<>();
if (retroactiveContext != null) {
ret.add(retroactiveContext);
}
if (resilientWitnessHeader != null) {
ret.add(resilientWitnessHeader);
ret.addAll(resilientWitnesses);
}
if (genericWitnessTable != null) {
ret.add(genericWitnessTable);
}
return ret;
}
@Override
@@ -97,14 +158,13 @@ public final class TargetProtocolConformanceDescriptor extends SwiftTypeMetadata
@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",
StructureDataType struct = new StructureDataType(CATEGORY_PATH, getStructureName(), 0);
struct.add(SwiftUtils.PTR_RELATIVE_MASKED, "Protocol", "The protocol being conformed to");
struct.add(SwiftUtils.PTR_RELATIVE, "TypeRef",
"Some description of the type that conforms to the protocol");
struct.add(DWORD, "ProtocolWitnessTable",
struct.add(DWORD, "WitnessTablePattern",
"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));
struct.add(flags.toDataType(), "Flags", "Various flags, including the kind of conformance");
return struct;
}

View File

@@ -16,16 +16,18 @@
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.SwiftTypeMetadataStructure;
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
* Represents a Swift {@code TargetProtocolDescriptor} structure
*
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/ABI/Metadata.h">swift/ABI/Metadata.h</a>
*/
@@ -36,6 +38,9 @@ public final class TargetProtocolDescriptor extends TargetContextDescriptor {
private int numRequirements;
private int associatedTypeNames;
private List<TargetGenericRequirementsDescriptor> requirementsInSig = new ArrayList<>();
private List<TargetProtocolRequirement> requirements = new ArrayList<>();
/**
* Creates a new {@link TargetProtocolDescriptor}
*
@@ -48,49 +53,70 @@ public final class TargetProtocolDescriptor extends TargetContextDescriptor {
numRequirementsInSig = reader.readNextInt();
numRequirements = reader.readNextInt();
associatedTypeNames = reader.readNextInt();
for (int i = 0; i < numRequirementsInSig; i++) {
requirementsInSig.add(new TargetGenericRequirementsDescriptor(reader));
}
for (int i = 0; i < numRequirements; i++) {
requirements.add(new TargetProtocolRequirement(reader));
}
}
/**
* Gets the name of the protocol
*
* @return 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
* {@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
* {@return the number of requirements in the protocol}
*/
public int getNumRequirements() {
return numRequirements;
}
/**
* Gets the associated type names
*
* @return The associated type names
* @return the associated type names}
*/
public int getAssociatedTypeNames() {
return associatedTypeNames; // TODO: it's a list...improve
}
/**
* {@return a {@link List} of generic requirements in the requirement signature of the protocol}
*/
public List<TargetGenericRequirementsDescriptor> getRequirementsInSignature() {
return requirementsInSig;
}
/**
* {@return a {@link List} of requirements in the protocol}
*/
public List<TargetProtocolRequirement> getRequirements() {
return requirements;
}
@Override
public String toString() {
return name;
}
@Override
public List<SwiftTypeMetadataStructure> getTrailingObjects() {
List<SwiftTypeMetadataStructure> ret = new ArrayList<>();
ret.addAll(requirementsInSig);
ret.addAll(requirements);
return ret;
}
@Override
public String getStructureName() {
return TargetProtocolDescriptor.class.getSimpleName();
@@ -103,15 +129,14 @@ public final class TargetProtocolDescriptor extends TargetContextDescriptor {
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(getStructureName(), 0);
StructureDataType struct = new StructureDataType(CATEGORY_PATH, 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",
struct.add(SwiftUtils.PTR_RELATIVE, "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;
}

View File

@@ -0,0 +1,79 @@
/* ###
* 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.SwiftTypeMetadataStructure;
import ghidra.app.util.bin.format.swift.SwiftUtils;
import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException;
public class TargetProtocolRequirement extends SwiftTypeMetadataStructure {
private ProtocolRequirementFlags flags;
private int impl;
/**
* Creates a new {@link TargetProtocolRequirement}
*
* @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 TargetProtocolRequirement(BinaryReader reader) throws IOException {
super(reader.getPointerIndex());
flags = new ProtocolRequirementFlags(reader);
impl = reader.readNextInt();
}
/**
* {@return the flags}
*/
public ProtocolRequirementFlags getFlags() {
return flags;
}
/**
* {@return the optional default implementation of the protocol}
*/
public int getImpl() {
return impl;
}
@Override
public String getStructureName() {
return TargetProtocolRequirement.class.getSimpleName();
}
@Override
public String getDescription() {
return "protocol requirement";
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
UnionDataType union = new UnionDataType(CATEGORY_PATH,
"Union_DefaultFuncImplementation_DefaultImplementation");
union.add(SwiftUtils.PTR_RELATIVE, "DefaultFuncImplementation", null);
union.add(SwiftUtils.PTR_RELATIVE, "DefaultImplementation", null);
StructureDataType struct = new StructureDataType(CATEGORY_PATH, getStructureName(), 0);
struct.add(flags.toDataType(), "Flags", null);
struct.add(union, "Implementation", "The optional default implementation.");
return struct;
}
}

View File

@@ -0,0 +1,67 @@
/* ###
* 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.SwiftTypeMetadataStructure;
import ghidra.app.util.bin.format.swift.SwiftUtils;
import ghidra.program.model.data.DataType;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift {@code TargetRelativeContextPointer} structure
*
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/ABI/MetadataRef.h">swift/ABI/MetadataRef.h</a>
*/
public class TargetRelativeContextPointer extends SwiftTypeMetadataStructure {
private int value;
/**
* Creates a new {@link TargetRelativeContextPointer}
*
* @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 TargetRelativeContextPointer(BinaryReader reader) throws IOException {
super(reader.getPointerIndex());
value = reader.readNextInt();
}
/**
* {@return the pointer value}
*/
public long getValue() {
return value;
}
@Override
public String getStructureName() {
return TargetRelativeContextPointer.class.getSimpleName();
}
@Override
public String getDescription() {
return "relative context pointer";
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
return SwiftUtils.PTR_RELATIVE_MASKED;
}
}

View File

@@ -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.SwiftTypeMetadataStructure;
import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift {@code TargetRelativeContextPointer} structure
*
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/ABI/Metadata.h">swift/ABI/Metadata.h</a>
*/
public class TargetRelativeProtocolRequirementPointer extends SwiftTypeMetadataStructure {
public static final TypeDef dataType =
new PointerTypedefBuilder(Pointer32DataType.dataType, null)
.type(PointerType.RELATIVE)
.bitMask(~1)
.build();
private int value;
/**
* Creates a new {@link TargetRelativeProtocolRequirementPointer}
*
* @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 TargetRelativeProtocolRequirementPointer(BinaryReader reader) throws IOException {
super(reader.getPointerIndex());
value = reader.readNextInt();
}
/**
* {@return the pointer value}
*/
public long getValue() {
return value;
}
@Override
public String getStructureName() {
return TargetRelativeProtocolRequirementPointer.class.getSimpleName();
}
@Override
public String getDescription() {
return "relative protocol requirement pointer";
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
return dataType;
}
}

View File

@@ -0,0 +1,78 @@
/* ###
* 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.SwiftTypeMetadataStructure;
import ghidra.app.util.bin.format.swift.SwiftUtils;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.StructureDataType;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift {@code TargetResilientSuperclass} structure
*
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/ABI/Metadata.h">swift/ABI/Metadata.h</a>
*/
public class TargetResilientSuperclass extends SwiftTypeMetadataStructure {
private int superclass;
/**
* Create a new {@link TargetResilientSuperclass}
*
* @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 TargetResilientSuperclass(BinaryReader reader) throws IOException {
super(reader.getPointerIndex());
superclass = reader.readNextInt();
}
/**
* {@return the superclass of this class, or 0 if there isn't one}
*/
public int getSuperclass() {
return superclass;
}
@Override
public String getStructureName() {
return getMyStructureName();
}
@Override
public String getDescription() {
return "resilient superclass";
}
/**
* {@return this class's structure name (will not be affected by subclass's name)}
*/
private final String getMyStructureName() {
return TargetResilientSuperclass.class.getSimpleName();
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(CATEGORY_PATH, getMyStructureName(), 0);
struct.add(SwiftUtils.PTR_RELATIVE, "Superclass", "The superclass of this class.");
return struct;
}
}

View File

@@ -0,0 +1,79 @@
/* ###
* 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.SwiftTypeMetadataStructure;
import ghidra.app.util.bin.format.swift.SwiftUtils;
import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException;
public class TargetResilientWitness extends SwiftTypeMetadataStructure {
private TargetRelativeProtocolRequirementPointer requirement;
private int impl;
/**
* Creates a new {@link TargetResilientWitness}
*
* @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 TargetResilientWitness(BinaryReader reader) throws IOException {
super(reader.getPointerIndex());
requirement = new TargetRelativeProtocolRequirementPointer(reader);
impl = reader.readNextInt();
}
/**
* {@return the requirement}
*/
public TargetRelativeProtocolRequirementPointer getRequirement() {
return requirement;
}
/**
* {@return the implementation}
*/
public int getImpl() {
return impl;
}
@Override
public String getStructureName() {
return TargetResilientWitness.class.getSimpleName();
}
@Override
public String getDescription() {
return "resilient witness";
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
UnionDataType union = new UnionDataType(CATEGORY_PATH,
"Union_Impl_FuncImpl");
union.add(SwiftUtils.PTR_RELATIVE, "Impl", null);
union.add(SwiftUtils.PTR_RELATIVE, "FuncImpl", null);
StructureDataType struct = new StructureDataType(CATEGORY_PATH, getStructureName(), 0);
struct.add(TargetRelativeProtocolRequirementPointer.dataType, "Requirement", null);
struct.add(union, "Implementation", null);
return struct;
}
}

View File

@@ -0,0 +1,69 @@
/* ###
* 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.SwiftTypeMetadataStructure;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.StructureDataType;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift {@code TargetResilientWitnessHeader} structure
*
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/ABI/Metadata.h">swift/ABI/Metadata.h</a>
*/
public class TargetResilientWitnessHeader extends SwiftTypeMetadataStructure {
private long numWitnesses;
/**
* Creates a new {@link TargetResilientWitnessHeader}
*
* @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 TargetResilientWitnessHeader(BinaryReader reader) throws IOException {
super(reader.getPointerIndex());
numWitnesses = reader.readNextUnsignedInt();
}
/**
* {@return the number of witnesses}
*/
public long getNumWitnesses() {
return numWitnesses;
}
@Override
public String getStructureName() {
return TargetResilientWitnessHeader.class.getSimpleName();
}
@Override
public String getDescription() {
return "resilient witness header";
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(CATEGORY_PATH, getStructureName(), 0);
struct.add(DWORD, "NumWitnesses", null);
return struct;
}
}

View File

@@ -0,0 +1,114 @@
/* ###
* 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.SwiftTypeMetadataStructure;
import ghidra.app.util.bin.format.swift.SwiftUtils;
import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift {@code TargetSingletonMetadataInitialization} structure
*
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/ABI/Metadata.h">swift/ABI/Metadata.h</a>
*/
public class TargetSingletonMetadataInitialization extends SwiftTypeMetadataStructure {
private ContextDescriptorFlags flags;
private int initializationCache;
private int incompleteMetadata;
private int resilientPattern;
private int completionFunction;
/**
* Creates a new {@link TargetSingletonMetadataInitialization}
*
* @param reader A {@link BinaryReader} positioned at the start of the structure
* @param flags The {@link ContextDescriptorFlags}
* @throws IOException if there was an IO-related problem creating the structure
*/
public TargetSingletonMetadataInitialization(BinaryReader reader, ContextDescriptorFlags flags)
throws IOException {
super(reader.getPointerIndex());
this.flags = flags;
initializationCache = reader.readNextInt();
incompleteMetadata = reader.readNextInt();
resilientPattern = incompleteMetadata;
completionFunction = reader.readNextInt();
}
/**
* {@return the initialization cache}
*/
public int getInitializationCache() {
return initializationCache;
}
/**
* {@return the incomplete metadata for structs, enums, and classes if there is no resilient
* ancestry; otherwise, 0}
*/
public int getIncompleteMetadata() {
return !flags.hasClassResilientSuperclass() ? incompleteMetadata : 0;
}
/**
* {@return a pattern used to allocation and initialize metadata for this class if there is a
* resilient superclass; otherwise, 0}
*/
public int getResilientPattern() {
return flags.hasClassResilientSuperclass() ? resilientPattern : 0;
}
/**
* {@return the completion function (the pattern will always be null, even for a resilient
* class)}
*/
public int getCompletionFunction() {
return completionFunction;
}
@Override
public String getStructureName() {
return TargetSingletonMetadataInitialization.class.getSimpleName();
}
@Override
public String getDescription() {
return "singleton metadata initialization";
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
UnionDataType union =
new UnionDataType(CATEGORY_PATH, "Union_IncompleteMetadata_ResilientPattern");
union.add(SwiftUtils.PTR_RELATIVE, "IncompleteMetadata",
"The incomplete metadata, for structs, enums and classes without resilient ancestry.");
union.add(SwiftUtils.PTR_RELATIVE, "ResilientPattern",
"If the classes descriptor has a resilient superclass, this points at a pattern used to allcoate and initialize metadata for this class, since its size and contents is not known at compile time.");
StructureDataType struct = new StructureDataType(CATEGORY_PATH, getStructureName(), 0);
struct.add(SwiftUtils.PTR_RELATIVE, "InitializationCache", "The initialization cache.");
struct.add(union, union.getName(), null);
struct.add(SwiftUtils.PTR_RELATIVE, "CompletionFunction",
"The completion function. The pattern will always be null, even for a resilient class.");
return struct;
}
}

View File

@@ -16,15 +16,17 @@
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.program.model.data.CategoryPath;
import ghidra.app.util.bin.format.swift.SwiftTypeMetadataStructure;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.StructureDataType;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift TargetStructDescriptor structure
* Represents a Swift {@code TargetStructDescriptor} structure
*
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/ABI/Metadata.h">swift/ABI/Metadata.h</a>
*/
@@ -33,6 +35,11 @@ public final class TargetStructDescriptor extends TargetTypeContextDescriptor {
private int numFields;
private int fieldOffsetVectorOffset;
// Trailing objects
private TargetTypeGenericContextDescriptorHeader genericHeader;
private TargetSingletonMetadataInitialization singleton;
private TargetForeignMetadataInitialization foreign;
/**
* Creates a new {@link TargetStructDescriptor}
*
@@ -43,30 +50,93 @@ public final class TargetStructDescriptor extends TargetTypeContextDescriptor {
super(reader);
numFields = reader.readNextInt();
fieldOffsetVectorOffset = reader.readNextInt();
if (flags.isGeneric()) {
genericHeader = new TargetTypeGenericContextDescriptorHeader(reader);
}
switch (flags.getMetadataInitialization()) {
case NoMetadataInitialization:
break;
case SingletonMetadataInitialization:
singleton = new TargetSingletonMetadataInitialization(reader, flags);
break;
case ForeignMetadataInitialization:
foreign = new TargetForeignMetadataInitialization(reader);
break;
}
if (flags.isGeneric() &&
flags.hasCanonicalMetadataPrespecializationsOrSingletonMetadataPonter()) {
throw new IOException("Unimplemented TargetCanonicalSpecializedMetadatas detected.");
}
if (flags.hasInvertableProtocols()) {
throw new IOException("Unimplemented InvertibleProtocolSet detected.");
}
if (!flags.isGeneric() &&
flags.hasCanonicalMetadataPrespecializationsOrSingletonMetadataPonter()) {
throw new IOException("Unimplemented TargetSingletonMetadataPointer detected.");
}
}
/**
* 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.
* {@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.
* {@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;
}
/**
* {@return the {@link TargetTypeGenericContextDescriptorHeader}, or {@code null} if it doesn't
* exist}
*/
public TargetTypeGenericContextDescriptorHeader getGenericHeader() {
return genericHeader;
}
/**
* {@return the {@link TargetSingletonMetadataInitialization}, or {@code null} if it doesn't
* exist}
*/
public TargetSingletonMetadataInitialization getTargetSingletonMetadataInitialization() {
return singleton;
}
/**
* {@return the {@link TargetForeignMetadataInitialization}, or {@code null} if it doesn't
* exist}
*/
public TargetForeignMetadataInitialization getTargetForeignMetadataInitialization() {
return foreign;
}
@Override
public List<SwiftTypeMetadataStructure> getTrailingObjects() {
List<SwiftTypeMetadataStructure> ret = new ArrayList<>();
if (genericHeader != null) {
ret.add(genericHeader);
ret.addAll(genericHeader.getTrailingObjects());
}
if (singleton != null) {
ret.add(singleton);
}
if (foreign != null) {
ret.add(foreign);
}
return ret;
}
@Override
public String getStructureName() {
return TargetStructDescriptor.class.getSimpleName();
@@ -79,13 +149,12 @@ public final class TargetStructDescriptor extends TargetTypeContextDescriptor {
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(getStructureName(), 0);
StructureDataType struct = new StructureDataType(CATEGORY_PATH, 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;
}

View File

@@ -20,11 +20,12 @@ import java.util.Map;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.swift.SwiftUtils;
import ghidra.program.model.data.*;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.StructureDataType;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift TargetTypeContextDescriptor structure
* Represents a Swift {@code TargetTypeContextDescriptor} structure
*
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/ABI/Metadata.h">swift/ABI/Metadata.h</a>
*/
@@ -48,39 +49,32 @@ public class TargetTypeContextDescriptor extends TargetContextDescriptor {
}
/**
* Gets the name of the type
*
* @return 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
* {@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
* {@return the pointer to the field descriptor for the type, if any}
*/
public int getFields() {
return fields;
}
/**
* Gets this {@link TargetTypeContextDescriptor}'s {@link FieldDescriptor}
* {@return this {@link TargetTypeContextDescriptor}'s {@link FieldDescriptor}, or {@code null}
* if it doesn't have one}
*
* @param fieldDescriptors A {@link Map} of {@link FieldDescriptor}'s keyed by their base
* addresses
* @return This {@link TargetTypeContextDescriptor}'s {@link FieldDescriptor}, or null if it
* doesn't have one
*/
public FieldDescriptor getFieldDescriptor(Map<Long, FieldDescriptor> fieldDescriptors) {
FieldDescriptor fieldDescriptor =
@@ -104,9 +98,7 @@ public class TargetTypeContextDescriptor extends TargetContextDescriptor {
}
/**
* Gets this class's structure name (will not be affected by subclass's name)
*
* @return This class's structure name
* {@return this class's structure name (will not be affected by subclass's name)}
*/
private final String getMyStructureName() {
return TargetTypeContextDescriptor.class.getSimpleName();
@@ -114,14 +106,13 @@ public class TargetTypeContextDescriptor extends TargetContextDescriptor {
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(getMyStructureName(), 0);
StructureDataType struct = new StructureDataType(CATEGORY_PATH, 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;
}
}

View File

@@ -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 java.util.List;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.swift.SwiftTypeMetadataStructure;
import ghidra.app.util.bin.format.swift.SwiftUtils;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.StructureDataType;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift {@code TargetTypeGenericContextDescriptorHeader} structure
*
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/ABI/Metadata.h">swift/ABI/Metadata.h</a>
*/
public class TargetTypeGenericContextDescriptorHeader extends SwiftTypeMetadataStructure {
private int instantiationCache;
private int defaultInstallationPattern;
private TargetGenericContextDescriptorHeader base;
/**
* Creates a new {@link TargetTypeGenericContextDescriptorHeader}
*
* @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 TargetTypeGenericContextDescriptorHeader(BinaryReader reader) throws IOException {
super(reader.getPointerIndex());
instantiationCache = reader.readNextInt();
defaultInstallationPattern = reader.readNextInt();
base = new TargetGenericContextDescriptorHeader(reader);
}
/**
* {@return the metadata instantiation cache}
*/
public int getInstantiationCache() {
return instantiationCache;
}
/**
* {@return the default instantiation pattern}
*/
public int getDefaultInstallationPattern() {
return defaultInstallationPattern;
}
/**
* {@return the base header}
*/
public TargetGenericContextDescriptorHeader getBaseHeader() {
return base;
}
@Override
public List<SwiftTypeMetadataStructure> getTrailingObjects() {
return base.getTrailingObjects();
}
@Override
public String getStructureName() {
return TargetTypeGenericContextDescriptorHeader.class.getSimpleName();
}
@Override
public String getDescription() {
return "type generic context descriptor header";
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(CATEGORY_PATH, getStructureName(), 0);
struct.add(SwiftUtils.PTR_RELATIVE, "InstantiationCache",
"The metadata instantiation cache.");
struct.add(SwiftUtils.PTR_RELATIVE, "DefaultInstantiationPattern",
"The default instantiation pattern.");
struct.add(base.toDataType(), "Base", "The base header.");
return struct;
}
}

View File

@@ -0,0 +1,80 @@
/* ###
* 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.SwiftTypeMetadataStructure;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.StructureDataType;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift {@code TargetVTableDescriptorHeader} structure
*
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/ABI/Metadata.h">swift/ABI/Metadata.h</a>
*/
public class TargetVTableDescriptorHeader extends SwiftTypeMetadataStructure {
private long vtableOffset;
private long vtableSize;
/**
* Creates a new {@link TargetVTableDescriptorHeader}
*
* @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 TargetVTableDescriptorHeader(BinaryReader reader) throws IOException {
super(reader.getPointerIndex());
vtableOffset = reader.readNextUnsignedInt();
vtableSize = reader.readNextUnsignedInt();
}
/**
* {@return the offset of the vtable for this class in its metadata, if any, in words}
*/
public long getVTableOffset() {
return vtableOffset;
}
/**
* {@return the number of vtable entries}
*/
public long getVTableSize() {
return vtableSize;
}
@Override
public String getStructureName() {
return TargetVTableDescriptorHeader.class.getSimpleName();
}
@Override
public String getDescription() {
return "vtable descriptor header";
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(CATEGORY_PATH, getStructureName(), 0);
struct.add(DWORD, "VTableOffset",
"The offset of the vtable for this class in its metadata, if any, in words.");
struct.add(DWORD, "VTableSize", "The number of vtable entries.");
return struct;
}
}

View File

@@ -0,0 +1,76 @@
/* ###
* 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.Arrays;
import ghidra.app.util.bin.StructConverter;
import ghidra.app.util.bin.format.swift.SwiftTypeMetadataStructure;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.EnumDataType;
import ghidra.util.exception.DuplicateNameException;
/**
* Swift {@code TypeReferenceKind} values
*
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/ABI/MetadataValues.h">swift/ABI/MetadataValues.h</a>
*/
public enum TypeReferenceKind implements StructConverter {
DirectTypeDescriptor(0),
IndirectTypeDescriptor(1),
DirectObjCClassName(2),
IndirectObjCClass(3);
private int value;
/**
* Creates a new {@link TypeReferenceKind}
*
* @param value The kind value
*/
private TypeReferenceKind(int value) {
this.value = value;
}
/**
* {@return the kind value}
*/
public int getValue() {
return value;
}
/**
* {@return the {@link TypeReferenceKind} with the given kind value, or {@code null} if it
* does not exist}
*
* @param value The kind value to get the value of
*/
public static TypeReferenceKind valueOf(int value) {
return Arrays.stream(values()).filter(e -> e.getValue() == value).findFirst().orElse(null);
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
EnumDataType dt = new EnumDataType(SwiftTypeMetadataStructure.CATEGORY_PATH,
TypeReferenceKind.class.getSimpleName(), 1);
for (TypeReferenceKind kind : values()) {
dt.add(kind.name(), kind.getValue());
}
return dt;
}
}

View File

@@ -56,6 +56,7 @@ public enum SwiftDemangledNodeKind {
LazyProtocolWitnessTableAccessor,
LocalDeclName,
MergedFunction,
MethodDescriptor,
ModifyAccessor,
Module,
ModuleDescriptor,

View File

@@ -87,6 +87,7 @@ public abstract class SwiftNode {
case LazyProtocolWitnessTableAccessor -> new SwiftLazyProtocolWitnessTableAccessorNode();
case LocalDeclName -> new SwiftLocalDeclNameNode();
case MergedFunction -> new SwiftGenericPassthroughNode();
case MethodDescriptor -> new SwiftGenericDescriptorNode();
case ModifyAccessor -> new SwiftModifyAccessorNode();
case Module -> new SwiftGenericTextNode();
case ModuleDescriptor -> new SwiftGenericDescriptorNode();